DO NOT MERGE: BufferStateLayer: Mirror BufferQueue behavior in fence merging am: 92c2976f7c

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1538645

Change-Id: Ifc2f0f65ed0405861b14fc54a3053497488f81fc
diff --git a/.clang-format b/.clang-format
index 03af56d..6725a1f 100644
--- a/.clang-format
+++ b/.clang-format
@@ -11,3 +11,4 @@
 IndentWidth: 4
 PenaltyBreakBeforeFirstCallParameter: 100000
 SpacesBeforeTrailingComments: 1
+IncludeBlocks: Preserve
diff --git a/Android.bp b/Android.bp
index 9829c7f..6fe0246 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,41 @@
+package {
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change filtered out the below license kinds as false-positives:
+//   SPDX-license-identifier-LGPL
+//   SPDX-license-identifier-LGPL-2.1
+//   SPDX-license-identifier-LGPL-3.0
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-MIT",
+        "SPDX-license-identifier-Unicode-DFS",
+        "legacy_notice",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 ndk_headers {
     name: "libandroid_headers",
     from: "include/android",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 9cab9b4..16ebf6f 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,10 +5,10 @@
 # Only turn on clang-format check for the following subfolders.
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
                cmds/idlcli/
+               cmds/servicemanager/
                include/input/
                libs/binder/fuzzer/
-               libs/binder/ndk/
-               libs/binder/tests/fuzzers/
+               libs/binder/
                libs/binderthreadstate/
                libs/graphicsenv/
                libs/gui/
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 8173c89..f7d1dde 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -55,9 +55,6 @@
           "include-filter": "*RelativeZTest.*"
         }
       ]
-    },
-    {
-      "name": "libsurfaceflinger_unittest"
     }
   ]
 }
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index e7d0ad0..aa0ef25 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -1,5 +1,22 @@
 // Copyright 2012 The Android Open Source Project
 
+package {
+    default_applicable_licenses: ["frameworks_native_cmds_atrace_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_cmds_atrace_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_binary {
     name: "atrace",
     srcs: ["atrace.cpp"],
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 2519ffa..6f5f70d 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -62,7 +62,7 @@
 
 using std::string;
 
-#define MAX_SYS_FILES 11
+#define MAX_SYS_FILES 12
 
 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
 const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
@@ -175,6 +175,7 @@
         { OPT,      "events/power/suspend_resume/enable" },
         { OPT,      "events/cpuhp/cpuhp_enter/enable" },
         { OPT,      "events/cpuhp/cpuhp_exit/enable" },
+        { OPT,      "events/cpuhp/cpuhp_pause/enable" },
     } },
     { "membus",     "Memory Bus Utilization", 0, {
         { REQ,      "events/memory_bus/enable" },
@@ -319,9 +320,6 @@
 static const char* k_funcgraphProcPath =
     "options/funcgraph-proc";
 
-static const char* k_funcgraphFlatPath =
-    "options/funcgraph-flat";
-
 static const char* k_ftraceFilterPath =
     "set_ftrace_filter";
 
@@ -699,7 +697,6 @@
         ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
         ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
         ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
-        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
 
         // Set the requested filter functions.
         ok &= truncateFile(k_ftraceFilterPath);
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 994375b..37fc9a9 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -37,12 +37,18 @@
     chmod 0666 /sys/kernel/tracing/events/sched/sched_process_exit/enable
     chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_waking/enable
     chmod 0666 /sys/kernel/tracing/events/sched/sched_waking/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/enable
+    chmod 0666 /sys/kernel/tracing/events/sched/sched_wakeup_new/enable
     chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable
     chmod 0666 /sys/kernel/tracing/events/cgroup/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
     chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
     chmod 0666 /sys/kernel/tracing/events/power/cpu_idle/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/clock_enable/enable
+    chmod 0666 /sys/kernel/tracing/events/power/clock_enable/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/power/clock_disable/enable
+    chmod 0666 /sys/kernel/tracing/events/power/clock_disable/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
     chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
@@ -51,6 +57,8 @@
     chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_enter/enable
     chmod 0666 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit/enable
     chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_pause/enable
+    chmod 0666 /sys/kernel/tracing/events/cpuhp/cpuhp_pause/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
     chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
     chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/enable
@@ -79,6 +87,8 @@
     chmod 0666 /sys/kernel/tracing/events/binder/binder_locked/enable
     chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
     chmod 0666 /sys/kernel/tracing/events/binder/binder_unlock/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_set_priority/enable
+    chmod 0666 /sys/kernel/tracing/events/binder/binder_set_priority/enable
     chmod 0666 /sys/kernel/debug/tracing/events/i2c/enable
     chmod 0666 /sys/kernel/tracing/events/i2c/enable
     chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_read/enable
@@ -125,12 +135,48 @@
     chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable
     chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable
     chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/oom/mark_victim/enable
+    chmod 0666 /sys/kernel/tracing/events/oom/mark_victim/enable
     chmod 0666 /sys/kernel/debug/tracing/events/task/task_rename/enable
     chmod 0666 /sys/kernel/tracing/events/task/task_rename/enable
     chmod 0666 /sys/kernel/debug/tracing/events/task/task_newtask/enable
     chmod 0666 /sys/kernel/tracing/events/task/task_newtask/enable
     chmod 0666 /sys/kernel/debug/tracing/events/gpu_mem/gpu_mem_total/enable
     chmod 0666 /sys/kernel/tracing/events/gpu_mem/gpu_mem_total/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/irq_handler_entry/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/irq_handler_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/irq_handler_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_entry/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/softirq_entry/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/softirq_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_raise/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/softirq_raise/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_entry/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/tasklet_entry/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/tasklet_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_hi_entry/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/tasklet_hi_entry/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_hi_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/irq/tasklet_hi_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
+    chmod 0666 /sys/kernel/tracing/events/ipi/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_entry/enable
+    chmod 0666 /sys/kernel/tracing/events/ipi/ipi_entry/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/ipi/ipi_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_raise/enable
+    chmod 0666 /sys/kernel/tracing/events/ipi/ipi_raise/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_enable/enable
+    chmod 0666 /sys/kernel/tracing/events/clk/clk_disable/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_disable/enable
+    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
 
     # disk
     chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
@@ -220,6 +266,67 @@
     chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu15/trace
     chmod 0666 /sys/kernel/tracing/per_cpu/cpu15/trace
 
+on post-fs-data
+# Create MM Events Tracing Instance for Kmem Activity Trigger
+    mkdir /sys/kernel/debug/tracing/instances/mm_events 0755 system system
+    mkdir /sys/kernel/tracing/instances/mm_events 0755 system system
+
+# Read and set per CPU buffer size
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/buffer_size_kb
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/buffer_size_kb
+
+# Read and enable tracing
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/tracing_on
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/tracing_on
+
+# Read and truncate kernel trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/trace
+
+# Enable trace events
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/events/vmscan/mm_vmscan_kswapd_wake/enable
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/events/vmscan/mm_vmscan_kswapd_wake/enable
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/events/compaction/mm_compaction_begin/enable
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/events/compaction/mm_compaction_begin/enable
+
+# Read and clear per-CPU raw kernel trace
+# Cannot use wildcards in .rc files. Update this if there is a phone with
+# more CPUs.
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu0/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu0/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu1/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu1/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu2/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu2/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu3/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu3/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu4/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu4/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu5/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu5/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu6/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu6/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu7/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu7/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu8/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu8/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu9/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu9/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu10/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu10/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu11/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu11/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu12/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu12/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu13/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu13/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu14/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu14/trace
+    chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu15/trace
+    chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu15/trace
+
 on property:persist.debug.atrace.boottrace=1
     start boottrace
 
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 6c86c21..9186514 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -18,8 +18,3 @@
     chmod 0666 /sys/kernel/tracing/events/filemap/enable
     chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable
 
-    # irq
-    chmod 0666 /sys/kernel/tracing/events/irq/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
-    chmod 0666 /sys/kernel/tracing/events/ipi/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
diff --git a/cmds/bugreport/Android.bp b/cmds/bugreport/Android.bp
index 24044a6..8262aed 100644
--- a/cmds/bugreport/Android.bp
+++ b/cmds/bugreport/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "bugreport",
     srcs: ["bugreport.cpp"],
diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/bugreport/OWNERS
+++ b/cmds/bugreport/OWNERS
@@ -1,6 +1,4 @@
 set noparent
 
-felipeal@google.com
 nandana@google.com
 jsharkey@android.com
-enh@google.com
diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp
index 924a3a3..332f858 100644
--- a/cmds/bugreportz/Android.bp
+++ b/cmds/bugreportz/Android.bp
@@ -1,5 +1,14 @@
 // bugreportz
 // ==========
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "bugreportz",
 
diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/bugreportz/OWNERS
+++ b/cmds/bugreportz/OWNERS
@@ -1,6 +1,4 @@
 set noparent
 
-felipeal@google.com
 nandana@google.com
 jsharkey@android.com
-enh@google.com
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
index 8ea71cd..c900a24 100644
--- a/cmds/cmd/Android.bp
+++ b/cmds/cmd/Android.bp
@@ -1,3 +1,20 @@
+package {
+    default_applicable_licenses: ["frameworks_native_cmds_cmd_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_cmds_cmd_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_static {
     name: "libcmd",
 
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 80d14ac..aff32c3 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -13,6 +13,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "dumpstate_cflag_defaults",
     cflags: [
@@ -90,6 +99,7 @@
         "libhidlbase",
         "liblog",
         "libutils",
+        "libbinderdebug",
     ],
     srcs: [
         "DumpstateService.cpp",
@@ -112,6 +122,7 @@
     ],
     required: [
         "atrace",
+        "dmabuf_dump",
         "ip",
         "iptables",
         "librank",
diff --git a/cmds/dumpstate/DumpPool.cpp b/cmds/dumpstate/DumpPool.cpp
index e15ac3f..c2c8a72 100644
--- a/cmds/dumpstate/DumpPool.cpp
+++ b/cmds/dumpstate/DumpPool.cpp
@@ -64,8 +64,8 @@
     if (shutdown_ || threads_.empty()) {
         return;
     }
-    while (!tasks_.empty()) tasks_.pop();
     futures_map_.clear();
+    while (!tasks_.empty()) tasks_.pop();
 
     shutdown_ = true;
     condition_variable_.notify_all();
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index bfcc058..ba25a5a 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -39,8 +39,13 @@
     std::string calling_package;
 };
 
-static binder::Status exception(uint32_t code, const std::string& msg) {
-    MYLOGE("%s (%d) ", msg.c_str(), code);
+static binder::Status exception(uint32_t code, const std::string& msg,
+                                const std::string& extra_msg = "") {
+    if (extra_msg.empty()) {
+        MYLOGE("%s (%d) ", msg.c_str(), code);
+    } else {
+        MYLOGE("%s %s (%d) ", msg.c_str(), extra_msg.c_str(), code);
+    }
     return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
 }
 
@@ -60,7 +65,7 @@
 
 }  // namespace
 
-DumpstateService::DumpstateService() : ds_(nullptr) {
+DumpstateService::DumpstateService() : ds_(nullptr), calling_uid_(-1), calling_package_() {
 }
 
 char const* DumpstateService::getServiceName() {
@@ -131,6 +136,10 @@
     ds_->SetOptions(std::move(options));
     ds_->listener_ = listener;
 
+    // Track caller info for cancellation purposes.
+    calling_uid_ = calling_uid;
+    calling_package_ = calling_package;
+
     DumpstateInfo* ds_info = new DumpstateInfo();
     ds_info->ds = ds_;
     ds_info->calling_uid = calling_uid;
@@ -149,8 +158,20 @@
     return binder::Status::ok();
 }
 
-binder::Status DumpstateService::cancelBugreport() {
+binder::Status DumpstateService::cancelBugreport(int32_t calling_uid,
+                                                 const std::string& calling_package) {
     std::lock_guard<std::mutex> lock(lock_);
+    if (calling_uid != calling_uid_ || calling_package != calling_package_) {
+        // Note: we use a SecurityException to prevent BugreportManagerServiceImpl from killing the
+        // report in progress (from another caller).
+        return exception(
+            binder::Status::EX_SECURITY,
+            StringPrintf("Cancellation requested by %d/%s does not match report in "
+                         "progress",
+                         calling_uid, calling_package.c_str()),
+            // Sharing the owner of the BR is a (minor) leak, so leave it out of the app's exception
+            StringPrintf("started by %d/%s", calling_uid_, calling_package_.c_str()));
+    }
     ds_->Cancel();
     return binder::Status::ok();
 }
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index ac8d3ac..3ec8471 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -44,8 +44,7 @@
                                   const sp<IDumpstateListener>& listener,
                                   bool is_screenshot_requested) override;
 
-    // No-op
-    binder::Status cancelBugreport();
+    binder::Status cancelBugreport(int32_t calling_uid, const std::string& calling_package);
 
   private:
     // Dumpstate object which contains all the bugreporting logic.
@@ -53,6 +52,8 @@
     // one bugreport.
     // This service does not own this object.
     Dumpstate* ds_;
+    int32_t calling_uid_;
+    std::string calling_package_;
     std::mutex lock_;
 };
 
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index eeaa5a3..c833d0e 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -124,6 +124,12 @@
     return *this;
 }
 
+CommandOptions::CommandOptionsBuilder&
+CommandOptions::CommandOptionsBuilder::CloseAllFileDescriptorsOnExec() {
+    values.close_all_fds_on_exec_ = true;
+    return *this;
+}
+
 CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Log(
     const std::string& message) {
     values.logging_message_ = message;
@@ -137,6 +143,7 @@
 CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout_ms)
     : timeout_ms_(timeout_ms),
       always_(false),
+      close_all_fds_on_exec_(false),
       account_mode_(DONT_DROP_ROOT),
       output_mode_(NORMAL_OUTPUT),
       logging_message_("") {
@@ -157,6 +164,10 @@
     return values.always_;
 }
 
+bool CommandOptions::ShouldCloseAllFileDescriptorsOnExec() const {
+    return values.close_all_fds_on_exec_;
+}
+
 PrivilegeMode CommandOptions::PrivilegeMode() const {
     return values.account_mode_;
 }
@@ -277,7 +288,8 @@
         MYLOGI(logging_message.c_str(), command_string.c_str());
     }
 
-    bool silent = (options.OutputMode() == REDIRECT_TO_STDERR);
+    bool silent = (options.OutputMode() == REDIRECT_TO_STDERR ||
+                   options.ShouldCloseAllFileDescriptorsOnExec());
     bool redirecting_to_fd = STDOUT_FILENO != fd;
 
     if (PropertiesHelper::IsDryRun() && !options.Always()) {
@@ -314,7 +326,27 @@
             return -1;
         }
 
-        if (silent) {
+        if (options.ShouldCloseAllFileDescriptorsOnExec()) {
+            int devnull_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
+            TEMP_FAILURE_RETRY(dup2(devnull_fd, STDIN_FILENO));
+            close(devnull_fd);
+            devnull_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY));
+            TEMP_FAILURE_RETRY(dup2(devnull_fd, STDOUT_FILENO));
+            TEMP_FAILURE_RETRY(dup2(devnull_fd, STDERR_FILENO));
+            close(devnull_fd);
+            // This is to avoid leaking FDs that, accidentally, have not been
+            // marked as O_CLOEXEC. Leaking FDs across exec can cause failures
+            // when execing a process that has a SELinux auto_trans rule.
+            // Here we assume that the dumpstate process didn't open more than
+            // 1000 FDs. In theory we could iterate through /proc/self/fd/, but
+            // doing that in a fork-safe way is too complex and not worth it
+            // (opendir()/readdir() do heap allocations and take locks).
+            for (int i = 0; i < 1000; i++) {
+                if (i != STDIN_FILENO && i!= STDOUT_FILENO && i != STDERR_FILENO) {
+                    close(i);
+                }
+            }
+        } else if (silent) {
             // Redirects stdout to stderr
             TEMP_FAILURE_RETRY(dup2(STDERR_FILENO, STDOUT_FILENO));
         } else if (redirecting_to_fd) {
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index b099443..b00c46e 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -80,6 +80,7 @@
 
         int64_t timeout_ms_;
         bool always_;
+        bool close_all_fds_on_exec_;
         PrivilegeMode account_mode_;
         OutputMode output_mode_;
         std::string logging_message_;
@@ -112,6 +113,13 @@
         CommandOptionsBuilder& DropRoot();
         /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */
         CommandOptionsBuilder& RedirectStderr();
+        /* Closes all file descriptors before exec-ing the target process. This
+         * includes also stdio pipes, which are dup-ed on /dev/null. It prevents
+         * leaking opened FDs to the target process, which in turn can hit
+         * selinux denials in presence of auto_trans rules.
+         */
+        CommandOptionsBuilder& CloseAllFileDescriptorsOnExec();
+
         /* When not empty, logs a message before executing the command.
          * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */
         CommandOptionsBuilder& Log(const std::string& message);
@@ -130,6 +138,8 @@
     int64_t TimeoutInMs() const;
     /* Checks whether the command should always be run, even on dry-run mode. */
     bool Always() const;
+    /* Checks whether all FDs should be closed prior to the exec() calls. */
+    bool ShouldCloseAllFileDescriptorsOnExec() const;
     /** Gets the PrivilegeMode of the command. */
     PrivilegeMode PrivilegeMode() const;
     /** Gets the OutputMode of the command. */
diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS
index 1ba7cff..2a9b681 100644
--- a/cmds/dumpstate/OWNERS
+++ b/cmds/dumpstate/OWNERS
@@ -1,6 +1,4 @@
 set noparent
 
-felipeal@google.com
 nandana@google.com
 jsharkey@android.com
-enh@google.com
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index ba008bb..0793f0b 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2016, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,9 +19,9 @@
 import android.os.IDumpstateListener;
 
 /**
-  * Binder interface for the currently running dumpstate process.
-  * {@hide}
-  */
+ * Binder interface for the currently running dumpstate process.
+ * {@hide}
+ */
 interface IDumpstate {
 
     // NOTE: If you add to or change these modes, please also change the corresponding enums
@@ -49,10 +49,10 @@
     // Default mode.
     const int BUGREPORT_MODE_DEFAULT = 6;
 
-    /*
+    /**
      * Starts a bugreport in the background.
      *
-     *<p>Shows the user a dialog to get consent for sharing the bugreport with the calling
+     * <p>Shows the user a dialog to get consent for sharing the bugreport with the calling
      * application. If they deny {@link IDumpstateListener#onError} will be called. If they
      * consent and bugreport generation is successful artifacts will be copied to the given fds and
      * {@link IDumpstateListener#onFinished} will be called. If there
@@ -71,8 +71,15 @@
                         int bugreportMode, IDumpstateListener listener,
                         boolean isScreenshotRequested);
 
-    /*
+    /**
      * Cancels the bugreport currently in progress.
+     *
+     * <p>The caller must match the original caller of {@link #startBugreport} in order for the
+     * report to actually be cancelled. A {@link SecurityException} is reported if a mismatch is
+     * detected.
+     *
+     * @param callingUid UID of the original application that requested the cancellation.
+     * @param callingPackage package of the original application that requested the cancellation.
      */
-    void cancelBugreport();
+    void cancelBugreport(int callingUid, @utf8InCpp String callingPackage);
 }
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 85e6969..50c1624 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -21,8 +21,6 @@
   *
   * <p>When bugreport creation is complete one of {@code onError} or {@code onFinished} is called.
   *
-  * <p>These methods are synchronous by design in order to make dumpstate's lifecycle simpler
-  * to handle.
   *
   * {@hide}
   */
@@ -54,10 +52,8 @@
 
     /**
      * Called on an error condition with one of the error codes listed above.
-     * This is not an asynchronous method since it can race with dumpstate exiting, thus triggering
-     * death recipient.
      */
-    void onError(int errorCode);
+    oneway void onError(int errorCode);
 
     /**
      * Called when taking bugreport finishes successfully.
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index a1ee285..501e281 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mount.h>
 #include <sys/poll.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
@@ -174,6 +175,7 @@
 #define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
 #define LINKERCONFIG_DIR "/linkerconfig"
 #define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
+#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
 
 // TODO(narayan): Since this information has to be kept in sync
 // with tombstoned, we should just put it in a common header.
@@ -227,7 +229,6 @@
 static const std::string DUMP_HALS_TASK = "DUMP HALS";
 static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
 static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
-static const std::string DUMP_APP_INFOS_TASK = "DUMP APP INFOS";
 
 namespace android {
 namespace os {
@@ -792,6 +793,9 @@
     if (module_metadata_version != 0) {
         printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
     }
+    printf("SDK extension versions [r=%s s=%s]\n",
+           android::base::GetProperty("build.version.extensions.r", "-").c_str(),
+           android::base::GetProperty("build.version.extensions.s", "-").c_str());
 
     printf("Kernel: ");
     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
@@ -1053,6 +1057,24 @@
     }
 }
 
+static void MaybeAddSystemTraceToZip() {
+    // This function copies into the .zip the system trace that was snapshotted
+    // by the early call to MaybeSnapshotSystemTrace(), if any background
+    // tracing was happening.
+    if (!ds.IsZipping()) {
+        MYLOGD("Not dumping system trace because it's not a zipped bugreport\n");
+        return;
+    }
+    if (!ds.has_system_trace_) {
+        // No background trace was happening at the time dumpstate was invoked.
+        return;
+    }
+    ds.AddZipEntry(
+            ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
+            SYSTEM_TRACE_SNAPSHOT);
+    android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
+}
+
 static void DumpVisibleWindowViews() {
     if (!ds.IsZipping()) {
         MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
@@ -1189,10 +1211,6 @@
 
 static void DumpPacketStats() {
     DumpFile("NETWORK DEV INFO", "/proc/net/dev");
-    DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
-    DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
-    DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
-    DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
 }
 
 static void DumpIpAddrAndRules() {
@@ -1549,7 +1567,7 @@
     dprintf(out_fd, "========================================================\n");
 
     RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
-            DUMPSYS_COMPONENTS_OPTIONS, out_fd);
+            DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
 
     dprintf(out_fd, "========================================================\n");
     dprintf(out_fd, "== Running Application Providers (non-platform)\n");
@@ -1576,7 +1594,6 @@
         ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
         ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
         ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
-        ds.dump_pool_->enqueueTaskWithFd(DUMP_APP_INFOS_TASK, &DumpAppInfos, _1);
     }
 
     // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
@@ -1623,6 +1640,10 @@
         MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
     } else {
         RunCommand("LSMOD", {"lsmod"});
+        RunCommand("MODULES INFO",
+                   {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
+                    "    while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
+                    "done"}, CommandOptions::AS_ROOT);
     }
 
     if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
@@ -1638,8 +1659,6 @@
     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
 
-    /* Dump Bluetooth HCI logs */
-    ds.AddDir("/data/misc/bluetooth/logs", true);
     /* Dump Nfc NCI logs */
     ds.AddDir("/data/misc/nfc/logs", true);
 
@@ -1650,6 +1669,8 @@
 
     AddAnrTraceFiles();
 
+    MaybeAddSystemTraceToZip();
+
     // NOTE: tombstones are always added as separate entries in the zip archive
     // and are not interspersed with the main report.
     const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
@@ -1723,17 +1744,16 @@
 
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
 
+    /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
+    ds.AddDir("/data/misc/bluetooth/logs", true);
+
     if (ds.dump_pool_) {
         WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
     } else {
         RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
     }
 
-    if (ds.dump_pool_) {
-        WAIT_TASK_WITH_CONSENT_CHECK(DUMP_APP_INFOS_TASK, ds.dump_pool_);
-    } else {
-        RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_APP_INFOS_TASK, DumpAppInfos);
-    }
+    RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
 
     printf("========================================================\n");
     printf("== Dropbox crashes\n");
@@ -1829,10 +1849,8 @@
     RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
 
     // Gather shared memory buffer info if the product implements it
-    struct stat st;
-    if (!stat("/product/bin/dmabuf_dump", &st)) {
-        RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
-    }
+    RunCommand("Dmabuf dump", {"dmabuf_dump"});
+    RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
 
     DumpFile("PSI cpu", "/proc/pressure/cpu");
     DumpFile("PSI memory", "/proc/pressure/memory");
@@ -2045,7 +2063,7 @@
 }
 
 Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
-    const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
+    const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
     const size_t buf_size = temp_file_pattern.length() + 1;
     std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
     memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
@@ -2162,6 +2180,21 @@
         return;
     }
 
+    /*
+     * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
+     * set to true and unmount it after invoking dumpstateBoard_* methods.
+     * This is to enable debug builds to not have debugfs mounted during runtime.
+     * It will also ensure that debugfs is only accessed by the dumpstate HAL.
+     */
+    auto mount_debugfs =
+        android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
+    if (mount_debugfs) {
+        RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
+                   AS_ROOT_20);
+        RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"},
+                   AS_ROOT_20);
+    }
+
     std::vector<std::string> paths;
     std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
     for (int i = 0; i < NUM_OF_DUMPS; i++) {
@@ -2261,6 +2294,13 @@
                "there might be racing in content\n", killing_timeout_sec);
     }
 
+    if (mount_debugfs) {
+        auto keep_debugfs_mounted =
+            android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
+        if (keep_debugfs_mounted.empty())
+            RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
+    }
+
     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
     for (size_t i = 0; i < paths.size(); i++) {
         struct stat s;
@@ -2871,6 +2911,17 @@
         RunDumpsysCritical();
     }
     MaybeTakeEarlyScreenshot();
+
+    if (!is_dumpstate_restricted) {
+        // Snapshot the system trace now (if running) to avoid that dumpstate's
+        // own activity pushes out interesting data from the trace ring buffer.
+        // The trace file is added to the zip by MaybeAddSystemTraceToZip().
+        MaybeSnapshotSystemTrace();
+
+        // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
+        // from WMTRACE_DATA_DIR.
+        MaybeSnapshotWinTrace();
+    }
     onUiIntensiveBugreportDumpsFinished(calling_uid);
     MaybeCheckUserConsent(calling_uid, calling_package);
     if (options_->telephony_only) {
@@ -2961,6 +3012,37 @@
     TakeScreenshot();
 }
 
+void Dumpstate::MaybeSnapshotSystemTrace() {
+    // If a background system trace is happening and is marked as "suitable for
+    // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
+    // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
+    // case that no trace is ongoing, this command is a no-op.
+    // Note: this should not be enqueued as we need to freeze the trace before
+    // dumpstate starts. Otherwise the trace ring buffers will contain mostly
+    // the dumpstate's own activity which is irrelevant.
+    int res = RunCommand(
+        "SERIALIZE PERFETTO TRACE",
+        {"perfetto", "--save-for-bugreport"},
+        CommandOptions::WithTimeout(10)
+            .DropRoot()
+            .CloseAllFileDescriptorsOnExec()
+            .Build());
+    has_system_trace_ = res == 0;
+    // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
+    // file in the later stages.
+}
+
+void Dumpstate::MaybeSnapshotWinTrace() {
+    // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
+    for (const auto& service : {"window", "input_method"}) {
+        RunCommand(
+            // Empty name because it's not intended to be classified as a bugreport section.
+            // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
+            "", {"cmd", service, "tracing", "save-for-bugreport"},
+            CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
+    }
+}
+
 void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
     if (calling_uid == AID_SHELL || !CalledByApi()) {
         return;
@@ -3005,6 +3087,9 @@
     android::os::UnlinkAndLogOnError(tmp_path_);
     android::os::UnlinkAndLogOnError(screenshot_path_);
     android::os::UnlinkAndLogOnError(path_);
+    if (dump_traces_path != nullptr) {
+        android::os::UnlinkAndLogOnError(dump_traces_path);
+    }
 }
 
 void Dumpstate::EnableParallelRunIfNeeded() {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 255243f..83e6787 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -458,6 +458,11 @@
     // Whether it should take an screenshot earlier in the process.
     bool do_early_screenshot_ = false;
 
+    // This is set to true when the trace snapshot request in the early call to
+    // MaybeSnapshotSystemTrace(). When this is true, the later stages of
+    // dumpstate will append the trace to the zip archive.
+    bool has_system_trace_ = false;
+
     std::unique_ptr<Progress> progress_;
 
     // When set, defines a socket file-descriptor use to report progress to bugreportz
@@ -543,6 +548,8 @@
     RunStatus DumpstateDefaultAfterCritical();
 
     void MaybeTakeEarlyScreenshot();
+    void MaybeSnapshotSystemTrace();
+    void MaybeSnapshotWinTrace();
 
     void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid);
 
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index fe6a34a..0712c0a 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -310,8 +310,12 @@
     // FS/proc/*/mountinfo size > 0
     FileExists("FS/proc/1/mountinfo", 0U, 100000U);
 
-    // FS/data/misc/profiles/cur/0/*/primary.prof size > 0
-    FileExists("FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", 0U, 100000U);
+    // FS/data/misc/profiles/cur/0/*/primary.prof should exist. Also, since dumpstate only adds
+    // profiles to the zip in the non-user build, a build checking is necessary here.
+    if (!PropertiesHelper::IsUserBuild()) {
+        ZipEntry entry;
+        GetEntry(handle, "FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", &entry);
+    }
 }
 
 /**
@@ -319,6 +323,16 @@
  */
 class BugreportSectionTest : public Test {
   public:
+    ZipArchiveHandle handle;
+
+    void SetUp() {
+        ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath().c_str(), &handle), 0);
+    }
+
+    void TearDown() {
+        CloseArchive(handle);
+    }
+
     static void SetUpTestCase() {
         ParseSections(ZippedBugreportGenerationTest::getZipFilePath().c_str(),
                       ZippedBugreportGenerationTest::sections.get());
@@ -343,6 +357,19 @@
         }
         FAIL() << sectionName << " not found.";
     }
+
+    /**
+     * Whether or not the content of the section is injected by other commands.
+     */
+    bool IsContentInjectedByOthers(const std::string& line) {
+        // Command header such as `------ APP ACTIVITIES (/system/bin/dumpsys activity -v) ------`.
+        static const std::regex kCommandHeader = std::regex{"------ .+ \\(.+\\) ------"};
+        std::smatch match;
+        if (std::regex_match(line, match, kCommandHeader)) {
+          return true;
+        }
+        return false;
+    }
 };
 
 TEST_F(BugreportSectionTest, Atleast3CriticalDumpsysSectionsGenerated) {
@@ -384,7 +411,6 @@
 }
 
 TEST_F(BugreportSectionTest, ConnectivitySectionsGenerated) {
-    SectionExists("HIGH connectivity", /* bytes= */ 3000);
     SectionExists("connectivity", /* bytes= */ 5000);
 }
 
@@ -400,6 +426,28 @@
     SectionExists("wifi", /* bytes= */ 100000);
 }
 
+TEST_F(BugreportSectionTest, NoInjectedContentByOtherCommand) {
+    // Extract the main entry to a temp file
+    TemporaryFile tmp_binary;
+    ASSERT_NE(-1, tmp_binary.fd);
+    ExtractBugreport(&handle, tmp_binary.fd);
+
+    // Read line by line and identify sections
+    std::ifstream ifs(tmp_binary.path, std::ifstream::in);
+    std::string line;
+    std::string current_section_name;
+    while (std::getline(ifs, line)) {
+        std::string section_name;
+        if (IsSectionStart(line, &section_name)) {
+            current_section_name = section_name;
+        } else if (IsSectionEnd(line)) {
+            current_section_name = "";
+        } else if (!current_section_name.empty()) {
+            EXPECT_FALSE(IsContentInjectedByOthers(line));
+        }
+    }
+}
+
 class DumpstateBinderTest : public Test {
   protected:
     void SetUp() override {
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index b2518ad..db508b5 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1032,12 +1032,12 @@
     ZipArchiveHandle handle_;
 };
 
-// Generate a quick wifi report redirected to a file, open it and verify entry exist.
-TEST_F(ZippedBugReportStreamTest, StreamWifiReport) {
-    std::string out_path = kTestDataPath + "out.zip";
+// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
+TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
+    std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
     android::base::unique_fd out_fd;
     CreateFd(out_path, &out_fd);
-    ds_.options_->wifi_only = true;
+    ds_.options_->limited_only = true;
     ds_.options_->stream_to_socket = true;
     RedirectOutputToFd(out_fd);
 
@@ -1051,7 +1051,7 @@
     ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
                     entry.uncompressed_length);
     EXPECT_THAT(bugreport_txt_name,
-                testing::ContainsRegex("(bugreport-.+-wifi(-[[:digit:]]+){6}\\.txt)"));
+                testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)"));
     VerifyEntry(handle_, bugreport_txt_name, &entry);
 }
 
@@ -1762,6 +1762,27 @@
     EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
 }
 
+TEST_F(DumpPoolTest, Shutdown_withoutCrash) {
+    bool run_1 = false;
+    auto dump_func_1 = [&]() {
+        run_1 = true;
+    };
+    auto dump_func = []() {
+        sleep(1);
+    };
+
+    dump_pool_->start(/* thread_counts = */1);
+    dump_pool_->enqueueTask(/* task_name = */"1", dump_func_1);
+    dump_pool_->enqueueTask(/* task_name = */"2", dump_func);
+    dump_pool_->enqueueTask(/* task_name = */"3", dump_func);
+    dump_pool_->enqueueTask(/* task_name = */"4", dump_func);
+    dump_pool_->waitForTask("1", "", out_fd_.get());
+    dump_pool_->shutdown();
+
+    EXPECT_TRUE(run_1);
+    EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
+}
+
 class TaskQueueTest : public DumpstateBaseTest {
 public:
     void SetUp() {
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index f99588f..6ab6b7f 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -1,3 +1,20 @@
+package {
+    default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_cmds_dumpsys_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "dumpsys_defaults",
 
@@ -15,6 +32,7 @@
         "libutils",
         "liblog",
         "libbinder",
+        "libbinderdebug",
     ],
 
     static_libs: [
diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS
index 1ba7cff..4f6a89e 100644
--- a/cmds/dumpsys/OWNERS
+++ b/cmds/dumpsys/OWNERS
@@ -1,6 +1,7 @@
 set noparent
 
-felipeal@google.com
 nandana@google.com
 jsharkey@android.com
-enh@google.com
+
+# for ServiceManager mock
+per-file dumpsys_test.cpp=smoreland@google.com
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 1327cfd..ba1c449 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -25,6 +25,7 @@
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
 #include <binder/TextOutput.h>
+#include <binderdebug/BinderDebug.h>
 #include <serviceutils/PriorityDumper.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
@@ -60,13 +61,15 @@
             "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
+            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--thread] [--help | -l | "
+            "--skip SERVICES "
             "| SERVICE [ARGS]]\n"
             "         --help: shows this help\n"
             "         -l: only list services, do not dump them\n"
             "         -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
             "         -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
             "         --pid: dump PID instead of usual dump\n"
+            "         --thread: dump thread usage instead of usual dump\n"
             "         --proto: filter services that support dumping data in proto format. Dumps\n"
             "               will be in proto format.\n"
             "         --priority LEVEL: filter services based on specified priority\n"
@@ -125,7 +128,8 @@
     Type type = Type::DUMP;
     int timeoutArgMs = 10000;
     int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
-    static struct option longOptions[] = {{"pid", no_argument, 0, 0},
+    static struct option longOptions[] = {{"thread", no_argument, 0, 0},
+                                          {"pid", no_argument, 0, 0},
                                           {"priority", required_argument, 0, 0},
                                           {"proto", no_argument, 0, 0},
                                           {"skip", no_argument, 0, 0},
@@ -163,6 +167,8 @@
                 }
             } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
                 type = Type::PID;
+            } else if (!strcmp(longOptions[optionIndex].name, "thread")) {
+                type = Type::THREAD;
             }
             break;
 
@@ -329,6 +335,23 @@
      return OK;
 }
 
+static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) {
+    pid_t pid;
+    status_t status = service->getDebugPid(&pid);
+    if (status != OK) {
+        return status;
+    }
+    BinderPidInfo pidInfo;
+    status = getBinderPidInfo(BinderDebugContext::BINDER, pid, &pidInfo);
+    if (status != OK) {
+        return status;
+    }
+    WriteStringToFd("Threads in use: " + std::to_string(pidInfo.threadUsage) + "/" +
+                        std::to_string(pidInfo.threadCount) + "\n",
+                    fd.get());
+    return OK;
+}
+
 status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
                                   const Vector<String16>& args) {
     sp<IBinder> service = sm_->checkService(serviceName);
@@ -359,6 +382,9 @@
         case Type::PID:
             err = dumpPidToFd(service, remote_end);
             break;
+        case Type::THREAD:
+            err = dumpThreadsToFd(service, remote_end);
+            break;
         default:
             std::cerr << "Unknown dump type" << static_cast<int>(type) << std::endl;
             return;
@@ -427,7 +453,7 @@
                  << strerror(errno) << std::endl;
             status = -errno;
             break;
-        } else if (rc == 0) {
+        } else if (rc == 0 || time_left_ms() == 0) {
             status = TIMED_OUT;
             break;
         }
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 929c55c..349947c 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -52,13 +52,14 @@
     static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
 
     enum class Type {
-        DUMP,  // dump using `dump` function
-        PID,   // dump pid of server only
+        DUMP,    // dump using `dump` function
+        PID,     // dump pid of server only
+        THREAD,  // dump thread usage of server only
     };
 
     /**
      * Starts a thread to connect to a service and get its dump output. The thread redirects
-     * the output to a pipe. Thread must be stopped by a subsequent callto {@code
+     * the output to a pipe. Thread must be stopped by a subsequent call to {@code
      * stopDumpThread}.
      * @param serviceName
      * @param args list of arguments to pass to service dump method.
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index e182b9d..58fec30 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -1,4 +1,13 @@
 // Build the unit tests for dumpsys
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_cmds_dumpsys_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"],
+}
+
 cc_test {
     name: "dumpsys_test",
     test_suites: ["device-tests"],
@@ -10,6 +19,7 @@
         "libbase",
         "libbinder",
         "libutils",
+        "libbinderdebug",
     ],
 
     static_libs: [
@@ -17,6 +27,4 @@
         "libgmock",
         "libserviceutils",
     ],
-
-    clang: true,
 }
diff --git a/cmds/dumpsys/tests/AndroidTest.xml b/cmds/dumpsys/tests/AndroidTest.xml
index 1a8c67f..c2351d9 100644
--- a/cmds/dumpsys/tests/AndroidTest.xml
+++ b/cmds/dumpsys/tests/AndroidTest.xml
@@ -23,4 +23,4 @@
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="dumpsys_test" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 67a77f6..c9d2dbb 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -16,12 +16,15 @@
 
 #include "../dumpsys.h"
 
+#include <regex>
 #include <vector>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include <android-base/file.h>
+#include <binder/Binder.h>
+#include <binder/ProcessState.h>
 #include <serviceutils/PriorityDumper.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
@@ -56,6 +59,7 @@
     MOCK_METHOD1(waitForService, sp<IBinder>(const String16&));
     MOCK_METHOD1(isDeclared, bool(const String16&));
     MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
+    MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&));
   protected:
     MOCK_METHOD0(onAsBinder, IBinder*());
 };
@@ -222,6 +226,10 @@
         EXPECT_THAT(stdout_, HasSubstr(expected));
     }
 
+    void AssertOutputFormat(const std::string format) {
+        EXPECT_THAT(stdout_, testing::MatchesRegex(format));
+    }
+
     void AssertDumped(const std::string& service, const std::string& dump) {
         EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
         EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: "));
@@ -574,6 +582,30 @@
     AssertOutput(std::to_string(getpid()) + "\n");
 }
 
+// Tests 'dumpsys --thread'
+TEST_F(DumpsysTest, ListAllServicesWithThread) {
+    ExpectListServices({"Locksmith", "Valet"});
+    ExpectCheckService("Locksmith");
+    ExpectCheckService("Valet");
+
+    CallMain({"--thread"});
+
+    AssertRunningServices({"Locksmith", "Valet"});
+
+    const std::string format("(.|\n)*((Threads in use: [0-9]+/[0-9]+)?\n-(.|\n)*){2}");
+    AssertOutputFormat(format);
+}
+
+// Tests 'dumpsys --thread service_name'
+TEST_F(DumpsysTest, ListServiceWithThread) {
+    ExpectCheckService("Locksmith");
+
+    CallMain({"--thread", "Locksmith"});
+    // returns an empty string without root enabled
+    const std::string format("(^$|Threads in use: [0-9]/[0-9]+\n)");
+    AssertOutputFormat(format);
+}
+
 TEST_F(DumpsysTest, GetBytesWritten) {
     const char* serviceName = "service2";
     const char* dumpContents = "dump1";
@@ -599,3 +631,13 @@
                         /* as_proto = */ false, elapsedDuration, bytesWritten);
     EXPECT_THAT(status, Eq(INVALID_OPERATION));
 }
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // start a binder thread pool for testing --thread option
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(8);
+    ProcessState::self()->startThreadPool();
+
+    return RUN_ALL_TESTS();
+}
diff --git a/cmds/flatland/Android.mk b/cmds/flatland/Android.mk
index 7aa111c..754a99c 100644
--- a/cmds/flatland/Android.mk
+++ b/cmds/flatland/Android.mk
@@ -11,6 +11,9 @@
 LOCAL_CFLAGS := -Wall -Werror
 
 LOCAL_MODULE:= flatland
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 402767a..99e0f4c 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -12,10 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "idlcli-defaults",
     shared_libs: [
-        "android.hardware.vibrator-ndk_platform",
+        "android.hardware.vibrator-V1-ndk_platform",
         "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
         "android.hardware.vibrator@1.2",
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 523115f..18c267d 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "installd_defaults",
 
@@ -38,6 +47,12 @@
         "libutils",
         "server_configurable_flags",
     ],
+    static_libs: [
+        "libasync_safe",
+    ],
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
 
     product_variables: {
         arc: {
@@ -177,8 +192,8 @@
         "liblog",
         "libutils",
     ],
-    static_libs: [
-        "libapexd",
+    required: [
+      "apexd"
     ],
 }
 
@@ -239,6 +254,7 @@
     ],
 
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libotapreoptparameters",
     ],
diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp
index e080291..6027139 100644
--- a/cmds/installd/QuotaUtils.cpp
+++ b/cmds/installd/QuotaUtils.cpp
@@ -35,7 +35,7 @@
 /* Map of all quota mounts from target to source */
 std::unordered_map<std::string, std::string> mQuotaReverseMounts;
 
-std::string& FindQuotaDeviceForUuid(const std::string& uuid) {
+std::string FindQuotaDeviceForUuid(const std::string& uuid) {
     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
     auto path = create_data_path(uuid.empty() ? nullptr : uuid.c_str());
     return mQuotaReverseMounts[path];
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 65fc46e..204953c 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -36,6 +36,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <async_safe/log.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
@@ -727,7 +728,8 @@
 
         if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
             if (errno != EWOULDBLOCK) {
-                PLOG(WARNING) << "Error locking profile " << package_name;
+                async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Error locking profile %s: %d",
+                        package_name.c_str(), errno);
             }
             // This implies that the app owning this profile is running
             // (and has acquired the lock).
@@ -735,13 +737,15 @@
             // The app never acquires the lock for the reference profiles of primary apks.
             // Only dex2oat from installd will do that. Since installd is single threaded
             // we should not see this case. Nevertheless be prepared for it.
-            PLOG(WARNING) << "Failed to flock " << package_name;
+            async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Failed to flock %s: %d",
+                    package_name.c_str(), errno);
             return false;
         }
 
         bool truncated = ftruncate(out_fd.get(), 0) == 0;
         if (!truncated) {
-            PLOG(WARNING) << "Could not truncate " << package_name;
+            async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Could not truncate %s: %d",
+                    package_name.c_str(), errno);
         }
 
         // Copy over data.
@@ -755,7 +759,8 @@
             write(out_fd.get(), buffer, bytes);
         }
         if (flock(out_fd.get(), LOCK_UN) != 0) {
-            PLOG(WARNING) << "Error unlocking profile " << package_name;
+            async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Error unlocking profile %s: %d",
+                    package_name.c_str(), errno);
         }
         // Use _exit since we don't want to run the global destructors in the child.
         // b/62597429
@@ -1130,23 +1135,6 @@
     return true;
 }
 
-// Updates the access times of out_oat_path based on those from apk_path.
-void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
-    struct stat input_stat;
-    memset(&input_stat, 0, sizeof(input_stat));
-    if (stat(apk_path, &input_stat) != 0) {
-        PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
-        return;
-    }
-
-    struct utimbuf ut;
-    ut.actime = input_stat.st_atime;
-    ut.modtime = input_stat.st_mtime;
-    if (utime(out_oat_path, &ut) != 0) {
-        PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
-    }
-}
-
 // Runs (execv) dexoptanalyzer on the given arguments.
 // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
 // If this is for a profile guided compilation, profile_was_updated will tell whether or not
@@ -1530,7 +1518,8 @@
 
         // Validate the path structure.
         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
-            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
             _exit(kSecondaryDexDexoptAnalyzerSkippedValidatePath);
         }
 
@@ -1826,7 +1815,8 @@
         drop_capabilities(uid);
 
         if (flock(out_oat.fd(), LOCK_EX | LOCK_NB) != 0) {
-            PLOG(ERROR) << "flock(" << out_oat.path() << ") failed";
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "flock(%s) failed",
+                    out_oat.path().c_str());
             _exit(DexoptReturnCodes::kFlock);
         }
 
@@ -1843,8 +1833,6 @@
         }
     }
 
-    update_out_oat_access_times(dex_path, out_oat.path().c_str());
-
     // We've been successful, don't delete output.
     out_oat.DisableCleanup();
     out_vdex.DisableCleanup();
@@ -1923,7 +1911,8 @@
         const char* volume_uuid_cstr = volume_uuid ? volume_uuid->c_str() : nullptr;
         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr,
                 uid, storage_flag)) {
-            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
             _exit(kReconcileSecondaryDexValidationError);
         }
 
@@ -1936,7 +1925,8 @@
             case kSecondaryDexAccessIOError: _exit(kReconcileSecondaryDexAccessIOError);
             case kSecondaryDexAccessPermissionError: _exit(kReconcileSecondaryDexValidationError);
             default:
-                LOG(ERROR) << "Unexpected result from check_secondary_dex_access: " << access_check;
+                async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                        "Unexpected result from check_secondary_dex_access: %d", access_check);
                 _exit(kReconcileSecondaryDexValidationError);
         }
 
@@ -1949,7 +1939,7 @@
             std::string error_msg;
             if (!create_secondary_dex_oat_layout(
                     dex_path,isas[i], oat_dir, oat_isa_dir, oat_path, &error_msg)) {
-                LOG(ERROR) << error_msg;
+                async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "%s", error_msg.c_str());
                 _exit(kReconcileSecondaryDexValidationError);
             }
 
@@ -1976,7 +1966,8 @@
             result = rmdir_if_empty(oat_dir) && result;
         }
         if (!result) {
-            PLOG(ERROR) << "Failed to clean secondary dex artifacts for location " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
         }
         _exit(result ? kReconcileSecondaryDexCleanedUp : kReconcileSecondaryDexAccessIOError);
     }
@@ -2049,7 +2040,8 @@
         pipe_read.reset();
 
         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
-            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
             _exit(DexoptReturnCodes::kHashValidatePath);
         }
 
@@ -2060,6 +2052,8 @@
                 _exit(0);
             }
             PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Failed to open secondary dex %s: %d", dex_path.c_str(), errno);
             _exit(DexoptReturnCodes::kHashOpenPath);
         }
 
@@ -2072,7 +2066,8 @@
             if (bytes_read == 0) {
                 break;
             } else if (bytes_read == -1) {
-                PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
+                async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                        "Failed to read secondary dex %s: %d", dex_path.c_str(), errno);
                 _exit(DexoptReturnCodes::kHashReadDex);
             }
 
@@ -2131,8 +2126,9 @@
     {
         struct stat s;
         if (stat(b_path.c_str(), &s) != 0) {
-            // Silently ignore for now. The service calling this isn't smart enough to understand
-            // lack of artifacts at the moment.
+            // Ignore for now. The service calling this isn't smart enough to
+            // understand lack of artifacts at the moment.
+            LOG(VERBOSE) << "A/B artifact " << b_path << " does not exist!";
             return false;
         }
         if (!S_ISREG(s.st_mode)) {
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h
index 3e2f815..88801ca 100644
--- a/cmds/installd/file_parsing.h
+++ b/cmds/installd/file_parsing.h
@@ -19,18 +19,14 @@
 
 #include <fstream>
 #include <functional>
-#include <string>
+#include <string_view>
+#include "android-base/unique_fd.h"
 
 namespace android {
 namespace installd {
 
-bool ParseFile(const std::string& strFile, std::function<bool (const std::string&)> parse) {
-    std::ifstream input_stream(strFile);
-
-    if (!input_stream.is_open()) {
-        return false;
-    }
-
+template<typename Func>
+bool ParseFile(std::istream& input_stream, Func parse) {
     while (!input_stream.eof()) {
         // Read the next line.
         std::string line;
@@ -54,6 +50,15 @@
     return true;
 }
 
+template<typename Func>
+bool ParseFile(std::string_view str_file, Func parse) {
+  std::ifstream ifs(str_file);
+  if (!ifs.is_open()) {
+    return false;
+  }
+  return ParseFile(ifs, parse);
+}
+
 }  // namespace installd
 }  // namespace android
 
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 443821c..6aa32b8 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -26,6 +26,7 @@
 #include <sys/capability.h>
 #include <sys/prctl.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
@@ -36,6 +37,7 @@
 #include <log/log.h>
 #include <private/android_filesystem_config.h>
 
+#include "android-base/file.h"
 #include "dexopt.h"
 #include "file_parsing.h"
 #include "globals.h"
@@ -175,8 +177,10 @@
 private:
 
     bool ReadSystemProperties() {
+        // TODO This file does not have a stable format. It should be read by
+        // code shared by init and otapreopt. See b/181182967#comment80
         static constexpr const char* kPropertyFiles[] = {
-                "/default.prop", "/system/build.prop"
+                "/system/build.prop"
         };
 
         for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
@@ -193,26 +197,61 @@
         //   export NAME VALUE
         // For simplicity, don't respect string quotation. The values we are interested in can be
         // encoded without them.
+        //
+        // init.environ.rc and derive_classpath all have the same format for
+        // environment variable exports (since they are all meant to be read by
+        // init) and can be matched by the same regex.
+
         std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
-        bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
-            std::smatch export_match;
-            if (!std::regex_match(line, export_match, export_regex)) {
-                return true;
-            }
+        auto parse_results = [&](auto& input) {
+          ParseFile(input, [&](const std::string& line) {
+              std::smatch export_match;
+              if (!std::regex_match(line, export_match, export_regex)) {
+                  return true;
+              }
 
-            if (export_match.size() != 3) {
-                return true;
-            }
+              if (export_match.size() != 3) {
+                  return true;
+              }
 
-            std::string name = export_match[1].str();
-            std::string value = export_match[2].str();
+              std::string name = export_match[1].str();
+              std::string value = export_match[2].str();
 
-            system_properties_.SetProperty(name, value);
+              system_properties_.SetProperty(name, value);
 
-            return true;
-        });
-        if (!parse_result) {
+              return true;
+          });
+        };
+
+        // TODO Just like with the system-properties above we really should have
+        // common code between init and otapreopt to deal with reading these
+        // things. See b/181182967
+        // There have been a variety of places the various env-vars have been
+        // over the years.  Expand or reduce this list as needed.
+        static constexpr const char* kEnvironmentVariableSources[] = {
+                "/init.environ.rc",
+        };
+        // First get everything from the static files.
+        for (const char* env_vars_file : kEnvironmentVariableSources) {
+          parse_results(env_vars_file);
+        }
+
+        // Next get everything from derive_classpath, since we're already in the
+        // chroot it will get the new versions of any dependencies.
+        {
+          android::base::unique_fd fd(memfd_create("derive_classpath_temp", MFD_CLOEXEC));
+          if (!fd.ok()) {
+            LOG(ERROR) << "Unable to create fd for derive_classpath";
             return false;
+          }
+          std::string memfd_file = StringPrintf("/proc/%d/fd/%d", getpid(), fd.get());
+          std::string error_msg;
+          if (!Exec({"/apex/com.android.sdkext/bin/derive_classpath", memfd_file}, &error_msg)) {
+            PLOG(ERROR) << "Running derive_classpath failed: " << error_msg;
+            return false;
+          }
+          std::ifstream ifs(memfd_file);
+          parse_results(ifs);
         }
 
         if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
@@ -337,9 +376,6 @@
             }
         }
 
-        // Clear cached artifacts.
-        ClearDirectory(isa_path);
-
         // Check whether we have a boot image.
         // TODO: check that the files are correct wrt/ jars.
         std::string preopted_boot_art_path =
@@ -383,37 +419,6 @@
         return false;
     }
 
-    static void ClearDirectory(const std::string& dir) {
-        DIR* c_dir = opendir(dir.c_str());
-        if (c_dir == nullptr) {
-            PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
-            return;
-        }
-
-        for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
-            const char* name = de->d_name;
-            if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
-                continue;
-            }
-            // We only want to delete regular files and symbolic links.
-            std::string file = StringPrintf("%s/%s", dir.c_str(), name);
-            if (de->d_type != DT_REG && de->d_type != DT_LNK) {
-                LOG(WARNING) << "Unexpected file "
-                             << file
-                             << " of type "
-                             << std::hex
-                             << de->d_type
-                             << " encountered.";
-            } else {
-                // Try to unlink the file.
-                if (unlink(file.c_str()) != 0) {
-                    PLOG(ERROR) << "Unable to unlink " << file;
-                }
-            }
-        }
-        CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
-    }
-
     static const char* ParseNull(const char* arg) {
         return (strcmp(arg, "!") == 0) ? nullptr : arg;
     }
@@ -473,24 +478,29 @@
     // Run dexopt with the parameters of parameters_.
     // TODO(calin): embed the profile name in the parameters.
     int Dexopt() {
-        std::string dummy;
-        return dexopt(parameters_.apk_path,
-                      parameters_.uid,
-                      parameters_.pkgName,
-                      parameters_.instruction_set,
-                      parameters_.dexopt_needed,
-                      parameters_.oat_dir,
-                      parameters_.dexopt_flags,
-                      parameters_.compiler_filter,
-                      parameters_.volume_uuid,
-                      parameters_.shared_libraries,
-                      parameters_.se_info,
-                      parameters_.downgrade,
-                      parameters_.target_sdk_version,
-                      parameters_.profile_name,
-                      parameters_.dex_metadata_path,
-                      parameters_.compilation_reason,
-                      &dummy);
+        std::string error;
+        int res = dexopt(parameters_.apk_path,
+                         parameters_.uid,
+                         parameters_.pkgName,
+                         parameters_.instruction_set,
+                         parameters_.dexopt_needed,
+                         parameters_.oat_dir,
+                         parameters_.dexopt_flags,
+                         parameters_.compiler_filter,
+                         parameters_.volume_uuid,
+                         parameters_.shared_libraries,
+                         parameters_.se_info,
+                         parameters_.downgrade,
+                         parameters_.target_sdk_version,
+                         parameters_.profile_name,
+                         parameters_.dex_metadata_path,
+                         parameters_.compilation_reason,
+                         &error);
+        if (res != 0) {
+            LOG(ERROR) << "During preopt of " << parameters_.apk_path << " got result " << res
+                       << " error: " << error;
+        }
+        return res;
     }
 
     int RunPreopt() {
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 72c03bf..c62734a 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -20,16 +20,19 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#include <array>
+#include <fstream>
 #include <sstream>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <libdm/dm.h>
 #include <selinux/android.h>
 
-#include <apexd.h>
-
 #include "installd_constants.h"
 #include "otapreopt_utils.h"
 
@@ -59,28 +62,23 @@
     }
 }
 
-static std::vector<apex::ApexFile> ActivateApexPackages() {
-    // The logic here is (partially) copied and adapted from
-    // system/apex/apexd/apexd.cpp.
-    //
-    // Only scan the APEX directory under /system, /system_ext and /vendor (within the chroot dir).
-    std::vector<const char*> apex_dirs{apex::kApexPackageSystemDir, apex::kApexPackageSystemExtDir,
-                                       apex::kApexPackageVendorDir};
-    for (const auto& dir : apex_dirs) {
-        // Cast call to void to suppress warn_unused_result.
-        static_cast<void>(apex::ScanPackagesDirAndActivate(dir));
+static void ActivateApexPackages() {
+    std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--otachroot-bootstrap"};
+    std::string apexd_error_msg;
+
+    bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
+    if (!exec_result) {
+        PLOG(ERROR) << "Running otapreopt failed: " << apexd_error_msg;
+        exit(220);
     }
-    return apex::GetActivePackages();
 }
 
-static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
-    for (const apex::ApexFile& apex_file : active_packages) {
-        const std::string& package_path = apex_file.GetPath();
-        base::Result<void> status = apex::DeactivatePackage(package_path);
-        if (!status.ok()) {
-            LOG(ERROR) << "Failed to deactivate " << package_path << ": "
-                       << status.error();
-        }
+static void DeactivateApexPackages() {
+    std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--unmount-all"};
+    std::string apexd_error_msg;
+    bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
+    if (!exec_result) {
+        PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg;
     }
 }
 
@@ -181,6 +179,18 @@
     // want it for product APKs. Same notes as vendor above.
     TryExtraMount("product", arg[2], "/postinstall/product");
 
+    // Try to mount the system_ext partition. update_engine doesn't do this for
+    // us, but we want it for system_ext APKs. Same notes as vendor and product
+    // above.
+    TryExtraMount("system_ext", arg[2], "/postinstall/system_ext");
+
+    constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig";
+    // Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot
+    if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) {
+        PLOG(ERROR) << "Failed to mount a tmpfs for " << kPostInstallLinkerconfig;
+        exit(215);
+    }
+
     // Setup APEX mount point and its security context.
     static constexpr const char* kPostinstallApexDir = "/postinstall/apex";
     // The following logic is similar to the one in system/core/rootdir/init.rc:
@@ -236,20 +246,71 @@
         exit(205);
     }
 
+    // Call apexd --unmount-all to free up loop and dm block devices, so that we can re-use
+    // them during the next invocation. Since otapreopt_chroot calls exit in case something goes
+    // wrong we need to register our own atexit handler.
+    // We want to register this handler before actually activating apex packages. This is mostly
+    // due to the fact that if fail to unmount apexes, then on the next run of otapreopt_chroot
+    // we will ask for new loop devices instead of re-using existing ones, and we really don't want
+    // to do that. :)
+    if (atexit(DeactivateApexPackages) != 0) {
+        LOG(ERROR) << "Failed to register atexit hander";
+        exit(206);
+    }
+
     // Try to mount APEX packages in "/apex" in the chroot dir. We need at least
     // the ART APEX, as it is required by otapreopt to run dex2oat.
-    std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
+    ActivateApexPackages();
 
+    auto cleanup = android::base::make_scope_guard([](){
+        std::vector<std::string> apexd_cmd{"/system/bin/apexd", "--unmount-all"};
+        std::string apexd_error_msg;
+        bool exec_result = Exec(apexd_cmd, &apexd_error_msg);
+        if (!exec_result) {
+            PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg;
+        }
+    });
     // Check that an ART APEX has been activated; clean up and exit
     // early otherwise.
-    if (std::none_of(active_packages.begin(),
-                     active_packages.end(),
-                     [](const apex::ApexFile& package){
-                         return package.GetManifest().name() == "com.android.art";
-                     })) {
-        LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package.";
-        DeactivateApexPackages(active_packages);
-        exit(217);
+    static constexpr const std::string_view kRequiredApexs[] = {
+      "com.android.art",
+      "com.android.runtime",
+      "com.android.sdkext",  // For derive_classpath
+    };
+    std::array<bool, arraysize(kRequiredApexs)> found_apexs{ false, false };
+    DIR* apex_dir = opendir("/apex");
+    if (apex_dir == nullptr) {
+        PLOG(ERROR) << "unable to open /apex";
+        exit(220);
+    }
+    for (dirent* entry = readdir(apex_dir); entry != nullptr; entry = readdir(apex_dir)) {
+        for (int i = 0; i < found_apexs.size(); i++) {
+            if (kRequiredApexs[i] == std::string_view(entry->d_name)) {
+                found_apexs[i] = true;
+                break;
+            }
+        }
+    }
+    closedir(apex_dir);
+    auto it = std::find(found_apexs.cbegin(), found_apexs.cend(), false);
+    if (it != found_apexs.cend()) {
+        LOG(ERROR) << "No activated " << kRequiredApexs[std::distance(found_apexs.cbegin(), it)]
+                   << " package!";
+        exit(221);
+    }
+
+    // Setup /linkerconfig. Doing it after the chroot means it doesn't need its own category
+    if (selinux_android_restorecon("/linkerconfig", 0) < 0) {
+        PLOG(ERROR) << "Failed to restorecon /linkerconfig";
+        exit(219);
+    }
+    std::vector<std::string> linkerconfig_cmd{"/apex/com.android.runtime/bin/linkerconfig",
+                                              "--target", "/linkerconfig"};
+    std::string linkerconfig_error_msg;
+    bool linkerconfig_exec_result = Exec(linkerconfig_cmd, &linkerconfig_error_msg);
+    if (!linkerconfig_exec_result) {
+        LOG(ERROR) << "Running linkerconfig failed: " << linkerconfig_error_msg;
+        exit(218);
     }
 
     // Now go on and run otapreopt.
@@ -272,9 +333,6 @@
         LOG(ERROR) << "Running otapreopt failed: " << error_msg;
     }
 
-    // Tear down the work down by the apexd logic. (i.e. deactivate packages).
-    DeactivateApexPackages(active_packages);
-
     if (!exec_result) {
         exit(213);
     }
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index 17ea903..a27fd10 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -86,7 +86,7 @@
                             bool generate_compact_dex,
                             bool use_jitzygote_image,
                             const char* compilation_reason) {
-    PrepareBootImageAndBootClasspathFlags(use_jitzygote_image);
+    PrepareBootImageFlags(use_jitzygote_image);
 
     PrepareInputFileFlags(output_oat, output_vdex, output_image, input_dex, input_vdex,
                           dex_metadata, profile, swap_fd, class_loader_context,
@@ -112,7 +112,7 @@
 
 RunDex2Oat::~RunDex2Oat() {}
 
-void RunDex2Oat::PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image) {
+void RunDex2Oat::PrepareBootImageFlags(bool use_jitzygote_image) {
     std::string boot_image;
     if (use_jitzygote_image) {
         boot_image = StringPrintf("--boot-image=%s", kJitZygoteImage);
@@ -120,23 +120,6 @@
         boot_image = MapPropertyToArg("dalvik.vm.boot-image", "--boot-image=%s");
     }
     AddArg(boot_image);
-
-    // If DEX2OATBOOTCLASSPATH is not in the environment, dex2oat is going to query
-    // BOOTCLASSPATH.
-    char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
-    if (dex2oat_bootclasspath != nullptr) {
-        AddRuntimeArg(StringPrintf("-Xbootclasspath:%s", dex2oat_bootclasspath));
-    }
-
-    std::string updatable_bcp_packages =
-            MapPropertyToArg("dalvik.vm.dex2oat-updatable-bcp-packages-file",
-                             "--updatable-bcp-packages-file=%s");
-    if (updatable_bcp_packages.empty()) {
-        // Make dex2oat fail by providing non-existent file name.
-        updatable_bcp_packages =
-                "--updatable-bcp-packages-file=/nonx/updatable-bcp-packages.txt";
-    }
-    AddArg(updatable_bcp_packages);
 }
 
 void RunDex2Oat::PrepareInputFileFlags(const UniqueFile& output_oat,
diff --git a/cmds/installd/run_dex2oat.h b/cmds/installd/run_dex2oat.h
index 325a3a2..475e124 100644
--- a/cmds/installd/run_dex2oat.h
+++ b/cmds/installd/run_dex2oat.h
@@ -56,7 +56,7 @@
     void Exec(int exit_code);
 
   protected:
-    void PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image);
+    void PrepareBootImageFlags(bool use_jitzygote_image);
     void PrepareInputFileFlags(const UniqueFile& output_oat,
                                const UniqueFile& output_vdex,
                                const UniqueFile& output_image,
diff --git a/cmds/installd/run_dex2oat_test.cpp b/cmds/installd/run_dex2oat_test.cpp
index 3813cf7..0a638cd 100644
--- a/cmds/installd/run_dex2oat_test.cpp
+++ b/cmds/installd/run_dex2oat_test.cpp
@@ -175,8 +175,6 @@
         default_expected_flags_["--swap-fd"] = FLAG_UNUSED;
         default_expected_flags_["--class-loader-context"] = FLAG_UNUSED;
         default_expected_flags_["--class-loader-context-fds"] = FLAG_UNUSED;
-        default_expected_flags_["--updatable-bcp-packages-file"] =
-                "=/nonx/updatable-bcp-packages.txt";
 
         // Arch
         default_expected_flags_["--instruction-set"] = "=arm64";
@@ -320,28 +318,6 @@
     VerifyExpectedFlags();
 }
 
-TEST_F(RunDex2OatTest, DEX2OATBOOTCLASSPATH) {
-    ASSERT_EQ(nullptr, getenv("DEX2OATBOOTCLASSPATH"));
-    ASSERT_EQ(0, setenv("DEX2OATBOOTCLASSPATH", "foobar", /*override=*/ false))
-        << "Failed to setenv: " << strerror(errno);
-
-    CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
-
-    SetExpectedFlagUsed("-Xbootclasspath", ":foobar");
-    VerifyExpectedFlags();
-
-    ASSERT_EQ(0, unsetenv("DEX2OATBOOTCLASSPATH"))
-        << "Failed to setenv: " << strerror(errno);
-}
-
-TEST_F(RunDex2OatTest, UpdatableBootClassPath) {
-    setSystemProperty("dalvik.vm.dex2oat-updatable-bcp-packages-file", "/path/to/file");
-    CallRunDex2Oat(RunDex2OatArgs::MakeDefaultTestArgs());
-
-    SetExpectedFlagUsed("--updatable-bcp-packages-file", "=/path/to/file");
-    VerifyExpectedFlags();
-}
-
 TEST_F(RunDex2OatTest, DoNotGenerateCompactDex) {
     auto args = RunDex2OatArgs::MakeDefaultTestArgs();
     args->generate_compact_dex = false;
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 7c9e3b2..7082017 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -1,4 +1,13 @@
 // Build the unit tests for installd
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "installd_utils_test",
     test_suites: ["device-tests"],
@@ -11,6 +20,7 @@
         "libcutils",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -35,6 +45,7 @@
         "server_configurable_flags",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -75,6 +86,7 @@
         "server_configurable_flags",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -115,6 +127,7 @@
         "server_configurable_flags",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -157,4 +170,3 @@
         "libotapreoptparameters"
     ],
 }
-
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index fbf1e0c..e272025 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -351,7 +351,7 @@
             uid = kTestAppUid;
         }
         if (class_loader_context == nullptr) {
-            class_loader_context = "&";
+            class_loader_context = "PCL[]";
         }
         int32_t dexopt_needed = 0;  // does not matter;
         std::optional<std::string> out_path; // does not matter
@@ -478,7 +478,7 @@
                            bool should_binder_call_succeed,
                            /*out */ binder::Status* binder_result) {
         std::optional<std::string> out_path = oat_dir ? std::make_optional<std::string>(oat_dir) : std::nullopt;
-        std::string class_loader_context = "&";
+        std::string class_loader_context = "PCL[]";
         int32_t target_sdk_version = 0;  // default
         std::string profile_name = "primary.prof";
         std::optional<std::string> dm_path_opt = dm_path ? std::make_optional<std::string>(dm_path) : std::nullopt;
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index c47df52..c4ecd07 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -1062,6 +1062,8 @@
 
 static const char* kProcFilesystems = "/proc/filesystems";
 bool supports_sdcardfs() {
+    if (!property_get_bool("external_storage.sdcardfs.enabled", true))
+        return false;
     std::string supported;
     if (!android::base::ReadFileToString(kProcFilesystems, &supported)) {
         PLOG(ERROR) << "Failed to read supported filesystems";
diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk
index e1e2204..396ae9d 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/cmds/ip-up-vpn/Android.mk
@@ -21,6 +21,9 @@
 LOCAL_CFLAGS := -Wall -Werror
 LOCAL_SHARED_LIBRARIES := libcutils liblog
 LOCAL_MODULE := ip-up-vpn
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
 LOCAL_MODULE_TAGS := optional
 
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 0cbb80f..649e53a 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "liblshal",
     shared_libs: [
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index 72958bd..ccf1ab1 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -28,7 +28,7 @@
 }
 
 std::string DebugCommand::getSimpleDescription() const {
-    return "Debug a specified HAL.";
+    return "Debug a specified HIDL HAL.";
 }
 
 Status DebugCommand::parseArgs(const Arg &arg) {
@@ -78,7 +78,7 @@
             "debug:\n"
             "    lshal debug [-E] <interface> [options [options [...]]] \n"
             "        Print debug information of a specified interface.\n"
-            "        -E: excludes debug output if HAL is actually a subclass.\n"
+            "        -E: excludes debug output if HIDL HAL is actually a subclass.\n"
             "        <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
             "            If instance name is missing `default` is used.\n"
             "        options: space separated options to IBase::debug.\n";
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 22268ac..2722e21 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -81,7 +81,7 @@
     return "list";
 }
 std::string ListCommand::getSimpleDescription() const {
-    return "List HALs.";
+    return "List HIDL HALs.";
 }
 
 std::string ListCommand::parseCmdline(pid_t pid) const {
@@ -295,21 +295,21 @@
     }
 
     mServicesTable.setDescription(
-            "| All binderized services (registered with hwservicemanager)");
+            "| All HIDL binderized services (registered with hwservicemanager)");
     mPassthroughRefTable.setDescription(
-            "| All interfaces that getService() has ever returned as a passthrough interface;\n"
+            "| All HIDL interfaces getService() has ever returned as a passthrough interface;\n"
             "| PIDs / processes shown below might be inaccurate because the process\n"
             "| might have relinquished the interface or might have died.\n"
             "| The Server / Server CMD column can be ignored.\n"
             "| The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
             "| the library and successfully fetched the passthrough implementation.");
     mImplementationsTable.setDescription(
-            "| All available passthrough implementations (all -impl.so files).\n"
+            "| All available HIDL passthrough implementations (all -impl.so files).\n"
             "| These may return subclasses through their respective HIDL_FETCH_I* functions.");
     mManifestHalsTable.setDescription(
-            "| All HALs that are in VINTF manifest.");
+            "| All HIDL HALs that are in VINTF manifest.");
     mLazyHalsTable.setDescription(
-            "| All HALs that are declared in VINTF manifest:\n"
+            "| All HIDL HALs that are declared in VINTF manifest:\n"
             "|    - as hwbinder HALs but are not registered to hwservicemanager, and\n"
             "|    - as hwbinder/passthrough HALs with no implementation.");
 }
@@ -417,7 +417,7 @@
         }
     }
     out << "-->" << std::endl;
-    out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlags::HALS_ONLY);
+    out << vintf::toXml(manifest, vintf::SerializeFlags::HALS_ONLY);
 }
 
 std::string ListCommand::INIT_VINTF_NOTES{
@@ -903,11 +903,11 @@
         thiz->mSelectedColumns.push_back(TableColumnType::VINTF);
         return OK;
     }, "print VINTF info. This column contains a comma-separated list of:\n"
-       "    - DM: if the HAL is in the device manifest\n"
-       "    - DC: if the HAL is in the device compatibility matrix\n"
-       "    - FM: if the HAL is in the framework manifest\n"
-       "    - FC: if the HAL is in the framework compatibility matrix\n"
-       "    - X: if the HAL is in none of the above lists"});
+       "    - DM: if the HIDL HAL is in the device manifest\n"
+       "    - DC: if the HIDL HAL is in the device compatibility matrix\n"
+       "    - FM: if the HIDL HAL is in the framework manifest\n"
+       "    - FC: if the HIDL HAL is in the framework compatibility matrix\n"
+       "    - X: if the HIDL HAL is in none of the above lists"});
     mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
         thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
         return OK;
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 99cb93a..bc99f4d 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -59,7 +59,8 @@
 }
 
 void Lshal::usage() {
-    err() << "lshal: List and debug HALs." << std::endl << std::endl
+    err() << "lshal: List and debug HIDL HALs." << std::endl
+          << "   (for AIDL HALs, see `dumpsys`)" << std::endl << std::endl
           << "commands:" << std::endl;
 
     size_t nameMaxLength = 0;
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
index 65b41b9..437a66a 100644
--- a/cmds/lshal/WaitCommand.cpp
+++ b/cmds/lshal/WaitCommand.cpp
@@ -29,7 +29,7 @@
 }
 
 std::string WaitCommand::getSimpleDescription() const {
-    return "Wait for HAL to start if it is not already started.";
+    return "Wait for HIDL HAL to start if it is not already started.";
 }
 
 Status WaitCommand::parseArgs(const Arg &arg) {
diff --git a/cmds/lshal/libprocpartition/Android.bp b/cmds/lshal/libprocpartition/Android.bp
index 9592111..cbfbdc9 100644
--- a/cmds/lshal/libprocpartition/Android.bp
+++ b/cmds/lshal/libprocpartition/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libprocpartition",
     shared_libs: [
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index b6ff28d..6f08f74 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -47,8 +47,6 @@
 using ::android::hardware::Void;
 using android::vintf::Arch;
 using android::vintf::CompatibilityMatrix;
-using android::vintf::gCompatibilityMatrixConverter;
-using android::vintf::gHalManifestConverter;
 using android::vintf::HalManifest;
 using android::vintf::Transport;
 using android::vintf::VintfObject;
@@ -508,10 +506,10 @@
     EXPECT_THAT(output, HasSubstr("a.h.foo6@6.0::IFoo/6"));
     EXPECT_EQ("", err.str());
 
+    std::string error;
     vintf::HalManifest m;
-    EXPECT_EQ(true, vintf::gHalManifestConverter(&m, out.str()))
-        << "--init-vintf does not emit valid HAL manifest: "
-        << vintf::gHalManifestConverter.lastError();
+    EXPECT_EQ(true, vintf::fromXml(&m, out.str(), &error))
+        << "--init-vintf does not emit valid HAL manifest: " << error;
 }
 
 // test default columns
@@ -775,10 +773,10 @@
     auto deviceMatrix = std::make_shared<CompatibilityMatrix>();
     auto frameworkMatrix = std::make_shared<CompatibilityMatrix>();
 
-    ASSERT_TRUE(gHalManifestConverter(deviceManifest.get(), deviceManifestXml));
-    ASSERT_TRUE(gHalManifestConverter(frameworkManifest.get(), frameworkManifestXml));
-    ASSERT_TRUE(gCompatibilityMatrixConverter(deviceMatrix.get(), deviceMatrixXml));
-    ASSERT_TRUE(gCompatibilityMatrixConverter(frameworkMatrix.get(), frameworkMatrixXml));
+    ASSERT_TRUE(fromXml(deviceManifest.get(), deviceManifestXml));
+    ASSERT_TRUE(fromXml(frameworkManifest.get(), frameworkManifestXml));
+    ASSERT_TRUE(fromXml(deviceMatrix.get(), deviceMatrixXml));
+    ASSERT_TRUE(fromXml(frameworkMatrix.get(), frameworkMatrixXml));
 
     ON_CALL(*mockList, getDeviceManifest()).WillByDefault(Return(deviceManifest));
     ON_CALL(*mockList, getDeviceMatrix()).WillByDefault(Return(deviceMatrix));
@@ -964,7 +962,7 @@
                 "    </hal>\n"
                 "</manifest>";
         auto manifest = std::make_shared<HalManifest>();
-        EXPECT_TRUE(gHalManifestConverter(manifest.get(), mockManifestXml));
+        EXPECT_TRUE(fromXml(manifest.get(), mockManifestXml));
         EXPECT_CALL(*mockList, getDeviceManifest())
             .Times(AnyNumber())
             .WillRepeatedly(Return(manifest));
diff --git a/cmds/rawbu/Android.bp b/cmds/rawbu/Android.bp
index 363ffc1..e34119d 100644
--- a/cmds/rawbu/Android.bp
+++ b/cmds/rawbu/Android.bp
@@ -1,5 +1,22 @@
 // Copyright 2009 The Android Open Source Project
 
+package {
+    default_applicable_licenses: ["frameworks_native_cmds_rawbu_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_cmds_rawbu_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_binary {
     name: "rawbu",
 
diff --git a/cmds/rss_hwm_reset/Android.bp b/cmds/rss_hwm_reset/Android.bp
index 15f10ef..cd335d4 100644
--- a/cmds/rss_hwm_reset/Android.bp
+++ b/cmds/rss_hwm_reset/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "rss_hwm_reset",
 
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index a5b1ac5..3e8e3f6 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -1,3 +1,20 @@
+package {
+    default_applicable_licenses: ["frameworks_native_cmds_service_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_cmds_service_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_binary {
     name: "service",
 
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index b139251..3ebdeee 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "servicemanager_defaults",
 
@@ -5,6 +14,7 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
 
     srcs: [
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index b21010d..90db509 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -58,22 +58,34 @@
     return false;
 }
 
-static bool isVintfDeclared(const std::string& name) {
-    size_t firstSlash = name.find('/');
-    size_t lastDot = name.rfind('.', firstSlash);
-    if (firstSlash == std::string::npos || lastDot == std::string::npos) {
-        LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
-                   << "some.package.foo.IFoo/default) but got: " << name;
-        return false;
-    }
-    const std::string package = name.substr(0, lastDot);
-    const std::string iface = name.substr(lastDot+1, firstSlash-lastDot-1);
-    const std::string instance = name.substr(firstSlash+1);
+struct AidlName {
+    std::string package;
+    std::string iface;
+    std::string instance;
 
-    bool found = forEachManifest([&] (const ManifestWithDescription& mwd) {
-        if (mwd.manifest->hasAidlInstance(package, iface, instance)) {
+    static bool fill(const std::string& name, AidlName* aname) {
+        size_t firstSlash = name.find('/');
+        size_t lastDot = name.rfind('.', firstSlash);
+        if (firstSlash == std::string::npos || lastDot == std::string::npos) {
+            LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
+                       << "some.package.foo.IFoo/default) but got: " << name;
+            return false;
+        }
+        aname->package = name.substr(0, lastDot);
+        aname->iface = name.substr(lastDot + 1, firstSlash - lastDot - 1);
+        aname->instance = name.substr(firstSlash + 1);
+        return true;
+    }
+};
+
+static bool isVintfDeclared(const std::string& name) {
+    AidlName aname;
+    if (!AidlName::fill(name, &aname)) return false;
+
+    bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
+        if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) {
             LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
-            return true;
+            return true; // break
         }
         return false;  // continue
     });
@@ -81,13 +93,34 @@
     if (!found) {
         // Although it is tested, explicitly rebuilding qualified name, in case it
         // becomes something unexpected.
-        LOG(ERROR) << "Could not find " << package << "." << iface << "/" << instance
-                   << " in the VINTF manifest.";
+        LOG(ERROR) << "Could not find " << aname.package << "." << aname.iface << "/"
+                   << aname.instance << " in the VINTF manifest.";
     }
 
     return found;
 }
 
+static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
+    AidlName aname;
+    if (!AidlName::fill(name, &aname)) return std::nullopt;
+
+    std::optional<std::string> updatableViaApex;
+
+    forEachManifest([&](const ManifestWithDescription& mwd) {
+        mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+            if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
+            if (manifestInstance.package() != aname.package) return true;
+            if (manifestInstance.interface() != aname.iface) return true;
+            if (manifestInstance.instance() != aname.instance) return true;
+            updatableViaApex = manifestInstance.updatableViaApex();
+            return false; // break (libvintf uses opposite convention)
+        });
+        return false; // continue
+    });
+
+    return updatableViaApex;
+}
+
 static std::vector<std::string> getVintfInstances(const std::string& interface) {
     size_t lastDot = interface.rfind('.');
     if (lastDot == std::string::npos) {
@@ -239,7 +272,8 @@
 #endif  // !VENDORSERVICEMANAGER
 
     // implicitly unlinked when the binder is removed
-    if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
+    if (binder->remoteBinder() != nullptr &&
+        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
         LOG(ERROR) << "Could not linkToDeath when adding " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -307,7 +341,9 @@
         return Status::fromExceptionCode(Status::EX_NULL_POINTER);
     }
 
-    if (OK != IInterface::asBinder(callback)->linkToDeath(this)) {
+    if (OK !=
+        IInterface::asBinder(callback)->linkToDeath(
+                sp<ServiceManager>::fromExisting(this))) {
         LOG(ERROR) << "Could not linkToDeath when adding " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -385,6 +421,22 @@
     return Status::ok();
 }
 
+Status ServiceManager::updatableViaApex(const std::string& name,
+                                        std::optional<std::string>* outReturn) {
+    auto ctx = mAccess->getCallingContext();
+
+    if (!mAccess->canFind(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    *outReturn = std::nullopt;
+
+#ifndef VENDORSERVICEMANAGER
+    *outReturn = getVintfUpdatableApex(name);
+#endif
+    return Status::ok();
+}
+
 void ServiceManager::removeRegistrationCallback(const wp<IBinder>& who,
                                     ServiceCallbackMap::iterator* it,
                                     bool* found) {
@@ -429,7 +481,12 @@
           name.c_str());
 
     std::thread([=] {
-        (void)base::SetProperty("ctl.interface_start", "aidl/" + name);
+        if (!base::SetProperty("ctl.interface_start", "aidl/" + name)) {
+            LOG(INFO) << "Tried to start aidl service " << name
+                      << " as a lazy service, but was unable to. Usually this happens when a "
+                         "service is not installed, but if the service is intended to be used as a "
+                         "lazy service, then it may be configured incorrectly.";
+        }
     }).detach();
 }
 
@@ -461,7 +518,8 @@
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
     }
 
-    if (OK != IInterface::asBinder(cb)->linkToDeath(this)) {
+    if (OK !=
+        IInterface::asBinder(cb)->linkToDeath(sp<ServiceManager>::fromExisting(this))) {
         LOG(ERROR) << "Could not linkToDeath when adding client callback for " << name;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
@@ -491,7 +549,7 @@
 }
 
 ssize_t ServiceManager::Service::getNodeStrongRefCount() {
-    sp<BpBinder> bpBinder = binder->remoteBinder();
+    sp<BpBinder> bpBinder = sp<BpBinder>::fromExisting(binder->remoteBinder());
     if (bpBinder == nullptr) return -1;
 
     return ProcessState::self()->getStrongRefCountForNode(bpBinder);
@@ -623,4 +681,21 @@
     return Status::ok();
 }
 
+Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
+    if (!mAccess->canList(mAccess->getCallingContext())) {
+        return Status::fromExceptionCode(Status::EX_SECURITY);
+    }
+
+    outReturn->reserve(mNameToService.size());
+    for (auto const& [name, service] : mNameToService) {
+        ServiceDebugInfo info;
+        info.name = name;
+        info.debugPid = service.debugPid;
+
+        outReturn->push_back(std::move(info));
+    }
+
+    return Status::ok();
+}
+
 }  // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 9f43eb4..4f23c21 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -26,6 +26,7 @@
 
 using os::IClientCallback;
 using os::IServiceCallback;
+using os::ServiceDebugInfo;
 
 class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
 public:
@@ -45,9 +46,12 @@
 
     binder::Status isDeclared(const std::string& name, bool* outReturn) override;
     binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override;
+    binder::Status updatableViaApex(const std::string& name,
+                                    std::optional<std::string>* outReturn) override;
     binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service,
                                           const sp<IClientCallback>& cb) override;
     binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override;
+    binder::Status getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) override;
     void binderDied(const wp<IBinder>& who) override;
     void handleClientCallbacks();
 
diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp
index b1bc6dc..8c1beac 100644
--- a/cmds/servicemanager/main.cpp
+++ b/cmds/servicemanager/main.cpp
@@ -39,16 +39,12 @@
 class BinderCallback : public LooperCallback {
 public:
     static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
-        sp<BinderCallback> cb = new BinderCallback;
+        sp<BinderCallback> cb = sp<BinderCallback>::make();
 
         int binder_fd = -1;
         IPCThreadState::self()->setupPolling(&binder_fd);
         LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);
 
-        // Flush after setupPolling(), to make sure the binder driver
-        // knows about this thread handling commands.
-        IPCThreadState::self()->flushCommands();
-
         int ret = looper->addFd(binder_fd,
                                 Looper::POLL_CALLBACK,
                                 Looper::EVENT_INPUT,
@@ -69,7 +65,7 @@
 class ClientCallbackCallback : public LooperCallback {
 public:
     static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper, const sp<ServiceManager>& manager) {
-        sp<ClientCallbackCallback> cb = new ClientCallbackCallback(manager);
+        sp<ClientCallbackCallback> cb = sp<ClientCallbackCallback>::make(manager);
 
         int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0 /*flags*/);
         LOG_ALWAYS_FATAL_IF(fdTimer < 0, "Failed to timerfd_create: fd: %d err: %d", fdTimer, errno);
@@ -109,6 +105,7 @@
         return 1;  // Continue receiving callbacks.
     }
 private:
+    friend sp<ClientCallbackCallback>;
     ClientCallbackCallback(const sp<ServiceManager>& manager) : mManager(manager) {}
     sp<ServiceManager> mManager;
 };
@@ -124,7 +121,7 @@
     ps->setThreadPoolMaxThreadCount(0);
     ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
 
-    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
+    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
     if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
         LOG(ERROR) << "Could not self register servicemanager";
     }
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index fb9f9df..5d5a75e 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -46,7 +46,7 @@
         }
     };
 
-    return new LinkableBinder;
+    return sp<LinkableBinder>::make();
 }
 
 class MockAccess : public Access {
@@ -71,7 +71,7 @@
     ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true));
     ON_CALL(*access, canList(_)).WillByDefault(Return(true));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
     return sm;
 }
 
@@ -119,7 +119,7 @@
             .uid = uid,
         }));
         EXPECT_CALL(*access, canAdd(_, _)).Times(0);
-        sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+        sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
         EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
             IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -161,7 +161,7 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -194,7 +194,7 @@
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
     EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -218,7 +218,7 @@
     EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true));
     EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     sp<IBinder> service = getBinder();
     EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
@@ -244,7 +244,7 @@
     // TODO(b/136023468): when security check is first, this should be called first
     // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
@@ -261,7 +261,7 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canList(_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access));
+    sp<ServiceManager> sm = sp<NiceMock<MockServiceManager>>::make(std::move(access));
 
     std::vector<std::string> out;
     EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk());
@@ -329,9 +329,9 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = sp<ServiceManager>::make(std::move(access));
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_EQ(sm->registerForNotifications("foofoo", cb).exceptionCode(),
         Status::EX_SECURITY);
@@ -343,9 +343,9 @@
     EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{}));
     EXPECT_CALL(*access, canFind(_,_)).WillOnce(Return(false));
 
-    sp<ServiceManager> sm = new ServiceManager(std::move(access));
+    sp<ServiceManager> sm = sp<ServiceManager>::make(std::move(access));
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     // should always hit security error first
     EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
@@ -355,7 +355,7 @@
 TEST(ServiceNotifications, InvalidName) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_EQ(sm->registerForNotifications("foo@foo", cb).exceptionCode(),
         Status::EX_ILLEGAL_ARGUMENT);
@@ -371,7 +371,7 @@
 TEST(ServiceNotifications, Unregister) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
     EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(), 0);
@@ -380,7 +380,7 @@
 TEST(ServiceNotifications, UnregisterWhenNoRegistrationExists) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_EQ(sm->unregisterForNotifications("foofoo", cb).exceptionCode(),
         Status::EX_ILLEGAL_STATE);
@@ -389,7 +389,7 @@
 TEST(ServiceNotifications, NoNotification) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     EXPECT_TRUE(sm->registerForNotifications("foofoo", cb).isOk());
     EXPECT_TRUE(sm->addService("otherservice", getBinder(),
@@ -402,7 +402,7 @@
 TEST(ServiceNotifications, GetNotification) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     sp<IBinder> service = getBinder();
 
@@ -417,7 +417,7 @@
 TEST(ServiceNotifications, GetNotificationForAlreadyRegisteredService) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     sp<IBinder> service = getBinder();
 
@@ -433,7 +433,7 @@
 TEST(ServiceNotifications, GetMultipleNotification) {
     auto sm = getPermissiveServiceManager();
 
-    sp<CallbackHistorian> cb = new CallbackHistorian;
+    sp<CallbackHistorian> cb = sp<CallbackHistorian>::make();
 
     sp<IBinder> binder1 = getBinder();
     sp<IBinder> binder2 = getBinder();
diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp
index d4c037a..34fc8b1 100644
--- a/cmds/surfacereplayer/Android.bp
+++ b/cmds/surfacereplayer/Android.bp
@@ -1,4 +1,13 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 subdirs = [
     "proto",
     "replayer",
-]
\ No newline at end of file
+]
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
index 71a5e23..dae976e 100644
--- a/cmds/surfacereplayer/proto/Android.bp
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libtrace_proto",
     srcs: [
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
index 7632311..3985230 100644
--- a/cmds/surfacereplayer/replayer/Android.bp
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libsurfacereplayer",
     srcs: [
diff --git a/data/etc/android.hardware.keystore.app_attest_key.xml b/data/etc/android.hardware.keystore.app_attest_key.xml
new file mode 100644
index 0000000..8adc439
--- /dev/null
+++ b/data/etc/android.hardware.keystore.app_attest_key.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- Feature for devices that support app attestation keys (i.e. KeyMint 1.0). -->
+<permissions>
+    <feature name="android.hardware.keystore.app_attest_key" />
+</permissions>
diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml
new file mode 100644
index 0000000..5217086
--- /dev/null
+++ b/data/etc/android.hardware.keystore.limited_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- Feature for devices with KeyMint that can enforce limited use key
+     in hardware with any max usage count (including count equals to 1). -->
+<permissions>
+    <feature name="android.hardware.keystore.limited_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml
new file mode 100644
index 0000000..40e80aa
--- /dev/null
+++ b/data/etc/android.hardware.keystore.single_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- Feature for devices with KeyMint that only can enforce limited use key
+     in hardware with max usage count equals to 1. -->
+<permissions>
+    <feature name="android.hardware.keystore.single_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.telephony.ims.singlereg.xml b/data/etc/android.hardware.telephony.ims.singlereg.xml
new file mode 100644
index 0000000..9a6cec0
--- /dev/null
+++ b/data/etc/android.hardware.telephony.ims.singlereg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- Feature for devices that have an IMS service that supports all IMS
+     applications using a single IMS registration. -->
+<permissions>
+  <feature name="android.hardware.telephony.ims" />
+  <feature name="android.hardware.telephony.ims.singlereg" />
+</permissions>
diff --git a/headers/Android.bp b/headers/Android.bp
index 8f41c2b..7481a23 100644
--- a/headers/Android.bp
+++ b/headers/Android.bp
@@ -1,3 +1,13 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "media_plugin_headers",
     vendor_available: true,
diff --git a/include/OWNERS b/include/OWNERS
index db52850..c98e87a 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,3 +1,4 @@
+alecmouri@google.com
 alexeykuzmin@google.com
 dangittik@google.com
 jreck@google.com
@@ -8,7 +9,6 @@
 racarr@google.com
 romainguy@android.com
 santoscordon@google.com
-stoza@google.com
 svv@google.com
 
 # For multinetwork.h only.
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index f195399..a70dffd 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -28,8 +28,13 @@
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <stddef.h>
 #include <jni.h>
 
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -117,8 +122,6 @@
 int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                           AndroidBitmapInfo* info);
 
-#if __ANDROID_API__ >= 30
-
 /**
  * Given a java bitmap object, return its {@link ADataSpace}.
  *
@@ -130,8 +133,6 @@
  */
 int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap)  __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 /**
  * Given a java bitmap object, attempt to lock the pixel address.
  * Locking will ensure that the memory for the pixels will not move
@@ -152,8 +153,6 @@
  */
 int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
 
-#if __ANDROID_API__ >= 30
-
 // Note: these values match android.graphics.Bitmap#compressFormat.
 
 /**
@@ -254,8 +253,6 @@
 int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap,
         AHardwareBuffer** outBuffer) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index e9f559c..8039bb0 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -61,8 +61,6 @@
  */
 typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
 
-#if __ANDROID_API__ >= 24
-
 /**
  * Get the AChoreographer instance for the current thread. This must be called
  * on an ALooper thread.
@@ -86,10 +84,6 @@
                                              long delayMillis) __INTRODUCED_IN(24)
         __DEPRECATED_IN(29);
 
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Power a callback to be run on the next frame.  The data pointer provided will
  * be passed to the callback function when it's called.
@@ -111,10 +105,6 @@
                                                AChoreographer_frameCallback64 callback, void* data,
                                                uint32_t delayMillis) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
-#if __ANDROID_API__ >= 30
-
 /**
  * Registers a callback to be run when the display refresh rate changes. The
  * data pointer provided will be passed to the callback function when it's
@@ -160,7 +150,6 @@
 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
                                                   AChoreographer_refreshRateCallback, void* data)
         __INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
 
 __END_DECLS
 
diff --git a/include/android/configuration.h b/include/android/configuration.h
index ccf3e59..88019ae 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -645,14 +645,12 @@
  */
 void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
 
-#if __ANDROID_API__ >= 30
 /**
  * Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
  *
  * Available since API level 30.
  */
 int32_t AConfiguration_getScreenRound(AConfiguration* config) __INTRODUCED_IN(30);
-#endif
 
 /**
  * Set the current screen round in the configuration.
@@ -712,7 +710,6 @@
  */
 void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
 
-#if __ANDROID_API__ >= 17
 /**
  * Return the configuration's layout direction, or
  * ACONFIGURATION_LAYOUTDIR_ANY if not set.
@@ -727,7 +724,6 @@
  * Available since API level 17.
  */
 void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
-#endif /* __ANDROID_API__ >= 17 */
 
 /**
  * Perform a diff between two configurations.  Returns a bit mask of
diff --git a/include/android/font.h b/include/android/font.h
index 1618096..a172618 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -51,8 +51,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 enum {
     /** The minimum value fot the font weight value. */
     AFONT_WEIGHT_MIN = 0,
@@ -297,8 +295,6 @@
 float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
       __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
 __END_DECLS
 
 #endif // ANDROID_FONT_H
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892..49e478c 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -97,8 +97,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 enum {
     /** A family variant value for the system default variant. */
     AFAMILY_VARIANT_DEFAULT = 0,
@@ -217,8 +215,6 @@
         const uint32_t textLength,
         uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
 __END_DECLS
 
 #endif // ANDROID_FONT_MATCHER_H
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index d7e6e41..1298c62 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -51,14 +51,16 @@
 #include <android/rect.h>
 #include <stdint.h>
 
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 struct AAsset;
 
-#if __ANDROID_API__ >= 30
-
 /**
  *  {@link AImageDecoder} functions result code. Many functions will return one of these
  *  to indicate success ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason
@@ -527,8 +529,6 @@
                               void* pixels, size_t stride,
                               size_t size) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index c6d1c94..424299d 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,8 +60,6 @@
  * on failure with an appropriate errno value set.
  */
 
-#if __ANDROID_API__ >= 23
-
 /**
  * Set the network to be used by the given socket file descriptor.
  *
@@ -111,10 +109,6 @@
         const char *node, const char *service,
         const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
 
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Possible values of the flags argument to android_res_nsend and android_res_nquery.
  * Values are ORed together.
@@ -187,8 +181,6 @@
  */
 void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
 __END_DECLS
 
 #endif  // ANDROID_MULTINETWORK_H
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe..071ec79 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,7 +44,6 @@
  */
 ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
 
-#if __ANDROID_API__ >= 26
 /**
  * Return a Java Surface object derived from the ANativeWindow, for interacting
  * with it through Java code. The returned Java object acquires a reference on
@@ -55,7 +54,6 @@
  * Available since API level 26.
  */
 jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
-#endif
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sensor.h b/include/android/sensor.h
index eb40779..6447844 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -52,6 +52,13 @@
 #include <math.h>
 #include <stdint.h>
 
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+#if !defined(__DEPRECATED_IN)
+#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__))
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -553,13 +560,8 @@
  *     ASensorManager* sensorManager = ASensorManager_getInstance();
  *
  */
-#if __ANDROID_API__ >= 26
-__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
-#else
-ASensorManager* ASensorManager_getInstance();
-#endif
+ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26);
 
-#if __ANDROID_API__ >= 26
 /**
  * Get a reference to the sensor manager. ASensorManager is a singleton
  * per package as different packages may have access to different sensors.
@@ -571,7 +573,6 @@
  * Available since API level 26.
  */
 ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
-#endif
 
 /**
  * Returns the list of available sensors.
@@ -584,7 +585,6 @@
  */
 ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
 
-#if __ANDROID_API__ >= 21
 /**
  * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
  * of this type and wakeUp properties exists.
@@ -592,7 +592,6 @@
  * Available since API level 21.
  */
 ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
-#endif
 
 /**
  * Creates a new sensor event queue and associate it with a looper.
@@ -609,7 +608,6 @@
  */
 int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
 
-#if __ANDROID_API__ >= 26
 /**
  * Create direct channel based on shared memory
  *
@@ -706,7 +704,6 @@
  */
 int ASensorManager_configureDirectReport(ASensorManager* manager,
         ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
 
 /*****************************************************************************/
 
@@ -795,7 +792,6 @@
  */
 ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
 
-#if __ANDROID_API__ >= 29
 /**
  * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
  * the given {@link ASensorEventQueue}.
@@ -819,7 +815,6 @@
  * \return 0 on success or a negative error code on failure
  */
 int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
 
 /*****************************************************************************/
 
@@ -850,7 +845,6 @@
  */
 int ASensor_getMinDelay(ASensor const* sensor);
 
-#if __ANDROID_API__ >= 21
 /**
  * Returns the maximum size of batches for this sensor. Batches will often be
  * smaller, as the hardware fifo might be used for other sensors.
@@ -886,9 +880,7 @@
  * Available since API level 21.
  */
 bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
 
-#if __ANDROID_API__ >= 26
 /**
  * Test if sensor supports a certain type of direct channel.
  *
@@ -914,9 +906,7 @@
  *         does not support direct report.
  */
 int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
 
-#if __ANDROID_API__ >= 29
 /**
  * Returns the sensor's handle.
  *
@@ -934,7 +924,6 @@
  * Available since API level 29.
  */
 int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
 
 #ifdef __cplusplus
 };
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 5f74682..7994aa9 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -50,8 +50,6 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= 26
-
 /**
  * Create a shared memory region.
  *
@@ -121,8 +119,6 @@
  */
 int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
 
-#endif // __ANDROID_API__ >= 26
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 13e56e6..bbac785 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -52,8 +52,6 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= 27
-
 /**
  * Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
  * descriptor has all the same properties & capabilities as the FD returned from
@@ -72,8 +70,6 @@
  */
 int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
 
-#endif // __ANDROID_API__ >= 27
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index cbcf6ec..27b880d 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -35,8 +35,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 struct ASurfaceControl;
 
 /**
@@ -405,10 +403,6 @@
                                                  struct AHdrMetadata_cta861_3* metadata)
                                                  __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
 /**
  * Sets the intended frame rate for |surface_control|.
  *
@@ -435,8 +429,6 @@
                                       ASurfaceControl* surface_control, float frameRate,
                                       int8_t compatibility) __INTRODUCED_IN(30);
 
-#endif // __ANDROID_API__ >= 30
-
 __END_DECLS
 
 #endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa..b227b32 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -59,8 +59,6 @@
  */
 typedef struct ASurfaceTexture ASurfaceTexture;
 
-#if __ANDROID_API__ >= 28
-
 /**
  * Release the reference to the native ASurfaceTexture acquired with
  * ASurfaceTexture_fromSurfaceTexture().
@@ -175,8 +173,6 @@
  */
 int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
 
-#endif /* __ANDROID_API__ >= 28 */
-
 __END_DECLS
 
 #endif /* ANDROID_NATIVE_SURFACE_TEXTURE_H */
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d54..e40686d 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 28
-
 /**
  * Get a reference to the native ASurfaceTexture from the corresponding java object.
  *
@@ -52,8 +50,6 @@
  */
 ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
 
-#endif
-
 __END_DECLS
 
 #endif /* ANDROID_NATIVE_SURFACE_TEXTURE_JNI_H */
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c..b0bbb95 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -87,8 +87,6 @@
 
 __BEGIN_DECLS
 
-#if __ANDROID_API__ >= 29
-
 /**
  * ASystemFontIterator provides access to the system font configuration.
  *
@@ -128,8 +126,6 @@
  */
 AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
 
-#endif // __ANDROID_API__ >= 29
-
 __END_DECLS
 
 #endif // ANDROID_SYSTEM_FONTS_H
diff --git a/include/android/thermal.h b/include/android/thermal.h
index 83582d6..6ec68d9 100644
--- a/include/android/thermal.h
+++ b/include/android/thermal.h
@@ -53,7 +53,7 @@
 #include <sys/types.h>
 
 #if !defined(__INTRODUCED_IN)
-#define __INTRODUCED_IN(30) /* Introduced in API level 30 */
+#define __INTRODUCED_IN(__api_level) /* nothing */
 #endif
 
 #ifdef __cplusplus
@@ -109,8 +109,6 @@
  */
 typedef void (*AThermal_StatusCallback)(void *data, AThermalStatus status);
 
-#if __ANDROID_API__ >= 30
-
 /**
   * Acquire an instance of the thermal manager. This must be freed using
   * {@link AThermal_releaseManager}.
@@ -179,8 +177,6 @@
 int AThermal_unregisterThermalStatusListener(AThermalManager *manager,
         AThermal_StatusCallback callback, void *data) __INTRODUCED_IN(30);
 
-#endif  //  __ANDROID_API__ >= 30
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/android/trace.h b/include/android/trace.h
index dbad6f6..dcefffb 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -40,8 +40,6 @@
 extern "C" {
 #endif
 
-#if __ANDROID_API__ >= 23
-
 /**
  * Returns true if tracing is enabled. Use this to avoid expensive computation only necessary
  * when tracing is enabled.
@@ -72,10 +70,6 @@
  */
 void ATrace_endSection() __INTRODUCED_IN(23);
 
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Writes a trace message to indicate that a given section of code has
  * begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same
@@ -112,8 +106,6 @@
  */
 void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
index 8883c04..16cded8 100644
--- a/libs/adbd_auth/Android.bp
+++ b/libs/adbd_auth/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libadbd_auth",
     cflags: [
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
index dae6eeb..15bd5c3 100644
--- a/libs/adbd_auth/adbd_auth.cpp
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -282,9 +282,8 @@
             LOG(FATAL) << "adbd_auth: unhandled packet type?";
         }
 
-        output_queue_.pop_front();
-
         ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
+        output_queue_.pop_front();
         if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
             PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
             ReplaceFrameworkFd(unique_fd());
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
index 8f834df..1dcf540 100644
--- a/libs/adbd_auth/include/adbd_auth.h
+++ b/libs/adbd_auth/include/adbd_auth.h
@@ -26,7 +26,6 @@
 #endif
 
 __BEGIN_DECLS
-#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
 
 // The transport type of the device connection.
 enum AdbTransportType : int32_t {
@@ -186,5 +185,4 @@
  */
 bool adbd_auth_supports_feature(AdbdAuthFeature feature);
 
-#endif  //!__ANDROID__ || __ANDROID_API__ >= 30
 __END_DECLS
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index cdd7764..b74923c 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -30,6 +30,15 @@
 // instead of libandroid_runtime. When they are used by a vendor process,
 // depending on libandroid_runtime is meaningless. In this case,
 // they can depend on libandroid_runtime_lazy.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libandroid_runtime_lazy",
     vendor_available: true,
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 80aa891..bb40f51 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_native_libs_arect_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_arect_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 ndk_headers {
     name: "libarect_headers_for_ndk",
     from: "include/android",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 08b984e..31227ab 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libbinder_headers",
     export_include_dirs: ["include"],
@@ -22,14 +31,21 @@
 
     header_libs: [
         "libbase_headers",
+        "libbinder_headers_platform_shared",
         "libcutils_headers",
         "libutils_headers",
     ],
     export_header_lib_headers: [
         "libbase_headers",
+        "libbinder_headers_platform_shared",
         "libcutils_headers",
         "libutils_headers",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
     min_sdk_version: "29",
     target: {
         darwin: {
@@ -42,21 +58,11 @@
 // transport itself and should be moved to AIDL or in domain-specific libs.
 //
 // Currently, these are only on system android (not vendor, not host)
+// TODO(b/183654927) - move these into separate libraries
 libbinder_device_interface_sources = [
-    "ActivityManager.cpp",
-    "AppOpsManager.cpp",
-    "IActivityManager.cpp",
-    "IAppOpsCallback.cpp",
-    "IAppOpsService.cpp",
-    "IBatteryStats.cpp",
-    "IMediaResourceMonitor.cpp",
     "IPermissionController.cpp",
-    "IProcessInfoService.cpp",
-    "IUidObserver.cpp",
     "PermissionCache.cpp",
     "PermissionController.cpp",
-    "ProcessInfoService.cpp",
-    "IpPrefix.cpp",
 ]
 
 cc_library {
@@ -108,11 +114,16 @@
         "ParcelFileDescriptor.cpp",
         "PersistableBundle.cpp",
         "ProcessState.cpp",
+        "RpcAddress.cpp",
+        "RpcSession.cpp",
+        "RpcServer.cpp",
+        "RpcState.cpp",
         "Static.cpp",
         "Stability.cpp",
         "Status.cpp",
         "TextOutput.cpp",
         "Utils.cpp",
+        ":packagemanager_aidl",
         ":libbinder_aidl",
     ],
 
@@ -148,6 +159,7 @@
         "-Werror",
         "-Wzero-as-null-pointer-constant",
         "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     product_variables: {
         binder32bit: {
@@ -180,29 +192,46 @@
         // Only check our headers
         "--header-filter=^.*frameworks/native/libs/binder/.*.h$",
     ],
-    tidy_checks_as_errors: [
-        "*",
-        "-clang-analyzer-core.CallAndMessage",
-        "-clang-analyzer-core.uninitialized.Assign",
-        "-clang-analyzer-unix.Malloc,",
-        "-clang-analyzer-deadcode.DeadStores",
-        "-clang-analyzer-optin.cplusplus.UninitializedObject",
-        "-misc-no-recursion",
-        "-misc-redundant-expression",
-        "-misc-unused-using-decls",
+    tidy_checks: [
+        "-performance-no-int-to-ptr",
     ],
+    tidy_checks_as_errors: [
+        // Explicitly list the checks that should not occur in this module.
+        "abseil-*",
+        "android-*",
+        "bugprone-*",
+        "cert-*",
+        "clang-analyzer-*",
+        "google-*",
+        "misc-*",
+        "performance*",
+        "portability*",
+    ],
+
+    pgo: {
+        sampling: true,
+        profile_file: "libbinder/libbinder.profdata",
+    },
 }
 
 // AIDL interface between libbinder and framework.jar
 filegroup {
     name: "libbinder_aidl",
     srcs: [
-        "aidl/android/content/pm/IPackageChangeObserver.aidl",
-        "aidl/android/content/pm/IPackageManagerNative.aidl",
-        "aidl/android/content/pm/PackageChangeEvent.aidl",
         "aidl/android/os/IClientCallback.aidl",
         "aidl/android/os/IServiceCallback.aidl",
         "aidl/android/os/IServiceManager.aidl",
+        "aidl/android/os/ServiceDebugInfo.aidl",
+    ],
+    path: "aidl",
+}
+
+filegroup {
+    name: "packagemanager_aidl",
+    srcs: [
+        "aidl/android/content/pm/IPackageChangeObserver.aidl",
+        "aidl/android/content/pm/IPackageManagerNative.aidl",
+        "aidl/android/content/pm/PackageChangeEvent.aidl",
     ],
     path: "aidl",
 }
@@ -219,3 +248,56 @@
         },
     },
 }
+
+// libbinder historically contained additional interfaces that provided specific
+// functionality in the platform but have nothing to do with binder itself. These
+// are moved out of libbinder in order to avoid the overhead of their vtables.
+// If you are working on or own one of these interfaces, the responsible things
+// to would be:
+// - give them a new home
+// - convert them to AIDL instead of having manually written parceling code
+
+cc_library {
+    name: "libbatterystats_aidl",
+    srcs: [
+        "IBatteryStats.cpp",
+    ],
+    export_include_dirs: ["include_batterystats"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+}
+
+cc_library {
+    name: "libprocessinfoservice_aidl",
+    srcs: [
+        "IProcessInfoService.cpp",
+        "ProcessInfoService.cpp",
+    ],
+    export_include_dirs: ["include_processinfo"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "liblog",
+    ],
+}
+
+cc_library {
+    name: "libactivitymanager_aidl",
+    srcs: [
+        "ActivityManager.cpp",
+        "IActivityManager.cpp",
+        "IUidObserver.cpp",
+        ":activity_manager_procstate_aidl",
+    ],
+    export_include_dirs: ["include_activitymanager"],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "liblog",
+    ],
+    aidl: {
+        export_aidl_headers: true,
+    },
+}
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index d964d25..d5bdd1c 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -29,6 +29,16 @@
 
 namespace android {
 
+// Service implementations inherit from BBinder and IBinder, and this is frozen
+// in prebuilts.
+#ifdef __LP64__
+static_assert(sizeof(IBinder) == 24);
+static_assert(sizeof(BBinder) == 40);
+#else
+static_assert(sizeof(IBinder) == 12);
+static_assert(sizeof(BBinder) == 20);
+#endif
+
 // ---------------------------------------------------------------------------
 
 IBinder::IBinder()
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index bf4387a..1dcb94c 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -21,6 +21,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <binder/IResultReceiver.h>
+#include <binder/RpcSession.h>
 #include <binder/Stability.h>
 #include <cutils/compiler.h>
 #include <utils/Log.h>
@@ -106,8 +107,7 @@
 
 // ---------------------------------------------------------------------------
 
-
-BpBinder* BpBinder::create(int32_t handle) {
+sp<BpBinder> BpBinder::create(int32_t handle) {
     int32_t trackedUid = -1;
     if (sCountByUidEnabled) {
         trackedUid = IPCThreadState::self()->getCallingUid();
@@ -133,25 +133,56 @@
         }
         sTrackingMap[trackedUid]++;
     }
-    return new BpBinder(handle, trackedUid);
+    return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);
 }
 
-BpBinder::BpBinder(int32_t handle, int32_t trackedUid)
-    : mStability(0)
-    , mHandle(handle)
-    , mAlive(1)
-    , mObitsSent(0)
-    , mObituaries(nullptr)
-    , mTrackedUid(trackedUid)
-{
-    ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
+sp<BpBinder> BpBinder::create(const sp<RpcSession>& session, const RpcAddress& address) {
+    LOG_ALWAYS_FATAL_IF(session == nullptr, "BpBinder::create null session");
 
+    // These are not currently tracked, since there is no UID or other
+    // identifier to track them with. However, if similar functionality is
+    // needed, session objects keep track of all BpBinder objects on a
+    // per-session basis.
+
+    return sp<BpBinder>::make(RpcHandle{session, address});
+}
+
+BpBinder::BpBinder(Handle&& handle)
+      : mStability(0),
+        mHandle(handle),
+        mAlive(true),
+        mObitsSent(false),
+        mObituaries(nullptr),
+        mTrackedUid(-1) {
     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
-    IPCThreadState::self()->incWeakHandle(handle, this);
 }
 
-int32_t BpBinder::handle() const {
-    return mHandle;
+BpBinder::BpBinder(BinderHandle&& handle, int32_t trackedUid) : BpBinder(Handle(handle)) {
+    mTrackedUid = trackedUid;
+
+    ALOGV("Creating BpBinder %p handle %d\n", this, this->binderHandle());
+
+    IPCThreadState::self()->incWeakHandle(this->binderHandle(), this);
+}
+
+BpBinder::BpBinder(RpcHandle&& handle) : BpBinder(Handle(handle)) {
+    LOG_ALWAYS_FATAL_IF(rpcSession() == nullptr, "BpBinder created w/o session object");
+}
+
+bool BpBinder::isRpcBinder() const {
+    return std::holds_alternative<RpcHandle>(mHandle);
+}
+
+const RpcAddress& BpBinder::rpcAddress() const {
+    return std::get<RpcHandle>(mHandle).address;
+}
+
+const sp<RpcSession>& BpBinder::rpcSession() const {
+    return std::get<RpcHandle>(mHandle).session;
+}
+
+int32_t BpBinder::binderHandle() const {
+    return std::get<BinderHandle>(mHandle).handle;
 }
 
 bool BpBinder::isDescriptorCached() const {
@@ -162,10 +193,13 @@
 const String16& BpBinder::getInterfaceDescriptor() const
 {
     if (isDescriptorCached() == false) {
-        Parcel send, reply;
+        sp<BpBinder> thiz = sp<BpBinder>::fromExisting(const_cast<BpBinder*>(this));
+
+        Parcel data;
+        data.markForBinder(thiz);
+        Parcel reply;
         // do the IPC without a lock held.
-        status_t err = const_cast<BpBinder*>(this)->transact(
-                INTERFACE_TRANSACTION, send, &reply);
+        status_t err = thiz->transact(INTERFACE_TRANSACTION, data, &reply);
         if (err == NO_ERROR) {
             String16 res(reply.readString16());
             Mutex::Autolock _l(mLock);
@@ -190,9 +224,10 @@
 
 status_t BpBinder::pingBinder()
 {
-    Parcel send;
+    Parcel data;
+    data.markForBinder(sp<BpBinder>::fromExisting(this));
     Parcel reply;
-    return transact(PING_TRANSACTION, send, &reply);
+    return transact(PING_TRANSACTION, data, &reply);
 }
 
 status_t BpBinder::dump(int fd, const Vector<String16>& args)
@@ -228,15 +263,21 @@
                 : Stability::getLocalLevel();
 
             if (CC_UNLIKELY(!Stability::check(category, required))) {
-                ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
+                ALOGE("Cannot do a user transaction on a %s binder (%s) in a %s context.",
                     category.debugString().c_str(),
+                    String8(getInterfaceDescriptor()).c_str(),
                     Stability::levelString(required).c_str());
                 return BAD_TYPE;
             }
         }
 
-        status_t status = IPCThreadState::self()->transact(
-            mHandle, code, data, reply, flags);
+        status_t status;
+        if (CC_UNLIKELY(isRpcBinder())) {
+            status = rpcSession()->transact(rpcAddress(), code, data, reply, flags);
+        } else {
+            status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
+        }
+
         if (status == DEAD_OBJECT) mAlive = 0;
 
         return status;
@@ -249,6 +290,8 @@
 status_t BpBinder::linkToDeath(
     const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
 {
+    if (isRpcBinder()) return UNKNOWN_TRANSACTION;
+
     Obituary ob;
     ob.recipient = recipient;
     ob.cookie = cookie;
@@ -266,10 +309,10 @@
                 if (!mObituaries) {
                     return NO_MEMORY;
                 }
-                ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
+                ALOGV("Requesting death notification: %p handle %d\n", this, binderHandle());
                 getWeakRefs()->incWeak(this);
                 IPCThreadState* self = IPCThreadState::self();
-                self->requestDeathNotification(mHandle, this);
+                self->requestDeathNotification(binderHandle(), this);
                 self->flushCommands();
             }
             ssize_t res = mObituaries->add(ob);
@@ -285,6 +328,8 @@
     const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
     wp<DeathRecipient>* outRecipient)
 {
+    if (isRpcBinder()) return UNKNOWN_TRANSACTION;
+
     AutoMutex _l(mLock);
 
     if (mObitsSent) {
@@ -302,9 +347,9 @@
             }
             mObituaries->removeAt(i);
             if (mObituaries->size() == 0) {
-                ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
+                ALOGV("Clearing death notification: %p handle %d\n", this, binderHandle());
                 IPCThreadState* self = IPCThreadState::self();
-                self->clearDeathNotification(mHandle, this);
+                self->clearDeathNotification(binderHandle(), this);
                 self->flushCommands();
                 delete mObituaries;
                 mObituaries = nullptr;
@@ -318,8 +363,10 @@
 
 void BpBinder::sendObituary()
 {
-    ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
-        this, mHandle, mObitsSent ? "true" : "false");
+    LOG_ALWAYS_FATAL_IF(isRpcBinder(), "Cannot send obituary for remote binder.");
+
+    ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n", this, binderHandle(),
+          mObitsSent ? "true" : "false");
 
     mAlive = 0;
     if (mObitsSent) return;
@@ -327,9 +374,9 @@
     mLock.lock();
     Vector<Obituary>* obits = mObituaries;
     if(obits != nullptr) {
-        ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
+        ALOGV("Clearing sent death notification: %p handle %d\n", this, binderHandle());
         IPCThreadState* self = IPCThreadState::self();
-        self->clearDeathNotification(mHandle, this);
+        self->clearDeathNotification(binderHandle(), this);
         self->flushCommands();
         mObituaries = nullptr;
     }
@@ -355,7 +402,7 @@
     ALOGV("Reporting death to recipient: %p\n", recipient.get());
     if (recipient == nullptr) return;
 
-    recipient->binderDied(this);
+    recipient->binderDied(wp<BpBinder>::fromExisting(this));
 }
 
 
@@ -387,7 +434,9 @@
 
 BpBinder::~BpBinder()
 {
-    ALOGV("Destroying BpBinder %p handle %d\n", this, mHandle);
+    ALOGV("Destroying BpBinder %p handle %d\n", this, binderHandle());
+
+    if (CC_UNLIKELY(isRpcBinder())) return;
 
     IPCThreadState* ipc = IPCThreadState::self();
 
@@ -395,7 +444,8 @@
         AutoMutex _l(sTrackingLock);
         uint32_t trackedValue = sTrackingMap[mTrackedUid];
         if (CC_UNLIKELY((trackedValue & COUNTING_VALUE_MASK) == 0)) {
-            ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this, mHandle);
+            ALOGE("Unexpected Binder Proxy tracking decrement in %p handle %d\n", this,
+                  binderHandle());
         } else {
             if (CC_UNLIKELY(
                 (trackedValue & LIMIT_REACHED_MASK) &&
@@ -412,26 +462,31 @@
     }
 
     if (ipc) {
-        ipc->expungeHandle(mHandle, this);
-        ipc->decWeakHandle(mHandle);
+        ipc->expungeHandle(binderHandle(), this);
+        ipc->decWeakHandle(binderHandle());
     }
 }
 
 void BpBinder::onFirstRef()
 {
-    ALOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
+    ALOGV("onFirstRef BpBinder %p handle %d\n", this, binderHandle());
+    if (CC_UNLIKELY(isRpcBinder())) return;
     IPCThreadState* ipc = IPCThreadState::self();
-    if (ipc) ipc->incStrongHandle(mHandle, this);
+    if (ipc) ipc->incStrongHandle(binderHandle(), this);
 }
 
 void BpBinder::onLastStrongRef(const void* /*id*/)
 {
-    ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
+    ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, binderHandle());
+    if (CC_UNLIKELY(isRpcBinder())) {
+        (void)rpcSession()->sendDecStrong(rpcAddress());
+        return;
+    }
     IF_ALOGV() {
         printRefs();
     }
     IPCThreadState* ipc = IPCThreadState::self();
-    if (ipc) ipc->decStrongHandle(mHandle);
+    if (ipc) ipc->decStrongHandle(binderHandle());
 
     mLock.lock();
     Vector<Obituary>* obits = mObituaries;
@@ -441,7 +496,7 @@
                   mDescriptorCache.size() ? String8(mDescriptorCache).c_str() : "<uncached descriptor>");
         }
 
-        if (ipc) ipc->clearDeathNotification(mHandle, this);
+        if (ipc) ipc->clearDeathNotification(binderHandle(), this);
         mObituaries = nullptr;
     }
     mLock.unlock();
@@ -456,9 +511,12 @@
 
 bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
 {
-    ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
+    // RPC binder doesn't currently support inc from weak binders
+    if (CC_UNLIKELY(isRpcBinder())) return false;
+
+    ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, binderHandle());
     IPCThreadState* ipc = IPCThreadState::self();
-    return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
+    return ipc ? ipc->attemptIncStrongHandle(binderHandle()) == NO_ERROR : false;
 }
 
 uint32_t BpBinder::getBinderProxyCount(uint32_t uid)
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 88c85bf..a90bfd2 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "BufferedTextOutput.h"
-#include <binder/Debug.h>
 
 #include <cutils/atomic.h>
 #include <utils/Log.h>
@@ -26,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "Debug.h"
 #include "Static.h"
 
 // ---------------------------------------------------------------------------
@@ -254,7 +254,7 @@
         BufferState* bs = ts.states[mIndex].get();
         if (bs != nullptr && bs->seq == mSeq) return bs;
 
-        ts.states.editItemAt(mIndex) = new BufferState(mIndex);
+        ts.states.editItemAt(mIndex) = sp<BufferState>::make(mIndex);
         bs = ts.states[mIndex].get();
         if (bs != nullptr) return bs;
     }
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index 3a62059..8676955 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#include <binder/Debug.h>
+#include "Debug.h"
+
 #include <binder/ProcessState.h>
 
 #include <utils/misc.h>
@@ -25,6 +26,22 @@
 
 namespace android {
 
+std::string hexString(const void* bytes, size_t len) {
+    if (bytes == nullptr) return "<null>";
+
+    const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+    const char chars[] = "0123456789abcdef";
+    std::string result;
+    result.resize(len * 2);
+
+    for (size_t i = 0; i < len; i++) {
+        result[2 * i] = chars[bytes8[i] >> 4];
+        result[2 * i + 1] = chars[bytes8[i] & 0xf];
+    }
+
+    return result;
+}
+
 // ---------------------------------------------------------------------
 
 static const char indentStr[] =
diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/Debug.h
similarity index 89%
rename from libs/binder/include/binder/Debug.h
rename to libs/binder/Debug.h
index ac71e00..7ca087e 100644
--- a/libs/binder/include/binder/Debug.h
+++ b/libs/binder/Debug.h
@@ -17,13 +17,13 @@
 #pragma once
 
 #include <stdint.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
+#include <string>
 
 namespace android {
 // ---------------------------------------------------------------------------
 
-__BEGIN_DECLS
+std::string hexString(const void* data, size_t size);
 
 const char* stringForIndent(int32_t indentLevel);
 
@@ -37,10 +37,7 @@
     size_t alignment=0, bool cArrayStyle=false,
     debugPrintFunc func = nullptr, void* cookie = nullptr);
 
-
-ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
-
-__END_DECLS
+extern "C" ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
 
 // ---------------------------------------------------------------------------
 } // namespace android
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index d0085df..0de804c 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <binder/IBatteryStats.h>
+#include <batterystats/IBatteryStats.h>
 
 #include <utils/Log.h>
 #include <binder/Parcel.h>
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index b19004d..2780bd4 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -33,14 +33,14 @@
 sp<IBinder> IInterface::asBinder(const IInterface* iface)
 {
     if (iface == nullptr) return nullptr;
-    return const_cast<IInterface*>(iface)->onAsBinder();
+    return sp<IBinder>::fromExisting(const_cast<IInterface*>(iface)->onAsBinder());
 }
 
 // static
 sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
 {
     if (iface == nullptr) return nullptr;
-    return iface->onAsBinder();
+    return sp<IBinder>::fromExisting(iface->onAsBinder());
 }
 
 
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
deleted file mode 100644
index f5fa817..0000000
--- a/libs/binder/IMediaResourceMonitor.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2016 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 <binder/IMediaResourceMonitor.h>
-#include <binder/Parcel.h>
-#include <utils/Errors.h>
-#include <sys/types.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class BpMediaResourceMonitor : public BpInterface<IMediaResourceMonitor> {
-public:
-    explicit BpMediaResourceMonitor(const sp<IBinder>& impl)
-        : BpInterface<IMediaResourceMonitor>(impl) {}
-
-    virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaResourceMonitor::getInterfaceDescriptor());
-        data.writeInt32(pid);
-        data.writeInt32(type);
-        remote()->transact(NOTIFY_RESOURCE_GRANTED, data, &reply, IBinder::FLAG_ONEWAY);
-    }
-};
-
-IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor")
-
-// ----------------------------------------------------------------------
-
-// NOLINTNEXTLINE(google-default-arguments)
-status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
-        uint32_t flags) {
-    switch(code) {
-        case NOTIFY_RESOURCE_GRANTED: {
-            CHECK_INTERFACE(IMediaResourceMonitor, data, reply);
-            int32_t pid = data.readInt32();
-            const int32_t type = data.readInt32();
-            notifyResourceGranted(/*in*/ pid, /*in*/ type);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------
-
-} // namespace android
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index cca8f81..bd974b0 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -68,7 +68,7 @@
     // TODO: Reimplemement based on standard C++ container?
 };
 
-static sp<HeapCache> gHeapCache = new HeapCache();
+static sp<HeapCache> gHeapCache = sp<HeapCache>::make();
 
 /******************************************************************************/
 
@@ -288,7 +288,7 @@
     int32_t heapId = mHeapId.load(memory_order_acquire);
     if (heapId == -1) {
         sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
-        sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
+        sp<BpMemoryHeap> heap = sp<BpMemoryHeap>::cast(find_heap(binder));
         heap->assertReallyMapped();
         if (heap->mBase != MAP_FAILED) {
             Mutex::Autolock _l(mLock);
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 7d01e0b..ef7fd44 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -29,8 +29,6 @@
 #include <utils/SystemClock.h>
 #include <utils/threads.h>
 
-#include <private/binder/binder_module.h>
-
 #include <atomic>
 #include <errno.h>
 #include <inttypes.h>
@@ -43,6 +41,7 @@
 #include <unistd.h>
 
 #include "Static.h"
+#include "binder_module.h"
 
 #if LOG_NDEBUG
 
@@ -90,6 +89,8 @@
     "BR_DEAD_BINDER",
     "BR_CLEAR_DEATH_NOTIFICATION_DONE",
     "BR_FAILED_REPLY",
+    "BR_FROZEN_REPLY",
+    "BR_ONEWAY_SPAM_SUSPECT",
     "BR_TRANSACTION_SEC_CTX",
 };
 
@@ -486,15 +487,30 @@
     }
 }
 
+bool IPCThreadState::flushIfNeeded()
+{
+    if (mIsLooper || mServingStackPointer != nullptr) {
+        return false;
+    }
+    // In case this thread is not a looper and is not currently serving a binder transaction,
+    // there's no guarantee that this thread will call back into the kernel driver any time
+    // soon. Therefore, flush pending commands such as BC_FREE_BUFFER, to prevent them from getting
+    // stuck in this thread's out buffer.
+    flushCommands();
+    return true;
+}
+
 void IPCThreadState::blockUntilThreadAvailable()
 {
     pthread_mutex_lock(&mProcess->mThreadCountLock);
+    mProcess->mWaitingForThreads++;
     while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) {
         ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n",
                 static_cast<unsigned long>(mProcess->mExecutingThreadsCount),
                 static_cast<unsigned long>(mProcess->mMaxThreads));
         pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock);
     }
+    mProcess->mWaitingForThreads--;
     pthread_mutex_unlock(&mProcess->mThreadCountLock);
 }
 
@@ -534,7 +550,12 @@
             }
             mProcess->mStarvationStartTimeMs = 0;
         }
-        pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
+
+        // Cond broadcast can be expensive, so don't send it every time a binder
+        // call is processed. b/168806193
+        if (mProcess->mWaitingForThreads > 0) {
+            pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
+        }
         pthread_mutex_unlock(&mProcess->mThreadCountLock);
     }
 
@@ -591,12 +612,19 @@
     mPostWriteStrongDerefs.clear();
 }
 
+void IPCThreadState::createTransactionReference(RefBase* ref)
+{
+    ref->incStrong(mProcess.get());
+    mPostWriteStrongDerefs.push(ref);
+}
+
 void IPCThreadState::joinThreadPool(bool isMain)
 {
     LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
 
     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
 
+    mIsLooper = true;
     status_t result;
     do {
         processPendingDerefs();
@@ -619,6 +647,7 @@
         (void*)pthread_self(), getpid(), result);
 
     mOut.writeInt32(BC_EXIT_LOOPER);
+    mIsLooper = false;
     talkWithDriver(false);
 }
 
@@ -629,6 +658,7 @@
     }
 
     mOut.writeInt32(BC_ENTER_LOOPER);
+    flushCommands();
     *fd = mProcess->mDriverFD;
     return 0;
 }
@@ -660,6 +690,8 @@
                                   uint32_t code, const Parcel& data,
                                   Parcel* reply, uint32_t flags)
 {
+    LOG_ALWAYS_FATAL_IF(data.isForRpc(), "Parcel constructed for RPC, but being used with binder.");
+
     status_t err;
 
     flags |= TF_ACCEPT_FDS;
@@ -731,9 +763,11 @@
     LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle);
     mOut.writeInt32(BC_ACQUIRE);
     mOut.writeInt32(handle);
-    // Create a temp reference until the driver has handled this command.
-    proxy->incStrong(mProcess.get());
-    mPostWriteStrongDerefs.push(proxy);
+    if (!flushIfNeeded()) {
+        // Create a temp reference until the driver has handled this command.
+        proxy->incStrong(mProcess.get());
+        mPostWriteStrongDerefs.push(proxy);
+    }
 }
 
 void IPCThreadState::decStrongHandle(int32_t handle)
@@ -741,6 +775,7 @@
     LOG_REMOTEREFS("IPCThreadState::decStrongHandle(%d)\n", handle);
     mOut.writeInt32(BC_RELEASE);
     mOut.writeInt32(handle);
+    flushIfNeeded();
 }
 
 void IPCThreadState::incWeakHandle(int32_t handle, BpBinder *proxy)
@@ -748,9 +783,11 @@
     LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
     mOut.writeInt32(BC_INCREFS);
     mOut.writeInt32(handle);
-    // Create a temp reference until the driver has handled this command.
-    proxy->getWeakRefs()->incWeak(mProcess.get());
-    mPostWriteWeakDerefs.push(proxy->getWeakRefs());
+    if (!flushIfNeeded()) {
+        // Create a temp reference until the driver has handled this command.
+        proxy->getWeakRefs()->incWeak(mProcess.get());
+        mPostWriteWeakDerefs.push(proxy->getWeakRefs());
+    }
 }
 
 void IPCThreadState::decWeakHandle(int32_t handle)
@@ -758,6 +795,7 @@
     LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle);
     mOut.writeInt32(BC_DECREFS);
     mOut.writeInt32(handle);
+    flushIfNeeded();
 }
 
 status_t IPCThreadState::attemptIncStrongHandle(int32_t handle)
@@ -813,6 +851,7 @@
       mServingStackPointer(nullptr),
       mWorkSource(kUnsetWorkSource),
       mPropagateWorkSource(false),
+      mIsLooper(false),
       mStrictModePolicy(0),
       mLastTransactionBinderFlags(0),
       mCallRestriction(mProcess->mCallRestriction)
@@ -856,6 +895,11 @@
         }
 
         switch (cmd) {
+        case BR_ONEWAY_SPAM_SUSPECT:
+            ALOGE("Process seems to be sending too many oneway calls.");
+            CallStack::logStack("oneway spamming", CallStack::getCurrent().get(),
+                    ANDROID_LOG_ERROR);
+            [[fallthrough]];
         case BR_TRANSACTION_COMPLETE:
             if (!reply && !acquireResult) goto finish;
             break;
@@ -1393,6 +1437,7 @@
     IPCThreadState* state = self();
     state->mOut.writeInt32(BC_FREE_BUFFER);
     state->mOut.writePointer((uintptr_t)data);
+    state->flushIfNeeded();
 }
 
 } // namespace android
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index 570edb9..d26754e 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <binder/IProcessInfoService.h>
+#include <processinfo/IProcessInfoService.h>
 #include <binder/Parcel.h>
 #include <utils/Errors.h>
 #include <sys/types.h>
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index ca067e2..f684cf6 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -75,6 +75,7 @@
     sp<IBinder> waitForService(const String16& name16) override;
     bool isDeclared(const String16& name) override;
     Vector<String16> getDeclaredInstances(const String16& interface) override;
+    std::optional<String16> updatableViaApex(const String16& name) override;
 
     // for legacy ABI
     const String16& getInterfaceDescriptor() const override {
@@ -102,7 +103,7 @@
             }
         }
 
-        gDefaultServiceManager = new ServiceManagerShim(sm);
+        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
     });
 
     return gDefaultServiceManager;
@@ -324,7 +325,7 @@
     }
     if (out != nullptr) return out;
 
-    sp<Waiter> waiter = new Waiter;
+    sp<Waiter> waiter = sp<Waiter>::make();
     if (!mTheRealServiceManager->registerForNotifications(
             name, waiter).isOk()) {
         return nullptr;
@@ -388,4 +389,12 @@
     return res;
 }
 
+std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) {
+    std::optional<std::string> declared;
+    if (!mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared).isOk()) {
+        return std::nullopt;
+    }
+    return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
+}
+
 } // namespace android
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
deleted file mode 100644
index 8d62266..0000000
--- a/libs/binder/IpPrefix.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-#define LOG_TAG "IpPrefix"
-
-#include <binder/IpPrefix.h>
-#include <vector>
-
-#include <binder/IBinder.h>
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-
-using android::BAD_TYPE;
-using android::BAD_VALUE;
-using android::NO_ERROR;
-using android::Parcel;
-using android::status_t;
-using android::UNEXPECTED_NULL;
-
-namespace android {
-
-namespace net {
-
-#define RETURN_IF_FAILED(calledOnce)                                     \
-    {                                                                    \
-        status_t returnStatus = calledOnce;                              \
-        if (returnStatus) {                                              \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return returnStatus;                                         \
-         }                                                               \
-    }
-
-status_t IpPrefix::writeToParcel(Parcel* parcel) const {
-    /*
-     * Keep implementation in sync with writeToParcel() in
-     * frameworks/base/core/java/android/net/IpPrefix.java.
-     */
-    std::vector<uint8_t> byte_vector;
-
-    if (mIsIpv6) {
-        const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mIn6Addr);
-        byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
-    } else {
-        const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mInAddr);
-        byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
-    }
-
-    RETURN_IF_FAILED(parcel->writeByteVector(byte_vector));
-    RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(mPrefixLength)));
-
-    return NO_ERROR;
-}
-
-status_t IpPrefix::readFromParcel(const Parcel* parcel) {
-    /*
-     * Keep implementation in sync with readFromParcel() in
-     * frameworks/base/core/java/android/net/IpPrefix.java.
-     */
-    std::vector<uint8_t> byte_vector;
-
-    RETURN_IF_FAILED(parcel->readByteVector(&byte_vector));
-    RETURN_IF_FAILED(parcel->readInt32(&mPrefixLength));
-
-    if (byte_vector.size() == 16) {
-        mIsIpv6 = true;
-        memcpy((void*)&mUnion.mIn6Addr, &byte_vector[0], sizeof(mUnion.mIn6Addr));
-
-    } else if (byte_vector.size() == 4) {
-        mIsIpv6 = false;
-        memcpy((void*)&mUnion.mInAddr, &byte_vector[0], sizeof(mUnion.mInAddr));
-
-    } else {
-        ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-        return BAD_VALUE;
-    }
-
-    return NO_ERROR;
-}
-
-const struct in6_addr& IpPrefix::getAddressAsIn6Addr() const
-{
-    return mUnion.mIn6Addr;
-}
-
-const struct in_addr& IpPrefix::getAddressAsInAddr() const
-{
-    return mUnion.mInAddr;
-}
-
-bool IpPrefix::getAddressAsIn6Addr(struct in6_addr* addr) const
-{
-    if (isIpv6()) {
-        *addr = mUnion.mIn6Addr;
-        return true;
-    }
-    return false;
-}
-
-bool IpPrefix::getAddressAsInAddr(struct in_addr* addr) const
-{
-    if (isIpv4()) {
-        *addr = mUnion.mInAddr;
-        return true;
-    }
-    return false;
-}
-
-bool IpPrefix::isIpv6() const
-{
-    return mIsIpv6;
-}
-
-bool IpPrefix::isIpv4() const
-{
-    return !mIsIpv6;
-}
-
-int32_t IpPrefix::getPrefixLength() const
-{
-    return mPrefixLength;
-}
-
-void IpPrefix::setAddress(const struct in6_addr& addr)
-{
-    mUnion.mIn6Addr = addr;
-    mIsIpv6 = true;
-}
-
-void IpPrefix::setAddress(const struct in_addr& addr)
-{
-    mUnion.mInAddr = addr;
-    mIsIpv6 = false;
-}
-
-void IpPrefix::setPrefixLength(int32_t prefix)
-{
-    mPrefixLength = prefix;
-}
-
-bool operator==(const IpPrefix& lhs, const IpPrefix& rhs)
-{
-    if (lhs.mIsIpv6 != rhs.mIsIpv6) {
-        return false;
-    }
-
-    if (lhs.mPrefixLength != rhs.mPrefixLength) {
-        return false;
-    }
-
-    if (lhs.mIsIpv6) {
-        return 0 == memcmp(lhs.mUnion.mIn6Addr.s6_addr, rhs.mUnion.mIn6Addr.s6_addr, sizeof(struct in6_addr));
-    }
-
-    return 0 == memcmp(&lhs.mUnion.mInAddr, &rhs.mUnion.mInAddr, sizeof(struct in_addr));
-}
-
-}  // namespace net
-
-}  // namespace android
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index 325e204..6165911 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "log/log_main.h"
 #define LOG_TAG "AidlLazyServiceRegistrar"
 
 #include <binder/LazyServiceRegistrar.h>
@@ -29,18 +30,20 @@
 
 using AidlServiceManager = android::os::IServiceManager;
 
-class ClientCounterCallback : public ::android::os::BnClientCallback {
+class ClientCounterCallbackImpl : public ::android::os::BnClientCallback {
 public:
-    ClientCounterCallback() : mNumConnectedServices(0), mForcePersist(false) {}
+    ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {}
 
     bool registerService(const sp<IBinder>& service, const std::string& name,
                          bool allowIsolated, int dumpFlags);
-
-    /**
-     * Set a flag to prevent services from automatically shutting down
-     */
     void forcePersist(bool persist);
 
+    void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
+
+    bool tryUnregister();
+
+    void reRegister();
+
 protected:
     Status onClients(const sp<IBinder>& service, bool clients) override;
 
@@ -53,6 +56,7 @@
         // whether, based on onClients calls, we know we have a client for this
         // service or not
         bool clients = false;
+        bool registered = true;
     };
 
     /**
@@ -66,16 +70,52 @@
      */
     void tryShutdown();
 
+    /**
+     * Try to shutdown the process, unless:
+     * - 'forcePersist' is 'true', or
+     * - The active services count callback returns 'true', or
+     * - Some services have clients.
+     */
+    void maybeTryShutdown();
+
     // count of services with clients
     size_t mNumConnectedServices;
 
+    // previous value passed to the active services callback
+    std::optional<bool> mPreviousHasClients;
+
     // map of registered names and services
     std::map<std::string, Service> mRegisteredServices;
 
     bool mForcePersist;
+
+    // Callback used to report if there are services with clients
+    std::function<bool(bool)> mActiveServicesCallback;
 };
 
-bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
+class ClientCounterCallback {
+public:
+    ClientCounterCallback();
+
+    bool registerService(const sp<IBinder>& service, const std::string& name,
+                                            bool allowIsolated, int dumpFlags);
+
+    /**
+     * Set a flag to prevent services from automatically shutting down
+     */
+    void forcePersist(bool persist);
+
+    void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
+
+    bool tryUnregister();
+
+    void reRegister();
+
+private:
+    sp<ClientCounterCallbackImpl> mImpl;
+};
+
+bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name,
                                             bool allowIsolated, int dumpFlags) {
     auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
 
@@ -83,14 +123,20 @@
     std::string regStr = (reRegister) ? "Re-registering" : "Registering";
     ALOGI("%s service %s", regStr.c_str(), name.c_str());
 
-    if (!manager->addService(name.c_str(), service, allowIsolated, dumpFlags).isOk()) {
-        ALOGE("Failed to register service %s", name.c_str());
+    if (Status status = manager->addService(name.c_str(), service, allowIsolated, dumpFlags);
+        !status.isOk()) {
+        ALOGE("Failed to register service %s (%s)", name.c_str(), status.toString8().c_str());
         return false;
     }
 
     if (!reRegister) {
-        if (!manager->registerClientCallback(name, service, this).isOk()) {
-            ALOGE("Failed to add client callback for service %s", name.c_str());
+        if (Status status =
+                    manager->registerClientCallback(name, service,
+                                                    sp<android::os::IClientCallback>::fromExisting(
+                                                            this));
+            !status.isOk()) {
+            ALOGE("Failed to add client callback for service %s (%s)", name.c_str(),
+                  status.toString8().c_str());
             return false;
         }
 
@@ -105,7 +151,7 @@
     return true;
 }
 
-std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) {
+std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) {
     LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service");
     for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) {
         auto const& [name, registered] = *it;
@@ -117,10 +163,66 @@
     __builtin_unreachable();
 }
 
-void ClientCounterCallback::forcePersist(bool persist) {
+void ClientCounterCallbackImpl::forcePersist(bool persist) {
     mForcePersist = persist;
-    if(!mForcePersist) {
+    if (!mForcePersist) {
         // Attempt a shutdown in case the number of clients hit 0 while the flag was on
+        maybeTryShutdown();
+    }
+}
+
+bool ClientCounterCallbackImpl::tryUnregister() {
+    auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
+
+    for (auto& [name, entry] : mRegisteredServices) {
+        Status status = manager->tryUnregisterService(name, entry.service);
+
+        if (!status.isOk()) {
+            ALOGI("Failed to unregister service %s (%s)", name.c_str(), status.toString8().c_str());
+            return false;
+        }
+        entry.registered = false;
+    }
+
+    return true;
+}
+
+void ClientCounterCallbackImpl::reRegister() {
+    for (auto& [name, entry] : mRegisteredServices) {
+        // re-register entry if not already registered
+        if (entry.registered) {
+            continue;
+        }
+
+        if (!registerService(entry.service, name, entry.allowIsolated,
+                             entry.dumpFlags)) {
+            // Must restart. Otherwise, clients will never be able to get a hold of this service.
+            LOG_ALWAYS_FATAL("Bad state: could not re-register services");
+        }
+
+        entry.registered = true;
+    }
+}
+
+void ClientCounterCallbackImpl::maybeTryShutdown() {
+    if (mForcePersist) {
+        ALOGI("Shutdown prevented by forcePersist override flag.");
+        return;
+    }
+
+    bool handledInCallback = false;
+    if (mActiveServicesCallback != nullptr) {
+        bool hasClients = mNumConnectedServices != 0;
+        if (hasClients != mPreviousHasClients) {
+            handledInCallback = mActiveServicesCallback(hasClients);
+            mPreviousHasClients = hasClients;
+        }
+    }
+
+    // If there is no callback defined or the callback did not handle this
+    // client count change event, try to shutdown the process if its services
+    // have no clients.
+    if (!handledInCallback && mNumConnectedServices == 0) {
         tryShutdown();
     }
 }
@@ -129,7 +231,7 @@
  * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
  * invocations could occur on different threads however.
  */
-Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) {
+Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) {
     auto & [name, registered] = *assertRegisteredService(service);
     if (registered.clients == clients) {
         LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has "
@@ -150,54 +252,50 @@
     ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
           mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
 
-    tryShutdown();
+    maybeTryShutdown();
     return Status::ok();
 }
 
-void ClientCounterCallback::tryShutdown() {
-    if(mNumConnectedServices > 0) {
-        // Should only shut down if there are no clients
-        return;
-    }
+ void ClientCounterCallbackImpl::tryShutdown() {
+     ALOGI("Trying to shut down the service. No clients in use for any service in process.");
 
-    if(mForcePersist) {
-        ALOGI("Shutdown prevented by forcePersist override flag.");
-        return;
-    }
+    if (tryUnregister()) {
+         ALOGI("Unregistered all clients and exiting");
+         exit(EXIT_SUCCESS);
+     }
 
-    ALOGI("Trying to shut down the service. No clients in use for any service in process.");
+    reRegister();
+}
 
-    auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
+void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>&
+                                                          activeServicesCallback) {
+    mActiveServicesCallback = activeServicesCallback;
+}
 
-    auto unRegisterIt = mRegisteredServices.begin();
-    for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
-        auto& entry = (*unRegisterIt);
+ClientCounterCallback::ClientCounterCallback() {
+      mImpl = sp<ClientCounterCallbackImpl>::make();
+}
 
-        bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk();
+bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
+                                            bool allowIsolated, int dumpFlags) {
+    return mImpl->registerService(service, name, allowIsolated, dumpFlags);
+}
 
+void ClientCounterCallback::forcePersist(bool persist) {
+    mImpl->forcePersist(persist);
+}
 
-        if (!success) {
-            ALOGI("Failed to unregister service %s", entry.first.c_str());
-            break;
-        }
-    }
+void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>&
+                                                      activeServicesCallback) {
+    mImpl->setActiveServicesCallback(activeServicesCallback);
+}
 
-    if (unRegisterIt == mRegisteredServices.end()) {
-        ALOGI("Unregistered all clients and exiting");
-        exit(EXIT_SUCCESS);
-    }
+bool ClientCounterCallback::tryUnregister() {
+    return mImpl->tryUnregister();
+}
 
-    for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
-         reRegisterIt++) {
-        auto& entry = (*reRegisterIt);
-
-        // re-register entry
-        if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated,
-                             entry.second.dumpFlags)) {
-            // Must restart. Otherwise, clients will never be able to get a hold of this service.
-            ALOGE("Bad state: could not re-register services");
-        }
-    }
+void ClientCounterCallback::reRegister() {
+    mImpl->reRegister();
 }
 
 }  // namespace internal
@@ -223,5 +321,18 @@
     mClientCC->forcePersist(persist);
 }
 
+void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>&
+                                                     activeServicesCallback) {
+    mClientCC->setActiveServicesCallback(activeServicesCallback);
+}
+
+bool LazyServiceRegistrar::tryUnregister() {
+    return mClientCC->tryUnregister();
+}
+
+void LazyServiceRegistrar::reRegister() {
+    mClientCC->reRegister();
+}
+
 }  // namespace hardware
 }  // namespace android
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index b46b3e8..c4475c7 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -228,10 +228,8 @@
 // ----------------------------------------------------------------------------
 
 MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
-    : mHeap(new MemoryHeapBase(size, flags, name)),
-    mAllocator(new SimpleBestFitAllocator(size))
-{    
-}
+      : mHeap(sp<MemoryHeapBase>::make(size, flags, name)),
+        mAllocator(new SimpleBestFitAllocator(size)) {}
 
 MemoryDealer::~MemoryDealer()
 {
@@ -243,7 +241,7 @@
     sp<IMemory> memory;
     const ssize_t offset = allocator()->allocate(size);
     if (offset >= 0) {
-        memory = new Allocation(this, heap(), offset, size);
+        memory = sp<Allocation>::make(sp<MemoryDealer>::fromExisting(this), heap(), offset, size);
     }
     return memory;
 }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9bba369..e4dfa52 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -41,15 +41,17 @@
 #include <binder/TextOutput.h>
 
 #include <cutils/ashmem.h>
+#include <cutils/compiler.h>
 #include <utils/Flattenable.h>
 #include <utils/Log.h>
-#include <utils/misc.h>
-#include <utils/String8.h>
 #include <utils/String16.h>
+#include <utils/String8.h>
+#include <utils/misc.h>
 
-#include <private/binder/binder_module.h>
+#include "RpcState.h"
 #include "Static.h"
 #include "Utils.h"
+#include "binder_module.h"
 
 #define LOG_REFS(...)
 //#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
@@ -76,7 +78,11 @@
 namespace android {
 
 // many things compile this into prebuilts on the stack
-static_assert(sizeof(Parcel) == 60 || sizeof(Parcel) == 120);
+#ifdef __LP64__
+static_assert(sizeof(Parcel) == 120);
+#else
+static_assert(sizeof(Parcel) == 60);
+#endif
 
 static std::atomic<size_t> gParcelGlobalAllocCount;
 static std::atomic<size_t> gParcelGlobalAllocSize;
@@ -191,6 +197,22 @@
 
 status_t Parcel::flattenBinder(const sp<IBinder>& binder)
 {
+    if (isForRpc()) {
+        if (binder) {
+            status_t status = writeInt32(1); // non-null
+            if (status != OK) return status;
+            RpcAddress address = RpcAddress::zero();
+            status = mSession->state()->onBinderLeaving(mSession, binder, &address);
+            if (status != OK) return status;
+            status = address.writeToParcel(this);
+            if (status != OK) return status;
+        } else {
+            status_t status = writeInt32(0); // null
+            if (status != OK) return status;
+        }
+        return finishFlattenBinder(binder);
+    }
+
     flat_binder_object obj;
     obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
 
@@ -205,8 +227,13 @@
             BpBinder *proxy = binder->remoteBinder();
             if (proxy == nullptr) {
                 ALOGE("null proxy");
+            } else {
+                if (proxy->isRpcBinder()) {
+                    ALOGE("Sending a socket binder over RPC is prohibited");
+                    return INVALID_OPERATION;
+                }
             }
-            const int32_t handle = proxy ? proxy->getPrivateAccessorForHandle().handle() : 0;
+            const int32_t handle = proxy ? proxy->getPrivateAccessorForId().binderHandle() : 0;
             obj.hdr.type = BINDER_TYPE_HANDLE;
             obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
             obj.handle = handle;
@@ -245,12 +272,32 @@
 
 status_t Parcel::unflattenBinder(sp<IBinder>* out) const
 {
+    if (isForRpc()) {
+        LOG_ALWAYS_FATAL_IF(mSession == nullptr, "RpcSession required to read from remote parcel");
+
+        int32_t isNull;
+        status_t status = readInt32(&isNull);
+        if (status != OK) return status;
+
+        sp<IBinder> binder;
+
+        if (isNull & 1) {
+            auto addr = RpcAddress::zero();
+            status_t status = addr.readFromParcel(*this);
+            if (status != OK) return status;
+            binder = mSession->state()->onBinderEntering(mSession, addr);
+        }
+
+        return finishUnflattenBinder(binder, out);
+    }
+
     const flat_binder_object* flat = readObject(false);
 
     if (flat) {
         switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER: {
-                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
+                sp<IBinder> binder =
+                        sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie));
                 return finishUnflattenBinder(binder, out);
             }
             case BINDER_TYPE_HANDLE: {
@@ -375,6 +422,11 @@
 
 status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len)
 {
+    if (parcel->isForRpc() != isForRpc()) {
+        ALOGE("Cannot append Parcel of one format to another.");
+        return BAD_TYPE;
+    }
+
     status_t err;
     const uint8_t *data = parcel->mData;
     const binder_size_t *objects = parcel->mObjects;
@@ -511,6 +563,26 @@
     mDeallocZero = true;
 }
 
+void Parcel::markForBinder(const sp<IBinder>& binder) {
+    LOG_ALWAYS_FATAL_IF(mData != nullptr, "format must be set before data is written");
+
+    if (binder && binder->remoteBinder() && binder->remoteBinder()->isRpcBinder()) {
+        markForRpc(binder->remoteBinder()->getPrivateAccessorForId().rpcSession());
+    }
+}
+
+void Parcel::markForRpc(const sp<RpcSession>& session) {
+    LOG_ALWAYS_FATAL_IF(mData != nullptr && mOwner == nullptr,
+                        "format must be set before data is written OR on IPC data");
+
+    LOG_ALWAYS_FATAL_IF(session == nullptr, "markForRpc requires session");
+    mSession = session;
+}
+
+bool Parcel::isForRpc() const {
+    return mSession != nullptr;
+}
+
 void Parcel::updateWorkSourceRequestHeaderPosition() const {
     // Only update the request headers once. We only want to point
     // to the first headers read/written.
@@ -533,12 +605,14 @@
 }
 
 status_t Parcel::writeInterfaceToken(const char16_t* str, size_t len) {
-    const IPCThreadState* threadState = IPCThreadState::self();
-    writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
-    updateWorkSourceRequestHeaderPosition();
-    writeInt32(threadState->shouldPropagateWorkSource() ?
-            threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
-    writeInt32(kHeader);
+    if (CC_LIKELY(!isForRpc())) {
+        const IPCThreadState* threadState = IPCThreadState::self();
+        writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
+        updateWorkSourceRequestHeaderPosition();
+        writeInt32(threadState->shouldPropagateWorkSource() ? threadState->getCallingWorkSourceUid()
+                                                            : IPCThreadState::kUnsetWorkSource);
+        writeInt32(kHeader);
+    }
 
     // currently the interface identification token is just its name as a string
     return writeString16(str, len);
@@ -585,31 +659,34 @@
                               size_t len,
                               IPCThreadState* threadState) const
 {
-    // StrictModePolicy.
-    int32_t strictPolicy = readInt32();
-    if (threadState == nullptr) {
-        threadState = IPCThreadState::self();
+    if (CC_LIKELY(!isForRpc())) {
+        // StrictModePolicy.
+        int32_t strictPolicy = readInt32();
+        if (threadState == nullptr) {
+            threadState = IPCThreadState::self();
+        }
+        if ((threadState->getLastTransactionBinderFlags() & IBinder::FLAG_ONEWAY) != 0) {
+            // For one-way calls, the callee is running entirely
+            // disconnected from the caller, so disable StrictMode entirely.
+            // Not only does disk/network usage not impact the caller, but
+            // there's no way to communicate back violations anyway.
+            threadState->setStrictModePolicy(0);
+        } else {
+            threadState->setStrictModePolicy(strictPolicy);
+        }
+        // WorkSource.
+        updateWorkSourceRequestHeaderPosition();
+        int32_t workSource = readInt32();
+        threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
+        // vendor header
+        int32_t header = readInt32();
+        if (header != kHeader) {
+            ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader,
+                  header);
+            return false;
+        }
     }
-    if ((threadState->getLastTransactionBinderFlags() &
-         IBinder::FLAG_ONEWAY) != 0) {
-      // For one-way calls, the callee is running entirely
-      // disconnected from the caller, so disable StrictMode entirely.
-      // Not only does disk/network usage not impact the caller, but
-      // there's no way to commuicate back any violations anyway.
-      threadState->setStrictModePolicy(0);
-    } else {
-      threadState->setStrictModePolicy(strictPolicy);
-    }
-    // WorkSource.
-    updateWorkSourceRequestHeaderPosition();
-    int32_t workSource = readInt32();
-    threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
-    // vendor header
-    int32_t header = readInt32();
-    if (header != kHeader) {
-        ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header);
-        return false;
-    }
+
     // Interface descriptor.
     size_t parcel_interface_len;
     const char16_t* parcel_interface = readString16Inplace(&parcel_interface_len);
@@ -769,200 +846,116 @@
     return NO_ERROR;
 }
 
-status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) {
-  if (!str) {
-    return writeInt32(-1);
-  }
-  return writeUtf8AsUtf16(*str);
-}
 
-status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {
-  if (!str) {
-    return writeInt32(-1);
-  }
-  return writeUtf8AsUtf16(*str);
-}
+status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) { return writeData(str); }
+status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) { return writeData(str); }
 
-status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
-    if (size > std::numeric_limits<int32_t>::max()) {
-        return BAD_VALUE;
-    }
+status_t Parcel::writeString16(const std::optional<String16>& str) { return writeData(str); }
+status_t Parcel::writeString16(const std::unique_ptr<String16>& str) { return writeData(str); }
 
-    status_t status = writeInt32(size);
-    if (status != OK) {
-        return status;
-    }
+status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val) { return writeData(val); }
+status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val){ return writeData(val); }
+status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) { return writeData(val); }
+status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val) { return writeData(val); }
+status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) { return writeData(val); }
+status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val) { return writeData(val); }
+status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val) { return writeData(val); }
+status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) { return writeData(val); }
+status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val) { return writeData(val); }
+status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val) { return writeData(val); }
+status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) { return writeData(val); }
+status_t Parcel::writeFloatVector(const std::vector<float>& val) { return writeData(val); }
+status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val) { return writeData(val); }
+status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val) { return writeData(val); }
+status_t Parcel::writeDoubleVector(const std::vector<double>& val) { return writeData(val); }
+status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val) { return writeData(val); }
+status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) { return writeData(val); }
+status_t Parcel::writeBoolVector(const std::vector<bool>& val) { return writeData(val); }
+status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val) { return writeData(val); }
+status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) { return writeData(val); }
+status_t Parcel::writeCharVector(const std::vector<char16_t>& val) { return writeData(val); }
+status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val) { return writeData(val); }
+status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) { return writeData(val); }
 
-    return write(data, size);
-}
-
-status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
-    return writeByteVectorInternal(val.data(), val.size());
-}
-
-status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val)
-{
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(val->data(), val->size());
-}
-
-status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
-{
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(val->data(), val->size());
-}
-
-status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
-}
-
-status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val)
-{
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-
-status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
-{
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-
-status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
-{
-    return writeTypedVector(val, &Parcel::writeInt32);
-}
-
-status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeInt32);
-}
-
-status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeInt32);
-}
-
-status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
-{
-    return writeTypedVector(val, &Parcel::writeInt64);
-}
-
-status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeInt64);
-}
-
-status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeInt64);
-}
-
-status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val)
-{
-    return writeTypedVector(val, &Parcel::writeUint64);
-}
-
-status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeUint64);
-}
-
-status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeUint64);
-}
-
-status_t Parcel::writeFloatVector(const std::vector<float>& val)
-{
-    return writeTypedVector(val, &Parcel::writeFloat);
-}
-
-status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeFloat);
-}
-
-status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeFloat);
-}
-
-status_t Parcel::writeDoubleVector(const std::vector<double>& val)
-{
-    return writeTypedVector(val, &Parcel::writeDouble);
-}
-
-status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeDouble);
-}
-
-status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeDouble);
-}
-
-status_t Parcel::writeBoolVector(const std::vector<bool>& val)
-{
-    return writeTypedVector(val, &Parcel::writeBool);
-}
-
-status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeBool);
-}
-
-status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeBool);
-}
-
-status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
-{
-    return writeTypedVector(val, &Parcel::writeChar);
-}
-
-status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeChar);
-}
-
-status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeChar);
-}
-
-status_t Parcel::writeString16Vector(const std::vector<String16>& val)
-{
-    return writeTypedVector(val, &Parcel::writeString16);
-}
-
+status_t Parcel::writeString16Vector(const std::vector<String16>& val) { return writeData(val); }
 status_t Parcel::writeString16Vector(
-        const std::optional<std::vector<std::optional<String16>>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeString16);
-}
-
+        const std::optional<std::vector<std::optional<String16>>>& val) { return writeData(val); }
 status_t Parcel::writeString16Vector(
-        const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeString16);
-}
-
+        const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) { return writeData(val); }
 status_t Parcel::writeUtf8VectorAsUtf16Vector(
-                        const std::optional<std::vector<std::optional<std::string>>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16);
-}
-
+                        const std::optional<std::vector<std::optional<std::string>>>& val) { return writeData(val); }
 status_t Parcel::writeUtf8VectorAsUtf16Vector(
-                        const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16);
-}
+                        const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) { return writeData(val); }
+status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) { return writeData(val); }
 
-status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) {
-    return writeTypedVector(val, &Parcel::writeUtf8AsUtf16);
-}
+status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) { return writeData(val); }
+status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) { return writeData(val); }
+status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) { return writeData(val); }
+
+status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) { return writeData(val); }
+status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val) { return writeData(val); }
+status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) { return writeData(val); }
+
+status_t Parcel::writeParcelable(const Parcelable& parcelable) { return writeData(parcelable); }
+
+status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const { return readData(str); }
+status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { return readData(str); }
+
+status_t Parcel::readString16(std::optional<String16>* pArg) const { return readData(pArg); }
+status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const { return readData(pArg); }
+
+status_t Parcel::readByteVector(std::vector<int8_t>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const { return readData(val); }
+status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { return readData(val); }
+status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const { return readData(val); }
+status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { return readData(val); }
+status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const { return readData(val); }
+status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const { return readData(val); }
+status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const { return readData(val); }
+status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const { return readData(val); }
+status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const { return readData(val); }
+status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const { return readData(val); }
+status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const { return readData(val); }
+status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const { return readData(val); }
+status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const { return readData(val); }
+status_t Parcel::readFloatVector(std::vector<float>* val) const { return readData(val); }
+status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const { return readData(val); }
+status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const { return readData(val); }
+status_t Parcel::readDoubleVector(std::vector<double>* val) const { return readData(val); }
+status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { return readData(val); }
+status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { return readData(val); }
+status_t Parcel::readBoolVector(std::vector<bool>* val) const { return readData(val); }
+status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const { return readData(val); }
+status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const { return readData(val); }
+status_t Parcel::readCharVector(std::vector<char16_t>* val) const { return readData(val); }
+
+status_t Parcel::readString16Vector(
+        std::optional<std::vector<std::optional<String16>>>* val) const { return readData(val); }
+status_t Parcel::readString16Vector(
+        std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const { return readData(val); }
+status_t Parcel::readString16Vector(std::vector<String16>* val) const { return readData(val); }
+status_t Parcel::readUtf8VectorFromUtf16Vector(
+        std::optional<std::vector<std::optional<std::string>>>* val) const { return readData(val); }
+status_t Parcel::readUtf8VectorFromUtf16Vector(
+        std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const { return readData(val); }
+status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const { return readData(val); }
+
+status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const { return readData(val); }
+status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const { return readData(val); }
+status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const { return readData(val); }
+
+status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const { return readData(val); }
+status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const { return readData(val); }
+status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const { return readData(val); }
+
+status_t Parcel::readParcelable(Parcelable* parcelable) const { return readData(parcelable); }
 
 status_t Parcel::writeInt32(int32_t val)
 {
@@ -1091,24 +1084,6 @@
     return err;
 }
 
-status_t Parcel::writeString16(const std::optional<String16>& str)
-{
-    if (!str) {
-        return writeInt32(-1);
-    }
-
-    return writeString16(*str);
-}
-
-status_t Parcel::writeString16(const std::unique_ptr<String16>& str)
-{
-    if (!str) {
-        return writeInt32(-1);
-    }
-
-    return writeString16(*str);
-}
-
 status_t Parcel::writeString16(const String16& str)
 {
     return writeString16(str.string(), str.size());
@@ -1138,32 +1113,6 @@
     return flattenBinder(val);
 }
 
-status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
-{
-    return writeTypedVector(val, &Parcel::writeStrongBinder);
-}
-
-status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeStrongBinder);
-}
-
-status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val)
-{
-    return writeNullableTypedVector(val, &Parcel::writeStrongBinder);
-}
-
-status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readNullableStrongBinder);
-}
-
-status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readNullableStrongBinder);
-}
-
-status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
-    return readTypedVector(val, &Parcel::readStrongBinder);
-}
 
 status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) {
     if (!parcelable) {
@@ -1173,14 +1122,6 @@
     return writeParcelable(*parcelable);
 }
 
-status_t Parcel::writeParcelable(const Parcelable& parcelable) {
-    status_t status = writeInt32(1);  // parcelable is not null.
-    if (status != OK) {
-        return status;
-    }
-    return parcelable.writeToParcel(this);
-}
-
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
     if (!handle || handle->version != sizeof(native_handle))
@@ -1206,6 +1147,11 @@
 
 status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
 {
+    if (isForRpc()) {
+        ALOGE("Cannot write file descriptor to remote binder.");
+        return BAD_TYPE;
+    }
+
     flat_binder_object obj;
     obj.hdr.type = BINDER_TYPE_FD;
     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
@@ -1251,18 +1197,6 @@
     return writeDupFileDescriptor(fd.get());
 }
 
-status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) {
-    return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor);
-}
-
-status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor);
-}
-
-status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor);
-}
-
 status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
     if (len > INT32_MAX) {
@@ -1580,236 +1514,6 @@
     return err;
 }
 
-status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    return readByteVectorInternal(val, size);
-}
-
-status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    return readByteVectorInternal(val, size);
-}
-
-status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (!*val) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null byte vector.
-        return OK;
-    }
-    return readByteVectorInternal(&**val, size);
-}
-
-status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (val->get() == nullptr) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null byte vector.
-        return OK;
-    }
-    return readByteVectorInternal(val->get(), size);
-}
-
-status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (!*val) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null byte vector.
-        return OK;
-    }
-    return readByteVectorInternal(&**val, size);
-}
-
-status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (val->get() == nullptr) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null byte vector.
-        return OK;
-    }
-    return readByteVectorInternal(val->get(), size);
-}
-
-status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readInt32);
-}
-
-status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readInt32);
-}
-
-status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
-    return readTypedVector(val, &Parcel::readInt32);
-}
-
-status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readInt64);
-}
-
-status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readInt64);
-}
-
-status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
-    return readTypedVector(val, &Parcel::readInt64);
-}
-
-status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readUint64);
-}
-
-status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readUint64);
-}
-
-status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const {
-    return readTypedVector(val, &Parcel::readUint64);
-}
-
-status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readFloat);
-}
-
-status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readFloat);
-}
-
-status_t Parcel::readFloatVector(std::vector<float>* val) const {
-    return readTypedVector(val, &Parcel::readFloat);
-}
-
-status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readDouble);
-}
-
-status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readDouble);
-}
-
-status_t Parcel::readDoubleVector(std::vector<double>* val) const {
-    return readTypedVector(val, &Parcel::readDouble);
-}
-
-status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const {
-    const int32_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    val->emplace();
-
-    status = readBoolVector(&**val);
-
-    if (status != OK) {
-        val->reset();
-    }
-
-    return status;
-}
-
-status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const {
-    const int32_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    val->reset(new (std::nothrow) std::vector<bool>());
-
-    status = readBoolVector(val->get());
-
-    if (status != OK) {
-        val->reset();
-    }
-
-    return status;
-}
-
-status_t Parcel::readBoolVector(std::vector<bool>* val) const {
-    int32_t size;
-    status_t status = readInt32(&size);
-
-    if (status != OK) {
-        return status;
-    }
-
-    if (size < 0) {
-        return UNEXPECTED_NULL;
-    }
-
-    val->resize(size);
-
-    /* C++ bool handling means a vector of bools isn't necessarily addressable
-     * (we might use individual bits)
-     */
-    bool data;
-    for (int32_t i = 0; i < size; ++i) {
-        status = readBool(&data);
-        (*val)[i] = data;
-
-        if (status != OK) {
-            return status;
-        }
-    }
-
-    return OK;
-}
-
-status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readChar);
-}
-
-status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readChar);
-}
-
-status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
-    return readTypedVector(val, &Parcel::readChar);
-}
-
-status_t Parcel::readString16Vector(
-        std::optional<std::vector<std::optional<String16>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readString16);
-}
-
-status_t Parcel::readString16Vector(
-        std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readString16);
-}
-
-status_t Parcel::readString16Vector(std::vector<String16>* val) const {
-    return readTypedVector(val, &Parcel::readString16);
-}
-
-status_t Parcel::readUtf8VectorFromUtf16Vector(
-        std::optional<std::vector<std::optional<std::string>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16);
-}
-
-status_t Parcel::readUtf8VectorFromUtf16Vector(
-        std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16);
-}
-
-status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const {
-    return readTypedVector(val, &Parcel::readUtf8FromUtf16);
-}
-
 status_t Parcel::readInt32(int32_t *pArg) const
 {
     return readAligned(pArg);
@@ -1982,36 +1686,6 @@
     return NO_ERROR;
 }
 
-status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const {
-    const int32_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    str->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    str->emplace();
-    return readUtf8FromUtf16(&**str);
-}
-
-status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const {
-    const int32_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    str->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    str->reset(new (std::nothrow) std::string());
-    return readUtf8FromUtf16(str->get());
-}
-
 const char* Parcel::readCString() const
 {
     if (mDataPos < mDataSize) {
@@ -2059,7 +1733,10 @@
         *outLen = size;
         const char* str = (const char*)readInplace(size+1);
         if (str != nullptr) {
-            return str;
+            if (str[size] == '\0') {
+                return str;
+            }
+            android_errorWriteLog(0x534e4554, "172655291");
         }
     }
     *outLen = 0;
@@ -2075,51 +1752,6 @@
     return String16();
 }
 
-status_t Parcel::readString16(std::optional<String16>* pArg) const
-{
-    const int32_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    pArg->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    pArg->emplace();
-
-    status = readString16(&**pArg);
-
-    if (status != OK) {
-        pArg->reset();
-    }
-
-    return status;
-}
-
-status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const
-{
-    const int32_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    pArg->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    pArg->reset(new (std::nothrow) String16());
-
-    status = readString16(pArg->get());
-
-    if (status != OK) {
-        pArg->reset();
-    }
-
-    return status;
-}
 
 status_t Parcel::readString16(String16* pArg) const
 {
@@ -2142,7 +1774,10 @@
         *outLen = size;
         const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
         if (str != nullptr) {
-            return str;
+            if (str[size] == u'\0') {
+                return str;
+            }
+            android_errorWriteLog(0x534e4554, "172655291");
         }
     }
     *outLen = 0;
@@ -2173,18 +1808,6 @@
     return val;
 }
 
-status_t Parcel::readParcelable(Parcelable* parcelable) const {
-    int32_t have_parcelable = 0;
-    status_t status = readInt32(&have_parcelable);
-    if (status != OK) {
-        return status;
-    }
-    if (!have_parcelable) {
-        return UNEXPECTED_NULL;
-    }
-    return parcelable->readFromParcel(this);
-}
-
 int32_t Parcel::readExceptionCode() const
 {
     binder::Status status;
@@ -2260,7 +1883,7 @@
         ssize_t written = TEMP_FAILURE_RETRY(
             ::write(comm, &message, sizeof(message)));
 
-        if (written == -1 || written != sizeof(message)) {
+        if (written != sizeof(message)) {
             ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
                 written, strerror(errno));
             return BAD_TYPE;
@@ -2303,18 +1926,6 @@
     return OK;
 }
 
-status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
-}
-
-status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
-}
-
-status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const {
-    return readTypedVector(val, &Parcel::readUniqueFileDescriptor);
-}
-
 status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
 {
     int32_t blobType;
@@ -2503,6 +2114,9 @@
 void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,
     const binder_size_t* objects, size_t objectsCount, release_func relFunc)
 {
+    // this code uses 'mOwner == nullptr' to understand whether it owns memory
+    LOG_ALWAYS_FATAL_IF(relFunc == nullptr, "must provide cleanup function");
+
     freeData();
 
     mData = const_cast<uint8_t*>(data);
@@ -2884,6 +2498,7 @@
     mDataPos = 0;
     ALOGV("initState Setting data size of %p to %zu", this, mDataSize);
     ALOGV("initState Setting data pos of %p to %zu", this, mDataPos);
+    mSession = nullptr;
     mObjects = nullptr;
     mObjectsSize = 0;
     mObjectsCapacity = 0;
diff --git a/libs/binder/ParcelableHolder.cpp b/libs/binder/ParcelableHolder.cpp
index b2b8671..2e86b74 100644
--- a/libs/binder/ParcelableHolder.cpp
+++ b/libs/binder/ParcelableHolder.cpp
@@ -37,7 +37,7 @@
         size_t sizePos = p->dataPosition();
         RETURN_ON_FAILURE(p->writeInt32(0));
         size_t dataStartPos = p->dataPosition();
-        RETURN_ON_FAILURE(p->writeUtf8AsUtf16(this->mParcelableName));
+        RETURN_ON_FAILURE(p->writeString16(this->mParcelableName));
         this->mParcelable->writeToParcel(p);
         size_t dataSize = p->dataPosition() - dataStartPos;
 
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 6eae5ef..670fd55 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -109,5 +109,10 @@
     return granted;
 }
 
+void PermissionCache::purgeCache() {
+    PermissionCache& pc(PermissionCache::getInstance());
+    pc.purge();
+}
+
 // ---------------------------------------------------------------------------
 } // namespace android
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index c807cfe..406fee0 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -31,7 +31,6 @@
 using android::BAD_VALUE;
 using android::NO_ERROR;
 using android::Parcel;
-using android::sp;
 using android::status_t;
 using android::UNEXPECTED_NULL;
 
diff --git a/libs/binder/ProcessInfoService.cpp b/libs/binder/ProcessInfoService.cpp
index f75141e..0fb954a 100644
--- a/libs/binder/ProcessInfoService.cpp
+++ b/libs/binder/ProcessInfoService.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <binder/ProcessInfoService.h>
+#include <processinfo/ProcessInfoService.h>
 #include <binder/IServiceManager.h>
 
 #include <utils/Log.h>
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index b5e4dfe..f7ca1e6 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -27,8 +27,8 @@
 #include <utils/String8.h>
 #include <utils/threads.h>
 
-#include <private/binder/binder_module.h>
 #include "Static.h"
+#include "binder_module.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -43,6 +43,7 @@
 
 #define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
 #define DEFAULT_MAX_BINDER_THREADS 15
+#define DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION 1
 
 #ifdef __ANDROID_VNDK__
 const char* kDefaultDriver = "/dev/vndbinder";
@@ -105,7 +106,7 @@
         }
 
         std::lock_guard<std::mutex> l(gProcessMutex);
-        gProcess = new ProcessState(driver);
+        gProcess = sp<ProcessState>::make(driver);
     });
 
     if (requireDefault) {
@@ -205,10 +206,12 @@
 //
 // Returns -1 in case of failure, otherwise the strong reference count.
 ssize_t ProcessState::getStrongRefCountForNode(const sp<BpBinder>& binder) {
+    if (binder->isRpcBinder()) return -1;
+
     binder_node_info_for_ref info;
     memset(&info, 0, sizeof(binder_node_info_for_ref));
 
-    info.handle = binder->getPrivateAccessorForHandle().handle();
+    info.handle = binder->getPrivateAccessorForId().binderHandle();
 
     status_t result = ioctl(mDriverFD, BINDER_GET_NODE_INFO_FOR_REF, &info);
 
@@ -297,8 +300,8 @@
                    return nullptr;
             }
 
-            b = BpBinder::create(handle);
-            e->binder = b;
+            sp<BpBinder> b = BpBinder::create(handle);
+            e->binder = b.get();
             if (b) e->refs = b->getWeakRefs();
             result = b;
         } else {
@@ -338,7 +341,7 @@
     if (mThreadPoolStarted) {
         String8 name = makeBinderThreadName();
         ALOGV("Spawning new pooled thread, name=%s\n", name.string());
-        sp<Thread> t = new PoolThread(isMain);
+        sp<Thread> t = sp<PoolThread>::make(isMain);
         t->run(name.string());
     }
 }
@@ -356,6 +359,15 @@
     return result;
 }
 
+status_t ProcessState::enableOnewaySpamDetection(bool enable) {
+    uint32_t enableDetection = enable ? 1 : 0;
+    if (ioctl(mDriverFD, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enableDetection) == -1) {
+        ALOGI("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+        return -errno;
+    }
+    return NO_ERROR;
+}
+
 void ProcessState::giveThreadPoolName() {
     androidSetThreadName( makeBinderThreadName().string() );
 }
@@ -386,6 +398,11 @@
         if (result == -1) {
             ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
         }
+        uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
+        result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
+        if (result == -1) {
+            ALOGI("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+        }
     } else {
         ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
     }
@@ -399,6 +416,7 @@
     , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
     , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
     , mExecutingThreadsCount(0)
+    , mWaitingForThreads(0)
     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
     , mStarvationStartTimeMs(0)
     , mThreadPoolStarted(false)
diff --git a/libs/binder/RpcAddress.cpp b/libs/binder/RpcAddress.cpp
new file mode 100644
index 0000000..5c32320
--- /dev/null
+++ b/libs/binder/RpcAddress.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 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 <binder/RpcAddress.h>
+
+#include <binder/Parcel.h>
+
+#include "Debug.h"
+#include "RpcState.h"
+#include "RpcWireFormat.h"
+
+namespace android {
+
+RpcAddress RpcAddress::zero() {
+    return RpcAddress();
+}
+
+bool RpcAddress::isZero() const {
+    RpcWireAddress ZERO{0};
+    return memcmp(mRawAddr.get(), &ZERO, sizeof(RpcWireAddress)) == 0;
+}
+
+static void ReadRandomBytes(uint8_t* buf, size_t len) {
+    int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+    if (fd == -1) {
+        ALOGE("%s: cannot read /dev/urandom", __func__);
+        return;
+    }
+
+    size_t n;
+    while ((n = TEMP_FAILURE_RETRY(read(fd, buf, len))) > 0) {
+        len -= n;
+        buf += n;
+    }
+    if (len > 0) {
+        ALOGW("%s: there are %d bytes skipped", __func__, (int)len);
+    }
+    close(fd);
+}
+
+RpcAddress RpcAddress::unique() {
+    RpcAddress ret;
+    ReadRandomBytes((uint8_t*)ret.mRawAddr.get(), sizeof(RpcWireAddress));
+    LOG_RPC_DETAIL("Creating new address: %s", ret.toString().c_str());
+    return ret;
+}
+
+RpcAddress RpcAddress::fromRawEmbedded(const RpcWireAddress* raw) {
+    RpcAddress addr;
+    memcpy(addr.mRawAddr.get(), raw, sizeof(RpcWireAddress));
+    return addr;
+}
+
+const RpcWireAddress& RpcAddress::viewRawEmbedded() const {
+    return *mRawAddr.get();
+}
+
+bool RpcAddress::operator<(const RpcAddress& rhs) const {
+    return std::memcmp(mRawAddr.get(), rhs.mRawAddr.get(), sizeof(RpcWireAddress)) < 0;
+}
+
+std::string RpcAddress::toString() const {
+    return hexString(mRawAddr.get(), sizeof(RpcWireAddress));
+}
+
+status_t RpcAddress::writeToParcel(Parcel* parcel) const {
+    return parcel->write(mRawAddr.get(), sizeof(RpcWireAddress));
+}
+
+status_t RpcAddress::readFromParcel(const Parcel& parcel) {
+    return parcel.read(mRawAddr.get(), sizeof(RpcWireAddress));
+}
+
+RpcAddress::~RpcAddress() {}
+RpcAddress::RpcAddress() : mRawAddr(std::make_shared<RpcWireAddress>()) {}
+
+} // namespace android
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
new file mode 100644
index 0000000..c0cdcd6
--- /dev/null
+++ b/libs/binder/RpcServer.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "RpcServer"
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <thread>
+#include <vector>
+
+#include <binder/Parcel.h>
+#include <binder/RpcServer.h>
+#include <log/log.h>
+#include "RpcState.h"
+
+#include "RpcSocketAddress.h"
+#include "RpcWireFormat.h"
+
+namespace android {
+
+using base::unique_fd;
+
+RpcServer::RpcServer() {}
+RpcServer::~RpcServer() {}
+
+sp<RpcServer> RpcServer::make() {
+    return sp<RpcServer>::make();
+}
+
+void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
+    mAgreedExperimental = true;
+}
+
+bool RpcServer::setupUnixDomainServer(const char* path) {
+    return setupSocketServer(UnixSocketAddress(path));
+}
+
+bool RpcServer::setupVsockServer(unsigned int port) {
+    // realizing value w/ this type at compile time to avoid ubsan abort
+    constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
+
+    return setupSocketServer(VsockSocketAddress(kAnyCid, port));
+}
+
+bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) {
+    const char* kAddr = "127.0.0.1";
+
+    if (assignedPort != nullptr) *assignedPort = 0;
+    auto aiStart = InetSocketAddress::getAddrInfo(kAddr, port);
+    if (aiStart == nullptr) return false;
+    for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+        InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
+        if (!setupSocketServer(socketAddress)) {
+            continue;
+        }
+
+        LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet");
+        sockaddr_in addr{};
+        socklen_t len = sizeof(addr);
+        if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
+            int savedErrno = errno;
+            ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
+                  strerror(savedErrno));
+            return false;
+        }
+        LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu",
+                            static_cast<size_t>(len), sizeof(addr));
+        unsigned int realPort = ntohs(addr.sin_port);
+        LOG_ALWAYS_FATAL_IF(port != 0 && realPort != port,
+                            "Requesting inet server on %s but it is set up on %u.",
+                            socketAddress.toString().c_str(), realPort);
+
+        if (assignedPort != nullptr) {
+            *assignedPort = realPort;
+        }
+
+        return true;
+    }
+    ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
+          port);
+    return false;
+}
+
+void RpcServer::setMaxThreads(size_t threads) {
+    LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads");
+    LOG_ALWAYS_FATAL_IF(mStarted, "must be called before started");
+    mMaxThreads = threads;
+}
+
+size_t RpcServer::getMaxThreads() {
+    return mMaxThreads;
+}
+
+void RpcServer::setRootObject(const sp<IBinder>& binder) {
+    std::lock_guard<std::mutex> _l(mLock);
+    mRootObject = binder;
+}
+
+sp<IBinder> RpcServer::getRootObject() {
+    std::lock_guard<std::mutex> _l(mLock);
+    return mRootObject;
+}
+
+void RpcServer::join() {
+    LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join.");
+    }
+
+    while (true) {
+        unique_fd clientFd(TEMP_FAILURE_RETRY(
+                accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
+
+        if (clientFd < 0) {
+            ALOGE("Could not accept4 socket: %s", strerror(errno));
+            continue;
+        }
+        LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+
+        // TODO(b/183988761): cannot trust this simple ID, should not block this
+        // thread
+        LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+        int32_t id;
+        if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
+            ALOGE("Could not read ID from fd %d", clientFd.get());
+            continue;
+        }
+
+        {
+            std::lock_guard<std::mutex> _l(mLock);
+
+            sp<RpcSession> session;
+            if (id == RPC_SESSION_ID_NEW) {
+                // new client!
+                LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
+                mSessionIdCounter++;
+
+                session = RpcSession::make();
+                session->setForServer(wp<RpcServer>::fromExisting(this), mSessionIdCounter);
+
+                mSessions[mSessionIdCounter] = session;
+            } else {
+                auto it = mSessions.find(id);
+                if (it == mSessions.end()) {
+                    ALOGE("Cannot add thread, no record of session with ID %d", id);
+                    continue;
+                }
+                session = it->second;
+            }
+
+            session->startThread(std::move(clientFd));
+        }
+    }
+}
+
+std::vector<sp<RpcSession>> RpcServer::listSessions() {
+    std::lock_guard<std::mutex> _l(mLock);
+    std::vector<sp<RpcSession>> sessions;
+    for (auto& [id, session] : mSessions) {
+        (void)id;
+        sessions.push_back(session);
+    }
+    return sessions;
+}
+
+bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
+    LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
+
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcServer can only have one server.");
+    }
+
+    unique_fd serverFd(
+            TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+    if (serverFd == -1) {
+        ALOGE("Could not create socket: %s", strerror(errno));
+        return false;
+    }
+
+    if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
+        int savedErrno = errno;
+        ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+        return false;
+    }
+
+    if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) {
+        int savedErrno = errno;
+        ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
+        return false;
+    }
+
+    LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str());
+
+    mServer = std::move(serverFd);
+    return true;
+}
+
+void RpcServer::onSessionTerminating(const sp<RpcSession>& session) {
+    auto id = session->mId;
+    LOG_ALWAYS_FATAL_IF(id == std::nullopt, "Server sessions must be initialized with ID");
+    LOG_RPC_DETAIL("Dropping session %d", *id);
+
+    std::lock_guard<std::mutex> _l(mLock);
+    auto it = mSessions.find(*id);
+    LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %d", *id);
+    LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %d", *id);
+    (void)mSessions.erase(it);
+}
+
+} // namespace android
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
new file mode 100644
index 0000000..3e83c99
--- /dev/null
+++ b/libs/binder/RpcSession.cpp
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "RpcSession"
+
+#include <binder/RpcSession.h>
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <string_view>
+
+#include <binder/Parcel.h>
+#include <binder/RpcServer.h>
+#include <binder/Stability.h>
+#include <utils/String8.h>
+
+#include "RpcSocketAddress.h"
+#include "RpcState.h"
+#include "RpcWireFormat.h"
+
+#ifdef __GLIBC__
+extern "C" pid_t gettid();
+#endif
+
+namespace android {
+
+using base::unique_fd;
+
+RpcSession::RpcSession() {
+    LOG_RPC_DETAIL("RpcSession created %p", this);
+
+    mState = std::make_unique<RpcState>();
+}
+RpcSession::~RpcSession() {
+    LOG_RPC_DETAIL("RpcSession destroyed %p", this);
+
+    std::lock_guard<std::mutex> _l(mMutex);
+    LOG_ALWAYS_FATAL_IF(mServerConnections.size() != 0,
+                        "Should not be able to destroy a session with servers in use.");
+}
+
+sp<RpcSession> RpcSession::make() {
+    return sp<RpcSession>::make();
+}
+
+bool RpcSession::setupUnixDomainClient(const char* path) {
+    return setupSocketClient(UnixSocketAddress(path));
+}
+
+bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) {
+    return setupSocketClient(VsockSocketAddress(cid, port));
+}
+
+bool RpcSession::setupInetClient(const char* addr, unsigned int port) {
+    auto aiStart = InetSocketAddress::getAddrInfo(addr, port);
+    if (aiStart == nullptr) return false;
+    for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+        InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, addr, port);
+        if (setupSocketClient(socketAddress)) return true;
+    }
+    ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port);
+    return false;
+}
+
+bool RpcSession::addNullDebuggingClient() {
+    unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
+
+    if (serverFd == -1) {
+        ALOGE("Could not connect to /dev/null: %s", strerror(errno));
+        return false;
+    }
+
+    addClient(std::move(serverFd));
+    return true;
+}
+
+sp<IBinder> RpcSession::getRootObject() {
+    ExclusiveConnection connection(sp<RpcSession>::fromExisting(this), ConnectionUse::CLIENT);
+    return state()->getRootObject(connection.fd(), sp<RpcSession>::fromExisting(this));
+}
+
+status_t RpcSession::getRemoteMaxThreads(size_t* maxThreads) {
+    ExclusiveConnection connection(sp<RpcSession>::fromExisting(this), ConnectionUse::CLIENT);
+    return state()->getMaxThreads(connection.fd(), sp<RpcSession>::fromExisting(this), maxThreads);
+}
+
+status_t RpcSession::transact(const RpcAddress& address, uint32_t code, const Parcel& data,
+                              Parcel* reply, uint32_t flags) {
+    ExclusiveConnection connection(sp<RpcSession>::fromExisting(this),
+                                   (flags & IBinder::FLAG_ONEWAY) ? ConnectionUse::CLIENT_ASYNC
+                                                                  : ConnectionUse::CLIENT);
+    return state()->transact(connection.fd(), address, code, data,
+                             sp<RpcSession>::fromExisting(this), reply, flags);
+}
+
+status_t RpcSession::sendDecStrong(const RpcAddress& address) {
+    ExclusiveConnection connection(sp<RpcSession>::fromExisting(this),
+                                   ConnectionUse::CLIENT_REFCOUNT);
+    return state()->sendDecStrong(connection.fd(), address);
+}
+
+status_t RpcSession::readId() {
+    {
+        std::lock_guard<std::mutex> _l(mMutex);
+        LOG_ALWAYS_FATAL_IF(mForServer != nullptr, "Can only update ID for client.");
+    }
+
+    int32_t id;
+
+    ExclusiveConnection connection(sp<RpcSession>::fromExisting(this), ConnectionUse::CLIENT);
+    status_t status =
+            state()->getSessionId(connection.fd(), sp<RpcSession>::fromExisting(this), &id);
+    if (status != OK) return status;
+
+    LOG_RPC_DETAIL("RpcSession %p has id %d", this, id);
+    mId = id;
+    return OK;
+}
+
+void RpcSession::startThread(unique_fd client) {
+    std::lock_guard<std::mutex> _l(mMutex);
+    sp<RpcSession> holdThis = sp<RpcSession>::fromExisting(this);
+    int fd = client.release();
+    auto thread = std::thread([=] {
+        holdThis->join(unique_fd(fd));
+        {
+            std::lock_guard<std::mutex> _l(holdThis->mMutex);
+            auto it = mThreads.find(std::this_thread::get_id());
+            LOG_ALWAYS_FATAL_IF(it == mThreads.end());
+            it->second.detach();
+            mThreads.erase(it);
+        }
+    });
+    mThreads[thread.get_id()] = std::move(thread);
+}
+
+void RpcSession::join(unique_fd client) {
+    // must be registered to allow arbitrary client code executing commands to
+    // be able to do nested calls (we can't only read from it)
+    sp<RpcConnection> connection = assignServerToThisThread(std::move(client));
+
+    while (true) {
+        status_t error =
+                state()->getAndExecuteCommand(connection->fd, sp<RpcSession>::fromExisting(this));
+
+        if (error != OK) {
+            ALOGI("Binder connection thread closing w/ status %s", statusToString(error).c_str());
+            break;
+        }
+    }
+
+    LOG_ALWAYS_FATAL_IF(!removeServerConnection(connection),
+                        "bad state: connection object guaranteed to be in list");
+}
+
+void RpcSession::terminateLocked() {
+    // TODO(b/185167543):
+    // - kindly notify other side of the connection of termination (can't be
+    // locked)
+    // - prevent new client/servers from being added
+    // - stop all threads which are currently reading/writing
+    // - terminate RpcState?
+
+    if (mTerminated) return;
+
+    sp<RpcServer> server = mForServer.promote();
+    if (server) {
+        server->onSessionTerminating(sp<RpcSession>::fromExisting(this));
+    }
+}
+
+wp<RpcServer> RpcSession::server() {
+    return mForServer;
+}
+
+bool RpcSession::setupSocketClient(const RpcSocketAddress& addr) {
+    {
+        std::lock_guard<std::mutex> _l(mMutex);
+        LOG_ALWAYS_FATAL_IF(mClientConnections.size() != 0,
+                            "Must only setup session once, but already has %zu clients",
+                            mClientConnections.size());
+    }
+
+    if (!setupOneSocketClient(addr, RPC_SESSION_ID_NEW)) return false;
+
+    // TODO(b/185167543): we should add additional sessions dynamically
+    // instead of all at once.
+    // TODO(b/186470974): first risk of blocking
+    size_t numThreadsAvailable;
+    if (status_t status = getRemoteMaxThreads(&numThreadsAvailable); status != OK) {
+        ALOGE("Could not get max threads after initial session to %s: %s", addr.toString().c_str(),
+              statusToString(status).c_str());
+        return false;
+    }
+
+    if (status_t status = readId(); status != OK) {
+        ALOGE("Could not get session id after initial session to %s; %s", addr.toString().c_str(),
+              statusToString(status).c_str());
+        return false;
+    }
+
+    // we've already setup one client
+    for (size_t i = 0; i + 1 < numThreadsAvailable; i++) {
+        // TODO(b/185167543): shutdown existing connections?
+        if (!setupOneSocketClient(addr, mId.value())) return false;
+    }
+
+    return true;
+}
+
+bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) {
+    for (size_t tries = 0; tries < 5; tries++) {
+        if (tries > 0) usleep(10000);
+
+        unique_fd serverFd(
+                TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+        if (serverFd == -1) {
+            int savedErrno = errno;
+            ALOGE("Could not create socket at %s: %s", addr.toString().c_str(),
+                  strerror(savedErrno));
+            return false;
+        }
+
+        if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
+            if (errno == ECONNRESET) {
+                ALOGW("Connection reset on %s", addr.toString().c_str());
+                continue;
+            }
+            int savedErrno = errno;
+            ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
+                  strerror(savedErrno));
+            return false;
+        }
+
+        if (sizeof(id) != TEMP_FAILURE_RETRY(write(serverFd.get(), &id, sizeof(id)))) {
+            int savedErrno = errno;
+            ALOGE("Could not write id to socket at %s: %s", addr.toString().c_str(),
+                  strerror(savedErrno));
+            return false;
+        }
+
+        LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
+
+        addClient(std::move(serverFd));
+        return true;
+    }
+
+    ALOGE("Ran out of retries to connect to %s", addr.toString().c_str());
+    return false;
+}
+
+void RpcSession::addClient(unique_fd fd) {
+    std::lock_guard<std::mutex> _l(mMutex);
+    sp<RpcConnection> session = sp<RpcConnection>::make();
+    session->fd = std::move(fd);
+    mClientConnections.push_back(session);
+}
+
+void RpcSession::setForServer(const wp<RpcServer>& server, int32_t sessionId) {
+    mId = sessionId;
+    mForServer = server;
+}
+
+sp<RpcSession::RpcConnection> RpcSession::assignServerToThisThread(unique_fd fd) {
+    std::lock_guard<std::mutex> _l(mMutex);
+    sp<RpcConnection> session = sp<RpcConnection>::make();
+    session->fd = std::move(fd);
+    session->exclusiveTid = gettid();
+    mServerConnections.push_back(session);
+
+    return session;
+}
+
+bool RpcSession::removeServerConnection(const sp<RpcConnection>& connection) {
+    std::lock_guard<std::mutex> _l(mMutex);
+    if (auto it = std::find(mServerConnections.begin(), mServerConnections.end(), connection);
+        it != mServerConnections.end()) {
+        mServerConnections.erase(it);
+        if (mServerConnections.size() == 0) {
+            terminateLocked();
+        }
+        return true;
+    }
+    return false;
+}
+
+RpcSession::ExclusiveConnection::ExclusiveConnection(const sp<RpcSession>& session,
+                                                     ConnectionUse use)
+      : mSession(session) {
+    pid_t tid = gettid();
+    std::unique_lock<std::mutex> _l(mSession->mMutex);
+
+    mSession->mWaitingThreads++;
+    while (true) {
+        sp<RpcConnection> exclusive;
+        sp<RpcConnection> available;
+
+        // CHECK FOR DEDICATED CLIENT SOCKET
+        //
+        // A server/looper should always use a dedicated session if available
+        findConnection(tid, &exclusive, &available, mSession->mClientConnections,
+                       mSession->mClientConnectionsOffset);
+
+        // WARNING: this assumes a server cannot request its client to send
+        // a transaction, as mServerConnections is excluded below.
+        //
+        // Imagine we have more than one thread in play, and a single thread
+        // sends a synchronous, then an asynchronous command. Imagine the
+        // asynchronous command is sent on the first client connection. Then, if
+        // we naively send a synchronous command to that same connection, the
+        // thread on the far side might be busy processing the asynchronous
+        // command. So, we move to considering the second available thread
+        // for subsequent calls.
+        if (use == ConnectionUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
+            mSession->mClientConnectionsOffset =
+                    (mSession->mClientConnectionsOffset + 1) % mSession->mClientConnections.size();
+        }
+
+        // USE SERVING SOCKET (for nested transaction)
+        //
+        // asynchronous calls cannot be nested
+        if (use != ConnectionUse::CLIENT_ASYNC) {
+            // server connections are always assigned to a thread
+            findConnection(tid, &exclusive, nullptr /*available*/, mSession->mServerConnections,
+                           0 /* index hint */);
+        }
+
+        // if our thread is already using a session, prioritize using that
+        if (exclusive != nullptr) {
+            mConnection = exclusive;
+            mReentrant = true;
+            break;
+        } else if (available != nullptr) {
+            mConnection = available;
+            mConnection->exclusiveTid = tid;
+            break;
+        }
+
+        // in regular binder, this would usually be a deadlock :)
+        LOG_ALWAYS_FATAL_IF(mSession->mClientConnections.size() == 0,
+                            "Not a client of any session. You must create a session to an "
+                            "RPC server to make any non-nested (e.g. oneway or on another thread) "
+                            "calls.");
+
+        LOG_RPC_DETAIL("No available session (have %zu clients and %zu servers). Waiting...",
+                       mSession->mClientConnections.size(), mSession->mServerConnections.size());
+        mSession->mAvailableConnectionCv.wait(_l);
+    }
+    mSession->mWaitingThreads--;
+}
+
+void RpcSession::ExclusiveConnection::findConnection(pid_t tid, sp<RpcConnection>* exclusive,
+                                                     sp<RpcConnection>* available,
+                                                     std::vector<sp<RpcConnection>>& sockets,
+                                                     size_t socketsIndexHint) {
+    LOG_ALWAYS_FATAL_IF(sockets.size() > 0 && socketsIndexHint >= sockets.size(),
+                        "Bad index %zu >= %zu", socketsIndexHint, sockets.size());
+
+    if (*exclusive != nullptr) return; // consistent with break below
+
+    for (size_t i = 0; i < sockets.size(); i++) {
+        sp<RpcConnection>& socket = sockets[(i + socketsIndexHint) % sockets.size()];
+
+        // take first available session (intuition = caching)
+        if (available && *available == nullptr && socket->exclusiveTid == std::nullopt) {
+            *available = socket;
+            continue;
+        }
+
+        // though, prefer to take session which is already inuse by this thread
+        // (nested transactions)
+        if (exclusive && socket->exclusiveTid == tid) {
+            *exclusive = socket;
+            break; // consistent with return above
+        }
+    }
+}
+
+RpcSession::ExclusiveConnection::~ExclusiveConnection() {
+    // reentrant use of a session means something less deep in the call stack
+    // is using this fd, and it retains the right to it. So, we don't give up
+    // exclusive ownership, and no thread is freed.
+    if (!mReentrant) {
+        std::unique_lock<std::mutex> _l(mSession->mMutex);
+        mConnection->exclusiveTid = std::nullopt;
+        if (mSession->mWaitingThreads > 0) {
+            _l.unlock();
+            mSession->mAvailableConnectionCv.notify_one();
+        }
+    }
+}
+
+} // namespace android
diff --git a/libs/binder/RpcSocketAddress.h b/libs/binder/RpcSocketAddress.h
new file mode 100644
index 0000000..c7ba5d9
--- /dev/null
+++ b/libs/binder/RpcSocketAddress.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <string>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "vm_sockets.h"
+
+namespace android {
+
+class RpcSocketAddress {
+public:
+    virtual ~RpcSocketAddress() {}
+    virtual std::string toString() const = 0;
+    virtual const sockaddr* addr() const = 0;
+    virtual size_t addrSize() const = 0;
+};
+
+class UnixSocketAddress : public RpcSocketAddress {
+public:
+    explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) {
+        unsigned int pathLen = strlen(path) + 1;
+        LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "Socket path is too long: %u %s",
+                            pathLen, path);
+        memcpy(mAddr.sun_path, path, pathLen);
+    }
+    virtual ~UnixSocketAddress() {}
+    std::string toString() const override {
+        return String8::format("path '%.*s'", static_cast<int>(sizeof(mAddr.sun_path)),
+                               mAddr.sun_path)
+                .c_str();
+    }
+    const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
+    size_t addrSize() const override { return sizeof(mAddr); }
+
+private:
+    sockaddr_un mAddr;
+};
+
+class VsockSocketAddress : public RpcSocketAddress {
+public:
+    VsockSocketAddress(unsigned int cid, unsigned int port)
+          : mAddr({
+                    .svm_family = AF_VSOCK,
+                    .svm_port = port,
+                    .svm_cid = cid,
+            }) {}
+    virtual ~VsockSocketAddress() {}
+    std::string toString() const override {
+        return String8::format("cid %u port %u", mAddr.svm_cid, mAddr.svm_port).c_str();
+    }
+    const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
+    size_t addrSize() const override { return sizeof(mAddr); }
+
+private:
+    sockaddr_vm mAddr;
+};
+
+class InetSocketAddress : public RpcSocketAddress {
+public:
+    InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port)
+          : mSockAddr(sockAddr), mSize(size), mAddr(addr), mPort(port) {}
+    [[nodiscard]] std::string toString() const override {
+        return String8::format("%s:%u", mAddr, mPort).c_str();
+    }
+    [[nodiscard]] const sockaddr* addr() const override { return mSockAddr; }
+    [[nodiscard]] size_t addrSize() const override { return mSize; }
+
+    using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
+    static AddrInfo getAddrInfo(const char* addr, unsigned int port) {
+        addrinfo hint{
+                .ai_flags = 0,
+                .ai_family = AF_UNSPEC,
+                .ai_socktype = SOCK_STREAM,
+                .ai_protocol = 0,
+        };
+        addrinfo* aiStart = nullptr;
+        if (int rc = getaddrinfo(addr, std::to_string(port).data(), &hint, &aiStart); 0 != rc) {
+            ALOGE("Unable to resolve %s:%u: %s", addr, port, gai_strerror(rc));
+            return AddrInfo(nullptr, nullptr);
+        }
+        if (aiStart == nullptr) {
+            ALOGE("Unable to resolve %s:%u: getaddrinfo returns null", addr, port);
+            return AddrInfo(nullptr, nullptr);
+        }
+        return AddrInfo(aiStart, &freeaddrinfo);
+    }
+
+private:
+    const sockaddr* mSockAddr;
+    size_t mSize;
+    const char* mAddr;
+    unsigned int mPort;
+};
+
+} // namespace android
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
new file mode 100644
index 0000000..20fdbfe
--- /dev/null
+++ b/libs/binder/RpcState.cpp
@@ -0,0 +1,746 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "RpcState"
+
+#include "RpcState.h"
+
+#include <binder/BpBinder.h>
+#include <binder/RpcServer.h>
+
+#include "Debug.h"
+#include "RpcWireFormat.h"
+
+#include <inttypes.h>
+
+namespace android {
+
+RpcState::RpcState() {}
+RpcState::~RpcState() {}
+
+status_t RpcState::onBinderLeaving(const sp<RpcSession>& session, const sp<IBinder>& binder,
+                                   RpcAddress* outAddress) {
+    bool isRemote = binder->remoteBinder();
+    bool isRpc = isRemote && binder->remoteBinder()->isRpcBinder();
+
+    if (isRpc && binder->remoteBinder()->getPrivateAccessorForId().rpcSession() != session) {
+        // We need to be able to send instructions over the socket for how to
+        // connect to a different server, and we also need to let the host
+        // process know that this is happening.
+        ALOGE("Cannot send binder from unrelated binder RPC session.");
+        return INVALID_OPERATION;
+    }
+
+    if (isRemote && !isRpc) {
+        // Without additional work, this would have the effect of using this
+        // process to proxy calls from the socket over to the other process, and
+        // it would make those calls look like they come from us (not over the
+        // sockets). In order to make this work transparently like binder, we
+        // would instead need to send instructions over the socket for how to
+        // connect to the host process, and we also need to let the host process
+        // know this was happening.
+        ALOGE("Cannot send binder proxy %p over sockets", binder.get());
+        return INVALID_OPERATION;
+    }
+
+    std::lock_guard<std::mutex> _l(mNodeMutex);
+
+    // TODO(b/182939933): maybe move address out of BpBinder, and keep binder->address map
+    // in RpcState
+    for (auto& [addr, node] : mNodeForAddress) {
+        if (binder == node.binder) {
+            if (isRpc) {
+                const RpcAddress& actualAddr =
+                        binder->remoteBinder()->getPrivateAccessorForId().rpcAddress();
+                // TODO(b/182939933): this is only checking integrity of data structure
+                // a different data structure doesn't need this
+                LOG_ALWAYS_FATAL_IF(addr < actualAddr, "Address mismatch");
+                LOG_ALWAYS_FATAL_IF(actualAddr < addr, "Address mismatch");
+            }
+            node.timesSent++;
+            node.sentRef = binder; // might already be set
+            *outAddress = addr;
+            return OK;
+        }
+    }
+    LOG_ALWAYS_FATAL_IF(isRpc, "RPC binder must have known address at this point");
+
+    auto&& [it, inserted] = mNodeForAddress.insert({RpcAddress::unique(),
+                                                    BinderNode{
+                                                            .binder = binder,
+                                                            .timesSent = 1,
+                                                            .sentRef = binder,
+                                                    }});
+    // TODO(b/182939933): better organization could avoid needing this log
+    LOG_ALWAYS_FATAL_IF(!inserted);
+
+    *outAddress = it->first;
+    return OK;
+}
+
+sp<IBinder> RpcState::onBinderEntering(const sp<RpcSession>& session, const RpcAddress& address) {
+    std::unique_lock<std::mutex> _l(mNodeMutex);
+
+    if (auto it = mNodeForAddress.find(address); it != mNodeForAddress.end()) {
+        sp<IBinder> binder = it->second.binder.promote();
+
+        // implicitly have strong RPC refcount, since we received this binder
+        it->second.timesRecd++;
+
+        _l.unlock();
+
+        // We have timesRecd RPC refcounts, but we only need to hold on to one
+        // when we keep the object. All additional dec strongs are sent
+        // immediately, we wait to send the last one in BpBinder::onLastDecStrong.
+        (void)session->sendDecStrong(address);
+
+        return binder;
+    }
+
+    auto&& [it, inserted] = mNodeForAddress.insert({address, BinderNode{}});
+    LOG_ALWAYS_FATAL_IF(!inserted, "Failed to insert binder when creating proxy");
+
+    // Currently, all binders are assumed to be part of the same session (no
+    // device global binders in the RPC world).
+    sp<IBinder> binder = BpBinder::create(session, it->first);
+    it->second.binder = binder;
+    it->second.timesRecd = 1;
+    return binder;
+}
+
+size_t RpcState::countBinders() {
+    std::lock_guard<std::mutex> _l(mNodeMutex);
+    return mNodeForAddress.size();
+}
+
+void RpcState::dump() {
+    std::lock_guard<std::mutex> _l(mNodeMutex);
+    ALOGE("DUMP OF RpcState %p", this);
+    ALOGE("DUMP OF RpcState (%zu nodes)", mNodeForAddress.size());
+    for (const auto& [address, node] : mNodeForAddress) {
+        sp<IBinder> binder = node.binder.promote();
+
+        const char* desc;
+        if (binder) {
+            if (binder->remoteBinder()) {
+                if (binder->remoteBinder()->isRpcBinder()) {
+                    desc = "(rpc binder proxy)";
+                } else {
+                    desc = "(binder proxy)";
+                }
+            } else {
+                desc = "(local binder)";
+            }
+        } else {
+            desc = "(null)";
+        }
+
+        ALOGE("- BINDER NODE: %p times sent:%zu times recd: %zu a:%s type:%s",
+              node.binder.unsafe_get(), node.timesSent, node.timesRecd, address.toString().c_str(),
+              desc);
+    }
+    ALOGE("END DUMP OF RpcState");
+}
+
+void RpcState::terminate() {
+    if (SHOULD_LOG_RPC_DETAIL) {
+        ALOGE("RpcState::terminate()");
+        dump();
+    }
+
+    // if the destructor of a binder object makes another RPC call, then calling
+    // decStrong could deadlock. So, we must hold onto these binders until
+    // mNodeMutex is no longer taken.
+    std::vector<sp<IBinder>> tempHoldBinder;
+
+    {
+        std::lock_guard<std::mutex> _l(mNodeMutex);
+        mTerminated = true;
+        for (auto& [address, node] : mNodeForAddress) {
+            sp<IBinder> binder = node.binder.promote();
+            LOG_ALWAYS_FATAL_IF(binder == nullptr, "Binder %p expected to be owned.", binder.get());
+
+            if (node.sentRef != nullptr) {
+                tempHoldBinder.push_back(node.sentRef);
+            }
+        }
+
+        mNodeForAddress.clear();
+    }
+}
+
+bool RpcState::rpcSend(const base::unique_fd& fd, const char* what, const void* data, size_t size) {
+    LOG_RPC_DETAIL("Sending %s on fd %d: %s", what, fd.get(), hexString(data, size).c_str());
+
+    if (size > std::numeric_limits<ssize_t>::max()) {
+        ALOGE("Cannot send %s at size %zu (too big)", what, size);
+        terminate();
+        return false;
+    }
+
+    ssize_t sent = TEMP_FAILURE_RETRY(send(fd.get(), data, size, MSG_NOSIGNAL));
+
+    if (sent < 0 || sent != static_cast<ssize_t>(size)) {
+        ALOGE("Failed to send %s (sent %zd of %zu bytes) on fd %d, error: %s", what, sent, size,
+              fd.get(), strerror(errno));
+
+        terminate();
+        return false;
+    }
+
+    return true;
+}
+
+bool RpcState::rpcRec(const base::unique_fd& fd, const char* what, void* data, size_t size) {
+    if (size > std::numeric_limits<ssize_t>::max()) {
+        ALOGE("Cannot rec %s at size %zu (too big)", what, size);
+        terminate();
+        return false;
+    }
+
+    ssize_t recd = TEMP_FAILURE_RETRY(recv(fd.get(), data, size, MSG_WAITALL | MSG_NOSIGNAL));
+
+    if (recd < 0 || recd != static_cast<ssize_t>(size)) {
+        terminate();
+
+        if (recd == 0 && errno == 0) {
+            LOG_RPC_DETAIL("No more data when trying to read %s on fd %d", what, fd.get());
+            return false;
+        }
+
+        ALOGE("Failed to read %s (received %zd of %zu bytes) on fd %d, error: %s", what, recd, size,
+              fd.get(), strerror(errno));
+        return false;
+    } else {
+        LOG_RPC_DETAIL("Received %s on fd %d: %s", what, fd.get(), hexString(data, size).c_str());
+    }
+
+    return true;
+}
+
+sp<IBinder> RpcState::getRootObject(const base::unique_fd& fd, const sp<RpcSession>& session) {
+    Parcel data;
+    data.markForRpc(session);
+    Parcel reply;
+
+    status_t status = transact(fd, RpcAddress::zero(), RPC_SPECIAL_TRANSACT_GET_ROOT, data, session,
+                               &reply, 0);
+    if (status != OK) {
+        ALOGE("Error getting root object: %s", statusToString(status).c_str());
+        return nullptr;
+    }
+
+    return reply.readStrongBinder();
+}
+
+status_t RpcState::getMaxThreads(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                 size_t* maxThreadsOut) {
+    Parcel data;
+    data.markForRpc(session);
+    Parcel reply;
+
+    status_t status = transact(fd, RpcAddress::zero(), RPC_SPECIAL_TRANSACT_GET_MAX_THREADS, data,
+                               session, &reply, 0);
+    if (status != OK) {
+        ALOGE("Error getting max threads: %s", statusToString(status).c_str());
+        return status;
+    }
+
+    int32_t maxThreads;
+    status = reply.readInt32(&maxThreads);
+    if (status != OK) return status;
+    if (maxThreads <= 0) {
+        ALOGE("Error invalid max maxThreads: %d", maxThreads);
+        return BAD_VALUE;
+    }
+
+    *maxThreadsOut = maxThreads;
+    return OK;
+}
+
+status_t RpcState::getSessionId(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                int32_t* sessionIdOut) {
+    Parcel data;
+    data.markForRpc(session);
+    Parcel reply;
+
+    status_t status = transact(fd, RpcAddress::zero(), RPC_SPECIAL_TRANSACT_GET_SESSION_ID, data,
+                               session, &reply, 0);
+    if (status != OK) {
+        ALOGE("Error getting session ID: %s", statusToString(status).c_str());
+        return status;
+    }
+
+    int32_t sessionId;
+    status = reply.readInt32(&sessionId);
+    if (status != OK) return status;
+
+    *sessionIdOut = sessionId;
+    return OK;
+}
+
+status_t RpcState::transact(const base::unique_fd& fd, const RpcAddress& address, uint32_t code,
+                            const Parcel& data, const sp<RpcSession>& session, Parcel* reply,
+                            uint32_t flags) {
+    uint64_t asyncNumber = 0;
+
+    if (!address.isZero()) {
+        std::lock_guard<std::mutex> _l(mNodeMutex);
+        if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races
+        auto it = mNodeForAddress.find(address);
+        LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(), "Sending transact on unknown address %s",
+                            address.toString().c_str());
+
+        if (flags & IBinder::FLAG_ONEWAY) {
+            asyncNumber = it->second.asyncNumber++;
+        }
+    }
+
+    if (!data.isForRpc()) {
+        ALOGE("Refusing to send RPC with parcel not crafted for RPC");
+        return BAD_TYPE;
+    }
+
+    if (data.objectsCount() != 0) {
+        ALOGE("Parcel at %p has attached objects but is being used in an RPC call", &data);
+        return BAD_TYPE;
+    }
+
+    RpcWireTransaction transaction{
+            .address = address.viewRawEmbedded(),
+            .code = code,
+            .flags = flags,
+            .asyncNumber = asyncNumber,
+    };
+
+    ByteVec transactionData(sizeof(RpcWireTransaction) + data.dataSize());
+    if (!transactionData.valid()) {
+        return NO_MEMORY;
+    }
+
+    memcpy(transactionData.data() + 0, &transaction, sizeof(RpcWireTransaction));
+    memcpy(transactionData.data() + sizeof(RpcWireTransaction), data.data(), data.dataSize());
+
+    if (transactionData.size() > std::numeric_limits<uint32_t>::max()) {
+        ALOGE("Transaction size too big %zu", transactionData.size());
+        return BAD_VALUE;
+    }
+
+    RpcWireHeader command{
+            .command = RPC_COMMAND_TRANSACT,
+            .bodySize = static_cast<uint32_t>(transactionData.size()),
+    };
+
+    if (!rpcSend(fd, "transact header", &command, sizeof(command))) {
+        return DEAD_OBJECT;
+    }
+    if (!rpcSend(fd, "command body", transactionData.data(), transactionData.size())) {
+        return DEAD_OBJECT;
+    }
+
+    if (flags & IBinder::FLAG_ONEWAY) {
+        return OK; // do not wait for result
+    }
+
+    LOG_ALWAYS_FATAL_IF(reply == nullptr, "Reply parcel must be used for synchronous transaction.");
+
+    return waitForReply(fd, session, reply);
+}
+
+static void cleanup_reply_data(Parcel* p, const uint8_t* data, size_t dataSize,
+                               const binder_size_t* objects, size_t objectsCount) {
+    (void)p;
+    delete[] const_cast<uint8_t*>(data - offsetof(RpcWireReply, data));
+    (void)dataSize;
+    LOG_ALWAYS_FATAL_IF(objects != nullptr);
+    LOG_ALWAYS_FATAL_IF(objectsCount, 0);
+}
+
+status_t RpcState::waitForReply(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                Parcel* reply) {
+    RpcWireHeader command;
+    while (true) {
+        if (!rpcRec(fd, "command header", &command, sizeof(command))) {
+            return DEAD_OBJECT;
+        }
+
+        if (command.command == RPC_COMMAND_REPLY) break;
+
+        status_t status = processServerCommand(fd, session, command);
+        if (status != OK) return status;
+    }
+
+    ByteVec data(command.bodySize);
+    if (!data.valid()) {
+        return NO_MEMORY;
+    }
+
+    if (!rpcRec(fd, "reply body", data.data(), command.bodySize)) {
+        return DEAD_OBJECT;
+    }
+
+    if (command.bodySize < sizeof(RpcWireReply)) {
+        ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcWireReply. Terminating!",
+              sizeof(RpcWireReply), command.bodySize);
+        terminate();
+        return BAD_VALUE;
+    }
+    RpcWireReply* rpcReply = reinterpret_cast<RpcWireReply*>(data.data());
+    if (rpcReply->status != OK) return rpcReply->status;
+
+    data.release();
+    reply->ipcSetDataReference(rpcReply->data, command.bodySize - offsetof(RpcWireReply, data),
+                               nullptr, 0, cleanup_reply_data);
+
+    reply->markForRpc(session);
+
+    return OK;
+}
+
+status_t RpcState::sendDecStrong(const base::unique_fd& fd, const RpcAddress& addr) {
+    {
+        std::lock_guard<std::mutex> _l(mNodeMutex);
+        if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races
+        auto it = mNodeForAddress.find(addr);
+        LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(), "Sending dec strong on unknown address %s",
+                            addr.toString().c_str());
+        LOG_ALWAYS_FATAL_IF(it->second.timesRecd <= 0, "Bad dec strong %s",
+                            addr.toString().c_str());
+
+        it->second.timesRecd--;
+        if (it->second.timesRecd == 0 && it->second.timesSent == 0) {
+            mNodeForAddress.erase(it);
+        }
+    }
+
+    RpcWireHeader cmd = {
+            .command = RPC_COMMAND_DEC_STRONG,
+            .bodySize = sizeof(RpcWireAddress),
+    };
+    if (!rpcSend(fd, "dec ref header", &cmd, sizeof(cmd))) return DEAD_OBJECT;
+    if (!rpcSend(fd, "dec ref body", &addr.viewRawEmbedded(), sizeof(RpcWireAddress)))
+        return DEAD_OBJECT;
+    return OK;
+}
+
+status_t RpcState::getAndExecuteCommand(const base::unique_fd& fd, const sp<RpcSession>& session) {
+    LOG_RPC_DETAIL("getAndExecuteCommand on fd %d", fd.get());
+
+    RpcWireHeader command;
+    if (!rpcRec(fd, "command header", &command, sizeof(command))) {
+        return DEAD_OBJECT;
+    }
+
+    return processServerCommand(fd, session, command);
+}
+
+status_t RpcState::processServerCommand(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                        const RpcWireHeader& command) {
+    switch (command.command) {
+        case RPC_COMMAND_TRANSACT:
+            return processTransact(fd, session, command);
+        case RPC_COMMAND_DEC_STRONG:
+            return processDecStrong(fd, command);
+    }
+
+    // We should always know the version of the opposing side, and since the
+    // RPC-binder-level wire protocol is not self synchronizing, we have no way
+    // to understand where the current command ends and the next one begins. We
+    // also can't consider it a fatal error because this would allow any client
+    // to kill us, so ending the session for misbehaving client.
+    ALOGE("Unknown RPC command %d - terminating session", command.command);
+    terminate();
+    return DEAD_OBJECT;
+}
+status_t RpcState::processTransact(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                   const RpcWireHeader& command) {
+    LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_TRANSACT, "command: %d", command.command);
+
+    ByteVec transactionData(command.bodySize);
+    if (!transactionData.valid()) {
+        return NO_MEMORY;
+    }
+    if (!rpcRec(fd, "transaction body", transactionData.data(), transactionData.size())) {
+        return DEAD_OBJECT;
+    }
+
+    return processTransactInternal(fd, session, std::move(transactionData));
+}
+
+static void do_nothing_to_transact_data(Parcel* p, const uint8_t* data, size_t dataSize,
+                                        const binder_size_t* objects, size_t objectsCount) {
+    (void)p;
+    (void)data;
+    (void)dataSize;
+    (void)objects;
+    (void)objectsCount;
+}
+
+status_t RpcState::processTransactInternal(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                           ByteVec transactionData) {
+    if (transactionData.size() < sizeof(RpcWireTransaction)) {
+        ALOGE("Expecting %zu but got %zu bytes for RpcWireTransaction. Terminating!",
+              sizeof(RpcWireTransaction), transactionData.size());
+        terminate();
+        return BAD_VALUE;
+    }
+    RpcWireTransaction* transaction = reinterpret_cast<RpcWireTransaction*>(transactionData.data());
+
+    // TODO(b/182939933): heap allocation just for lookup in mNodeForAddress,
+    // maybe add an RpcAddress 'view' if the type remains 'heavy'
+    auto addr = RpcAddress::fromRawEmbedded(&transaction->address);
+
+    status_t replyStatus = OK;
+    sp<IBinder> target;
+    if (!addr.isZero()) {
+        std::lock_guard<std::mutex> _l(mNodeMutex);
+
+        auto it = mNodeForAddress.find(addr);
+        if (it == mNodeForAddress.end()) {
+            ALOGE("Unknown binder address %s.", addr.toString().c_str());
+            replyStatus = BAD_VALUE;
+        } else {
+            target = it->second.binder.promote();
+            if (target == nullptr) {
+                // This can happen if the binder is remote in this process, and
+                // another thread has called the last decStrong on this binder.
+                // However, for local binders, it indicates a misbehaving client
+                // (any binder which is being transacted on should be holding a
+                // strong ref count), so in either case, terminating the
+                // session.
+                ALOGE("While transacting, binder has been deleted at address %s. Terminating!",
+                      addr.toString().c_str());
+                terminate();
+                replyStatus = BAD_VALUE;
+            } else if (target->localBinder() == nullptr) {
+                ALOGE("Transactions can only go to local binders, not address %s. Terminating!",
+                      addr.toString().c_str());
+                terminate();
+                replyStatus = BAD_VALUE;
+            } else if (transaction->flags & IBinder::FLAG_ONEWAY) {
+                if (transaction->asyncNumber != it->second.asyncNumber) {
+                    // we need to process some other asynchronous transaction
+                    // first
+                    // TODO(b/183140903): limit enqueues/detect overfill for bad client
+                    // TODO(b/183140903): detect when an object is deleted when it still has
+                    //        pending async transactions
+                    it->second.asyncTodo.push(BinderNode::AsyncTodo{
+                            .data = std::move(transactionData),
+                            .asyncNumber = transaction->asyncNumber,
+                    });
+                    LOG_RPC_DETAIL("Enqueuing %" PRId64 " on %s", transaction->asyncNumber,
+                                   addr.toString().c_str());
+                    return OK;
+                }
+            }
+        }
+    }
+
+    Parcel reply;
+    reply.markForRpc(session);
+
+    if (replyStatus == OK) {
+        Parcel data;
+        // transaction->data is owned by this function. Parcel borrows this data and
+        // only holds onto it for the duration of this function call. Parcel will be
+        // deleted before the 'transactionData' object.
+        data.ipcSetDataReference(transaction->data,
+                                 transactionData.size() - offsetof(RpcWireTransaction, data),
+                                 nullptr /*object*/, 0 /*objectCount*/,
+                                 do_nothing_to_transact_data);
+        data.markForRpc(session);
+
+        if (target) {
+            replyStatus = target->transact(transaction->code, data, &reply, transaction->flags);
+        } else {
+            LOG_RPC_DETAIL("Got special transaction %u", transaction->code);
+
+            sp<RpcServer> server = session->server().promote();
+            if (server) {
+                // special case for 'zero' address (special server commands)
+                switch (transaction->code) {
+                    case RPC_SPECIAL_TRANSACT_GET_ROOT: {
+                        replyStatus = reply.writeStrongBinder(server->getRootObject());
+                        break;
+                    }
+                    case RPC_SPECIAL_TRANSACT_GET_MAX_THREADS: {
+                        replyStatus = reply.writeInt32(server->getMaxThreads());
+                        break;
+                    }
+                    case RPC_SPECIAL_TRANSACT_GET_SESSION_ID: {
+                        // only sessions w/ services can be the source of a
+                        // session ID (so still guarded by non-null server)
+                        //
+                        // sessions associated with servers must have an ID
+                        // (hence abort)
+                        int32_t id = session->getPrivateAccessorForId().get().value();
+                        replyStatus = reply.writeInt32(id);
+                        break;
+                    }
+                    default: {
+                        replyStatus = UNKNOWN_TRANSACTION;
+                    }
+                }
+            } else {
+                ALOGE("Special command sent, but no server object attached.");
+            }
+        }
+    }
+
+    if (transaction->flags & IBinder::FLAG_ONEWAY) {
+        if (replyStatus != OK) {
+            ALOGW("Oneway call failed with error: %d", replyStatus);
+        }
+
+        LOG_RPC_DETAIL("Processed async transaction %" PRId64 " on %s", transaction->asyncNumber,
+                       addr.toString().c_str());
+
+        // Check to see if there is another asynchronous transaction to process.
+        // This behavior differs from binder behavior, since in the binder
+        // driver, asynchronous transactions will be processed after existing
+        // pending binder transactions on the queue. The downside of this is
+        // that asynchronous transactions can be drowned out by synchronous
+        // transactions. However, we have no easy way to queue these
+        // transactions after the synchronous transactions we may want to read
+        // from the wire. So, in socket binder here, we have the opposite
+        // downside: asynchronous transactions may drown out synchronous
+        // transactions.
+        {
+            std::unique_lock<std::mutex> _l(mNodeMutex);
+            auto it = mNodeForAddress.find(addr);
+            // last refcount dropped after this transaction happened
+            if (it == mNodeForAddress.end()) return OK;
+
+            // note - only updated now, instead of later, so that other threads
+            // will queue any later transactions
+
+            // TODO(b/183140903): support > 2**64 async transactions
+            //     (we can do this by allowing asyncNumber to wrap, since we
+            //     don't expect more than 2**64 simultaneous transactions)
+            it->second.asyncNumber++;
+
+            if (it->second.asyncTodo.size() == 0) return OK;
+            if (it->second.asyncTodo.top().asyncNumber == it->second.asyncNumber) {
+                LOG_RPC_DETAIL("Found next async transaction %" PRId64 " on %s",
+                               it->second.asyncNumber, addr.toString().c_str());
+
+                // justification for const_cast (consider avoiding priority_queue):
+                // - AsyncTodo operator< doesn't depend on 'data' object
+                // - gotta go fast
+                ByteVec data = std::move(
+                        const_cast<BinderNode::AsyncTodo&>(it->second.asyncTodo.top()).data);
+                it->second.asyncTodo.pop();
+                _l.unlock();
+                return processTransactInternal(fd, session, std::move(data));
+            }
+        }
+        return OK;
+    }
+
+    RpcWireReply rpcReply{
+            .status = replyStatus,
+    };
+
+    ByteVec replyData(sizeof(RpcWireReply) + reply.dataSize());
+    if (!replyData.valid()) {
+        return NO_MEMORY;
+    }
+    memcpy(replyData.data() + 0, &rpcReply, sizeof(RpcWireReply));
+    memcpy(replyData.data() + sizeof(RpcWireReply), reply.data(), reply.dataSize());
+
+    if (replyData.size() > std::numeric_limits<uint32_t>::max()) {
+        ALOGE("Reply size too big %zu", transactionData.size());
+        terminate();
+        return BAD_VALUE;
+    }
+
+    RpcWireHeader cmdReply{
+            .command = RPC_COMMAND_REPLY,
+            .bodySize = static_cast<uint32_t>(replyData.size()),
+    };
+
+    if (!rpcSend(fd, "reply header", &cmdReply, sizeof(RpcWireHeader))) {
+        return DEAD_OBJECT;
+    }
+    if (!rpcSend(fd, "reply body", replyData.data(), replyData.size())) {
+        return DEAD_OBJECT;
+    }
+    return OK;
+}
+
+status_t RpcState::processDecStrong(const base::unique_fd& fd, const RpcWireHeader& command) {
+    LOG_ALWAYS_FATAL_IF(command.command != RPC_COMMAND_DEC_STRONG, "command: %d", command.command);
+
+    ByteVec commandData(command.bodySize);
+    if (!commandData.valid()) {
+        return NO_MEMORY;
+    }
+    if (!rpcRec(fd, "dec ref body", commandData.data(), commandData.size())) {
+        return DEAD_OBJECT;
+    }
+
+    if (command.bodySize < sizeof(RpcWireAddress)) {
+        ALOGE("Expecting %zu but got %" PRId32 " bytes for RpcWireAddress. Terminating!",
+              sizeof(RpcWireAddress), command.bodySize);
+        terminate();
+        return BAD_VALUE;
+    }
+    RpcWireAddress* address = reinterpret_cast<RpcWireAddress*>(commandData.data());
+
+    // TODO(b/182939933): heap allocation just for lookup
+    auto addr = RpcAddress::fromRawEmbedded(address);
+    std::unique_lock<std::mutex> _l(mNodeMutex);
+    auto it = mNodeForAddress.find(addr);
+    if (it == mNodeForAddress.end()) {
+        ALOGE("Unknown binder address %s for dec strong.", addr.toString().c_str());
+        return OK;
+    }
+
+    sp<IBinder> target = it->second.binder.promote();
+    if (target == nullptr) {
+        ALOGE("While requesting dec strong, binder has been deleted at address %s. Terminating!",
+              addr.toString().c_str());
+        terminate();
+        return BAD_VALUE;
+    }
+
+    if (it->second.timesSent == 0) {
+        ALOGE("No record of sending binder, but requested decStrong: %s", addr.toString().c_str());
+        return OK;
+    }
+
+    LOG_ALWAYS_FATAL_IF(it->second.sentRef == nullptr, "Inconsistent state, lost ref for %s",
+                        addr.toString().c_str());
+
+    sp<IBinder> tempHold;
+
+    it->second.timesSent--;
+    if (it->second.timesSent == 0) {
+        tempHold = it->second.sentRef;
+        it->second.sentRef = nullptr;
+
+        if (it->second.timesRecd == 0) {
+            mNodeForAddress.erase(it);
+        }
+    }
+
+    _l.unlock();
+    tempHold = nullptr; // destructor may make binder calls on this session
+
+    return OK;
+}
+
+} // namespace android
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
new file mode 100644
index 0000000..83d0344
--- /dev/null
+++ b/libs/binder/RpcState.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <binder/RpcSession.h>
+
+#include <map>
+#include <optional>
+#include <queue>
+
+namespace android {
+
+struct RpcWireHeader;
+
+/**
+ * Log a lot more information about RPC calls, when debugging issues. Usually,
+ * you would want to enable this in only one process. If repeated issues require
+ * a specific subset of logs to debug, this could be broken up like
+ * IPCThreadState's.
+ */
+#define SHOULD_LOG_RPC_DETAIL false
+
+#if SHOULD_LOG_RPC_DETAIL
+#define LOG_RPC_DETAIL(...) ALOGI(__VA_ARGS__)
+#else
+#define LOG_RPC_DETAIL(...) ALOGV(__VA_ARGS__) // for type checking
+#endif
+
+/**
+ * Abstracts away management of ref counts and the wire format from
+ * RpcSession
+ */
+class RpcState {
+public:
+    RpcState();
+    ~RpcState();
+
+    // TODO(b/182940634): combine some special transactions into one "getServerInfo" call?
+    sp<IBinder> getRootObject(const base::unique_fd& fd, const sp<RpcSession>& session);
+    status_t getMaxThreads(const base::unique_fd& fd, const sp<RpcSession>& session,
+                           size_t* maxThreadsOut);
+    status_t getSessionId(const base::unique_fd& fd, const sp<RpcSession>& session,
+                          int32_t* sessionIdOut);
+
+    [[nodiscard]] status_t transact(const base::unique_fd& fd, const RpcAddress& address,
+                                    uint32_t code, const Parcel& data,
+                                    const sp<RpcSession>& session, Parcel* reply, uint32_t flags);
+    [[nodiscard]] status_t sendDecStrong(const base::unique_fd& fd, const RpcAddress& address);
+    [[nodiscard]] status_t getAndExecuteCommand(const base::unique_fd& fd,
+                                                const sp<RpcSession>& session);
+
+    /**
+     * Called by Parcel for outgoing binders. This implies one refcount of
+     * ownership to the outgoing binder.
+     */
+    [[nodiscard]] status_t onBinderLeaving(const sp<RpcSession>& session, const sp<IBinder>& binder,
+                                           RpcAddress* outAddress);
+
+    /**
+     * Called by Parcel for incoming binders. This either returns the refcount
+     * to the process, if this process already has one, or it takes ownership of
+     * that refcount
+     */
+    sp<IBinder> onBinderEntering(const sp<RpcSession>& session, const RpcAddress& address);
+
+    size_t countBinders();
+    void dump();
+
+private:
+    /**
+     * Called when reading or writing data to a session fails to clean up
+     * data associated with the session in order to cleanup binders.
+     * Specifically, we have a strong dependency cycle, since BpBinder is
+     * OBJECT_LIFETIME_WEAK (so that onAttemptIncStrong may return true).
+     *
+     *     BpBinder -> RpcSession -> RpcState
+     *      ^-----------------------------/
+     *
+     * In the success case, eventually all refcounts should be propagated over
+     * the session, though this could also be called to eagerly cleanup
+     * the session.
+     *
+     * WARNING: RpcState is responsible for calling this when the session is
+     * no longer recoverable.
+     */
+    void terminate();
+
+    // alternative to std::vector<uint8_t> that doesn't abort on too big of allocations
+    struct ByteVec {
+        explicit ByteVec(size_t size)
+              : mData(size > 0 ? new (std::nothrow) uint8_t[size] : nullptr), mSize(size) {}
+        bool valid() { return mSize == 0 || mData != nullptr; }
+        size_t size() { return mSize; }
+        uint8_t* data() { return mData.get(); }
+        uint8_t* release() { return mData.release(); }
+
+    private:
+        std::unique_ptr<uint8_t[]> mData;
+        size_t mSize;
+    };
+
+    [[nodiscard]] bool rpcSend(const base::unique_fd& fd, const char* what, const void* data,
+                               size_t size);
+    [[nodiscard]] bool rpcRec(const base::unique_fd& fd, const char* what, void* data, size_t size);
+
+    [[nodiscard]] status_t waitForReply(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                        Parcel* reply);
+    [[nodiscard]] status_t processServerCommand(const base::unique_fd& fd,
+                                                const sp<RpcSession>& session,
+                                                const RpcWireHeader& command);
+    [[nodiscard]] status_t processTransact(const base::unique_fd& fd, const sp<RpcSession>& session,
+                                           const RpcWireHeader& command);
+    [[nodiscard]] status_t processTransactInternal(const base::unique_fd& fd,
+                                                   const sp<RpcSession>& session,
+                                                   ByteVec transactionData);
+    [[nodiscard]] status_t processDecStrong(const base::unique_fd& fd,
+                                            const RpcWireHeader& command);
+
+    struct BinderNode {
+        // Two cases:
+        // A - local binder we are serving
+        // B - remote binder, we are sending transactions to
+        wp<IBinder> binder;
+
+        // if timesSent > 0, this will be equal to binder.promote()
+        sp<IBinder> sentRef;
+
+        // Number of times we've sent this binder out of process, which
+        // translates to an implicit strong count. A client must send RPC binder
+        // socket's dec ref for each time it is sent out of process in order to
+        // deallocate it. Note, a proxy binder we are holding onto might be
+        // sent (this is important when the only remaining refcount of this
+        // binder is the one associated with a transaction sending it back to
+        // its server)
+        size_t timesSent = 0;
+
+        // Number of times we've received this binder, each time corresponds to
+        // a reference we hold over the wire (not a local incStrong/decStrong)
+        size_t timesRecd = 0;
+
+        // transaction ID, for async transactions
+        uint64_t asyncNumber = 0;
+
+        //
+        // CASE A - local binder we are serving
+        //
+
+        // async transaction queue, _only_ for local binder
+        struct AsyncTodo {
+            ByteVec data;
+            uint64_t asyncNumber = 0;
+
+            bool operator<(const AsyncTodo& o) const {
+                return asyncNumber > /* !!! */ o.asyncNumber;
+            }
+        };
+        std::priority_queue<AsyncTodo> asyncTodo;
+
+        //
+        // CASE B - remote binder, we are sending transactions to
+        //
+
+        // (no additional data specific to remote binders)
+    };
+
+    std::mutex mNodeMutex;
+    bool mTerminated = false;
+    // binders known by both sides of a session
+    std::map<RpcAddress, BinderNode> mNodeForAddress;
+};
+
+} // namespace android
diff --git a/libs/binder/RpcWireFormat.h b/libs/binder/RpcWireFormat.h
new file mode 100644
index 0000000..c5fa008
--- /dev/null
+++ b/libs/binder/RpcWireFormat.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+namespace android {
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wpadded"
+
+enum : uint32_t {
+    /**
+     * follows is RpcWireTransaction, if flags != oneway, reply w/ RPC_COMMAND_REPLY expected
+     */
+    RPC_COMMAND_TRANSACT = 0,
+    /**
+     * follows is RpcWireReply
+     */
+    RPC_COMMAND_REPLY,
+    /**
+     * follows is RpcWireAddress
+     *
+     * note - this in the protocol directly instead of as a 'special
+     * transaction' in order to keep it as lightweight as possible (we don't
+     * want to create a 'Parcel' object for every decref)
+     */
+    RPC_COMMAND_DEC_STRONG,
+};
+
+/**
+ * These commands are used when the address in an RpcWireTransaction is zero'd
+ * out (no address). This allows the transact/reply flow to be used for
+ * additional server commands, without making the protocol for
+ * transactions/replies more complicated.
+ */
+enum : uint32_t {
+    RPC_SPECIAL_TRANSACT_GET_ROOT = 0,
+    RPC_SPECIAL_TRANSACT_GET_MAX_THREADS = 1,
+    RPC_SPECIAL_TRANSACT_GET_SESSION_ID = 2,
+};
+
+constexpr int32_t RPC_SESSION_ID_NEW = -1;
+
+// serialization is like:
+// |RpcWireHeader|struct desginated by 'command'| (over and over again)
+
+struct RpcWireHeader {
+    uint32_t command; // RPC_COMMAND_*
+    uint32_t bodySize;
+
+    uint32_t reserved[2];
+};
+
+struct RpcWireAddress {
+    uint8_t address[32];
+};
+
+struct RpcWireTransaction {
+    RpcWireAddress address;
+    uint32_t code;
+    uint32_t flags;
+
+    uint64_t asyncNumber;
+
+    uint32_t reserved[4];
+
+    uint8_t data[0];
+};
+
+struct RpcWireReply {
+    int32_t status; // transact return
+    uint8_t data[0];
+};
+
+#pragma clang diagnostic pop
+
+} // namespace android
diff --git a/libs/binder/Stability.cpp b/libs/binder/Stability.cpp
index 339c538..709cf67 100644
--- a/libs/binder/Stability.cpp
+++ b/libs/binder/Stability.cpp
@@ -38,6 +38,30 @@
     };
 }
 
+void Stability::forceDowngradeToStability(const sp<IBinder>& binder, Level level) {
+    // Downgrading a remote binder would require also copying the version from
+    // the binder sent here. In practice though, we don't need to downgrade the
+    // stability of a remote binder, since this would as an effect only restrict
+    // what we can do to it.
+    LOG_ALWAYS_FATAL_IF(!binder || !binder->localBinder(), "Can only downgrade local binder");
+
+    auto stability = Category::currentFromLevel(level);
+    status_t result = setRepr(binder.get(), stability.repr(), REPR_LOG | REPR_ALLOW_DOWNGRADE);
+    LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
+}
+
+void Stability::forceDowngradeToLocalStability(const sp<IBinder>& binder) {
+    forceDowngradeToStability(binder, getLocalLevel());
+}
+
+void Stability::forceDowngradeToSystemStability(const sp<IBinder>& binder) {
+    forceDowngradeToStability(binder, Level::SYSTEM);
+}
+
+void Stability::forceDowngradeToVendorStability(const sp<IBinder>& binder) {
+    forceDowngradeToStability(binder, Level::VENDOR);
+}
+
 std::string Stability::Category::debugString() {
     return levelString(level) + " wire protocol version "
         + std::to_string(version);
@@ -45,13 +69,13 @@
 
 void Stability::markCompilationUnit(IBinder* binder) {
     auto stability = Category::currentFromLevel(getLocalLevel());
-    status_t result = setRepr(binder, stability.repr(), true /*log*/);
+    status_t result = setRepr(binder, stability.repr(), REPR_LOG);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
 void Stability::markVintf(IBinder* binder) {
     auto stability = Category::currentFromLevel(Level::VINTF);
-    status_t result = setRepr(binder, stability.repr(), true /*log*/);
+    status_t result = setRepr(binder, stability.repr(), REPR_LOG);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
@@ -62,7 +86,7 @@
 
 void Stability::markVndk(IBinder* binder) {
     auto stability = Category::currentFromLevel(Level::VENDOR);
-    status_t result = setRepr(binder, stability.repr(), true /*log*/);
+    status_t result = setRepr(binder, stability.repr(), REPR_LOG);
     LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object.");
 }
 
@@ -72,7 +96,7 @@
 
 void Stability::tryMarkCompilationUnit(IBinder* binder) {
     auto stability = Category::currentFromLevel(getLocalLevel());
-    (void) setRepr(binder, stability.repr(), false /*log*/);
+    (void) setRepr(binder, stability.repr(), REPR_NONE);
 }
 
 Stability::Level Stability::getLocalLevel() {
@@ -94,7 +118,10 @@
 #endif
 }
 
-status_t Stability::setRepr(IBinder* binder, int32_t representation, bool log) {
+status_t Stability::setRepr(IBinder* binder, int32_t representation, uint32_t flags) {
+    bool log = flags & REPR_LOG;
+    bool allowDowngrade = flags & REPR_ALLOW_DOWNGRADE;
+
     auto current = getCategory(binder);
     auto setting = Category::fromRepr(representation);
 
@@ -129,7 +156,11 @@
         return BAD_TYPE;
     }
 
-    if (current.repr() != 0 && current != setting) {
+    if (current == setting) return OK;
+
+    bool hasAlreadyBeenSet = current.repr() != 0;
+    bool isAllowedDowngrade = allowDowngrade && check(current, setting.level);
+    if (hasAlreadyBeenSet && !isAllowedDowngrade) {
         if (log) {
             ALOGE("Interface being set with %s but it is already marked as %s",
                   setting.debugString().c_str(),
@@ -138,7 +169,11 @@
         return BAD_TYPE;
     }
 
-    if (current == setting) return OK;
+    if (isAllowedDowngrade) {
+        ALOGI("Interface set with %s downgraded to %s stability",
+              current.debugString().c_str(),
+              setting.debugString().c_str());
+    }
 
     BBinder* local = binder->localBinder();
     if (local != nullptr) {
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 97e282e..b58d919 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -10,6 +10,9 @@
       "name": "binderAllocationLimits"
     },
     {
+      "name": "binderClearBufTest"
+    },
+    {
       "name": "binderDriverInterfaceTest"
     },
     {
@@ -19,11 +22,10 @@
       "name": "binderParcelTest"
     },
     {
-      "name": "binderParcelTest",
-      "host": true
+      "name": "binderLibTest"
     },
     {
-      "name": "binderLibTest"
+      "name": "binderRpcTest"
     },
     {
       "name": "binderStabilityTest"
@@ -41,6 +43,9 @@
       "name": "aidl_integration_test"
     },
     {
+      "name": "memunreachable_binder_test"
+    },
+    {
       "name": "libbinderthreadstateutils_test"
     },
     {
@@ -62,6 +67,9 @@
     },
     {
       "name": "binderRustNdkInteropTest"
+    },
+    {
+      "name": "rustBinderSerializationTest"
     }
   ]
 }
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index 684a7dc..a0ade50 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -16,7 +16,7 @@
 
 #include <binder/TextOutput.h>
 
-#include <binder/Debug.h>
+#include "Debug.h"
 
 #include <utils/String8.h>
 #include <utils/String16.h>
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 2b1e492..75c4092 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -18,6 +18,7 @@
 
 import android.os.IClientCallback;
 import android.os.IServiceCallback;
+import android.os.ServiceDebugInfo;
 
 /**
  * Basic interface for finding and publishing system services.
@@ -42,9 +43,9 @@
      */
     const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3;
 
-    const int DUMP_FLAG_PRIORITY_ALL = 15;
-             // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
-             // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
+    const int DUMP_FLAG_PRIORITY_ALL =
+             DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
+             | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT;
 
     /* Allows services to dump sections in protobuf format. */
     const int DUMP_FLAG_PROTO = 1 << 4;
@@ -107,6 +108,11 @@
     @utf8InCpp String[] getDeclaredInstances(@utf8InCpp String iface);
 
     /**
+     * If updatable-via-apex, returns the APEX via which this is updated.
+     */
+    @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name);
+
+    /**
      * Request a callback when the number of clients of the service changes.
      * Used by LazyServiceRegistrar to dynamically stop services that have no clients.
      */
@@ -116,4 +122,9 @@
      * Attempt to unregister and remove a service. Will fail if the service is still in use.
      */
     void tryUnregisterService(@utf8InCpp String name, IBinder service);
+
+    /**
+     * Get debug information for all currently registered services.
+     */
+    ServiceDebugInfo[] getServiceDebugInfo();
 }
diff --git a/libs/binder/aidl/android/os/ServiceDebugInfo.aidl b/libs/binder/aidl/android/os/ServiceDebugInfo.aidl
new file mode 100644
index 0000000..b95d222
--- /dev/null
+++ b/libs/binder/aidl/android/os/ServiceDebugInfo.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Debug information associated with a registered service
+ * @hide
+ */
+parcelable ServiceDebugInfo {
+    /**
+     * Service name (see IServiceManager.addService/checkService/getService)
+     */
+    @utf8InCpp String name;
+    /**
+     * PID of service at the time of registration (may no longer be valid).
+     */
+    int debugPid;
+}
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/binder_module.h
similarity index 72%
rename from libs/binder/include/private/binder/binder_module.h
rename to libs/binder/binder_module.h
index 5a719b8..9dea3b4 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/binder_module.h
@@ -29,18 +29,14 @@
 #undef B_PACK_CHARS
 #endif
 
-#include <sys/ioctl.h>
 #include <linux/android/binder.h>
-
-#ifdef __cplusplus
-namespace android {
-#endif
+#include <sys/ioctl.h>
 
 #ifndef BR_FROZEN_REPLY
 // Temporary definition of BR_FROZEN_REPLY. For production
 // this will come from UAPI binder.h
 #define BR_FROZEN_REPLY _IO('r', 18)
-#endif //BR_FROZEN_REPLY
+#endif // BR_FROZEN_REPLY
 
 #ifndef BINDER_FREEZE
 /*
@@ -53,47 +49,53 @@
     //
     // Group-leader PID of process to be frozen
     //
-    uint32_t            pid;
+    uint32_t pid;
     //
     // Enable(1) / Disable(0) freeze for given PID
     //
-    uint32_t            enable;
+    uint32_t enable;
     //
     // Timeout to wait for transactions to drain.
     // 0: don't wait (ioctl will return EAGAIN if not drained)
     // N: number of ms to wait
-    uint32_t            timeout_ms;
+    uint32_t timeout_ms;
 };
-#endif //BINDER_FREEZE
+#endif // BINDER_FREEZE
 
 #ifndef BINDER_GET_FROZEN_INFO
 
-#define BINDER_GET_FROZEN_INFO          _IOWR('b', 15, struct binder_frozen_status_info)
+#define BINDER_GET_FROZEN_INFO _IOWR('b', 15, struct binder_frozen_status_info)
 
 struct binder_frozen_status_info {
     //
     // Group-leader PID of process to be queried
     //
-    __u32            pid;
+    __u32 pid;
     //
     // Indicates whether the process has received any sync calls since last
     // freeze (cleared at freeze/unfreeze)
     //
-    __u32            sync_recv;
+    __u32 sync_recv;
     //
     // Indicates whether the process has received any async calls since last
     // freeze (cleared at freeze/unfreeze)
     //
-    __u32            async_recv;
+    __u32 async_recv;
 };
-#endif //BINDER_GET_FROZEN_INFO
+#endif // BINDER_GET_FROZEN_INFO
 
-enum transaction_flags_ext {
-    TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */
-};
+#ifndef BR_ONEWAY_SPAM_SUSPECT
+// Temporary definition of BR_ONEWAY_SPAM_SUSPECT. For production
+// this will come from UAPI binder.h
+#define BR_ONEWAY_SPAM_SUSPECT _IO('r', 19)
+#endif // BR_ONEWAY_SPAM_SUSPECT
 
-#ifdef __cplusplus
-}   // namespace android
-#endif
+#ifndef BINDER_ENABLE_ONEWAY_SPAM_DETECTION
+/*
+ * Temporary definitions for oneway spam detection support. For the final version
+ * these will be defined in the UAPI binder.h file from upstream kernel.
+ */
+#define BINDER_ENABLE_ONEWAY_SPAM_DETECTION _IOW('b', 16, __u32)
+#endif // BINDER_ENABLE_ONEWAY_SPAM_DETECTION
 
 #endif // _BINDER_MODULE_H_
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 7079544..7e9be41 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -131,8 +131,8 @@
     virtual void            onLastStrongRef(const void* id);
     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
 
-    inline  IBinder*        remote()                { return mRemote; }
-    inline  IBinder*        remote() const          { return mRemote; }
+    inline IBinder* remote() const { return mRemote; }
+    inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); }
 
 private:
                             BpRefBase(const BpRefBase& o);
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 22300ac..61bf018 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -17,15 +17,19 @@
 #pragma once
 
 #include <binder/IBinder.h>
+#include <binder/RpcAddress.h>
 #include <utils/KeyedVector.h>
 #include <utils/Mutex.h>
 #include <utils/threads.h>
 
 #include <unordered_map>
+#include <variant>
 
 // ---------------------------------------------------------------------------
 namespace android {
 
+class RpcSession;
+class RpcState;
 namespace internal {
 class Stability;
 }
@@ -36,7 +40,15 @@
 class BpBinder : public IBinder
 {
 public:
-    static BpBinder*    create(int32_t handle);
+    static sp<BpBinder> create(int32_t handle);
+    static sp<BpBinder> create(const sp<RpcSession>& session, const RpcAddress& address);
+
+    /**
+     * Return value:
+     * true - this is associated with a socket RpcSession
+     * false - (usual) binder over e.g. /dev/binder
+     */
+    bool isRpcBinder() const;
 
     virtual const String16&    getInterfaceDescriptor() const;
     virtual bool        isBinderAlive() const;
@@ -108,33 +120,57 @@
         KeyedVector<const void*, entry_t> mObjects;
     };
 
-    class PrivateAccessorForHandle {
+    class PrivateAccessorForId {
     private:
-        friend BpBinder;
-        friend ::android::Parcel;
-        friend ::android::ProcessState;
-        explicit PrivateAccessorForHandle(const BpBinder* binder) : mBinder(binder) {}
-        int32_t handle() const { return mBinder->handle(); }
+        friend class BpBinder;
+        friend class ::android::Parcel;
+        friend class ::android::ProcessState;
+        friend class ::android::RpcState;
+        explicit PrivateAccessorForId(const BpBinder* binder) : mBinder(binder) {}
+
+        // valid if !isRpcBinder
+        int32_t binderHandle() const { return mBinder->binderHandle(); }
+
+        // valid if isRpcBinder
+        const RpcAddress& rpcAddress() const { return mBinder->rpcAddress(); }
+        const sp<RpcSession>& rpcSession() const { return mBinder->rpcSession(); }
+
         const BpBinder* mBinder;
     };
-    const PrivateAccessorForHandle getPrivateAccessorForHandle() const {
-        return PrivateAccessorForHandle(this);
+    const PrivateAccessorForId getPrivateAccessorForId() const {
+        return PrivateAccessorForId(this);
     }
 
 private:
-    friend PrivateAccessorForHandle;
+    friend PrivateAccessorForId;
+    friend class sp<BpBinder>;
 
-    int32_t             handle() const;
-                        BpBinder(int32_t handle,int32_t trackedUid);
+    struct BinderHandle {
+        int32_t handle;
+    };
+    struct RpcHandle {
+        sp<RpcSession> session;
+        RpcAddress address;
+    };
+    using Handle = std::variant<BinderHandle, RpcHandle>;
+
+    int32_t binderHandle() const;
+    const RpcAddress& rpcAddress() const;
+    const sp<RpcSession>& rpcSession() const;
+
+    explicit BpBinder(Handle&& handle);
+    BpBinder(BinderHandle&& handle, int32_t trackedUid);
+    explicit BpBinder(RpcHandle&& handle);
+
     virtual             ~BpBinder();
     virtual void        onFirstRef();
     virtual void        onLastStrongRef(const void* id);
     virtual bool        onIncStrongAttempted(uint32_t flags, const void* id);
 
     friend ::android::internal::Stability;
-            int32_t             mStability;
 
-    const   int32_t             mHandle;
+    int32_t mStability;
+    Handle mHandle;
 
     struct Obituary {
         wp<DeathRecipient> recipient;
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index c8fb448..97c826c 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android-base/unique_fd.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
@@ -49,30 +50,39 @@
 {
 public:
     enum {
-        FIRST_CALL_TRANSACTION  = 0x00000001,
-        LAST_CALL_TRANSACTION   = 0x00ffffff,
+        FIRST_CALL_TRANSACTION = 0x00000001,
+        LAST_CALL_TRANSACTION = 0x00ffffff,
 
-        PING_TRANSACTION        = B_PACK_CHARS('_','P','N','G'),
-        DUMP_TRANSACTION        = B_PACK_CHARS('_','D','M','P'),
-        SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
-        INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
-        SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
-        EXTENSION_TRANSACTION   = B_PACK_CHARS('_', 'E', 'X', 'T'),
-        DEBUG_PID_TRANSACTION   = B_PACK_CHARS('_', 'P', 'I', 'D'),
+        PING_TRANSACTION = B_PACK_CHARS('_', 'P', 'N', 'G'),
+        DUMP_TRANSACTION = B_PACK_CHARS('_', 'D', 'M', 'P'),
+        SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_', 'C', 'M', 'D'),
+        INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
+        SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
+        EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
+        DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
+
+        // See android.os.IBinder.TWEET_TRANSACTION
+        // Most importantly, messages can be anything not exceeding 130 UTF-8
+        // characters, and callees should exclaim "jolly good message old boy!"
+        TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'),
+
+        // See android.os.IBinder.LIKE_TRANSACTION
+        // Improve binder self-esteem.
+        LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'),
 
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
-        FLAG_ONEWAY             = 0x00000001,
+        FLAG_ONEWAY = 0x00000001,
 
         // Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call
         // is made
-        FLAG_CLEAR_BUF          = 0x00000020,
+        FLAG_CLEAR_BUF = 0x00000020,
 
         // Private userspace flag for transaction which is being requested from
         // a vendor context.
-        FLAG_PRIVATE_VENDOR     = 0x10000000,
+        FLAG_PRIVATE_VENDOR = 0x10000000,
     };
 
-                          IBinder();
+    IBinder();
 
     /**
      * Check if this IBinder implements the interface named by
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index f4a21dd..f35e2db 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -143,11 +143,10 @@
     {                                                                   \
         ::android::sp<I##INTERFACE> intr;                               \
         if (obj != nullptr) {                                           \
-            intr = static_cast<I##INTERFACE*>(                          \
-                obj->queryLocalInterface(                               \
-                        I##INTERFACE::descriptor).get());               \
+            intr = ::android::sp<I##INTERFACE>::cast(                   \
+                obj->queryLocalInterface(I##INTERFACE::descriptor));    \
             if (intr == nullptr) {                                      \
-                intr = new Bp##INTERFACE(obj);                          \
+                intr = ::android::sp<Bp##INTERFACE>::make(obj);         \
             }                                                           \
         }                                                               \
         return intr;                                                    \
@@ -186,7 +185,7 @@
 inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
         const String16& _descriptor)
 {
-    if (_descriptor == INTERFACE::descriptor) return this;
+    if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
     return nullptr;
 }
 
diff --git a/libs/binder/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
deleted file mode 100644
index f92d557..0000000
--- a/libs/binder/include/binder/IMediaResourceMonitor.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#ifndef __ANDROID_VNDK__
-
-#include <binder/IInterface.h>
-
-namespace android {
-
-// ----------------------------------------------------------------------
-
-class IMediaResourceMonitor : public IInterface {
-public:
-    DECLARE_META_INTERFACE(MediaResourceMonitor)
-
-    // Values should be in sync with Intent.EXTRA_MEDIA_RESOURCE_TYPE_XXX.
-    enum {
-        TYPE_VIDEO_CODEC = 0,
-        TYPE_AUDIO_CODEC = 1,
-    };
-
-    virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type) = 0;
-
-    enum {
-        NOTIFY_RESOURCE_GRANTED = IBinder::FIRST_CALL_TRANSACTION,
-    };
-};
-
-// ----------------------------------------------------------------------
-
-class BnMediaResourceMonitor : public BnInterface<IMediaResourceMonitor> {
-public:
-    // NOLINTNEXTLINE(google-default-arguments)
-    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-            uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------
-
-} // namespace android
-
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 4da8aa1..23a0cb0 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -110,6 +110,7 @@
             status_t            setupPolling(int* fd);
             status_t            handlePolledCommands();
             void                flushCommands();
+            bool                flushIfNeeded();
 
             void                joinThreadPool(bool isMain = true);
             
@@ -161,6 +162,12 @@
             // This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
             // side.
             static const int32_t kUnsetWorkSource = -1;
+
+            // Create a temp reference until commands in queue flushed to driver
+            // Internal only.
+            // @internal
+            void                 createTransactionReference(RefBase* ref);
+
 private:
                                 IPCThreadState();
                                 ~IPCThreadState();
@@ -204,6 +211,7 @@
             int32_t             mWorkSource;
             // Whether the work source should be propagated.
             bool                mPropagateWorkSource;
+            bool                mIsLooper;
             int32_t             mStrictModePolicy;
             int32_t             mLastTransactionBinderFlags;
             CallRestriction     mCallRestriction;
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 5f0d056..3dbe2c4 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -20,6 +20,8 @@
 #include <utils/Vector.h>
 #include <utils/String16.h>
 
+#include <optional>
+
 namespace android {
 
 // ----------------------------------------------------------------------
@@ -99,6 +101,12 @@
      * Get all instances of a service as declared in the VINTF manifest
      */
     virtual Vector<String16> getDeclaredInstances(const String16& interface) = 0;
+
+    /**
+     * If this instance is updatable via an APEX, returns the APEX with which
+     * this can be updated.
+     */
+    virtual std::optional<String16> updatableViaApex(const String16& name) = 0;
 };
 
 sp<IServiceManager> defaultServiceManager();
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
deleted file mode 100644
index a8faa3f..0000000
--- a/libs/binder/include/binder/IpPrefix.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#ifndef __ANDROID_VNDK__
-
-#include <netinet/in.h>
-
-#include <binder/Parcelable.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace net {
-
-/*
- * C++ implementation of the Java class android.net.IpPrefix
- */
-class IpPrefix : public Parcelable {
-public:
-    IpPrefix() = default;
-    virtual ~IpPrefix() = default;
-    IpPrefix(const IpPrefix& prefix) = default;
-
-    IpPrefix(const struct in6_addr& addr, int32_t plen):
-        mUnion(addr), mPrefixLength(plen), mIsIpv6(true) { }
-
-    IpPrefix(const struct in_addr& addr, int32_t plen):
-        mUnion(addr), mPrefixLength(plen), mIsIpv6(false) { }
-
-    bool getAddressAsIn6Addr(struct in6_addr* addr) const;
-    bool getAddressAsInAddr(struct in_addr* addr) const;
-
-    const struct in6_addr& getAddressAsIn6Addr() const;
-    const struct in_addr& getAddressAsInAddr() const;
-
-    bool isIpv6() const;
-    bool isIpv4() const;
-
-    int32_t getPrefixLength() const;
-
-    void setAddress(const struct in6_addr& addr);
-    void setAddress(const struct in_addr& addr);
-
-    void setPrefixLength(int32_t prefix);
-
-    friend bool operator==(const IpPrefix& lhs, const IpPrefix& rhs);
-
-    friend bool operator!=(const IpPrefix& lhs, const IpPrefix& rhs) {
-        return !(lhs == rhs);
-    }
-
-public:
-    // Overrides
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
-private:
-    union InternalUnion {
-        InternalUnion() = default;
-        explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { }
-        explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { }
-        struct in6_addr mIn6Addr;
-        struct in_addr mInAddr;
-    } mUnion;
-    int32_t mPrefixLength;
-    bool mIsIpv6;
-};
-
-}  // namespace net
-
-}  // namespace android
-
-#else // __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif // __ANDROID_VNDK__
diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h
index d18c88e..9659732 100644
--- a/libs/binder/include/binder/LazyServiceRegistrar.h
+++ b/libs/binder/include/binder/LazyServiceRegistrar.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <functional>
+
 #include <binder/IServiceManager.h>
 #include <binder/Status.h>
 #include <utils/StrongPointer.h>
@@ -53,6 +55,39 @@
       */
      void forcePersist(bool persist);
 
+     /**
+      * Set a callback that is invoked when the active service count (i.e. services with clients)
+      * registered with this process drops to zero (or becomes nonzero).
+      * The callback takes a boolean argument, which is 'true' if there is
+      * at least one service with clients.
+      *
+      * Callback return value:
+      * - false: Default behavior for lazy services (shut down the process if there
+      *          are no clients).
+      * - true:  Don't shut down the process even if there are no clients.
+      *
+      * This callback gives a chance to:
+      * 1 - Perform some additional operations before exiting;
+      * 2 - Prevent the process from exiting by returning "true" from the
+      *     callback.
+      *
+      * This method should be called before 'registerService' to avoid races.
+      */
+     void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback);
+
+    /**
+      * Try to unregister all services previously registered with 'registerService'.
+      * Returns 'true' if successful.
+      */
+     bool tryUnregister();
+
+     /**
+      * Re-register services that were unregistered by 'tryUnregister'.
+      * This method should be called in the case 'tryUnregister' fails
+      * (and should be called on the same thread).
+      */
+     void reRegister();
+
    private:
      std::shared_ptr<internal::ClientCounterCallback> mClientCC;
      LazyServiceRegistrar();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index b49951b..5aaaa0c 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -50,11 +50,14 @@
 class IBinder;
 class IPCThreadState;
 class ProcessState;
+class RpcSession;
 class String8;
 class TextOutput;
 
 class Parcel {
     friend class IPCThreadState;
+    friend class RpcState;
+
 public:
     class ReadableBlob;
     class WritableBlob;
@@ -92,7 +95,21 @@
     // In order to verify this, heap dumps should be used.
     void                markSensitive() const;
 
-    // Writes the RPC header.
+    // For a 'data' Parcel, this should mark the Parcel as being prepared for a
+    // transaction on this specific binder object. Based on this, the format of
+    // the wire binder protocol may change (data is written differently when it
+    // is for an RPC transaction).
+    void markForBinder(const sp<IBinder>& binder);
+
+    // Whenever possible, markForBinder should be preferred. This method is
+    // called automatically on reply Parcels for RPC transactions.
+    void markForRpc(const sp<RpcSession>& session);
+
+    // Whether this Parcel is written for RPC transactions (after calls to
+    // markForBinder or markForRpc).
+    bool isForRpc() const;
+
+    // Writes the IPC/RPC header.
     status_t            writeInterfaceToken(const String16& interface);
     status_t            writeInterfaceToken(const char16_t* str, size_t len);
 
@@ -190,34 +207,47 @@
     // Write an Enum vector with underlying type int8_t.
     // Does not use padding; each byte is contiguous.
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::vector<T>& val);
+    status_t            writeEnumVector(const std::vector<T>& val)
+            { return writeData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::optional<std::vector<T>>& val);
+    status_t            writeEnumVector(const std::optional<std::vector<T>>& val)
+            { return writeData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
+    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")))
+            { return writeData(val); }
     // Write an Enum vector with underlying type != int8_t.
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::vector<T>& val);
+    status_t            writeEnumVector(const std::vector<T>& val)
+            { return writeData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::optional<std::vector<T>>& val);
+    status_t            writeEnumVector(const std::optional<std::vector<T>>& val)
+            { return writeData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")));
+    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead")))
+            { return writeData(val); }
 
     template<typename T>
-    status_t            writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val);
+    status_t            writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val)
+            { return writeData(val); }
     template<typename T>
-    status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
+    status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
+            { return writeData(val); }
     template<typename T>
-    status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")));
+    status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead")))
+            { return writeData(val); }
     template<typename T>
-    status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val);
+    status_t            writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val)
+            { return writeData(val); }
     template<typename T>
-    status_t            writeParcelableVector(const std::vector<T>& val);
+    status_t            writeParcelableVector(const std::vector<T>& val)
+            { return writeData(val); }
 
     template<typename T>
-    status_t            writeNullableParcelable(const std::optional<T>& parcelable);
+    status_t            writeNullableParcelable(const std::optional<T>& parcelable)
+            { return writeData(parcelable); }
     template<typename T>
-    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")));
+    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")))
+            { return writeData(parcelable); }
 
     status_t            writeParcelable(const Parcelable& parcelable);
 
@@ -335,35 +365,48 @@
     // Read an Enum vector with underlying type int8_t.
     // Does not use padding; each byte is contiguous.
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::vector<T>* val) const;
+    status_t            readEnumVector(std::vector<T>* val) const
+            { return readData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
+    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
+            { return readData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::optional<std::vector<T>>* val) const;
+    status_t            readEnumVector(std::optional<std::vector<T>>* val) const
+            { return readData(val); }
     // Read an Enum vector with underlying type != int8_t.
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::vector<T>* val) const;
+    status_t            readEnumVector(std::vector<T>* val) const
+            { return readData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
+    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")))
+            { return readData(val); }
     template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
-    status_t            readEnumVector(std::optional<std::vector<T>>* val) const;
+    status_t            readEnumVector(std::optional<std::vector<T>>* val) const
+            { return readData(val); }
 
     template<typename T>
     status_t            readParcelableVector(
-                            std::optional<std::vector<std::optional<T>>>* val) const;
+                            std::optional<std::vector<std::optional<T>>>* val) const
+            { return readData(val); }
     template<typename T>
     status_t            readParcelableVector(
-                            std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")));
+                            std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead")))
+            { return readData(val); }
     template<typename T>
-    status_t            readParcelableVector(std::vector<T>* val) const;
+    status_t            readParcelableVector(std::vector<T>* val) const
+            { return readData(val); }
 
     status_t            readParcelable(Parcelable* parcelable) const;
 
     template<typename T>
-    status_t            readParcelable(std::optional<T>* parcelable) const;
+    status_t            readParcelable(std::optional<T>* parcelable) const
+            { return readData(parcelable); }
     template<typename T>
-    status_t            readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")));
+    status_t            readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")))
+            { return readData(parcelable); }
 
+    // If strong binder would be nullptr, readStrongBinder() returns an error.
+    // TODO: T must be derived from IInterface, fix for clarity.
     template<typename T>
     status_t            readStrongBinder(sp<T>* val) const;
 
@@ -418,20 +461,13 @@
     template<typename T>
     status_t            read(LightFlattenable<T>& val) const;
 
+    // resizeOutVector is used to resize AIDL out vector parameters.
     template<typename T>
     status_t            resizeOutVector(std::vector<T>* val) const;
     template<typename T>
     status_t            resizeOutVector(std::optional<std::vector<T>>* val) const;
     template<typename T>
     status_t            resizeOutVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead")));
-    template<typename T>
-    status_t            reserveOutVector(std::vector<T>* val, size_t* size) const;
-    template<typename T>
-    status_t            reserveOutVector(std::optional<std::vector<T>>* val,
-                                         size_t* size) const;
-    template<typename T>
-    status_t            reserveOutVector(std::unique_ptr<std::vector<T>>* val,
-                                         size_t* size) const __attribute__((deprecated("use std::optional version instead")));
 
     // Like Parcel.java's readExceptionCode().  Reads the first int32
     // off of a Parcel's header, returning 0 or the negative error
@@ -517,6 +553,7 @@
     void                initState();
     void                scanForFds() const;
     status_t            validateReadData(size_t len) const;
+
     void                updateWorkSourceRequestHeaderPosition() const;
 
     status_t            finishFlattenBinder(const sp<IBinder>& binder);
@@ -535,53 +572,544 @@
     status_t            writeRawNullableParcelable(const Parcelable*
                                                    parcelable);
 
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
-    status_t            writeEnum(const T& val);
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
-    status_t            writeEnum(const T& val);
+    //-----------------------------------------------------------------------------
+    // Generic type read and write methods for Parcel:
+    //
+    // readData(T *value) will read a value from the Parcel.
+    // writeData(const T& value) will write a value to the Parcel.
+    //
+    // Our approach to parceling is based on two overloaded functions
+    // readData() and writeData() that generate parceling code for an
+    // object automatically based on its type. The code from templates are generated at
+    // compile time (if constexpr), and decomposes an object through a call graph matching
+    // recursive descent of the template typename.
+    //
+    // This approach unifies handling of complex objects,
+    // resulting in fewer lines of code, greater consistency,
+    // extensibility to nested types, efficiency (decisions made at compile time),
+    // and better code maintainability and optimization.
+    //
+    // Design decision: Incorporate the read and write code into Parcel rather than
+    // as a non-intrusive serializer that emits a byte stream, as we have
+    // active objects, alignment, legacy code, and historical idiosyncrasies.
+    //
+    // --- Overview
+    //
+    // Parceling is a way of serializing objects into a sequence of bytes for communication
+    // between processes, as part of marshaling data for remote procedure calls.
+    //
+    // The Parcel instance contains objects serialized as bytes, such as the following:
+    //
+    // 1) Ordinary primitive data such as int, float.
+    // 2) Established structured data such as String16, std::string.
+    // 3) Parcelables, which are C++ objects that derive from Parcelable (and thus have a
+    //    readFromParcel and writeToParcel method).  (Similar for Java)
+    // 4) A std::vector<> of such data.
+    // 5) Nullable objects contained in std::optional, std::unique_ptr, or std::shared_ptr.
+    //
+    // And active objects from the Android ecosystem such as:
+    // 6) File descriptors, base::unique_fd (kernel object handles)
+    // 7) Binder objects, sp<IBinder> (active Android RPC handles)
+    //
+    // Objects from (1) through (5) serialize into the mData buffer.
+    // Active objects (6) and (7) serialize into both mData and mObjects buffers.
+    //
+    // --- Data layout details
+    //
+    // Data is read or written to the parcel by recursively decomposing the type of the parameter
+    // type T through readData() and writeData() methods.
+    //
+    // We focus on writeData() here in our explanation of the data layout.
+    //
+    // 1) Alignment
+    // Implementation detail: Regardless of the parameter type, writeData() calls are designed
+    // to finish at a multiple of 4 bytes, the default alignment of the Parcel.
+    //
+    // Writes of single uint8_t, int8_t, enums based on types of size 1, char16_t, etc
+    // will result in 4 bytes being written.  The data is widened to int32 and then written;
+    // hence the position of the nonzero bytes depend on the native endianness of the CPU.
+    //
+    // Writes of primitive values with 8 byte size, double, int64_t, uint64_t,
+    // are stored with 4 byte alignment.  The ARM and x86/x64 permit unaligned reads
+    // and writes (albeit with potential latency/throughput penalty) which may or may
+    // not be observable unless the process is IO bound.
+    //
+    // 2) Parcelables
+    // Parcelables are detected by the type's base class, and implemented through calling
+    // into the Parcelable type's readFromParcel() or writeToParcel() methods.
+    // Historically, due to null object detection, a (int32_t) 1 is prepended to the data written.
+    // Parcelables must have a default constructor (i.e. one that takes no arguments).
+    //
+    // 3) Arrays
+    // Arrays of uint8_t and int8_t, and enums based on size 1 are written as
+    // a contiguous packed byte stream.  Hidden zero padding is applied at the end of the byte
+    // stream to make a multiple of 4 bytes (and prevent info leakage when writing).
+    //
+    // All other array writes can be conceptually thought of as recursively calling
+    // writeData on the individual elements (though may be implemented differently for speed).
+    // As discussed in (1), alignment rules are therefore applied for each element
+    // write (not as an aggregate whole), so the wire representation of data can be
+    // substantially larger.
+    //
+    // Historical Note:
+    // Because of element-wise alignment, CharVector and BoolVector are expanded
+    // element-wise into integers even though they could have been optimized to be packed
+    // just like uint8_t, int8_t (size 1 data).
+    //
+    // 3.1) Arrays accessed by the std::vector type.  This is the default for AIDL.
+    //
+    // 4) Nullables
+    // std::optional, std::unique_ptr, std::shared_ptr are all parceled identically
+    // (i.e. result in identical byte layout).
+    // The target of the std::optional, std::unique_ptr, or std::shared_ptr
+    // can either be a std::vector, String16, std::string, or a Parcelable.
+    //
+    // Detection of null relies on peeking the first int32 data and checking if the
+    // the peeked value is considered invalid for the object:
+    // (-1 for vectors, String16, std::string) (0 for Parcelables).  If the peeked value
+    // is invalid, then a null is returned.
+    //
+    // Application Note: When to use each nullable type:
+    //
+    // std::optional: Embeds the object T by value rather than creating a new instance
+    // by managed pointer as std::unique_ptr or std::shared_ptr.  This will save a malloc
+    // when creating an optional instance.
+    //
+    // Use of std::optionals by value can result in copies of the underlying value stored in it,
+    // so a std::move may be used to move in and move out (for example) a vector value into
+    // the std::optional or for the std::optional itself.
+    //
+    // std::unique_ptr, std::shared_ptr: These are preferred when the lifetime of the object is
+    // already managed by the application.  This reduces unnecessary copying of data
+    // especially when the calls are local in-proc (rather than via binder rpc).
+    //
+    // 5) StrongBinder (sp<IBinder>)
+    // StrongBinder objects are written regardless of null. When read, null StrongBinder values
+    // will be interpreted as UNKNOWN_ERROR if the type is a single argument <sp<T>>
+    // or in a vector argument <std::vector<sp<T>>. However, they will be read without an error
+    // if present in a std::optional, std::unique_ptr, or std::shared_ptr vector, e.g.
+    // <std::optional<std::vector<sp<T>>>.
+    //
+    // See AIDL annotation @Nullable, readStrongBinder(), and readNullableStrongBinder().
+    //
+    // Historical Note: writing a vector of StrongBinder objects <std::vector<sp<T>>
+    // containing a null will not cause an error. However reading such a vector will cause
+    // an error _and_ early termination of the read.
 
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
-    status_t            readEnum(T* pArg) const;
-    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
-    status_t            readEnum(T* pArg) const;
+    //  --- Examples
+    //
+    // Using recursive parceling, we can parcel complex data types so long
+    // as they obey the rules described above.
+    //
+    // Example #1
+    // Parceling of a 3D vector
+    //
+    // std::vector<std::vector<std::vector<int32_t>>> v1 {
+    //     { {1}, {2, 3}, {4} },
+    //     {},
+    //     { {10}, {20}, {30, 40} },
+    // };
+    // Parcel p1;
+    // p1.writeData(v1);
+    // decltype(v1) v2;
+    // p1.setDataPosition(0);
+    // p1.readData(&v2);
+    // ASSERT_EQ(v1, v2);
+    //
+    // Example #2
+    // Parceling of mixed shared pointers
+    //
+    // Parcel p1;
+    // auto sp1 = std::make_shared<std::vector<std::shared_ptr<std::vector<int>>>>(3);
+    // (*sp1)[2] = std::make_shared<std::vector<int>>(3);
+    // (*(*sp1)[2])[2] = 2;
+    // p1.writeData(sp1);
+    // decltype(sp1) sp2;
+    // p1.setDataPosition(0);
+    // p1.readData(&sp2);
+    // ASSERT_EQ((*sp1)[0], (*sp2)[0]); // nullptr
+    // ASSERT_EQ((*sp1)[1], (*sp2)[1]); // nullptr
+    // ASSERT_EQ(*(*sp1)[2], *(*sp2)[2]); // { 0, 0, 2}
 
-    status_t writeByteVectorInternal(const int8_t* data, size_t size);
-    template<typename T>
-    status_t readByteVectorInternal(std::vector<T>* val, size_t size) const;
+    //  --- Helper Methods
+    // TODO: move this to a utils header.
+    //
+    // Determine if a type is a specialization of a templated type
+    // Example: is_specialization_v<T, std::vector>
 
-    template<typename T, typename U>
-    status_t            unsafeReadTypedVector(std::vector<T>* val,
-                                              status_t(Parcel::*read_func)(U*) const) const;
-    template<typename T>
-    status_t            readNullableTypedVector(std::optional<std::vector<T>>* val,
-                                                status_t(Parcel::*read_func)(T*) const) const;
-    template<typename T>
-    status_t            readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
-                                                status_t(Parcel::*read_func)(T*) const) const __attribute__((deprecated("use std::optional version instead")));
-    template<typename T>
-    status_t            readTypedVector(std::vector<T>* val,
-                                        status_t(Parcel::*read_func)(T*) const) const;
-    template<typename T, typename U>
-    status_t            unsafeWriteTypedVector(const std::vector<T>& val,
-                                               status_t(Parcel::*write_func)(U));
-    template<typename T>
-    status_t            writeNullableTypedVector(const std::optional<std::vector<T>>& val,
-                                                 status_t(Parcel::*write_func)(const T&));
-    template<typename T>
-    status_t            writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
-                                                 status_t(Parcel::*write_func)(const T&)) __attribute__((deprecated("use std::optional version instead")));
-    template<typename T>
-    status_t            writeNullableTypedVector(const std::optional<std::vector<T>>& val,
-                                                 status_t(Parcel::*write_func)(T));
-    template<typename T>
-    status_t            writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
-                                                 status_t(Parcel::*write_func)(T)) __attribute__((deprecated("use std::optional version instead")));
-    template<typename T>
-    status_t            writeTypedVector(const std::vector<T>& val,
-                                         status_t(Parcel::*write_func)(const T&));
-    template<typename T>
-    status_t            writeTypedVector(const std::vector<T>& val,
-                                         status_t(Parcel::*write_func)(T));
+    template <typename Test, template <typename...> class Ref>
+    struct is_specialization : std::false_type {};
+
+    template <template <typename...> class Ref, typename... Args>
+    struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
+
+    template <typename Test, template <typename...> class Ref>
+    static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value;
+
+    // Get the first template type from a container, the T from MyClass<T, ...>.
+    template<typename T> struct first_template_type;
+
+    template <template <typename ...> class V, typename T, typename... Args>
+    struct first_template_type<V<T, Args...>> {
+        using type_t = T;
+    };
+
+    template <typename T>
+    using first_template_type_t = typename first_template_type<T>::type_t;
+
+    // For static assert(false) we need a template version to avoid early failure.
+    template <typename T>
+    static inline constexpr bool dependent_false_v = false;
+
+    // primitive types that we consider packed and trivially copyable as an array
+    template <typename T>
+    static inline constexpr bool is_pointer_equivalent_array_v =
+            std::is_same_v<T, int8_t>
+            || std::is_same_v<T, uint8_t>
+            // We could support int16_t and uint16_t, but those aren't currently AIDL types.
+            || std::is_same_v<T, int32_t>
+            || std::is_same_v<T, uint32_t>
+            || std::is_same_v<T, float>
+            // are unaligned reads and write support is assumed.
+            || std::is_same_v<T, uint64_t>
+            || std::is_same_v<T, int64_t>
+            || std::is_same_v<T, double>
+            || (std::is_enum_v<T> && (sizeof(T) == 1 || sizeof(T) == 4)); // size check not type
+
+    // allowed "nullable" types
+    // These are nonintrusive containers std::optional, std::unique_ptr, std::shared_ptr.
+    template <typename T>
+    static inline constexpr bool is_parcel_nullable_type_v =
+            is_specialization_v<T, std::optional>
+            || is_specialization_v<T, std::unique_ptr>
+            || is_specialization_v<T, std::shared_ptr>;
+
+    // special int32 value to indicate NonNull or Null parcelables
+    // This is fixed to be only 0 or 1 by contract, do not change.
+    static constexpr int32_t kNonNullParcelableFlag = 1;
+    static constexpr int32_t kNullParcelableFlag = 0;
+
+    // special int32 size representing a null vector, when applicable in Nullable data.
+    // This fixed as -1 by contract, do not change.
+    static constexpr int32_t kNullVectorSize = -1;
+
+    // --- readData and writeData methods.
+    // We choose a mixture of function and template overloads to improve code readability.
+    // TODO: Consider C++20 concepts when they become available.
+
+    // writeData function overloads.
+    // Implementation detail: Function overloading improves code readability over
+    // template overloading, but prevents writeData<T> from being used for those types.
+
+    status_t writeData(bool t) {
+        return writeBool(t);  // this writes as int32_t
+    }
+
+    status_t writeData(int8_t t) {
+        return writeByte(t);  // this writes as int32_t
+    }
+
+    status_t writeData(uint8_t t) {
+        return writeByte(static_cast<int8_t>(t));  // this writes as int32_t
+    }
+
+    status_t writeData(char16_t t) {
+        return writeChar(t);  // this writes as int32_t
+    }
+
+    status_t writeData(int32_t t) {
+        return writeInt32(t);
+    }
+
+    status_t writeData(uint32_t t) {
+        return writeUint32(t);
+    }
+
+    status_t writeData(int64_t t) {
+        return writeInt64(t);
+    }
+
+    status_t writeData(uint64_t t) {
+        return writeUint64(t);
+    }
+
+    status_t writeData(float t) {
+        return writeFloat(t);
+    }
+
+    status_t writeData(double t) {
+        return writeDouble(t);
+    }
+
+    status_t writeData(const String16& t) {
+        return writeString16(t);
+    }
+
+    status_t writeData(const std::string& t) {
+        return writeUtf8AsUtf16(t);
+    }
+
+    status_t writeData(const base::unique_fd& t) {
+        return writeUniqueFileDescriptor(t);
+    }
+
+    status_t writeData(const Parcelable& t) {  // std::is_base_of_v<Parcelable, T>
+        // implemented here. writeParcelable() calls this.
+        status_t status = writeData(static_cast<int32_t>(kNonNullParcelableFlag));
+        if (status != OK) return status;
+        return t.writeToParcel(this);
+    }
+
+    // writeData<T> template overloads.
+    // Written such that the first template type parameter is the complete type
+    // of the first function parameter.
+    template <typename T,
+            typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
+    status_t writeData(const T& t) {
+        // implemented here. writeEnum() calls this.
+        using UT = std::underlying_type_t<T>;
+        return writeData(static_cast<UT>(t)); // recurse
+    }
+
+    template <typename T,
+            typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true>
+    status_t writeData(const T& t) {
+        return writeStrongBinder(t);
+    }
+
+    // std::optional, std::unique_ptr, std::shared_ptr special case.
+    template <typename CT,
+            typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true>
+    status_t writeData(const CT& c) {
+        using T = first_template_type_t<CT>;  // The T in CT == C<T, ...>
+        if constexpr (is_specialization_v<T, std::vector>
+                || std::is_same_v<T, String16>
+                || std::is_same_v<T, std::string>) {
+            if (!c) return writeData(static_cast<int32_t>(kNullVectorSize));
+        } else if constexpr (std::is_base_of_v<Parcelable, T>) {
+            if (!c) return writeData(static_cast<int32_t>(kNullParcelableFlag));
+        } else /* constexpr */ {  // could define this, but raise as error.
+            static_assert(dependent_false_v<CT>);
+        }
+        return writeData(*c);
+    }
+
+    template <typename CT,
+            typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
+    status_t writeData(const CT& c) {
+        using T = first_template_type_t<CT>;  // The T in CT == C<T, ...>
+        if (c.size() >  std::numeric_limits<int32_t>::max()) return BAD_VALUE;
+        const auto size = static_cast<int32_t>(c.size());
+        writeData(size);
+        if constexpr (is_pointer_equivalent_array_v<T>) {
+            constexpr size_t limit = std::numeric_limits<size_t>::max() / sizeof(T);
+            if (c.size() > limit) return BAD_VALUE;
+            // is_pointer_equivalent types do not have gaps which could leak info,
+            // which is only a concern when writing through binder.
+
+            // TODO: Padding of the write is suboptimal when the length of the
+            // data is not a multiple of 4.  Consider improving the write() method.
+            return write(c.data(), c.size() * sizeof(T));
+        } else if constexpr (std::is_same_v<T, bool>
+                || std::is_same_v<T, char16_t>) {
+            // reserve data space to write to
+            auto data = reinterpret_cast<int32_t*>(writeInplace(c.size() * sizeof(int32_t)));
+            if (data == nullptr) return BAD_VALUE;
+            for (const auto t: c) {
+                *data++ = static_cast<int32_t>(t);
+            }
+        } else /* constexpr */ {
+            for (const auto &t : c) {
+                const status_t status = writeData(t);
+                if (status != OK) return status;
+            }
+        }
+        return OK;
+    }
+
+    // readData function overloads.
+    // Implementation detail: Function overloading improves code readability over
+    // template overloading, but prevents readData<T> from being used for those types.
+
+    status_t readData(bool* t) const {
+        return readBool(t);  // this reads as int32_t
+    }
+
+    status_t readData(int8_t* t) const {
+        return readByte(t);  // this reads as int32_t
+    }
+
+    status_t readData(uint8_t* t) const {
+        return readByte(reinterpret_cast<int8_t*>(t));  // NOTE: this reads as int32_t
+    }
+
+    status_t readData(char16_t* t) const {
+        return readChar(t);  // this reads as int32_t
+    }
+
+    status_t readData(int32_t* t) const {
+        return readInt32(t);
+    }
+
+    status_t readData(uint32_t* t) const {
+        return readUint32(t);
+    }
+
+    status_t readData(int64_t* t) const {
+        return readInt64(t);
+    }
+
+    status_t readData(uint64_t* t) const {
+        return readUint64(t);
+    }
+
+    status_t readData(float* t) const {
+        return readFloat(t);
+    }
+
+    status_t readData(double* t) const {
+        return readDouble(t);
+    }
+
+    status_t readData(String16* t) const {
+        return readString16(t);
+    }
+
+    status_t readData(std::string* t) const {
+        return readUtf8FromUtf16(t);
+    }
+
+    status_t readData(base::unique_fd* t) const {
+        return readUniqueFileDescriptor(t);
+    }
+
+    status_t readData(Parcelable* t) const { // std::is_base_of_v<Parcelable, T>
+        // implemented here. readParcelable() calls this.
+        int32_t present;
+        status_t status = readData(&present);
+        if (status != OK) return status;
+        if (present != kNonNullParcelableFlag) return UNEXPECTED_NULL;
+        return t->readFromParcel(this);
+    }
+
+    // readData<T> template overloads.
+    // Written such that the first template type parameter is the complete type
+    // of the first function parameter.
+
+    template <typename T,
+            typename std::enable_if_t<std::is_enum_v<T>, bool> = true>
+    status_t readData(T* t) const {
+        // implemented here. readEnum() calls this.
+        using UT = std::underlying_type_t<T>;
+        return readData(reinterpret_cast<UT*>(t));
+    }
+
+    template <typename T,
+            typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true>
+    status_t readData(T* t) const {
+        return readStrongBinder(t);  // Note: on null, returns failure
+    }
+
+
+    template <typename CT,
+            typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true>
+    status_t readData(CT* c) const {
+        using T = first_template_type_t<CT>;  // The T in CT == C<T, ...>
+        const size_t startPos = dataPosition();
+        int32_t peek;
+        status_t status = readData(&peek);
+        if (status != OK) return status;
+        if constexpr (is_specialization_v<T, std::vector>
+                || std::is_same_v<T, String16>
+                || std::is_same_v<T, std::string>) {
+            if (peek == kNullVectorSize) {
+                c->reset();
+                return OK;
+            }
+        } else if constexpr (std::is_base_of_v<Parcelable, T>) {
+            if (peek == kNullParcelableFlag) {
+                c->reset();
+                return OK;
+            }
+        } else /* constexpr */ {  // could define this, but raise as error.
+            static_assert(dependent_false_v<CT>);
+        }
+        // create a new object.
+        if constexpr (is_specialization_v<CT, std::optional>) {
+            c->emplace();
+        } else /* constexpr */ {
+            T* const t = new (std::nothrow) T;  // contents read from Parcel below.
+            if (t == nullptr) return NO_MEMORY;
+            c->reset(t);
+        }
+        // rewind data ptr to reread (this is pretty quick), otherwise we could
+        // pass an optional argument to readData to indicate a peeked value.
+        setDataPosition(startPos);
+        if constexpr (is_specialization_v<T, std::vector>) {
+            return readData(&**c, READ_FLAG_SP_NULLABLE);  // nullable sp<> allowed now
+        } else {
+            return readData(&**c);
+        }
+    }
+
+    // std::vector special case, incorporating flags whether the vector
+    // accepts nullable sp<> to be read.
+    enum ReadFlags {
+        READ_FLAG_NONE = 0,
+        READ_FLAG_SP_NULLABLE = 1 << 0,
+    };
+
+    template <typename CT,
+            typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true>
+    status_t readData(CT* c, ReadFlags readFlags = READ_FLAG_NONE) const {
+        using T = first_template_type_t<CT>;  // The T in CT == C<T, ...>
+        int32_t size;
+        status_t status = readInt32(&size);
+        if (status != OK) return status;
+        if (size < 0) return UNEXPECTED_NULL;
+        const size_t availableBytes = dataAvail();  // coarse bound on vector size.
+        if (static_cast<size_t>(size) > availableBytes) return BAD_VALUE;
+        c->clear(); // must clear before resizing/reserving otherwise move ctors may be called.
+        if constexpr (is_pointer_equivalent_array_v<T>) {
+            // could consider POD without gaps and alignment of 4.
+            auto data = reinterpret_cast<const T*>(
+                    readInplace(static_cast<size_t>(size) * sizeof(T)));
+            if (data == nullptr) return BAD_VALUE;
+            c->insert(c->begin(), data, data + size); // insert should do a reserve().
+        } else if constexpr (std::is_same_v<T, bool>
+                || std::is_same_v<T, char16_t>) {
+            c->reserve(size); // avoids default initialization
+            auto data = reinterpret_cast<const int32_t*>(
+                    readInplace(static_cast<size_t>(size) * sizeof(int32_t)));
+            if (data == nullptr) return BAD_VALUE;
+            for (int32_t i = 0; i < size; ++i) {
+                c->emplace_back(static_cast<T>(*data++));
+            }
+        } else if constexpr (is_specialization_v<T, sp>) {
+            c->resize(size); // calls ctor
+            if (readFlags & READ_FLAG_SP_NULLABLE) {
+                for (auto &t : *c) {
+                    status = readNullableStrongBinder(&t);  // allow nullable
+                    if (status != OK) return status;
+                }
+            } else {
+                for (auto &t : *c) {
+                    status = readStrongBinder(&t);
+                    if (status != OK) return status;
+                }
+            }
+        } else /* constexpr */ {
+            c->resize(size); // calls ctor
+            for (auto &t : *c) {
+                status = readData(&t);
+                if (status != OK) return status;
+            }
+        }
+        return OK;
+    }
+
+    //-----------------------------------------------------------------------------
+    private:
 
     status_t            mError;
     uint8_t*            mData;
@@ -595,6 +1123,7 @@
     mutable bool        mObjectsSorted;
 
     mutable bool        mRequestHeaderPresent;
+
     mutable size_t      mWorkSourceRequestHeaderPosition;
 
     mutable bool        mFdsKnown;
@@ -607,8 +1136,7 @@
 
     release_func        mOwner;
 
-    // TODO(167966510): reserved for binder/version/stability
-    void*               mReserved = reinterpret_cast<void*>(0xAAAAAAAA);
+    sp<RpcSession> mSession;
 
     class Blob {
     public:
@@ -832,61 +1360,6 @@
 }
 
 template<typename T>
-status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const {
-    int32_t read_size;
-    status_t err = readInt32(&read_size);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    if (read_size < 0) {
-        return UNEXPECTED_NULL;
-    }
-    *size = static_cast<size_t>(read_size);
-    val->reserve(*size);
-    return OK;
-}
-
-template<typename T>
-status_t Parcel::reserveOutVector(std::optional<std::vector<T>>* val, size_t* size) const {
-    int32_t read_size;
-    status_t err = readInt32(&read_size);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    if (read_size >= 0) {
-        *size = static_cast<size_t>(read_size);
-        val->emplace();
-        (*val)->reserve(*size);
-    } else {
-        val->reset();
-    }
-
-    return OK;
-}
-
-template<typename T>
-status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val,
-                                  size_t* size) const {
-    int32_t read_size;
-    status_t err = readInt32(&read_size);
-    if (err != NO_ERROR) {
-        return err;
-    }
-
-    if (read_size >= 0) {
-        *size = static_cast<size_t>(read_size);
-        val->reset(new std::vector<T>());
-        (*val)->reserve(*size);
-    } else {
-        val->reset();
-    }
-
-    return OK;
-}
-
-template<typename T>
 status_t Parcel::readStrongBinder(sp<T>* val) const {
     sp<IBinder> tmp;
     status_t ret = readStrongBinder(&tmp);
@@ -918,422 +1391,6 @@
     return ret;
 }
 
-template<typename T, typename U>
-status_t Parcel::unsafeReadTypedVector(
-        std::vector<T>* val,
-        status_t(Parcel::*read_func)(U*) const) const {
-    int32_t size;
-    status_t status = this->readInt32(&size);
-
-    if (status != OK) {
-        return status;
-    }
-
-    if (size < 0) {
-        return UNEXPECTED_NULL;
-    }
-
-    if (val->max_size() < static_cast<size_t>(size)) {
-        return NO_MEMORY;
-    }
-
-    val->resize(static_cast<size_t>(size));
-
-    if (val->size() < static_cast<size_t>(size)) {
-        return NO_MEMORY;
-    }
-
-    for (auto& v: *val) {
-        status = (this->*read_func)(&v);
-
-        if (status != OK) {
-            return status;
-        }
-    }
-
-    return OK;
-}
-
-template<typename T>
-status_t Parcel::readTypedVector(std::vector<T>* val,
-                                 status_t(Parcel::*read_func)(T*) const) const {
-    return unsafeReadTypedVector(val, read_func);
-}
-
-template<typename T>
-status_t Parcel::readNullableTypedVector(std::optional<std::vector<T>>* val,
-                                         status_t(Parcel::*read_func)(T*) const) const {
-    const size_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    val->emplace();
-
-    status = unsafeReadTypedVector(&**val, read_func);
-
-    if (status != OK) {
-       val->reset();
-    }
-
-    return status;
-}
-
-template<typename T>
-status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
-                                         status_t(Parcel::*read_func)(T*) const) const {
-    const size_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    val->reset(new std::vector<T>());
-
-    status = unsafeReadTypedVector(val->get(), read_func);
-
-    if (status != OK) {
-        val->reset();
-    }
-
-    return status;
-}
-
-template<typename T, typename U>
-status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val,
-                                        status_t(Parcel::*write_func)(U)) {
-    if (val.size() > std::numeric_limits<int32_t>::max()) {
-        return BAD_VALUE;
-    }
-
-    status_t status = this->writeInt32(static_cast<int32_t>(val.size()));
-
-    if (status != OK) {
-        return status;
-    }
-
-    for (const auto& item : val) {
-        status = (this->*write_func)(item);
-
-        if (status != OK) {
-            return status;
-        }
-    }
-
-    return OK;
-}
-
-template<typename T>
-status_t Parcel::writeTypedVector(const std::vector<T>& val,
-                                  status_t(Parcel::*write_func)(const T&)) {
-    return unsafeWriteTypedVector(val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeTypedVector(const std::vector<T>& val,
-                                  status_t(Parcel::*write_func)(T)) {
-    return unsafeWriteTypedVector(val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::optional<std::vector<T>>& val,
-                                          status_t(Parcel::*write_func)(const T&)) {
-    if (!val) {
-        return this->writeInt32(-1);
-    }
-
-    return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
-                                          status_t(Parcel::*write_func)(const T&)) {
-    if (val.get() == nullptr) {
-        return this->writeInt32(-1);
-    }
-
-    return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::optional<std::vector<T>>& val,
-                                          status_t(Parcel::*write_func)(T)) {
-    if (!val) {
-        return this->writeInt32(-1);
-    }
-
-    return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
-                                          status_t(Parcel::*write_func)(T)) {
-    if (val.get() == nullptr) {
-        return this->writeInt32(-1);
-    }
-
-    return unsafeWriteTypedVector(*val, write_func);
-}
-
-template<typename T>
-status_t Parcel::readParcelableVector(std::vector<T>* val) const {
-    return unsafeReadTypedVector<T, Parcelable>(val, &Parcel::readParcelable);
-}
-
-template<typename T>
-status_t Parcel::readParcelableVector(std::optional<std::vector<std::optional<T>>>* val) const {
-    const size_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    val->emplace();
-
-    using NullableT = std::optional<T>;
-    status = unsafeReadTypedVector<NullableT, NullableT>(&**val, &Parcel::readParcelable);
-
-    if (status != OK) {
-        val->reset();
-    }
-
-    return status;
-}
-
-template<typename T>
-status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const {
-    const size_t start = dataPosition();
-    int32_t size;
-    status_t status = readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    setDataPosition(start);
-    val->reset(new std::vector<std::unique_ptr<T>>());
-
-    using NullableT = std::unique_ptr<T>;
-    status = unsafeReadTypedVector<NullableT, NullableT>(val->get(), &Parcel::readParcelable);
-
-    if (status != OK) {
-        val->reset();
-    }
-
-    return status;
-}
-
-template<typename T>
-status_t Parcel::readParcelable(std::optional<T>* parcelable) const {
-    const size_t start = dataPosition();
-    int32_t present;
-    status_t status = readInt32(&present);
-    parcelable->reset();
-
-    if (status != OK || !present) {
-        return status;
-    }
-
-    setDataPosition(start);
-    parcelable->emplace();
-
-    status = readParcelable(&**parcelable);
-
-    if (status != OK) {
-        parcelable->reset();
-    }
-
-    return status;
-}
-
-template<typename T>
-status_t Parcel::readParcelable(std::unique_ptr<T>* parcelable) const {
-    const size_t start = dataPosition();
-    int32_t present;
-    status_t status = readInt32(&present);
-    parcelable->reset();
-
-    if (status != OK || !present) {
-        return status;
-    }
-
-    setDataPosition(start);
-    parcelable->reset(new T());
-
-    status = readParcelable(parcelable->get());
-
-    if (status != OK) {
-        parcelable->reset();
-    }
-
-    return status;
-}
-
-template<typename T>
-status_t Parcel::writeNullableParcelable(const std::optional<T>& parcelable) {
-    return writeRawNullableParcelable(parcelable ? &*parcelable : nullptr);
-}
-
-template<typename T>
-status_t Parcel::writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
-    return writeRawNullableParcelable(parcelable.get());
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::vector<T>& val) {
-    return unsafeWriteTypedVector<T,const Parcelable&>(val, &Parcel::writeParcelable);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val) {
-    if (!val) {
-        return this->writeInt32(-1);
-    }
-
-    using NullableT = std::optional<T>;
-    return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) {
-    if (val.get() == nullptr) {
-        return this->writeInt32(-1);
-    }
-
-    return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) {
-    if (val.get() == nullptr) {
-        return this->writeInt32(-1);
-    }
-
-    using NullableT = std::unique_ptr<T>;
-    return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
-}
-
-template<typename T>
-status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val) {
-    if (val.get() == nullptr) {
-        return this->writeInt32(-1);
-    }
-
-    using NullableT = std::optional<T>;
-    return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
-}
-
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
-    return writeInt32(static_cast<int32_t>(val));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::writeEnum(const T& val) {
-    return writeInt64(static_cast<int64_t>(val));
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::optional<std::vector<T>>& val) {
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
-    if (!val) return writeInt32(-1);
-    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::vector<T>& val) {
-    return writeTypedVector(val, &Parcel::writeEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::optional<std::vector<T>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
-    return writeNullableTypedVector(val, &Parcel::writeEnum);
-}
-
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
-    return readInt32(reinterpret_cast<int32_t *>(pArg));
-}
-template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
-status_t Parcel::readEnum(T* pArg) const {
-    return readInt64(reinterpret_cast<int64_t *>(pArg));
-}
-
-template<typename T>
-inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const {
-  // readByteVectorInternal expects a vector that has been reserved (but not
-  // resized) to have the provided size.
-  const T* data = reinterpret_cast<const T*>(readInplace(size));
-  if (!data) return BAD_VALUE;
-  val->clear();
-  val->insert(val->begin(), data, data+size);
-  return NO_ERROR;
-}
-
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    return readByteVectorInternal(val, size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::optional<std::vector<T>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (!*val) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null Enum vector.
-        return OK;
-    }
-    return readByteVectorInternal(&**val, size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
-    size_t size;
-    if (status_t status = reserveOutVector(val, &size); status != OK) return status;
-    if (val->get() == nullptr) {
-        // reserveOutVector does not create the out vector if size is < 0.
-        // This occurs when writing a null Enum vector.
-        return OK;
-    }
-    return readByteVectorInternal(val->get(), size);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::vector<T>* val) const {
-    return readTypedVector(val, &Parcel::readEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::optional<std::vector<T>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readEnum);
-}
-template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
-status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
-    return readNullableTypedVector(val, &Parcel::readEnum);
-}
-
 // ---------------------------------------------------------------------------
 
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/include/binder/ParcelRef.h
similarity index 63%
copy from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
copy to libs/binder/include/binder/ParcelRef.h
index b92a6a9..497da2d 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/include/binder/ParcelRef.h
@@ -16,9 +16,28 @@
 
 #pragma once
 
-#include <binder/Parcel.h>
-#include <fuzzer/FuzzedDataProvider.h>
 
+#include <binder/Parcel.h>
+#include <utils/RefBase.h>
+
+// ---------------------------------------------------------------------------
 namespace android {
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
+
+/**
+ * internal use only
+ * @internal
+ */
+class ParcelRef : public Parcel, public RefBase
+{
+public:
+    static sp<ParcelRef> create() {
+        return new ParcelRef();
+    }
+
+private:
+    ParcelRef() = default;
+};
+
 } // namespace android
+
+// ---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h
index 7024a4b..9e4475c 100644
--- a/libs/binder/include/binder/ParcelableHolder.h
+++ b/libs/binder/include/binder/ParcelableHolder.h
@@ -18,6 +18,7 @@
 
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
+#include <utils/String16.h>
 #include <mutex>
 #include <optional>
 #include <tuple>
@@ -52,53 +53,59 @@
     }
 
     template <typename T>
-    bool setParcelable(T&& p) {
+    status_t setParcelable(T&& p) {
         using Tt = typename std::decay<T>::type;
         return setParcelable<Tt>(std::make_shared<Tt>(std::forward<T>(p)));
     }
 
     template <typename T>
-    bool setParcelable(std::shared_ptr<T> p) {
+    status_t setParcelable(std::shared_ptr<T> p) {
         static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
         if (p && this->getStability() > p->getStability()) {
-            return false;
+            return android::BAD_VALUE;
         }
         this->mParcelable = p;
         this->mParcelableName = T::getParcelableDescriptor();
         this->mParcelPtr = nullptr;
-        return true;
+        return android::OK;
     }
 
     template <typename T>
-    std::shared_ptr<T> getParcelable() const {
+    status_t getParcelable(std::shared_ptr<T>* ret) const {
         static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable");
-        const std::string& parcelableDesc = T::getParcelableDescriptor();
+        const String16& parcelableDesc = T::getParcelableDescriptor();
         if (!this->mParcelPtr) {
             if (!this->mParcelable || !this->mParcelableName) {
                 ALOGD("empty ParcelableHolder");
-                return nullptr;
+                *ret = nullptr;
+                return android::OK;
             } else if (parcelableDesc != *mParcelableName) {
                 ALOGD("extension class name mismatch expected:%s actual:%s",
-                      mParcelableName->c_str(), parcelableDesc.c_str());
-                return nullptr;
+                      String8(*mParcelableName).c_str(), String8(parcelableDesc).c_str());
+                *ret = nullptr;
+                return android::BAD_VALUE;
             }
-            return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
+            *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
+            return android::OK;
         }
         this->mParcelPtr->setDataPosition(0);
-        status_t status = this->mParcelPtr->readUtf8FromUtf16(&this->mParcelableName);
+        status_t status = this->mParcelPtr->readString16(&this->mParcelableName);
         if (status != android::OK || parcelableDesc != this->mParcelableName) {
             this->mParcelableName = std::nullopt;
-            return nullptr;
+            *ret = nullptr;
+            return status;
         }
         this->mParcelable = std::make_shared<T>();
         status = mParcelable.get()->readFromParcel(this->mParcelPtr.get());
         if (status != android::OK) {
             this->mParcelableName = std::nullopt;
             this->mParcelable = nullptr;
-            return nullptr;
+            *ret = nullptr;
+            return status;
         }
         this->mParcelPtr = nullptr;
-        return std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
+        *ret = std::shared_ptr<T>(mParcelable, reinterpret_cast<T*>(mParcelable.get()));
+        return android::OK;
     }
 
     Stability getStability() const override { return mStability; }
@@ -124,7 +131,7 @@
 
 private:
     mutable std::shared_ptr<Parcelable> mParcelable;
-    mutable std::optional<std::string> mParcelableName;
+    mutable std::optional<String16> mParcelableName;
     mutable std::unique_ptr<Parcel> mParcelPtr;
     Stability mStability;
 };
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index 835a3a8..21aa705 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -73,6 +73,8 @@
 
     static bool checkPermission(const String16& permission,
             pid_t pid, uid_t uid);
+
+    static void purgeCache();
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index bab6469..b9db5d7 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -58,6 +58,7 @@
             void                spawnPooledThread(bool isMain);
             
             status_t            setThreadPoolMaxThreadCount(size_t maxThreads);
+            status_t            enableOnewaySpamDetection(bool enable);
             void                giveThreadPoolName();
 
             String8             getDriverName();
@@ -88,7 +89,8 @@
     static  sp<ProcessState>    init(const char *defaultDriver, bool requireDefault);
 
     friend class IPCThreadState;
-    
+    friend class sp<ProcessState>;
+
             explicit            ProcessState(const char* driver);
                                 ~ProcessState();
 
@@ -107,11 +109,14 @@
             int                 mDriverFD;
             void*               mVMStart;
 
-            // Protects thread count variable below.
+            // Protects thread count and wait variables below.
             pthread_mutex_t     mThreadCountLock;
+            // Broadcast whenever mWaitingForThreads > 0
             pthread_cond_t      mThreadCountDecrement;
             // Number of binder threads current executing a command.
             size_t              mExecutingThreadsCount;
+            // Number of threads calling IPCThreadState::blockUntilThreadAvailable()
+            size_t              mWaitingForThreads;
             // Maximum number for binder threads allowed for this process.
             size_t              mMaxThreads;
             // Time when thread pool was emptied
@@ -121,7 +126,6 @@
 
             Vector<handle_entry>mHandleToObject;
 
-            String8             mRootDir;
             bool                mThreadPoolStarted;
     volatile int32_t            mThreadPoolSeq;
 
diff --git a/libs/binder/include/binder/RpcAddress.h b/libs/binder/include/binder/RpcAddress.h
new file mode 100644
index 0000000..5a3f3a6
--- /dev/null
+++ b/libs/binder/include/binder/RpcAddress.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <memory>
+
+#include <utils/Errors.h>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+class Parcel;
+struct RpcWireAddress;
+
+/**
+ * This class represents an identifier of a binder object.
+ *
+ * The purpose of this class it to hide the ABI of an RpcWireAddress, and
+ * potentially allow us to change the size of it in the future (RpcWireAddress
+ * is PIMPL, essentially - although the type that is used here is not exposed).
+ */
+class RpcAddress {
+public:
+    /**
+     * The zero address is used for special RPC transactions, but it might also
+     * be used in conjunction with readFromParcel.
+     */
+    static RpcAddress zero();
+
+    bool isZero() const;
+
+    /**
+     * Create a new address which is unique
+     */
+    static RpcAddress unique();
+
+    /**
+     * Creates a new address as a copy of an embedded object.
+     */
+    static RpcAddress fromRawEmbedded(const RpcWireAddress* raw);
+    const RpcWireAddress& viewRawEmbedded() const;
+
+    bool operator<(const RpcAddress& rhs) const;
+    std::string toString() const;
+
+    status_t writeToParcel(Parcel* parcel) const;
+    status_t readFromParcel(const Parcel& parcel);
+
+    ~RpcAddress();
+
+private:
+    RpcAddress();
+
+    std::shared_ptr<RpcWireAddress> mRawAddr;
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
new file mode 100644
index 0000000..3534d51
--- /dev/null
+++ b/libs/binder/include/binder/RpcServer.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/RpcSession.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <mutex>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+class RpcSocketAddress;
+
+/**
+ * This represents a server of an interface, which may be connected to by any
+ * number of clients over sockets.
+ *
+ * Usage:
+ *     auto server = RpcServer::make();
+ *     // only supports one now
+ *     if (!server->setup*Server(...)) {
+ *         :(
+ *     }
+ *     server->join();
+ */
+class RpcServer final : public virtual RefBase {
+public:
+    static sp<RpcServer> make();
+
+    /**
+     * This represents a session for responses, e.g.:
+     *
+     *     process A serves binder a
+     *     process B opens a session to process A
+     *     process B makes binder b and sends it to A
+     *     A uses this 'back session' to send things back to B
+     */
+    [[nodiscard]] bool setupUnixDomainServer(const char* path);
+
+    /**
+     * Creates an RPC server at the current port.
+     */
+    [[nodiscard]] bool setupVsockServer(unsigned int port);
+
+    /**
+     * Creates an RPC server at the current port using IPv4.
+     *
+     * TODO(b/182914638): IPv6 support
+     *
+     * Set |port| to 0 to pick an ephemeral port; see discussion of
+     * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
+     * will be set to the picked port number, if it is not null.
+     */
+    [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
+
+    void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+
+    /**
+     * This must be called before adding a client session.
+     *
+     * If this is not specified, this will be a single-threaded server.
+     *
+     * TODO(b/185167543): these are currently created per client, but these
+     * should be shared.
+     */
+    void setMaxThreads(size_t threads);
+    size_t getMaxThreads();
+
+    /**
+     * The root object can be retrieved by any client, without any
+     * authentication. TODO(b/183988761)
+     */
+    void setRootObject(const sp<IBinder>& binder);
+    sp<IBinder> getRootObject();
+
+    /**
+     * You must have at least one client session before calling this.
+     *
+     * TODO(b/185167543): way to shut down?
+     */
+    void join();
+
+    /**
+     * For debugging!
+     */
+    std::vector<sp<RpcSession>> listSessions();
+
+    ~RpcServer();
+
+    // internal use only
+
+    void onSessionTerminating(const sp<RpcSession>& session);
+
+private:
+    friend sp<RpcServer>;
+    RpcServer();
+
+    bool setupSocketServer(const RpcSocketAddress& address);
+
+    bool mAgreedExperimental = false;
+    bool mStarted = false; // TODO(b/185167543): support dynamically added clients
+    size_t mMaxThreads = 1;
+    base::unique_fd mServer; // socket we are accepting sessions on
+
+    std::mutex mLock; // for below
+    sp<IBinder> mRootObject;
+    std::map<int32_t, sp<RpcSession>> mSessions;
+    int32_t mSessionIdCounter = 0;
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
new file mode 100644
index 0000000..1657167
--- /dev/null
+++ b/libs/binder/include/binder/RpcSession.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <binder/IBinder.h>
+#include <binder/RpcAddress.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <map>
+#include <optional>
+#include <thread>
+#include <vector>
+
+// WARNING: This is a feature which is still in development, and it is subject
+// to radical change. Any production use of this may subject your code to any
+// number of problems.
+
+namespace android {
+
+class Parcel;
+class RpcServer;
+class RpcSocketAddress;
+class RpcState;
+
+/**
+ * This represents a session (group of connections) between a client
+ * and a server. Multiple connections are needed for multiple parallel "binder"
+ * calls which may also have nested calls.
+ */
+class RpcSession final : public virtual RefBase {
+public:
+    static sp<RpcSession> make();
+
+    /**
+     * This should be called once per thread, matching 'join' in the remote
+     * process.
+     */
+    [[nodiscard]] bool setupUnixDomainClient(const char* path);
+
+    /**
+     * Connects to an RPC server at the CVD & port.
+     */
+    [[nodiscard]] bool setupVsockClient(unsigned int cvd, unsigned int port);
+
+    /**
+     * Connects to an RPC server at the given address and port.
+     */
+    [[nodiscard]] bool setupInetClient(const char* addr, unsigned int port);
+
+    /**
+     * For debugging!
+     *
+     * Sets up an empty connection. All queries to this connection which require a
+     * response will never be satisfied. All data sent here will be
+     * unceremoniously cast down the bottomless pit, /dev/null.
+     */
+    [[nodiscard]] bool addNullDebuggingClient();
+
+    /**
+     * Query the other side of the session for the root object hosted by that
+     * process's RpcServer (if one exists)
+     */
+    sp<IBinder> getRootObject();
+
+    /**
+     * Query the other side of the session for the maximum number of threads
+     * it supports (maximum number of concurrent non-nested synchronous transactions)
+     */
+    status_t getRemoteMaxThreads(size_t* maxThreads);
+
+    [[nodiscard]] status_t transact(const RpcAddress& address, uint32_t code, const Parcel& data,
+                                    Parcel* reply, uint32_t flags);
+    [[nodiscard]] status_t sendDecStrong(const RpcAddress& address);
+
+    ~RpcSession();
+
+    wp<RpcServer> server();
+
+    // internal only
+    const std::unique_ptr<RpcState>& state() { return mState; }
+
+    class PrivateAccessorForId {
+    private:
+        friend class RpcSession;
+        friend class RpcState;
+        explicit PrivateAccessorForId(const RpcSession* session) : mSession(session) {}
+
+        const std::optional<int32_t> get() { return mSession->mId; }
+
+        const RpcSession* mSession;
+    };
+    PrivateAccessorForId getPrivateAccessorForId() const { return PrivateAccessorForId(this); }
+
+private:
+    friend PrivateAccessorForId;
+    friend sp<RpcSession>;
+    friend RpcServer;
+    RpcSession();
+
+    status_t readId();
+
+    void startThread(base::unique_fd client);
+    void join(base::unique_fd client);
+    void terminateLocked();
+
+    struct RpcConnection : public RefBase {
+        base::unique_fd fd;
+
+        // whether this or another thread is currently using this fd to make
+        // or receive transactions.
+        std::optional<pid_t> exclusiveTid;
+    };
+
+    bool setupSocketClient(const RpcSocketAddress& address);
+    bool setupOneSocketClient(const RpcSocketAddress& address, int32_t sessionId);
+    void addClient(base::unique_fd fd);
+    void setForServer(const wp<RpcServer>& server, int32_t sessionId);
+    sp<RpcConnection> assignServerToThisThread(base::unique_fd fd);
+    bool removeServerConnection(const sp<RpcConnection>& connection);
+
+    enum class ConnectionUse {
+        CLIENT,
+        CLIENT_ASYNC,
+        CLIENT_REFCOUNT,
+    };
+
+    // RAII object for session connection
+    class ExclusiveConnection {
+    public:
+        explicit ExclusiveConnection(const sp<RpcSession>& session, ConnectionUse use);
+        ~ExclusiveConnection();
+        const base::unique_fd& fd() { return mConnection->fd; }
+
+    private:
+        static void findConnection(pid_t tid, sp<RpcConnection>* exclusive,
+                                   sp<RpcConnection>* available,
+                                   std::vector<sp<RpcConnection>>& sockets,
+                                   size_t socketsIndexHint);
+
+        sp<RpcSession> mSession; // avoid deallocation
+        sp<RpcConnection> mConnection;
+
+        // whether this is being used for a nested transaction (being on the same
+        // thread guarantees we won't write in the middle of a message, the way
+        // the wire protocol is constructed guarantees this is safe).
+        bool mReentrant = false;
+    };
+
+    // On the other side of a session, for each of mClientConnections here, there should
+    // be one of mServerConnections on the other side (and vice versa).
+    //
+    // For the simplest session, a single server with one client, you would
+    // have:
+    //  - the server has a single 'mServerConnections' and a thread listening on this
+    //  - the client has a single 'mClientConnections' and makes calls to this
+    //  - here, when the client makes a call, the server can call back into it
+    //    (nested calls), but outside of this, the client will only ever read
+    //    calls from the server when it makes a call itself.
+    //
+    // For a more complicated case, the client might itself open up a thread to
+    // serve calls to the server at all times (e.g. if it hosts a callback)
+
+    wp<RpcServer> mForServer; // maybe null, for client sessions
+
+    // TODO(b/183988761): this shouldn't be guessable
+    std::optional<int32_t> mId;
+
+    std::unique_ptr<RpcState> mState;
+
+    std::mutex mMutex; // for all below
+
+    std::condition_variable mAvailableConnectionCv; // for mWaitingThreads
+    size_t mWaitingThreads = 0;
+    // hint index into clients, ++ when sending an async transaction
+    size_t mClientConnectionsOffset = 0;
+    std::vector<sp<RpcConnection>> mClientConnections;
+    std::vector<sp<RpcConnection>> mServerConnections;
+
+    // TODO(b/185167543): use for reverse sessions (allow client to also
+    // serve calls on a session).
+    // TODO(b/185167543): allow sharing between different sessions in a
+    // process? (or combine with mServerConnections)
+    std::map<std::thread::id, std::thread> mThreads;
+    bool mTerminated = false;
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 12272ba..f4bfac8 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -49,10 +49,42 @@
 // that it knows how to process. The summary of stability of a binder is
 // represented by a Stability::Category object.
 
-// WARNING: These APIs are only ever expected to be called by auto-generated code.
-//     Instead of calling them, you should set the stability of a .aidl interface
 class Stability final {
 public:
+    // Given a binder interface at a certain stability, there may be some
+    // requirements associated with that higher stability level. For instance, a
+    // VINTF stability binder is required to be in the VINTF manifest. This API
+    // can be called to use that same interface within the local partition.
+    static void forceDowngradeToLocalStability(const sp<IBinder>& binder);
+
+    // WARNING: Below APIs are only ever expected to be called by auto-generated code.
+    //     Instead of calling them, you should set the stability of a .aidl interface
+
+    // WARNING: The only client of
+    //      - forceDowngradeToSystemStability() and;
+    //      - korceDowngradeToVendorStability()
+    //  should be AIBinder_forceDowngradeToLocalStability().
+    //
+    // getLocalLevel() in libbinder returns Level::SYSTEM when called
+    // from libbinder_ndk (even on vendor partition). So we explicitly provide
+    // these methods for use by the NDK API:
+    //      AIBinder_forceDowngradeToLocalStability().
+    //
+    // This allows correctly downgrading the binder's stability to either system/vendor,
+    // depending on the partition.
+
+    // Given a binder interface at a certain stability, there may be some
+    // requirements associated with that higher stability level. For instance, a
+    // VINTF stability binder is required to be in the VINTF manifest. This API
+    // can be called to use that same interface within the vendor partition.
+    static void forceDowngradeToVendorStability(const sp<IBinder>& binder);
+
+    // Given a binder interface at a certain stability, there may be some
+    // requirements associated with that higher stability level. For instance, a
+    // VINTF stability binder is required to be in the VINTF manifest. This API
+    // can be called to use that same interface within the system partition.
+    static void forceDowngradeToSystemStability(const sp<IBinder>& binder);
+
     // WARNING: This is only ever expected to be called by auto-generated code. You likely want to
     // change or modify the stability class of the interface you are using.
     // This must be called as soon as the binder in question is constructed. No thread safety
@@ -139,9 +171,17 @@
     // returns the stability according to how this was built
     static Level getLocalLevel();
 
+    // Downgrades binder stability to the specified level.
+    static void forceDowngradeToStability(const sp<IBinder>& binder, Level level);
+
+    enum {
+      REPR_NONE = 0,
+      REPR_LOG = 1,
+      REPR_ALLOW_DOWNGRADE = 2,
+    };
     // applies stability to binder if stability level is known
     __attribute__((warn_unused_result))
-    static status_t setRepr(IBinder* binder, int32_t representation, bool log);
+    static status_t setRepr(IBinder* binder, int32_t representation, uint32_t flags);
 
     // get stability information as encoded on the wire
     static Category getCategory(IBinder* binder);
diff --git a/libs/binder/include/binder/Status.h b/libs/binder/include/binder/Status.h
index c30ae01..aaafa36 100644
--- a/libs/binder/include/binder/Status.h
+++ b/libs/binder/include/binder/Status.h
@@ -91,6 +91,9 @@
     static Status fromExceptionCode(int32_t exceptionCode,
                                     const char* message);
 
+    // warning: this is still considered an error if it is constructed with a
+    // zero value error code. Please use Status::ok() instead and avoid zero
+    // error codes
     static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
     static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
                                            const String8& message);
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include_activitymanager/binder/ActivityManager.h
similarity index 100%
rename from libs/binder/include/binder/ActivityManager.h
rename to libs/binder/include_activitymanager/binder/ActivityManager.h
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include_activitymanager/binder/IActivityManager.h
similarity index 99%
rename from libs/binder/include/binder/IActivityManager.h
rename to libs/binder/include_activitymanager/binder/IActivityManager.h
index fde56a0..e3b5e43 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include_activitymanager/binder/IActivityManager.h
@@ -18,8 +18,8 @@
 
 #ifndef __ANDROID_VNDK__
 
-#include <binder/IInterface.h>
 #include <binder/IUidObserver.h>
+#include <binder/IInterface.h>
 
 namespace android {
 
diff --git a/libs/binder/include/binder/IUidObserver.h b/libs/binder/include_activitymanager/binder/IUidObserver.h
similarity index 100%
rename from libs/binder/include/binder/IUidObserver.h
rename to libs/binder/include_activitymanager/binder/IUidObserver.h
diff --git a/libs/binder/include/binder/IBatteryStats.h b/libs/binder/include_batterystats/batterystats/IBatteryStats.h
similarity index 100%
rename from libs/binder/include/binder/IBatteryStats.h
rename to libs/binder/include_batterystats/batterystats/IBatteryStats.h
diff --git a/libs/binder/include/binder/IProcessInfoService.h b/libs/binder/include_processinfo/processinfo/IProcessInfoService.h
similarity index 100%
rename from libs/binder/include/binder/IProcessInfoService.h
rename to libs/binder/include_processinfo/processinfo/IProcessInfoService.h
diff --git a/libs/binder/include/binder/ProcessInfoService.h b/libs/binder/include_processinfo/processinfo/ProcessInfoService.h
similarity index 98%
rename from libs/binder/include/binder/ProcessInfoService.h
rename to libs/binder/include_processinfo/processinfo/ProcessInfoService.h
index 6b3b5ce..978856d 100644
--- a/libs/binder/include/binder/ProcessInfoService.h
+++ b/libs/binder/include_processinfo/processinfo/ProcessInfoService.h
@@ -18,7 +18,7 @@
 
 #ifndef __ANDROID_VNDK__
 
-#include <binder/IProcessInfoService.h>
+#include <processinfo/IProcessInfoService.h>
 #include <utils/Errors.h>
 #include <utils/Singleton.h>
 #include <sys/types.h>
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index bdb74dc..b03e24c 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -15,6 +15,23 @@
  */
 
 // TODO(b/31559095): bionic on host should define this
+package {
+    default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_binder_ndk_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "libbinder_ndk_host_user",
     target: {
@@ -38,7 +55,9 @@
     defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
 
-    llndk_stubs: "libbinder_ndk.llndk",
+    llndk: {
+        symbol_file: "libbinder_ndk.map.txt",
+    },
 
     export_include_dirs: [
         "include_cpp",
@@ -104,18 +123,51 @@
         "--header-filter=^.*frameworks/native/libs/binder/.*.h$",
     ],
     tidy_checks_as_errors: [
-        "*",
+        // Explicitly list the checks that should not occur in this module.
+        "abseil-*",
+        "android-*",
+        "bugprone-*",
+        "cert-*",
+        "clang-analyzer-*",
         "-clang-analyzer-core.CallAndMessage",
         "-clang-analyzer-core.uninitialized.Assign",
-        "-clang-analyzer-unix.Malloc,",
+        "-clang-analyzer-unix.Malloc",
         "-clang-analyzer-deadcode.DeadStores",
         "-clang-analyzer-optin.cplusplus.UninitializedObject",
+        "google-*",
+        "-google-readability-*",
+        "-google-runtime-references",
+        "misc-*",
         "-misc-no-recursion",
+        "-misc-non-private-member-variables-in-classes",
         "-misc-redundant-expression",
+        "-misc-unused-parameters",
         "-misc-unused-using-decls",
+        "performance*",
+        "portability*",
     ],
 }
 
+cc_library_headers {
+    name: "libbinder_headers_platform_shared",
+    export_include_dirs: ["include_cpp"],
+    vendor_available: true,
+    host_supported: true,
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
+    min_sdk_version: "29",
+}
+
 ndk_headers {
     name: "libbinder_ndk_headers",
     from: "include_ndk/android",
@@ -142,13 +194,3 @@
     symbol_file: "libbinder_ndk.map.txt",
     first_version: "29",
 }
-
-llndk_library {
-    name: "libbinder_ndk.llndk",
-    symbol_file: "libbinder_ndk.map.txt",
-    export_include_dirs: [
-        "include_cpp",
-        "include_ndk",
-        "include_platform",
-    ],
-}
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 350c658..883403a 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -181,7 +181,7 @@
 
         binder_status_t status = getClass()->onTransact(this, code, &in, &out);
         return PruneStatusT(status);
-    } else if (code == SHELL_COMMAND_TRANSACTION && getClass()->handleShellCommand != nullptr) {
+    } else if (code == SHELL_COMMAND_TRANSACTION) {
         int in = data.readFileDescriptor();
         int out = data.readFileDescriptor();
         int err = data.readFileDescriptor();
@@ -301,6 +301,26 @@
     return binder.get();
 }
 
+AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak) {
+    if (weak == nullptr) {
+        return nullptr;
+    }
+
+    return new AIBinder_Weak{weak->binder};
+}
+
+bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs) {
+    if (lhs == nullptr || rhs == nullptr) return lhs < rhs;
+
+    return const_cast<AIBinder*>(lhs)->getBinder() < const_cast<AIBinder*>(rhs)->getBinder();
+}
+
+bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) {
+    if (lhs == nullptr || rhs == nullptr) return lhs < rhs;
+
+    return lhs->binder < rhs->binder;
+}
+
 AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
                                AIBinder_Class_onDestroy onDestroy,
                                AIBinder_Class_onTransact onTransact)
@@ -343,7 +363,8 @@
 }
 
 void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
-    CHECK(who == mWho);
+    CHECK(who == mWho) << who.unsafe_get() << "(" << who.get_refs() << ") vs " << mWho.unsafe_get()
+                       << " (" << mWho.get_refs() << ")";
 
     mOnDied(mCookie);
 
@@ -577,14 +598,9 @@
         return STATUS_INVALID_OPERATION;
     }
 
-    if (!binder->isRemote()) {
-        LOG(WARNING) << "A binder object at " << binder
-                     << " is being transacted on, however, this object is in the same process as "
-                        "its proxy. Transacting with this binder is expensive compared to just "
-                        "calling the corresponding functionality in the same process.";
-    }
-
     *in = new AParcel(binder);
+    (*in)->get()->markForBinder(binder->getBinder());
+
     status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
     binder_status_t ret = PruneStatusT(status);
 
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 6824306..22cacb4 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -116,13 +116,13 @@
     const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
 
     // required to be non-null, implemented for every class
-    const AIBinder_Class_onCreate onCreate = nullptr;
-    const AIBinder_Class_onDestroy onDestroy = nullptr;
-    const AIBinder_Class_onTransact onTransact = nullptr;
+    const AIBinder_Class_onCreate onCreate;
+    const AIBinder_Class_onDestroy onDestroy;
+    const AIBinder_Class_onTransact onTransact;
 
     // optional methods for a class
-    AIBinder_onDump onDump = nullptr;
-    AIBinder_handleShellCommand handleShellCommand = nullptr;
+    AIBinder_onDump onDump;
+    AIBinder_handleShellCommand handleShellCommand;
 
    private:
     // Copy of the raw char string for when we don't have to return UTF-16
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 53871f2..0ad400b 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -259,10 +259,24 @@
     const char* getMessage() const { return AStatus_getMessage(get()); }
 
     std::string getDescription() const {
-        const char* cStr = AStatus_getDescription(get());
-        std::string ret = cStr;
-        AStatus_deleteDescription(cStr);
-        return ret;
+        if (__builtin_available(android 30, *)) {
+            const char* cStr = AStatus_getDescription(get());
+            std::string ret = cStr;
+            AStatus_deleteDescription(cStr);
+            return ret;
+        }
+        binder_exception_t exception = getExceptionCode();
+        std::string desc = std::to_string(exception);
+        if (exception == EX_SERVICE_SPECIFIC) {
+            desc += " (" + std::to_string(getServiceSpecificError()) + ")";
+        } else if (exception == EX_TRANSACTION_FAILED) {
+            desc += " (" + std::to_string(getStatus()) + ")";
+        }
+        if (const char* msg = getMessage(); msg != nullptr) {
+            desc += ": ";
+            desc += msg;
+        }
+        return desc;
     }
 
     /**
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index a4f4441..6c44726 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -82,8 +82,12 @@
      */
     template <class T, class... Args>
     static std::shared_ptr<T> make(Args&&... args) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
         T* t = new T(std::forward<Args>(args)...);
-        return t->template ref<T>();
+#pragma clang diagnostic pop
+        // warning: Potential leak of memory pointed to by 't' [clang-analyzer-unix.Malloc]
+        return t->template ref<T>();  // NOLINT(clang-analyzer-unix.Malloc)
     }
 
     static void operator delete(void* p) { std::free(p); }
@@ -246,7 +250,7 @@
     // ourselves. The defaults are harmless.
     AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
 #ifdef HAS_BINDER_SHELL_COMMAND
-    if (AIBinder_Class_setHandleShellCommand != nullptr) {
+    if (__builtin_available(android 30, *)) {
         AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
     }
 #endif
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
index e1d6c34..2277148 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -51,14 +51,27 @@
 
     binder_status_t writeToParcel(AParcel* parcel) const {
         RETURN_ON_FAILURE(AParcel_writeInt32(parcel, static_cast<int32_t>(this->mStability)));
-        RETURN_ON_FAILURE(AParcel_writeInt32(parcel, AParcel_getDataSize(this->mParcel.get())));
-        RETURN_ON_FAILURE(AParcel_appendFrom(this->mParcel.get(), parcel, 0,
-                                             AParcel_getDataSize(this->mParcel.get())));
+        if (__builtin_available(android 31, *)) {
+            int32_t size = AParcel_getDataSize(this->mParcel.get());
+            RETURN_ON_FAILURE(AParcel_writeInt32(parcel, size));
+        } else {
+            return STATUS_INVALID_OPERATION;
+        }
+        if (__builtin_available(android 31, *)) {
+            int32_t size = AParcel_getDataSize(this->mParcel.get());
+            RETURN_ON_FAILURE(AParcel_appendFrom(this->mParcel.get(), parcel, 0, size));
+        } else {
+            return STATUS_INVALID_OPERATION;
+        }
         return STATUS_OK;
     }
 
     binder_status_t readFromParcel(const AParcel* parcel) {
-        AParcel_reset(mParcel.get());
+        if (__builtin_available(android 31, *)) {
+            AParcel_reset(mParcel.get());
+        } else {
+            return STATUS_INVALID_OPERATION;
+        }
 
         RETURN_ON_FAILURE(AParcel_readInt32(parcel, &this->mStability));
         int32_t dataSize;
@@ -74,7 +87,11 @@
             return STATUS_BAD_VALUE;
         }
 
-        status = AParcel_appendFrom(parcel, mParcel.get(), dataStartPos, dataSize);
+        if (__builtin_available(android 31, *)) {
+            status = AParcel_appendFrom(parcel, mParcel.get(), dataStartPos, dataSize);
+        } else {
+            status = STATUS_INVALID_OPERATION;
+        }
         if (status != STATUS_OK) {
             return status;
         }
@@ -82,37 +99,52 @@
     }
 
     template <typename T>
-    bool setParcelable(const T& p) {
+    binder_status_t setParcelable(const T& p) {
         if (this->mStability > T::_aidl_stability) {
-            return false;
+            return STATUS_BAD_VALUE;
         }
-        AParcel_reset(mParcel.get());
+        if (__builtin_available(android 31, *)) {
+            AParcel_reset(mParcel.get());
+        } else {
+            return STATUS_INVALID_OPERATION;
+        }
         AParcel_writeString(mParcel.get(), T::descriptor, strlen(T::descriptor));
         p.writeToParcel(mParcel.get());
-        return true;
+        return STATUS_OK;
     }
 
     template <typename T>
-    std::unique_ptr<T> getParcelable() const {
+    binder_status_t getParcelable(std::optional<T>* ret) const {
         const std::string parcelableDesc(T::descriptor);
         AParcel_setDataPosition(mParcel.get(), 0);
-        if (AParcel_getDataSize(mParcel.get()) == 0) {
-            return nullptr;
+        if (__builtin_available(android 31, *)) {
+            if (AParcel_getDataSize(mParcel.get()) == 0) {
+                *ret = std::nullopt;
+                return STATUS_OK;
+            }
+        } else {
+            return STATUS_INVALID_OPERATION;
         }
         std::string parcelableDescInParcel;
         binder_status_t status = AParcel_readString(mParcel.get(), &parcelableDescInParcel);
         if (status != STATUS_OK || parcelableDesc != parcelableDescInParcel) {
-            return nullptr;
+            *ret = std::nullopt;
+            return status;
         }
-        std::unique_ptr<T> ret = std::make_unique<T>();
-        status = ret->readFromParcel(this->mParcel.get());
+        *ret = std::make_optional<T>();
+        status = (*ret)->readFromParcel(this->mParcel.get());
         if (status != STATUS_OK) {
-            return nullptr;
+            *ret = std::nullopt;
+            return status;
         }
-        return std::move(ret);
+        return STATUS_OK;
     }
 
-    void reset() { AParcel_reset(mParcel.get()); }
+    void reset() {
+        if (__builtin_available(android 31, *)) {
+            AParcel_reset(mParcel.get());
+        }
+    }
 
     inline bool operator!=(const AParcelableHolder& rhs) const { return this != &rhs; }
     inline bool operator<(const AParcelableHolder& rhs) const { return this < &rhs; }
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
new file mode 100644
index 0000000..ef71a81
--- /dev/null
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_to_string.h
+ * @brief Helper for parcelable.
+ */
+
+#pragma once
+
+#include <codecvt>
+#include <locale>
+#include <memory>
+#include <optional>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#if __has_include(<utils/StrongPointer.h>)
+#include <utils/StrongPointer.h>
+#define HAS_STRONG_POINTER
+#endif
+
+#if __has_include(<utils/String16.h>)
+#include <utils/String16.h>
+#define HAS_STRING16
+#endif
+
+#if __has_include(<android/binder_ibinder.h>)
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#define HAS_NDK_INTERFACE
+#else
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/ParcelableHolder.h>
+#endif  //_has_include
+
+namespace android {
+namespace internal {
+
+// ToString is a utility to generate string representation for various AIDL-supported types.
+template <typename _T>
+std::string ToString(const _T& t);
+
+namespace details {
+
+// Truthy if _T has toString() method.
+template <typename _T>
+class HasToStringMethod {
+    template <typename _U>
+    static auto _test(int) -> decltype(std::declval<_U>().toString(), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T has a overloaded toString(T)
+template <typename _T>
+class HasToStringFunction {
+    template <typename _U>
+    static auto _test(int) -> decltype(toString(std::declval<_U>()), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+template <typename T, template <typename...> typename U>
+struct IsInstantiationOf : std::false_type {};
+
+template <template <typename...> typename U, typename... Args>
+struct IsInstantiationOf<U<Args...>, U> : std::true_type {};
+
+// Truthy if _T is like a pointer: one of sp/optional/shared_ptr
+template <typename _T>
+class IsPointerLike {
+    template <typename _U>
+    static std::enable_if_t<
+#ifdef HAS_STRONG_POINTER
+            IsInstantiationOf<_U, sp>::value ||  // for IBinder and interface types in the C++
+                                                 // backend
+#endif
+                    IsInstantiationOf<_U, std::optional>::value ||  // for @nullable types in the
+                                                                    // C++/NDK backends
+                    IsInstantiationOf<_U, std::shared_ptr>::value,  // for interface types in the
+                                                                    // NDK backends
+
+            std::true_type>
+    _test(int);
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T is like a container
+template <typename _T>
+class IsIterable {
+    template <typename _U>
+    static auto _test(int)
+            -> decltype(begin(std::declval<_U>()), end(std::declval<_U>()), std::true_type());
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+template <typename _T>
+class ToEmptyString {
+    template <typename _U>
+    static std::enable_if_t<
+#ifdef HAS_NDK_INTERFACE
+            std::is_base_of_v<::ndk::ICInterface, _U> ||
+                    std::is_same_v<::ndk::AParcelableHolder, _U>
+#else
+            std::is_base_of_v<IInterface, _U> || std::is_same_v<IBinder, _U> ||
+                    std::is_same_v<os::ParcelFileDescriptor, _U> ||
+                    std::is_same_v<os::ParcelableHolder, _U>
+#endif
+            ,
+            std::true_type>
+    _test(int);
+    template <typename _U>
+    static std::false_type _test(...);
+
+   public:
+    enum { value = decltype(_test<_T>(0))::value };
+};
+
+}  // namespace details
+
+template <typename _T>
+std::string ToString(const _T& t) {
+    if constexpr (details::ToEmptyString<_T>::value) {
+        return "";
+    } else if constexpr (std::is_same_v<bool, _T>) {
+        return t ? "true" : "false";
+    } else if constexpr (std::is_same_v<char16_t, _T>) {
+        return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t);
+    } else if constexpr (std::is_arithmetic_v<_T>) {
+        return std::to_string(t);
+    } else if constexpr (std::is_same_v<std::string, _T>) {
+        return t;
+#ifdef HAS_NDK_INTERFACE
+    } else if constexpr (std::is_same_v<::ndk::SpAIBinder, _T>) {
+        return (t.get() == nullptr) ? "(null)" : "";
+    } else if constexpr (std::is_same_v<::ndk::ScopedFileDescriptor, _T>) {
+        return (t.get() == -1) ? "(null)" : "";
+#endif
+#ifdef HAS_STRING16
+    } else if constexpr (std::is_same_v<String16, _T>) {
+        std::stringstream out;
+        out << t;
+        return out.str();
+#endif
+    } else if constexpr (details::IsPointerLike<_T>::value || std::is_pointer_v<_T>) {
+        if (!t) return "(null)";
+        std::stringstream out;
+        out << ToString(*t);
+        return out.str();
+    } else if constexpr (details::HasToStringMethod<_T>::value) {
+        return t.toString();
+    } else if constexpr (details::HasToStringFunction<_T>::value) {
+        return toString(t);
+    } else if constexpr (details::IsIterable<_T>::value) {
+        std::stringstream out;
+        bool first = true;
+        out << "[";
+        for (const auto& e : t) {
+            if (first) {
+                first = false;
+            } else {
+                out << ", ";
+            }
+            // Use explicit type parameter in case deref of iterator has different type
+            // e.g. vector<bool>
+            out << ToString<typename _T::value_type>(e);
+        }
+        out << "]";
+        return out.str();
+    } else {
+        return "{no toString() implemented}";
+    }
+}
+
+}  // namespace internal
+}  // namespace android
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 5e1ed46..9e2050b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -36,13 +36,9 @@
 
 __BEGIN_DECLS
 
-#ifndef __ANDROID_API__
-#error Android builds must be compiled against a specific API. If this is an \
- android platform host build, you must use libbinder_ndk_host_user.
-#endif
-
-#if __ANDROID_API__ >= 29
-
+/**
+ * Flags for AIBinder_transact.
+ */
 typedef uint32_t binder_flags_t;
 enum {
     /**
@@ -54,7 +50,10 @@
     FLAG_ONEWAY = 0x01,
 };
 
-// Also see IBinder.h in libbinder
+/**
+ * Codes for AIBinder_transact. This defines the range of codes available for
+ * usage. Other codes are used or reserved by the Android system.
+ */
 typedef uint32_t transaction_code_t;
 enum {
     /**
@@ -174,7 +173,7 @@
  * Available since API level 29.
  *
  * \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
- * sanity checks on transactions.
+ * validity checks on transactions. This should be utf-8.
  * \param onCreate see AIBinder_Class_onCreate.
  * \param onDestroy see AIBinder_Class_onDestroy.
  * \param onTransact see AIBinder_Class_onTransact.
@@ -209,7 +208,8 @@
  *
  * Available since API level 29.
  *
- * \param dump function to call when an instance of this binder class is being dumped.
+ * \param clazz class which should use this dump function
+ * \param onDump function to call when an instance of this binder class is being dumped.
  */
 void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __INTRODUCED_IN(29);
 
@@ -567,10 +567,6 @@
  */
 void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
 /**
  * Gets the extension registered with AIBinder_setExtension.
  *
@@ -640,10 +636,6 @@
  */
 binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
 
-#endif  //__ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
 /**
  * Retrieve the class descriptor for the class.
  *
@@ -653,11 +645,82 @@
  *
  * \return the class descriptor string. This pointer will never be null; a
  * descriptor is required to define a class. The pointer is owned by the class
- * and will remain valid as long as the class does.
+ * and will remain valid as long as the class does. For a local class, this will
+ * be the same value (not necessarily pointer equal) as is passed into
+ * AIBinder_Class_define. Format is utf-8.
  */
 const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) __INTRODUCED_IN(31);
 
-#endif  //__ANDROID_API__ >= 31
+/**
+ * Whether AIBinder is less than another.
+ *
+ * This provides a per-process-unique total ordering of binders where a null
+ * AIBinder* object is considered to be before all other binder objects.
+ * For instance, two binders refer to the same object in a local or remote
+ * process when both AIBinder_lt(a, b) and AIBinder(b, a) are false. This API
+ * might be used to insert and lookup binders in binary search trees.
+ *
+ * AIBinder* pointers themselves actually also create a per-process-unique total
+ * ordering. However, this ordering is inconsistent with AIBinder_Weak_lt for
+ * remote binders. So, in general, this function should be preferred.
+ *
+ * Available since API level 31.
+ *
+ * \param lhs comparison object
+ * \param rhs comparison object
+ *
+ * \return whether "lhs < rhs" is true
+ */
+bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs) __INTRODUCED_IN(31);
+
+/**
+ * Clone an AIBinder_Weak. Useful because even if a weak binder promotes to a
+ * null value, after further binder transactions, it may no longer promote to a
+ * null value.
+ *
+ * Available since API level 31.
+ *
+ * \param weak Object to clone
+ *
+ * \return clone of the input parameter. This must be deleted with
+ * AIBinder_Weak_delete. Null if weak input parameter is also null.
+ */
+AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak) __INTRODUCED_IN(31);
+
+/**
+ * Whether AIBinder_Weak is less than another.
+ *
+ * This provides a per-process-unique total ordering of binders which is exactly
+ * the same as AIBinder_lt. Similarly, a null AIBinder_Weak* is considered to be
+ * ordered before all other weak references.
+ *
+ * This function correctly distinguishes binders even if one is deallocated. So,
+ * for instance, an AIBinder_Weak* entry representing a deleted binder will
+ * never compare as equal to an AIBinder_Weak* entry which represents a
+ * different allocation of a binder, even if the two binders were originally
+ * allocated at the same address. That is:
+ *
+ *     AIBinder* a = ...; // imagine this has address 0x8
+ *     AIBinder_Weak* bWeak = AIBinder_Weak_new(a);
+ *     AIBinder_decStrong(a); // a may be deleted, if this is the last reference
+ *     AIBinder* b = ...; // imagine this has address 0x8 (same address as b)
+ *     AIBinder_Weak* bWeak = AIBinder_Weak_new(b);
+ *
+ * Then when a/b are compared with other binders, their order will be preserved,
+ * and it will either be the case that AIBinder_Weak_lt(aWeak, bWeak) OR
+ * AIBinder_Weak_lt(bWeak, aWeak), but not both.
+ *
+ * Unlike AIBinder*, the AIBinder_Weak* addresses themselves have nothing to do
+ * with the underlying binder.
+ *
+ * Available since API level 31.
+ *
+ * \param lhs comparison object
+ * \param rhs comparison object
+ *
+ * \return whether "lhs < rhs" is true
+ */
+bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) __INTRODUCED_IN(31);
 
 __END_DECLS
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
index cd1ff1f..6880d86 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -31,7 +31,6 @@
 #include <jni.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
 
 /**
  * Converts an android.os.IBinder object into an AIBinder* object.
@@ -67,7 +66,6 @@
 __attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
         __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= 29
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 93c3f32..527b151 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -36,7 +36,6 @@
 typedef struct AIBinder AIBinder;
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
 
 /**
  * This object represents a package of data that can be sent between processes. When transacting, an
@@ -1119,8 +1118,6 @@
 
 // @END-PRIMITIVE-READ-WRITE
 
-#endif  //__ANDROID_API__ >= 29
-#if __ANDROID_API__ >= 31
 /**
  * Reset the parcel to the initial status.
  *
@@ -1166,7 +1163,6 @@
  * \return A parcel which is not related to any IBinder objects.
  */
 AParcel* AParcel_create() __INTRODUCED_IN(31);
-#endif  //__ANDROID_API__ >= 31
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
index 65e1704..384d4f7 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
@@ -31,7 +31,6 @@
 #include <jni.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 30
 
 /**
  * Converts an android.os.Parcel object into an AParcel* object.
@@ -50,7 +49,6 @@
 __attribute__((warn_unused_result)) AParcel* AParcel_fromJavaParcel(JNIEnv* env, jobject parcel)
         __INTRODUCED_IN(30);
 
-#endif  //__ANDROID_API__ >= 30
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 3a55f94..6f1fdfc 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -31,8 +31,17 @@
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
-#if __ANDROID_API__ >= 29
 
+#ifndef __ANDROID_API__
+#error Android builds must be compiled against a specific API. If this is an \
+ android platform host build, you must use libbinder_ndk_host_user.
+#endif
+
+/**
+ * Low-level status types for use in binder. This is the least preferable way to
+ * return an error for binder services (where binder_exception_t should be used,
+ * particularly EX_SERVICE_SPECIFIC).
+ */
 enum {
     STATUS_OK = 0,
 
@@ -63,6 +72,10 @@
  */
 typedef int32_t binder_status_t;
 
+/**
+ * Top level exceptions types for Android binder errors, mapping to Java
+ * exceptions. Also see Parcel.java.
+ */
 enum {
     EX_NONE = 0,
     EX_SECURITY = -1,
@@ -171,11 +184,12 @@
 /**
  * New status with binder_status_t. This is typically for low level failures when a binder_status_t
  * is returned by an API on AIBinder or AParcel, and that is to be returned from a method returning
- * an AStatus instance.
+ * an AStatus instance. This is the least preferable way to return errors.
+ * Prefer exceptions (particularly service-specific errors) when possible.
  *
  * Available since API level 29.
  *
- * \param a low-level error to associate with this status object.
+ * \param status a low-level error to associate with this status object.
  *
  * \return a newly constructed status object that the caller owns.
  */
@@ -275,7 +289,6 @@
  */
 void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
 
-#endif  //__ANDROID_API__ >= 29
 __END_DECLS
 
 /** @} */
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 2784aa8..a90b4aa 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -26,18 +26,25 @@
  * This registers the service with the default service manager under this instance name. This does
  * not take ownership of binder.
  *
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
  * \param binder object to register globally with the service manager.
  * \param instance identifier of the service. This will be used to lookup the service.
  *
  * \return EX_NONE on success.
  */
-binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance);
+__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addService(
+        AIBinder* binder, const char* instance);
 
 /**
  * Gets a binder object with this specific instance name. Will return nullptr immediately if the
  * service is not available This also implicitly calls AIBinder_incStrong (so the caller of this
  * function is responsible for calling AIBinder_decStrong).
  *
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
  * \param instance identifier of the service used to lookup the service.
  */
 __attribute__((warn_unused_result)) AIBinder* AServiceManager_checkService(const char* instance);
@@ -47,6 +54,9 @@
  * it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
  * for calling AIBinder_decStrong).
  *
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
  * \param instance identifier of the service used to lookup the service.
  */
 __attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
@@ -77,6 +87,9 @@
  * This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
  * for calling AIBinder_decStrong).
  *
+ * WARNING: when using this API across an APEX boundary, do not use with unstable
+ * AIDL services. TODO(b/139325195)
+ *
  * \param instance identifier of the service used to lookup the service.
  *
  * \return service if registered, null if not.
@@ -94,4 +107,77 @@
  */
 bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31);
 
+/**
+ * Returns all declared instances for a particular interface.
+ *
+ * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is
+ * passed here, then ["foo"] would be returned.
+ *
+ * See also AServiceManager_isDeclared.
+ *
+ * \param interface interface, e.g. 'android.foo.IFoo'
+ * \param context to pass to callback
+ * \param callback taking instance (e.g. 'foo') and context
+ */
+void AServiceManager_forEachDeclaredInstance(const char* interface, void* context,
+                                             void (*callback)(const char*, void*))
+        __INTRODUCED_IN(31);
+
+/**
+ * Check if a service is updatable via an APEX module.
+ *
+ * \param instance identifier of the service
+ *
+ * \return whether the interface is updatable via APEX
+ */
+bool AServiceManager_isUpdatableViaApex(const char* instance) __INTRODUCED_IN(31);
+
+/**
+ * Prevent lazy services without client from shutting down their process
+ *
+ * \param persist 'true' if the process should not exit.
+ */
+void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31);
+
+/**
+ * Set a callback that is invoked when the active service count (i.e. services with clients)
+ * registered with this process drops to zero (or becomes nonzero).
+ * The callback takes a boolean argument, which is 'true' if there is
+ * at least one service with clients.
+ *
+ * \param callback function to call when the number of services
+ *    with clients changes.
+ * \param context opaque pointer passed back as second parameter to the
+ * callback.
+ *
+ * The callback takes two arguments. The first is a boolean that represents if there are
+ * services with clients (true) or not (false).
+ * The second is the 'context' pointer passed during the registration.
+ *
+ * Callback return value:
+ * - false: Default behavior for lazy services (shut down the process if there
+ *          are no clients).
+ * - true:  Don't shut down the process even if there are no clients.
+ *
+ * This callback gives a chance to:
+ * 1 - Perform some additional operations before exiting;
+ * 2 - Prevent the process from exiting by returning "true" from the callback.
+ */
+void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context)
+        __INTRODUCED_IN(31);
+
+/**
+ * Try to unregister all services previously registered with 'registerService'.
+ *
+ * \return true on success.
+ */
+bool AServiceManager_tryUnregister() __INTRODUCED_IN(31);
+
+/**
+ * Re-register services that were unregistered by 'tryUnregister'.
+ * This method should be called in the case 'tryUnregister' fails
+ * (and should be called on the same thread).
+ */
+void AServiceManager_reRegister() __INTRODUCED_IN(31);
+
 __END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
index d54c1a1..6372449 100644
--- a/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_parcel_platform.h
@@ -20,9 +20,7 @@
 
 __BEGIN_DECLS
 
-#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__)
-#error this is only for platform code
-#endif
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
 
 /**
  * Gets whether or not FDs are allowed by this AParcel
@@ -33,6 +31,9 @@
  */
 bool AParcel_getAllowFds(const AParcel*);
 
+#endif
+
+#if !defined(__ANDROID_APEX__)
 /**
  * Data written to the parcel will be zero'd before being deleted or realloced.
  *
@@ -43,5 +44,6 @@
  * \param parcel The parcel to clear associated data from.
  */
 void AParcel_markSensitive(const AParcel* parcel);
+#endif
 
 __END_DECLS
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index f5e8bf6..f113ba8 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -30,7 +30,7 @@
     FLAG_PRIVATE_VENDOR = 0x10000000,
 };
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_VENDOR__)
 
 enum {
     FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
@@ -45,7 +45,19 @@
     AIBinder_markVendorStability(binder);
 }
 
-#else  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+/**
+ * Given a binder interface at a certain stability, there may be some
+ * requirements associated with that higher stability level. For instance, a
+ * VINTF stability binder is required to be in the VINTF manifest. This API
+ * can be called to use that same interface within the vendor partition.
+ */
+void AIBinder_forceDowngradeToVendorStability(AIBinder* binder);
+
+static inline void AIBinder_forceDowngradeToLocalStability(AIBinder* binder) {
+    AIBinder_forceDowngradeToVendorStability(binder);
+}
+
+#else  // defined(__ANDROID_VENDOR__)
 
 enum {
     FLAG_PRIVATE_LOCAL = 0,
@@ -62,9 +74,27 @@
     AIBinder_markSystemStability(binder);
 }
 
-#endif  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+/**
+ * Given a binder interface at a certain stability, there may be some
+ * requirements associated with that higher stability level. For instance, a
+ * VINTF stability binder is required to be in the VINTF manifest. This API
+ * can be called to use that same interface within the system partition.
+ */
+void AIBinder_forceDowngradeToSystemStability(AIBinder* binder);
+
+static inline void AIBinder_forceDowngradeToLocalStability(AIBinder* binder) {
+    AIBinder_forceDowngradeToSystemStability(binder);
+}
+
+#endif  // defined(__ANDROID_VENDOR__)
 
 /**
+ * WARNING: this is not expected to be used manually. When the build system has
+ * versioned checks in place for an interface that prevent it being changed year
+ * over year (specifically like those for @VintfStability stable AIDL
+ * interfaces), this could be called. Calling this without this or equivalent
+ * infrastructure will lead to de facto frozen APIs or GSI test failures.
+ *
  * This interface has system<->vendor stability
  */
 void AIBinder_markVintfStability(AIBinder* binder);
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index e233ffd..7d4b82e 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -117,11 +117,24 @@
     ABinderProcess_setupPolling; # apex
     AIBinder_getCallingSid; # apex
     AIBinder_setRequestingSid; # apex
+    AParcel_markSensitive; # llndk
+    AServiceManager_forEachDeclaredInstance; # apex llndk
+    AServiceManager_forceLazyServicesPersist; # llndk
     AServiceManager_isDeclared; # apex llndk
+    AServiceManager_isUpdatableViaApex; # apex
+    AServiceManager_reRegister; # llndk
     AServiceManager_registerLazyService; # llndk
+    AServiceManager_setActiveServicesCallback; # llndk
+    AServiceManager_tryUnregister; # llndk
     AServiceManager_waitForService; # apex llndk
 
+    AIBinder_forceDowngradeToSystemStability; # apex
+    AIBinder_forceDowngradeToVendorStability; # llndk
+
     AIBinder_Class_getDescriptor;
+    AIBinder_Weak_clone;
+    AIBinder_Weak_lt;
+    AIBinder_lt;
     AParcel_appendFrom;
     AParcel_create;
     AParcel_getDataSize;
@@ -131,7 +144,6 @@
 LIBBINDER_NDK_PLATFORM {
   global:
     AParcel_getAllowFds;
-    AParcel_markSensitive;
     extern "C++" {
         AIBinder_fromPlatformBinder*;
         AIBinder_toPlatformBinder*;
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index 6b7295e..b4f6358 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -27,9 +27,8 @@
     const ::android::Parcel* get() const { return mParcel; }
     ::android::Parcel* get() { return mParcel; }
 
-    explicit AParcel(const AIBinder* binder)
-        : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
-    AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
+    explicit AParcel(AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+    AParcel(AIBinder* binder, ::android::Parcel* parcel, bool owns)
         : mBinder(binder), mParcel(parcel), mOwns(owns) {}
 
     ~AParcel() {
@@ -38,7 +37,7 @@
         }
     }
 
-    static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
+    static const AParcel readOnly(AIBinder* binder, const ::android::Parcel* parcel) {
         return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
     }
 
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index c782d47..7649a26 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -19,6 +19,7 @@
 #include "ibinder_internal.h"
 #include "status_internal.h"
 
+#include <android-base/logging.h>
 #include <binder/IServiceManager.h>
 #include <binder/LazyServiceRegistrar.h>
 
@@ -28,6 +29,7 @@
 using ::android::sp;
 using ::android::status_t;
 using ::android::String16;
+using ::android::String8;
 
 binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) {
     if (binder == nullptr || instance == nullptr) {
@@ -92,3 +94,41 @@
     sp<IServiceManager> sm = defaultServiceManager();
     return sm->isDeclared(String16(instance));
 }
+void AServiceManager_forEachDeclaredInstance(const char* interface, void* context,
+                                             void (*callback)(const char*, void*)) {
+    CHECK(interface != nullptr);
+    // context may be nullptr
+    CHECK(callback != nullptr);
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    for (const String16& instance : sm->getDeclaredInstances(String16(interface))) {
+        callback(String8(instance).c_str(), context);
+    }
+}
+bool AServiceManager_isUpdatableViaApex(const char* instance) {
+    if (instance == nullptr) {
+        return false;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    return sm->updatableViaApex(String16(instance)) != std::nullopt;
+}
+void AServiceManager_forceLazyServicesPersist(bool persist) {
+    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+    serviceRegistrar.forcePersist(persist);
+}
+void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) {
+    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+    std::function<bool(bool)> fn = [=](bool hasClients) -> bool {
+        return callback(hasClients, context);
+    };
+    serviceRegistrar.setActiveServicesCallback(fn);
+}
+bool AServiceManager_tryUnregister() {
+    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+    return serviceRegistrar.tryUnregister();
+}
+void AServiceManager_reRegister() {
+    auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+    serviceRegistrar.reRegister();
+}
diff --git a/libs/binder/ndk/stability.cpp b/libs/binder/ndk/stability.cpp
index a5b3ece..7eafb9c 100644
--- a/libs/binder/ndk/stability.cpp
+++ b/libs/binder/ndk/stability.cpp
@@ -31,7 +31,7 @@
 #error libbinder_ndk should only be built in a system context
 #endif
 
-// explicit extern because symbol is only declared in header when __ANDROID_VNDK__
+// explicit extern because symbol is only declared in header when __ANDROID_VENDOR__
 extern "C" void AIBinder_markVendorStability(AIBinder* binder) {
     Stability::markVndk(binder->getBinder().get());
 }
@@ -43,3 +43,12 @@
 void AIBinder_markVintfStability(AIBinder* binder) {
     Stability::markVintf(binder->getBinder().get());
 }
+
+// explicit extern because symbol is only declared in header when __ANDROID_VENDOR__
+extern "C" void AIBinder_forceDowngradeToVendorStability(AIBinder* binder) {
+    Stability::forceDowngradeToVendorStability(binder->getBinder());
+}
+
+void AIBinder_forceDowngradeToSystemStability(AIBinder* binder) {
+    Stability::forceDowngradeToSystemStability(binder->getBinder());
+}
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 46e6270..bb51bf0 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -14,6 +14,15 @@
  * limitations under the License.
  */
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_libs_binder_ndk_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"],
+}
+
 cc_defaults {
     name: "test_libbinder_ndk_defaults",
     shared_libs: [
diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
index dc77467d..ecbd649 100644
--- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
+++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
@@ -28,4 +28,7 @@
     void forceFlushCommands();
 
     boolean getsRequestedSid();
+
+    void forcePersist(boolean persist);
+    void setCustomActiveServicesCallback();
 }
diff --git a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
index ad78e31..f3cd218 100644
--- a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
+++ b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
@@ -163,7 +163,8 @@
 
     // LOCAL SERVERS
     std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
-    AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
+    CHECK(STATUS_OK ==
+          AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str()));
 
     return RUN_ALL_TESTS();
 }
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index 2afe5d2..53b5c3c 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -118,7 +118,7 @@
     AIBinder_Weak_delete(mWeakBinder);
 }
 
-AIBinder* IFoo::getBinder() {
+binder_status_t IFoo::addService(const char* instance) {
     AIBinder* binder = nullptr;
 
     if (mWeakBinder != nullptr) {
@@ -132,18 +132,8 @@
             AIBinder_Weak_delete(mWeakBinder);
         }
         mWeakBinder = AIBinder_Weak_new(binder);
-
-        // WARNING: it is important that this class does not implement debug or
-        // shell functions because it does not use special C++ wrapper
-        // functions, and so this is how we test those functions.
     }
 
-    return binder;
-}
-
-binder_status_t IFoo::addService(const char* instance) {
-    AIBinder* binder = getBinder();
-
     binder_status_t status = AServiceManager_addService(binder, instance);
     // Strong references we care about kept by remote process
     AIBinder_decStrong(binder);
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index 7408d0c..244c985 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -31,9 +31,6 @@
 
     static AIBinder_Class* kClass;
 
-    // binder representing this interface with one reference count
-    AIBinder* getBinder();
-
     // Takes ownership of IFoo
     binder_status_t addService(const char* instance);
     static ::android::sp<IFoo> getService(const char* instance, AIBinder** outBinder = nullptr);
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index b7df115..1c43948 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -46,6 +46,11 @@
 constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
 constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
 constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
+constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
+constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
+
+constexpr unsigned int kShutdownWaitTime = 10;
+constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
 
 class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
     ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
@@ -76,6 +81,46 @@
         fsync(out);
         return STATUS_OK;
     }
+    ndk::ScopedAStatus forcePersist(bool persist) {
+        AServiceManager_forceLazyServicesPersist(persist);
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setCustomActiveServicesCallback() {
+        AServiceManager_setActiveServicesCallback(activeServicesCallback, this);
+        return ndk::ScopedAStatus::ok();
+    }
+    static bool activeServicesCallback(bool hasClients, void* context) {
+        if (hasClients) {
+            return false;
+        }
+
+        // Unregister all services
+        if (!AServiceManager_tryUnregister()) {
+            // Prevent shutdown (test will fail)
+            return false;
+        }
+
+        // Re-register all services
+        AServiceManager_reRegister();
+
+        // Unregister again before shutdown
+        if (!AServiceManager_tryUnregister()) {
+            // Prevent shutdown (test will fail)
+            return false;
+        }
+
+        // Check if the context was passed correctly
+        MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context);
+        if (service->contextTestValue != kContextTestValue) {
+            // Prevent shutdown (test will fail)
+            return false;
+        }
+
+        exit(EXIT_SUCCESS);
+        // Unreachable
+    }
+
+    uint64_t contextTestValue = kContextTestValue;
 };
 
 int generatedService() {
@@ -168,6 +213,16 @@
     return 1;  // should not return
 }
 
+bool isServiceRunning(const char* serviceName) {
+    AIBinder* binder = AServiceManager_checkService(serviceName);
+    if (binder == nullptr) {
+        return false;
+    }
+    AIBinder_decStrong(binder);
+
+    return true;
+}
+
 TEST(NdkBinder, GetServiceThatDoesntExist) {
     sp<IFoo> foo = IFoo::getService("asdfghkl;");
     EXPECT_EQ(nullptr, foo.get());
@@ -186,26 +241,6 @@
     AIBinder_decStrong(binder);
 }
 
-TEST(NdkBinder, UnimplementedDump) {
-    sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
-    ASSERT_NE(foo, nullptr);
-    AIBinder* binder = foo->getBinder();
-    EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0));
-    AIBinder_decStrong(binder);
-}
-
-TEST(NdkBinder, UnimplementedShell) {
-    // libbinder_ndk doesn't support calling shell, so we are calling from the
-    // libbinder across processes to the NDK service which doesn't implement
-    // shell
-    static const sp<android::IServiceManager> sm(android::defaultServiceManager());
-    sp<IBinder> testService = sm->getService(String16(IFoo::kSomeInstanceName));
-
-    Vector<String16> argsVec;
-    EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
-                                        argsVec, nullptr, nullptr));
-}
-
 TEST(NdkBinder, DoubleNumber) {
     sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
     ASSERT_NE(foo, nullptr);
@@ -215,6 +250,25 @@
     EXPECT_EQ(2, out);
 }
 
+void defaultInstanceCounter(const char* instance, void* context) {
+    if (strcmp(instance, "default") == 0) {
+        ++*(size_t*)(context);
+    }
+}
+
+TEST(NdkBinder, GetDeclaredInstances) {
+    bool hasLight = AServiceManager_isDeclared("android.hardware.light.ILights/default");
+
+    size_t count;
+    AServiceManager_forEachDeclaredInstance("android.hardware.light.ILights", &count,
+                                            defaultInstanceCounter);
+
+    // At the time of writing this test, there is no good interface guaranteed
+    // to be on all devices. Cuttlefish has light, so this will generally test
+    // things.
+    EXPECT_EQ(count, hasLight ? 1 : 0);
+}
+
 TEST(NdkBinder, GetLazyService) {
     // Not declared in the vintf manifest
     ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService));
@@ -226,6 +280,11 @@
     EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
 }
 
+TEST(NdkBinder, IsUpdatable) {
+    bool isUpdatable = AServiceManager_isUpdatableViaApex("android.hardware.light.ILights/default");
+    EXPECT_EQ(isUpdatable, false);
+}
+
 // This is too slow
 TEST(NdkBinder, CheckLazyServiceShutDown) {
     ndk::SpAIBinder binder(AServiceManager_waitForService(kLazyBinderNdkUnitTestService));
@@ -238,10 +297,51 @@
     service = nullptr;
     IPCThreadState::self()->flushCommands();
     // Make sure the service is dead after some time of no use
-    sleep(10);
+    sleep(kShutdownWaitTime);
     ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
 }
 
+TEST(NdkBinder, ForcedPersistenceTest) {
+    for (int i = 0; i < 2; i++) {
+        ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService));
+        std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+                aidl::IBinderNdkUnitTest::fromBinder(binder);
+        ASSERT_NE(service, nullptr);
+        ASSERT_TRUE(service->forcePersist(i == 0).isOk());
+
+        binder = nullptr;
+        service = nullptr;
+        IPCThreadState::self()->flushCommands();
+
+        sleep(kShutdownWaitTime);
+
+        bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);
+
+        if (i == 0) {
+            ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
+        } else {
+            ASSERT_FALSE(isRunning) << "Service failed to shut down.";
+        }
+    }
+}
+
+TEST(NdkBinder, ActiveServicesCallbackTest) {
+    ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService));
+    std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+            aidl::IBinderNdkUnitTest::fromBinder(binder);
+    ASSERT_NE(service, nullptr);
+    ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());
+
+    binder = nullptr;
+    service = nullptr;
+    IPCThreadState::self()->flushCommands();
+
+    sleep(kShutdownWaitTime);
+
+    ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
+            << "Service failed to shut down.";
+}
+
 void LambdaOnDeath(void* cookie) {
     auto onDeath = static_cast<std::function<void(void)>*>(cookie);
     (*onDeath)();
@@ -375,8 +475,7 @@
 
     AIBinder_decStrong(binder);
 
-    // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here
-    ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder));
+    ASSERT_EQ(nullptr, AIBinder_Weak_promote(wBinder));
 
     AIBinder_Weak_delete(wBinder);
 }
@@ -565,10 +664,18 @@
     }
     if (fork() == 0) {
         prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return lazyService(kForcePersistNdkUnitTestService);
+    }
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+        return lazyService(kActiveServicesNdkUnitTestService);
+    }
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
         return generatedService();
     }
 
-    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to recieve death notifications/callbacks
+    ABinderProcess_setThreadPoolMaxThreadCount(1);  // to receive death notifications/callbacks
     ABinderProcess_startThreadPool();
 
     return RUN_ALL_TESTS();
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index fd5f2f5..49d3401 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 rust_library {
     name: "libbinder_rs",
     crate_name: "binder",
@@ -14,7 +23,11 @@
         darwin: {
             enabled: false,
         }
-    }
+    },
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
 
 rust_library {
@@ -32,7 +45,13 @@
         darwin: {
             enabled: false,
         }
-    }
+    },
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
+    lints: "none",
+    clippy_lints: "none",
 }
 
 rust_bindgen {
@@ -48,15 +67,15 @@
         // rustified
         "--constified-enum", "android::c_interface::consts::.*",
 
-        "--whitelist-type", "android::c_interface::.*",
-        "--whitelist-type", "AStatus",
-        "--whitelist-type", "AIBinder_Class",
-        "--whitelist-type", "AIBinder",
-        "--whitelist-type", "AIBinder_Weak",
-        "--whitelist-type", "AIBinder_DeathRecipient",
-        "--whitelist-type", "AParcel",
-        "--whitelist-type", "binder_status_t",
-        "--whitelist-function", ".*",
+        "--allowlist-type", "android::c_interface::.*",
+        "--allowlist-type", "AStatus",
+        "--allowlist-type", "AIBinder_Class",
+        "--allowlist-type", "AIBinder",
+        "--allowlist-type", "AIBinder_Weak",
+        "--allowlist-type", "AIBinder_DeathRecipient",
+        "--allowlist-type", "AParcel",
+        "--allowlist-type", "binder_status_t",
+        "--allowlist-function", ".*",
     ],
     shared_libs: [
         "libbinder_ndk",
@@ -78,6 +97,10 @@
             enabled: false,
         },
     },
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
 }
 
 rust_test {
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index ed3b9ec..695a83e 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -16,25 +16,30 @@
 
 //! Trait definitions for binder objects
 
-use crate::error::{status_t, Result};
+use crate::error::{status_t, Result, StatusCode};
 use crate::parcel::Parcel;
-use crate::proxy::{DeathRecipient, SpIBinder};
+use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
 use crate::sys;
 
+use std::borrow::Borrow;
+use std::cmp::Ordering;
 use std::ffi::{c_void, CStr, CString};
+use std::fmt;
+use std::marker::PhantomData;
+use std::ops::Deref;
 use std::os::raw::c_char;
 use std::os::unix::io::AsRawFd;
 use std::ptr;
 
 /// Binder action to perform.
 ///
-/// This must be a number between [`IBinder::FIRST_CALL_TRANSACTION`] and
-/// [`IBinder::LAST_CALL_TRANSACTION`].
+/// This must be a number between [`FIRST_CALL_TRANSACTION`] and
+/// [`LAST_CALL_TRANSACTION`].
 pub type TransactionCode = u32;
 
 /// Additional operation flags.
 ///
-/// `IBinder::FLAG_*` values.
+/// `FLAG_*` values.
 pub type TransactionFlags = u32;
 
 /// Super-trait for Binder interfaces.
@@ -44,13 +49,33 @@
 /// interfaces) must implement this trait.
 ///
 /// This is equivalent `IInterface` in C++.
-pub trait Interface {
+pub trait Interface: Send {
     /// Convert this binder object into a generic [`SpIBinder`] reference.
     fn as_binder(&self) -> SpIBinder {
         panic!("This object was not a Binder object and cannot be converted into an SpIBinder.")
     }
 }
 
+/// Interface stability promise
+///
+/// An interface can promise to be a stable vendor interface ([`Vintf`]), or
+/// makes no stability guarantees ([`Local`]). [`Local`] is
+/// currently the default stability.
+pub enum Stability {
+    /// Default stability, visible to other modules in the same compilation
+    /// context (e.g. modules on system.img)
+    Local,
+
+    /// A Vendor Interface Object, which promises to be stable
+    Vintf,
+}
+
+impl Default for Stability {
+    fn default() -> Self {
+        Stability::Local
+    }
+}
+
 /// A local service that can be remotable via Binder.
 ///
 /// An object that implement this interface made be made into a Binder service
@@ -80,20 +105,24 @@
     fn get_class() -> InterfaceClass;
 }
 
-/// Interface of binder local or remote objects.
+/// First transaction code available for user commands (inclusive)
+pub const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
+/// Last transaction code available for user commands (inclusive)
+pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
+
+/// Corresponds to TF_ONE_WAY -- an asynchronous call.
+pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
+/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
+pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
+/// Set to the vendor flag if we are building for the VNDK, 0 otherwise
+pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL;
+
+/// Internal interface of binder local or remote objects for making
+/// transactions.
 ///
-/// This trait corresponds to the interface of the C++ `IBinder` class.
-pub trait IBinder {
-    /// First transaction code available for user commands (inclusive)
-    const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
-    /// Last transaction code available for user commands (inclusive)
-    const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
-
-    /// Corresponds to TF_ONE_WAY -- an asynchronous call.
-    const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
-    /// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
-    const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
-
+/// This trait corresponds to the parts of the interface of the C++ `IBinder`
+/// class which are internal implementation details.
+pub trait IBinderInternal: IBinder {
     /// Is this object still alive?
     fn is_binder_alive(&self) -> bool;
 
@@ -117,19 +146,24 @@
     /// * `data` - [`Parcel`] with input data
     /// * `reply` - Optional [`Parcel`] for reply data
     /// * `flags` - Transaction flags, e.g. marking the transaction as
-    /// asynchronous ([`FLAG_ONEWAY`](IBinder::FLAG_ONEWAY))
+    ///   asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY))
     fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
         &self,
         code: TransactionCode,
         flags: TransactionFlags,
         input_callback: F,
     ) -> Result<Parcel>;
+}
 
+/// Interface of binder local or remote objects.
+///
+/// This trait corresponds to the parts of the interface of the C++ `IBinder`
+/// class which are public.
+pub trait IBinder {
     /// Register the recipient for a notification if this binder
     /// goes away. If this binder object unexpectedly goes away
     /// (typically because its hosting process has been killed),
-    /// then DeathRecipient::binder_died() will be called with a reference
-    /// to this.
+    /// then the `DeathRecipient`'s callback will be called.
     ///
     /// You will only receive death notifications for remote binders,
     /// as local binders by definition can't die without you dying as well.
@@ -137,11 +171,6 @@
     /// INVALID_OPERATION code being returned and nothing happening.
     ///
     /// This link always holds a weak reference to its recipient.
-    ///
-    /// You will only receive a weak reference to the dead
-    /// binder. You should not try to promote this to a strong reference.
-    /// (Nor should you need to, as there is nothing useful you can
-    /// directly do with it now that it has passed on.)
     fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>;
 
     /// Remove a previously registered death notification.
@@ -217,7 +246,8 @@
             // the number of u16 elements before the null terminator.
 
             let raw_descriptor: *const c_char = sys::AIBinder_Class_getDescriptor(self.0);
-            CStr::from_ptr(raw_descriptor).to_str()
+            CStr::from_ptr(raw_descriptor)
+                .to_str()
                 .expect("Expected valid UTF-8 string from AIBinder_Class_getDescriptor")
                 .into()
         }
@@ -230,6 +260,132 @@
     }
 }
 
+/// Strong reference to a binder object
+pub struct Strong<I: FromIBinder + ?Sized>(Box<I>);
+
+impl<I: FromIBinder + ?Sized> Strong<I> {
+    /// Create a new strong reference to the provided binder object
+    pub fn new(binder: Box<I>) -> Self {
+        Self(binder)
+    }
+
+    /// Construct a new weak reference to this binder
+    pub fn downgrade(this: &Strong<I>) -> Weak<I> {
+        Weak::new(this)
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
+    fn clone(&self) -> Self {
+        // Since we hold a strong reference, we should always be able to create
+        // a new strong reference to the same interface type, so try_from()
+        // should never fail here.
+        FromIBinder::try_from(self.0.as_binder()).unwrap()
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> {
+    fn borrow(&self) -> &I {
+        &self.0
+    }
+}
+
+impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> {
+    fn as_ref(&self) -> &I {
+        &self.0
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Deref for Strong<I> {
+    type Target = I;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Ord for Strong<I> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.0.as_binder().cmp(&other.0.as_binder())
+    }
+}
+
+impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.0.as_binder().partial_cmp(&other.0.as_binder())
+    }
+}
+
+impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> {
+    fn eq(&self, other: &Self) -> bool {
+        self.0.as_binder().eq(&other.0.as_binder())
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Eq for Strong<I> {}
+
+/// Weak reference to a binder object
+#[derive(Debug)]
+pub struct Weak<I: FromIBinder + ?Sized> {
+    weak_binder: WpIBinder,
+    interface_type: PhantomData<I>,
+}
+
+impl<I: FromIBinder + ?Sized> Weak<I> {
+    /// Construct a new weak reference from a strong reference
+    fn new(binder: &Strong<I>) -> Self {
+        let weak_binder = binder.as_binder().downgrade();
+        Weak {
+            weak_binder,
+            interface_type: PhantomData,
+        }
+    }
+
+    /// Upgrade this weak reference to a strong reference if the binder object
+    /// is still alive
+    pub fn upgrade(&self) -> Result<Strong<I>> {
+        self.weak_binder
+            .promote()
+            .ok_or(StatusCode::DEAD_OBJECT)
+            .and_then(FromIBinder::try_from)
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Clone for Weak<I> {
+    fn clone(&self) -> Self {
+        Self {
+            weak_binder: self.weak_binder.clone(),
+            interface_type: PhantomData,
+        }
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Ord for Weak<I> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.weak_binder.cmp(&other.weak_binder)
+    }
+}
+
+impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.weak_binder.partial_cmp(&other.weak_binder)
+    }
+}
+
+impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> {
+    fn eq(&self, other: &Self) -> bool {
+        self.weak_binder == other.weak_binder
+    }
+}
+
+impl<I: FromIBinder + ?Sized> Eq for Weak<I> {}
+
 /// Create a function implementing a static getter for an interface class.
 ///
 /// Each binder interface (i.e. local [`Remotable`] service or remote proxy
@@ -354,12 +510,12 @@
 ///     }
 /// }
 /// ```
-pub trait FromIBinder {
+pub trait FromIBinder: Interface {
     /// Try to interpret a generic Binder object as this interface.
     ///
     /// Returns a trait object for the `Self` interface if this object
     /// implements that interface.
-    fn try_from(ibinder: SpIBinder) -> Result<Box<Self>>;
+    fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>;
 }
 
 /// Trait for transparent Rust wrappers around android C++ native types.
@@ -392,6 +548,28 @@
     }
 }
 
+/// The features to enable when creating a native Binder.
+///
+/// This should always be initialised with a default value, e.g.:
+/// ```
+/// # use binder::BinderFeatures;
+/// BinderFeatures {
+///   set_requesting_sid: true,
+///   ..BinderFeatures::default(),
+/// }
+/// ```
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct BinderFeatures {
+    /// Indicates that the service intends to receive caller security contexts. This must be true
+    /// for `ThreadState::with_calling_sid` to work.
+    pub set_requesting_sid: bool,
+    // Ensure that clients include a ..BinderFeatures::default() to preserve backwards compatibility
+    // when new fields are added. #[non_exhaustive] doesn't work because it prevents struct
+    // expressions entirely.
+    #[doc(hidden)]
+    pub _non_exhaustive: (),
+}
+
 /// Declare typed interfaces for a binder object.
 ///
 /// Given an interface trait and descriptor string, create a native and remote
@@ -468,6 +646,23 @@
             $interface[$descriptor] {
                 native: $native($on_transact),
                 proxy: $proxy {},
+                stability: $crate::Stability::default(),
+            }
+        }
+    };
+
+    {
+        $interface:path[$descriptor:expr] {
+            native: $native:ident($on_transact:path),
+            proxy: $proxy:ident,
+            stability: $stability:expr,
+        }
+    } => {
+        $crate::declare_binder_interface! {
+            $interface[$descriptor] {
+                native: $native($on_transact),
+                proxy: $proxy {},
+                stability: $stability,
             }
         }
     };
@@ -482,12 +677,33 @@
     } => {
         $crate::declare_binder_interface! {
             $interface[$descriptor] {
+                native: $native($on_transact),
+                proxy: $proxy {
+                    $($fname: $fty = $finit),*
+                },
+                stability: $crate::Stability::default(),
+            }
+        }
+    };
+
+    {
+        $interface:path[$descriptor:expr] {
+            native: $native:ident($on_transact:path),
+            proxy: $proxy:ident {
+                $($fname:ident: $fty:ty = $finit:expr),*
+            },
+            stability: $stability:expr,
+        }
+    } => {
+        $crate::declare_binder_interface! {
+            $interface[$descriptor] {
                 @doc[concat!("A binder [`Remotable`]($crate::Remotable) that holds an [`", stringify!($interface), "`] object.")]
                 native: $native($on_transact),
                 @doc[concat!("A binder [`Proxy`]($crate::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
                 proxy: $proxy {
                     $($fname: $fty = $finit),*
                 },
+                stability: $stability,
             }
         }
     };
@@ -501,6 +717,8 @@
             proxy: $proxy:ident {
                 $($fname:ident: $fty:ty = $finit:expr),*
             },
+
+            stability: $stability:expr,
         }
     } => {
         #[doc = $proxy_doc]
@@ -534,8 +752,10 @@
 
         impl $native {
             /// Create a new binder service.
-            pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> impl $interface {
-                $crate::Binder::new($native(Box::new(inner)))
+            pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
+                let mut binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability);
+                $crate::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
+                $crate::Strong::new(Box::new(binder))
             }
         }
 
@@ -577,7 +797,7 @@
         }
 
         impl $crate::FromIBinder for dyn $interface {
-            fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> {
+            fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> {
                 use $crate::AssociateClass;
 
                 let existing_class = ibinder.get_class();
@@ -590,7 +810,7 @@
                         // associated object as remote, because we can't cast it
                         // into a Rust service object without a matching class
                         // pointer.
-                        return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?));
+                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
                     }
                 }
 
@@ -600,10 +820,10 @@
                     if let Ok(service) = service {
                         // We were able to associate with our expected class and
                         // the service is local.
-                        return Ok(Box::new(service));
+                        return Ok($crate::Strong::new(Box::new(service)));
                     } else {
                         // Service is remote
-                        return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?));
+                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
                     }
                 }
 
@@ -613,7 +833,7 @@
 
         impl $crate::parcel::Serialize for dyn $interface + '_
         where
-            $interface: $crate::Interface
+            dyn $interface: $crate::Interface
         {
             fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
                 let binder = $crate::Interface::as_binder(self);
@@ -633,9 +853,9 @@
             }
         }
 
-        // Convert a &dyn $interface to Box<dyn $interface>
+        /// Convert a &dyn $interface to Strong<dyn $interface>
         impl std::borrow::ToOwned for dyn $interface {
-            type Owned = Box<dyn $interface>;
+            type Owned = $crate::Strong<dyn $interface>;
             fn to_owned(&self) -> Self::Owned {
                 self.as_binder().into_interface()
                     .expect(concat!("Error cloning interface ", stringify!($interface)))
diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs
index 4492cf7..2598ebc 100644
--- a/libs/binder/rust/src/error.rs
+++ b/libs/binder/rust/src/error.rs
@@ -77,9 +77,7 @@
         e if e == ExceptionCode::ILLEGAL_ARGUMENT as i32 => ExceptionCode::ILLEGAL_ARGUMENT,
         e if e == ExceptionCode::NULL_POINTER as i32 => ExceptionCode::NULL_POINTER,
         e if e == ExceptionCode::ILLEGAL_STATE as i32 => ExceptionCode::ILLEGAL_STATE,
-        e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => {
-            ExceptionCode::NETWORK_MAIN_THREAD
-        }
+        e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => ExceptionCode::NETWORK_MAIN_THREAD,
         e if e == ExceptionCode::UNSUPPORTED_OPERATION as i32 => {
             ExceptionCode::UNSUPPORTED_OPERATION
         }
@@ -96,6 +94,16 @@
 /// Used in AIDL transactions to represent failed transactions.
 pub struct Status(*mut sys::AStatus);
 
+// Safety: The `AStatus` that the `Status` points to must have an entirely thread-safe API for the
+// duration of the `Status` object's lifetime. We ensure this by not allowing mutation of a `Status`
+// in Rust, and the NDK API says we're the owner of our `AStatus` objects so outside code should not
+// be mutating them underneath us.
+unsafe impl Sync for Status {}
+
+// Safety: `Status` always contains an owning pointer to a global, immutable, interned `AStatus`.
+// A thread-local `AStatus` would not be valid.
+unsafe impl Send for Status {}
+
 impl Status {
     /// Create a status object representing a successful transaction.
     pub fn ok() -> Self {
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index edfb56a..2694cba 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -107,7 +107,9 @@
 pub mod parcel;
 
 pub use crate::binder::{
-    FromIBinder, IBinder, Interface, InterfaceClass, Remotable, TransactionCode, TransactionFlags,
+    BinderFeatures, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable,
+    Stability, Strong, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION,
+    FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
 };
 pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
 pub use native::add_service;
@@ -122,7 +124,8 @@
     pub use super::parcel::ParcelFileDescriptor;
     pub use super::{add_service, get_interface};
     pub use super::{
-        ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, WpIBinder,
+        BinderFeatures, DeathRecipient, ExceptionCode, IBinder, Interface, ProcessState, SpIBinder,
+        Status, StatusCode, Strong, ThreadState, Weak, WpIBinder,
     };
 
     /// Binder result containing a [`Status`] on error.
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 185645e..3b3fd08 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, TransactionCode};
+use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode};
 use crate::error::{status_result, status_t, Result, StatusCode};
 use crate::parcel::{Parcel, Serialize};
 use crate::proxy::SpIBinder;
@@ -49,11 +49,19 @@
 unsafe impl<T: Remotable> Send for Binder<T> {}
 
 impl<T: Remotable> Binder<T> {
-    /// Create a new Binder remotable object.
+    /// Create a new Binder remotable object with default stability
     ///
     /// This moves the `rust_object` into an owned [`Box`] and Binder will
     /// manage its lifetime.
     pub fn new(rust_object: T) -> Binder<T> {
+        Self::new_with_stability(rust_object, Stability::default())
+    }
+
+    /// Create a new Binder remotable object with the given stability
+    ///
+    /// This moves the `rust_object` into an owned [`Box`] and Binder will
+    /// manage its lifetime.
+    pub fn new_with_stability(rust_object: T, stability: Stability) -> Binder<T> {
         let class = T::get_class();
         let rust_object = Box::into_raw(Box::new(rust_object));
         let ibinder = unsafe {
@@ -65,10 +73,12 @@
             // ends.
             sys::AIBinder_new(class.into(), rust_object as *mut c_void)
         };
-        Binder {
+        let mut binder = Binder {
             ibinder,
             rust_object,
-        }
+        };
+        binder.mark_stability(stability);
+        binder
     }
 
     /// Set the extension of a binder interface. This allows a downstream
@@ -161,6 +171,42 @@
     pub fn get_descriptor() -> &'static str {
         T::get_descriptor()
     }
+
+    /// Mark this binder object with the given stability guarantee
+    fn mark_stability(&mut self, stability: Stability) {
+        match stability {
+            Stability::Local => self.mark_local_stability(),
+            Stability::Vintf => {
+                unsafe {
+                    // Safety: Self always contains a valid `AIBinder` pointer, so
+                    // we can always call this C API safely.
+                    sys::AIBinder_markVintfStability(self.as_native_mut());
+                }
+            }
+        }
+    }
+
+    /// Mark this binder object with local stability, which is vendor if we are
+    /// building for the VNDK and system otherwise.
+    #[cfg(vendor_ndk)]
+    fn mark_local_stability(&mut self) {
+        unsafe {
+            // Safety: Self always contains a valid `AIBinder` pointer, so
+            // we can always call this C API safely.
+            sys::AIBinder_markVendorStability(self.as_native_mut());
+        }
+    }
+
+    /// Mark this binder object with local stability, which is vendor if we are
+    /// building for the VNDK and system otherwise.
+    #[cfg(not(vendor_ndk))]
+    fn mark_local_stability(&mut self) {
+        unsafe {
+            // Safety: Self always contains a valid `AIBinder` pointer, so
+            // we can always call this C API safely.
+            sys::AIBinder_markSystemStability(self.as_native_mut());
+        }
+    }
 }
 
 impl<T: Remotable> Interface for Binder<T> {
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 138b360..f57788b 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
-use crate::binder::{AsNative, FromIBinder};
-use crate::error::{status_result, Result, Status, StatusCode};
+use crate::binder::{AsNative, FromIBinder, Strong};
+use crate::error::{status_result, status_t, Result, Status, StatusCode};
 use crate::parcel::Parcel;
 use crate::proxy::SpIBinder;
 use crate::sys;
 
 use std::convert::TryInto;
 use std::ffi::c_void;
-use std::os::raw::c_char;
+use std::os::raw::{c_char, c_ulong};
+use std::mem::{self, MaybeUninit};
 use std::ptr;
+use std::slice;
 
 /// A struct whose instances can be written to a [`Parcel`].
 // Might be able to hook this up as a serde backend in the future?
@@ -49,38 +51,109 @@
 pub trait SerializeArray: Serialize + Sized {
     /// Serialize an array of this type into the given [`Parcel`].
     fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> {
-        parcel.write_slice_size(Some(slice))?;
-
-        for item in slice {
-            parcel.write(item)?;
-        }
-
-        Ok(())
+        let res = unsafe {
+            // Safety: Safe FFI, slice will always be a safe pointer to pass.
+            sys::AParcel_writeParcelableArray(
+                parcel.as_native_mut(),
+                slice.as_ptr() as *const c_void,
+                slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?,
+                Some(serialize_element::<Self>),
+            )
+        };
+        status_result(res)
     }
 }
 
+/// Callback to serialize an element of a generic parcelable array.
+///
+/// Safety: We are relying on binder_ndk to not overrun our slice. As long as it
+/// doesn't provide an index larger than the length of the original slice in
+/// serialize_array, this operation is safe. The index provided is zero-based.
+unsafe extern "C" fn serialize_element<T: Serialize>(
+    parcel: *mut sys::AParcel,
+    array: *const c_void,
+    index: c_ulong,
+) -> status_t {
+    // c_ulong and usize are the same, but we need the explicitly sized version
+    // so the function signature matches what bindgen generates.
+    let index = index as usize;
+
+    let slice: &[T] = slice::from_raw_parts(array.cast(), index+1);
+
+    let mut parcel = match Parcel::borrowed(parcel) {
+        None => return StatusCode::UNEXPECTED_NULL as status_t,
+        Some(p) => p,
+    };
+
+    slice[index].serialize(&mut parcel)
+                .err()
+                .unwrap_or(StatusCode::OK)
+        as status_t
+}
+
 /// Helper trait for types that can be deserialized as arrays.
 /// Defaults to calling Deserialize::deserialize() manually for every element,
 /// but can be overridden for custom implementations like `readByteArray`.
 pub trait DeserializeArray: Deserialize {
     /// Deserialize an array of type from the given [`Parcel`].
     fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> {
-        let len: i32 = parcel.read()?;
-        if len < 0 {
-            return Ok(None);
-        }
-
-        // TODO: Assumes that usize is at least 32 bits
-        let mut vec = Vec::with_capacity(len as usize);
-
-        for _ in 0..len {
-            vec.push(parcel.read()?);
-        }
-
-        Ok(Some(vec))
+        let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
+        let res = unsafe {
+            // Safety: Safe FFI, vec is the correct opaque type expected by
+            // allocate_vec and deserialize_element.
+            sys::AParcel_readParcelableArray(
+                parcel.as_native(),
+                &mut vec as *mut _ as *mut c_void,
+                Some(allocate_vec::<Self>),
+                Some(deserialize_element::<Self>),
+            )
+        };
+        status_result(res)?;
+        let vec: Option<Vec<Self>> = unsafe {
+            // Safety: We are assuming that the NDK correctly initialized every
+            // element of the vector by now, so we know that all the
+            // MaybeUninits are now properly initialized. We can transmute from
+            // Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T> has the same
+            // alignment and size as T, so the pointer to the vector allocation
+            // will be compatible.
+            mem::transmute(vec)
+        };
+        Ok(vec)
     }
 }
 
+/// Callback to deserialize a parcelable element.
+///
+/// The opaque array data pointer must be a mutable pointer to an
+/// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid
+/// (zero-based).
+unsafe extern "C" fn deserialize_element<T: Deserialize>(
+    parcel: *const sys::AParcel,
+    array: *mut c_void,
+    index: c_ulong,
+) -> status_t {
+    // c_ulong and usize are the same, but we need the explicitly sized version
+    // so the function signature matches what bindgen generates.
+    let index = index as usize;
+
+    let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>);
+    let vec = match vec {
+        Some(v) => v,
+        None => return StatusCode::BAD_INDEX as status_t,
+    };
+
+    let parcel = match Parcel::borrowed(parcel as *mut _) {
+        None => return StatusCode::UNEXPECTED_NULL as status_t,
+        Some(p) => p,
+    };
+    let element = match parcel.read() {
+        Ok(e) => e,
+        Err(code) => return code as status_t,
+    };
+    ptr::write(vec[index].as_mut_ptr(), element);
+    StatusCode::OK as status_t
+}
+
 /// Helper trait for types that can be nullable when serialized.
 // We really need this trait instead of implementing `Serialize for Option<T>`
 // because of the Rust orphan rule which prevents us from doing
@@ -115,28 +188,54 @@
 
 /// Callback to allocate a vector for parcel array read functions.
 ///
+/// This variant is for APIs which use an out buffer pointer.
+///
 /// # Safety
 ///
 /// The opaque data pointer passed to the array read function must be a mutable
-/// pointer to an `Option<Vec<T>>`. `buffer` will be assigned a mutable pointer
+/// pointer to an `Option<Vec<MaybeUninit<T>>>`. `buffer` will be assigned a mutable pointer
 /// to the allocated vector data if this function returns true.
-unsafe extern "C" fn allocate_vec<T: Clone + Default>(
+unsafe extern "C" fn allocate_vec_with_buffer<T>(
     data: *mut c_void,
     len: i32,
     buffer: *mut *mut T,
 ) -> bool {
-    let vec = &mut *(data as *mut Option<Vec<T>>);
+    let res = allocate_vec::<T>(data, len);
+    let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
+    if let Some(new_vec) = vec {
+        *buffer = new_vec.as_mut_ptr() as *mut T;
+    }
+    res
+}
+
+/// Callback to allocate a vector for parcel array read functions.
+///
+/// # Safety
+///
+/// The opaque data pointer passed to the array read function must be a mutable
+/// pointer to an `Option<Vec<MaybeUninit<T>>>`.
+unsafe extern "C" fn allocate_vec<T>(
+    data: *mut c_void,
+    len: i32,
+) -> bool {
+    let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>);
     if len < 0 {
         *vec = None;
         return true;
     }
-    let mut new_vec: Vec<T> = Vec::with_capacity(len as usize);
-    new_vec.resize_with(len as usize, Default::default);
-    *buffer = new_vec.as_mut_ptr();
-    *vec = Some(new_vec);
+    let mut new_vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len as usize);
+
+    // Safety: We are filling the vector with uninitialized data here, but this
+    // is safe because the vector contains MaybeUninit elements which can be
+    // uninitialized. We're putting off the actual unsafe bit, transmuting the
+    // vector to a Vec<T> until the contents are initialized.
+    new_vec.set_len(len as usize);
+
+    ptr::write(vec, Some(new_vec));
     true
 }
 
+
 macro_rules! parcelable_primitives {
     {
         $(
@@ -204,19 +303,29 @@
     {DeserializeArray, $ty:ty, $read_array_fn:path} => {
         impl DeserializeArray for $ty {
             fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> {
-                let mut vec: Option<Vec<Self>> = None;
+                let mut vec: Option<Vec<MaybeUninit<Self>>> = None;
                 let status = unsafe {
                     // Safety: `Parcel` always contains a valid pointer to an
                     // `AParcel`. `allocate_vec<T>` expects the opaque pointer to
-                    // be of type `*mut Option<Vec<T>>`, so `&mut vec` is
+                    // be of type `*mut Option<Vec<MaybeUninit<T>>>`, so `&mut vec` is
                     // correct for it.
                     $read_array_fn(
                         parcel.as_native(),
                         &mut vec as *mut _ as *mut c_void,
-                        Some(allocate_vec),
+                        Some(allocate_vec_with_buffer),
                     )
                 };
                 status_result(status)?;
+                let vec: Option<Vec<Self>> = unsafe {
+                    // Safety: We are assuming that the NDK correctly
+                    // initialized every element of the vector by now, so we
+                    // know that all the MaybeUninits are now properly
+                    // initialized. We can transmute from Vec<MaybeUninit<T>> to
+                    // Vec<T> because MaybeUninit<T> has the same alignment and
+                    // size as T, so the pointer to the vector allocation will
+                    // be compatible.
+                    mem::transmute(vec)
+                };
                 Ok(vec)
             }
         }
@@ -414,7 +523,7 @@
             sys::AParcel_readString(
                 parcel.as_native(),
                 &mut vec as *mut _ as *mut c_void,
-                Some(allocate_vec),
+                Some(allocate_vec_with_buffer),
             )
         };
 
@@ -519,26 +628,26 @@
     }
 }
 
-impl<T: Serialize + ?Sized> Serialize for Box<T> {
+impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> {
     fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
         Serialize::serialize(&**self, parcel)
     }
 }
 
-impl<T: SerializeOption + ?Sized> SerializeOption for Box<T> {
+impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> {
     fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
         SerializeOption::serialize_option(this.map(|b| &**b), parcel)
     }
 }
 
-impl<T: FromIBinder + ?Sized> Deserialize for Box<T> {
+impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
     fn deserialize(parcel: &Parcel) -> Result<Self> {
         let ibinder: SpIBinder = parcel.read()?;
         FromIBinder::try_from(ibinder)
     }
 }
 
-impl<T: FromIBinder + ?Sized> DeserializeOption for Box<T> {
+impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
     fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
         let ibinder: Option<SpIBinder> = parcel.read()?;
         ibinder.map(FromIBinder::try_from).transpose()
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 17af099..52036f5 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -17,7 +17,8 @@
 //! Rust API for interacting with a remote binder service.
 
 use crate::binder::{
-    AsNative, FromIBinder, IBinder, Interface, InterfaceClass, TransactionCode, TransactionFlags,
+    AsNative, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Strong,
+    TransactionCode, TransactionFlags,
 };
 use crate::error::{status_result, Result, StatusCode};
 use crate::parcel::{
@@ -26,6 +27,7 @@
 };
 use crate::sys;
 
+use std::cmp::Ordering;
 use std::convert::TryInto;
 use std::ffi::{c_void, CString};
 use std::fmt;
@@ -70,6 +72,20 @@
         ptr.as_mut().map(|p| Self(p))
     }
 
+    /// Extract a raw `AIBinder` pointer from this wrapper.
+    ///
+    /// This method should _only_ be used for testing. Do not try to use the NDK
+    /// interface directly for anything else.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer is valid only as long as the SpIBinder is alive.
+    /// The SpIBinder object retains ownership of the AIBinder and the caller
+    /// should not attempt to free the returned pointer.
+    pub unsafe fn as_raw(&self) -> *mut sys::AIBinder {
+        self.0
+    }
+
     /// Return true if this binder object is hosted in a different process than
     /// the current one.
     pub fn is_remote(&self) -> bool {
@@ -85,7 +101,7 @@
     ///
     /// If this object does not implement the expected interface, the error
     /// `StatusCode::BAD_TYPE` is returned.
-    pub fn into_interface<I: FromIBinder + ?Sized>(self) -> Result<Box<I>> {
+    pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
         FromIBinder::try_from(self)
     }
 
@@ -134,6 +150,36 @@
     }
 }
 
+impl Ord for SpIBinder {
+    fn cmp(&self, other: &Self) -> Ordering {
+        let less_than = unsafe {
+            // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
+            // this pointer is always safe to pass to `AIBinder_lt` (null is
+            // also safe to pass to this function, but we should never do that).
+            sys::AIBinder_lt(self.0, other.0)
+        };
+        let greater_than = unsafe {
+            // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
+            // this pointer is always safe to pass to `AIBinder_lt` (null is
+            // also safe to pass to this function, but we should never do that).
+            sys::AIBinder_lt(other.0, self.0)
+        };
+        if !less_than && !greater_than {
+            Ordering::Equal
+        } else if less_than {
+            Ordering::Less
+        } else {
+            Ordering::Greater
+        }
+    }
+}
+
+impl PartialOrd for SpIBinder {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
 impl PartialEq for SpIBinder {
     fn eq(&self, other: &Self) -> bool {
         ptr::eq(self.0, other.0)
@@ -166,7 +212,7 @@
     }
 }
 
-impl<T: AsNative<sys::AIBinder>> IBinder for T {
+impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
     /// Perform a binder transaction
     fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
         &self,
@@ -255,9 +301,7 @@
     }
 
     fn set_requesting_sid(&mut self, enable: bool) {
-        unsafe {
-            sys::AIBinder_setRequestingSid(self.as_native_mut(), enable)
-        };
+        unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
     }
 
     fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
@@ -306,13 +350,15 @@
         status_result(status)?;
         Ok(ibinder)
     }
+}
 
+impl<T: AsNative<sys::AIBinder>> IBinder for T {
     fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
         status_result(unsafe {
             // Safety: `SpIBinder` guarantees that `self` always contains a
             // valid pointer to an `AIBinder`. `recipient` can always be
             // converted into a valid pointer to an
-            // `AIBinder_DeatRecipient`. Any value is safe to pass as the
+            // `AIBinder_DeathRecipient`. Any value is safe to pass as the
             // cookie, although we depend on this value being set by
             // `get_cookie` when the death recipient callback is called.
             sys::AIBinder_linkToDeath(
@@ -328,7 +374,7 @@
             // Safety: `SpIBinder` guarantees that `self` always contains a
             // valid pointer to an `AIBinder`. `recipient` can always be
             // converted into a valid pointer to an
-            // `AIBinder_DeatRecipient`. Any value is safe to pass as the
+            // `AIBinder_DeathRecipient`. Any value is safe to pass as the
             // cookie, although we depend on this value being set by
             // `get_cookie` when the death recipient callback is called.
             sys::AIBinder_unlinkToDeath(
@@ -416,6 +462,65 @@
     }
 }
 
+impl Clone for WpIBinder {
+    fn clone(&self) -> Self {
+        let ptr = unsafe {
+            // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
+            // so this pointer is always safe to pass to `AIBinder_Weak_clone`
+            // (although null is also a safe value to pass to this API).
+            //
+            // We get ownership of the returned pointer, so can construct a new
+            // WpIBinder object from it.
+            sys::AIBinder_Weak_clone(self.0)
+        };
+        assert!(
+            !ptr.is_null(),
+            "Unexpected null pointer from AIBinder_Weak_clone"
+        );
+        Self(ptr)
+    }
+}
+
+impl Ord for WpIBinder {
+    fn cmp(&self, other: &Self) -> Ordering {
+        let less_than = unsafe {
+            // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
+            // so this pointer is always safe to pass to `AIBinder_Weak_lt`
+            // (null is also safe to pass to this function, but we should never
+            // do that).
+            sys::AIBinder_Weak_lt(self.0, other.0)
+        };
+        let greater_than = unsafe {
+            // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
+            // so this pointer is always safe to pass to `AIBinder_Weak_lt`
+            // (null is also safe to pass to this function, but we should never
+            // do that).
+            sys::AIBinder_Weak_lt(other.0, self.0)
+        };
+        if !less_than && !greater_than {
+            Ordering::Equal
+        } else if less_than {
+            Ordering::Less
+        } else {
+            Ordering::Greater
+        }
+    }
+}
+
+impl PartialOrd for WpIBinder {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialEq for WpIBinder {
+    fn eq(&self, other: &Self) -> bool {
+        self.cmp(other) == Ordering::Equal
+    }
+}
+
+impl Eq for WpIBinder {}
+
 impl Drop for WpIBinder {
     fn drop(&mut self) {
         unsafe {
@@ -550,7 +655,7 @@
 
 /// Retrieve an existing service for a particular interface, blocking for a few
 /// seconds if it doesn't yet exist.
-pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Box<T>> {
+pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
     let service = get_service(name);
     match service {
         Some(service) => FromIBinder::try_from(service),
diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp
index ef142b5..65fa2ca 100644
--- a/libs/binder/rust/sys/BinderBindings.hpp
+++ b/libs/binder/rust/sys/BinderBindings.hpp
@@ -21,6 +21,7 @@
 #include <android/binder_parcel_platform.h>
 #include <android/binder_process.h>
 #include <android/binder_shell.h>
+#include <android/binder_stability.h>
 #include <android/binder_status.h>
 
 namespace android {
@@ -80,6 +81,7 @@
 enum {
     FLAG_ONEWAY = FLAG_ONEWAY,
     FLAG_CLEAR_BUF = FLAG_CLEAR_BUF,
+    FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_LOCAL,
 };
 
 } // namespace consts
diff --git a/libs/binder/rust/sys/lib.rs b/libs/binder/rust/sys/lib.rs
index 9095af2..1d1a295 100644
--- a/libs/binder/rust/sys/lib.rs
+++ b/libs/binder/rust/sys/lib.rs
@@ -16,14 +16,6 @@
 
 //! Generated Rust bindings to libbinder_ndk
 
-#![allow(
-    non_camel_case_types,
-    non_snake_case,
-    non_upper_case_globals,
-    unused,
-    improper_ctypes,
-    missing_docs
-)]
 use std::error::Error;
 use std::fmt;
 
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 5ae9c53..607860f 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 rust_test {
     name: "rustBinderTest",
     srcs: ["integration.rs"],
@@ -79,3 +88,50 @@
         "IBinderRustNdkInteropTest-rust",
     ],
 }
+
+cc_test {
+    name: "rustBinderSerializationTest",
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "libutils",
+        "libbase",
+    ],
+    static_libs: [
+        "libbinder_rs_serialization_test"
+    ],
+    srcs: [
+        "serialization.cpp",
+    ],
+    auto_gen_config: true,
+    test_suites: ["general-tests"],
+}
+
+rust_bindgen {
+    name: "libbinder_rs_serialization_bindgen",
+    crate_name: "binder_rs_serialization_bindgen",
+    wrapper_src: "serialization.hpp",
+    source_stem: "bindings",
+    cpp_std: "gnu++17",
+    bindgen_flags: [
+        "--allowlist-type", "Transaction",
+        "--allowlist-var", "TESTDATA_.*",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libc++",
+    ],
+}
+
+rust_ffi_static {
+    name: "libbinder_rs_serialization_test",
+    crate_name: "binder_rs_serialization_test",
+    srcs: [
+        "serialization.rs",
+        ":libbinder_rs_serialization_bindgen",
+    ],
+    rustlibs: [
+        "libbinder_rs",
+    ],
+}
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index bb8c492..0332007 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -18,7 +18,10 @@
 
 use binder::declare_binder_interface;
 use binder::parcel::Parcel;
-use binder::{Binder, IBinder, Interface, SpIBinder, StatusCode, ThreadState, TransactionCode};
+use binder::{
+    Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
+    FIRST_CALL_TRANSACTION,
+};
 use std::convert::{TryFrom, TryInto};
 
 /// Name of service runner.
@@ -52,7 +55,8 @@
         })));
         service.set_requesting_sid(true);
         if let Some(extension_name) = extension_name {
-            let extension = BnTest::new_binder(TestService { s: extension_name });
+            let extension =
+                BnTest::new_binder(TestService { s: extension_name }, BinderFeatures::default());
             service
                 .set_extension(&mut extension.as_binder())
                 .expect("Could not add extension");
@@ -83,7 +87,7 @@
 
 #[repr(u32)]
 enum TestTransactionCode {
-    Test = SpIBinder::FIRST_CALL_TRANSACTION,
+    Test = FIRST_CALL_TRANSACTION,
     GetSelinuxContext,
 }
 
@@ -196,7 +200,6 @@
 
 impl ITestSameDescriptor for Binder<BnTestSameDescriptor> {}
 
-
 #[cfg(test)]
 mod tests {
     use selinux_bindgen as selinux_sys;
@@ -209,9 +212,12 @@
     use std::thread;
     use std::time::Duration;
 
-    use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode};
+    use binder::{
+        Binder, BinderFeatures, DeathRecipient, FromIBinder, IBinder, IBinderInternal, Interface,
+        SpIBinder, StatusCode, Strong,
+    };
 
-    use super::{BnTest, ITest, ITestSameDescriptor, RUST_SERVICE_BINARY, TestService};
+    use super::{BnTest, ITest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
 
     pub struct ScopedServiceProcess(Child);
 
@@ -271,7 +277,7 @@
     fn trivial_client() {
         let service_name = "trivial_client_test";
         let _process = ScopedServiceProcess::new(service_name);
-        let test_client: Box<dyn ITest> =
+        let test_client: Strong<dyn ITest> =
             binder::get_interface(service_name).expect("Did not get manager binder service");
         assert_eq!(test_client.test().unwrap(), "trivial_client_test");
     }
@@ -280,7 +286,7 @@
     fn get_selinux_context() {
         let service_name = "get_selinux_context";
         let _process = ScopedServiceProcess::new(service_name);
-        let test_client: Box<dyn ITest> =
+        let test_client: Strong<dyn ITest> =
             binder::get_interface(service_name).expect("Did not get manager binder service");
         let expected_context = unsafe {
             let mut out_ptr = ptr::null_mut();
@@ -290,7 +296,9 @@
         };
         assert_eq!(
             test_client.get_selinux_context().unwrap(),
-            expected_context.to_str().expect("context was invalid UTF-8"),
+            expected_context
+                .to_str()
+                .expect("context was invalid UTF-8"),
         );
     }
 
@@ -453,7 +461,7 @@
 
             let extension = maybe_extension.expect("Remote binder did not have an extension");
 
-            let extension: Box<dyn ITest> = FromIBinder::try_from(extension)
+            let extension: Strong<dyn ITest> = FromIBinder::try_from(extension)
                 .expect("Extension could not be converted to the expected interface");
 
             assert_eq!(extension.test().unwrap(), extension_name);
@@ -479,20 +487,103 @@
 
         // This should succeed although we will have to treat the service as
         // remote.
-        let _interface: Box<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder())
-            .expect("Could not re-interpret service as the ITestSameDescriptor interface");
+        let _interface: Strong<dyn ITestSameDescriptor> =
+            FromIBinder::try_from(service.as_binder())
+                .expect("Could not re-interpret service as the ITestSameDescriptor interface");
     }
 
     /// Test that we can round-trip a rust service through a generic IBinder
     #[test]
     fn reassociate_rust_binder() {
         let service_name = "testing_service";
-        let service_ibinder = BnTest::new_binder(TestService { s: service_name.to_string() })
-            .as_binder();
+        let service_ibinder = BnTest::new_binder(
+            TestService {
+                s: service_name.to_string(),
+            },
+            BinderFeatures::default(),
+        )
+        .as_binder();
 
-        let service: Box<dyn ITest> = service_ibinder.into_interface()
+        let service: Strong<dyn ITest> = service_ibinder
+            .into_interface()
             .expect("Could not reassociate the generic ibinder");
 
         assert_eq!(service.test().unwrap(), service_name);
     }
+
+    #[test]
+    fn weak_binder_upgrade() {
+        let service_name = "testing_service";
+        let service = BnTest::new_binder(
+            TestService {
+                s: service_name.to_string(),
+            },
+            BinderFeatures::default(),
+        );
+
+        let weak = Strong::downgrade(&service);
+
+        let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
+
+        assert_eq!(service, upgraded);
+    }
+
+    #[test]
+    fn weak_binder_upgrade_dead() {
+        let service_name = "testing_service";
+        let weak = {
+            let service = BnTest::new_binder(
+                TestService {
+                    s: service_name.to_string(),
+                },
+                BinderFeatures::default(),
+            );
+
+            Strong::downgrade(&service)
+        };
+
+        assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT));
+    }
+
+    #[test]
+    fn weak_binder_clone() {
+        let service_name = "testing_service";
+        let service = BnTest::new_binder(
+            TestService {
+                s: service_name.to_string(),
+            },
+            BinderFeatures::default(),
+        );
+
+        let weak = Strong::downgrade(&service);
+        let cloned = weak.clone();
+        assert_eq!(weak, cloned);
+
+        let upgraded = weak.upgrade().expect("Could not upgrade weak binder");
+        let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder");
+
+        assert_eq!(service, upgraded);
+        assert_eq!(service, clone_upgraded);
+    }
+
+    #[test]
+    #[allow(clippy::eq_op)]
+    fn binder_ord() {
+        let service1 = BnTest::new_binder(
+            TestService {
+                s: "testing_service1".to_string(),
+            },
+            BinderFeatures::default(),
+        );
+        let service2 = BnTest::new_binder(
+            TestService {
+                s: "testing_service2".to_string(),
+            },
+            BinderFeatures::default(),
+        );
+
+        assert!(!(service1 < service1));
+        assert!(!(service1 > service1));
+        assert_eq!(service1 < service2, !(service2 < service1));
+    }
 }
diff --git a/libs/binder/rust/tests/ndk_rust_interop.rs b/libs/binder/rust/tests/ndk_rust_interop.rs
index 70a6dc0..4702e45 100644
--- a/libs/binder/rust/tests/ndk_rust_interop.rs
+++ b/libs/binder/rust/tests/ndk_rust_interop.rs
@@ -16,15 +16,13 @@
 
 //! Rust Binder NDK interop tests
 
-use std::ffi::CStr;
-use std::os::raw::{c_char, c_int};
-use ::IBinderRustNdkInteropTest::binder::{self, Interface, StatusCode};
 use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTest::{
     BnBinderRustNdkInteropTest, IBinderRustNdkInteropTest,
 };
-use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTestOther::{
-    IBinderRustNdkInteropTestOther,
-};
+use ::IBinderRustNdkInteropTest::aidl::IBinderRustNdkInteropTestOther::IBinderRustNdkInteropTestOther;
+use ::IBinderRustNdkInteropTest::binder::{self, BinderFeatures, Interface, StatusCode};
+use std::ffi::CStr;
+use std::os::raw::{c_char, c_int};
 
 /// Look up the provided AIDL service and call its echo method.
 ///
@@ -37,23 +35,26 @@
 
     // The Rust class descriptor pointer will not match the NDK one, but the
     // descriptor strings match so this needs to still associate.
-    let service: Box<dyn IBinderRustNdkInteropTest> = match binder::get_interface(service_name) {
-        Err(e) => {
-            eprintln!("Could not find Ndk service {}: {:?}", service_name, e);
-            return StatusCode::NAME_NOT_FOUND as c_int;
-        }
-        Ok(service) => service,
-    };
+    let service: binder::Strong<dyn IBinderRustNdkInteropTest> =
+        match binder::get_interface(service_name) {
+            Err(e) => {
+                eprintln!("Could not find Ndk service {}: {:?}", service_name, e);
+                return StatusCode::NAME_NOT_FOUND as c_int;
+            }
+            Ok(service) => service,
+        };
 
     match service.echo("testing") {
-        Ok(s) => if s != "testing" {
-            return StatusCode::BAD_VALUE as c_int;
-        },
+        Ok(s) => {
+            if s != "testing" {
+                return StatusCode::BAD_VALUE as c_int;
+            }
+        }
         Err(e) => return e.into(),
     }
 
     // Try using the binder service through the wrong interface type
-    let wrong_service: Result<Box<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
+    let wrong_service: Result<binder::Strong<dyn IBinderRustNdkInteropTestOther>, StatusCode> =
         binder::get_interface(service_name);
     match wrong_service {
         Err(e) if e == StatusCode::BAD_TYPE => {}
@@ -88,7 +89,7 @@
 #[no_mangle]
 pub unsafe extern "C" fn rust_start_service(service_name: *const c_char) -> c_int {
     let service_name = CStr::from_ptr(service_name).to_str().unwrap();
-    let service = BnBinderRustNdkInteropTest::new_binder(Service);
+    let service = BnBinderRustNdkInteropTest::new_binder(Service, BinderFeatures::default());
     match binder::add_service(&service_name, service.as_binder()) {
         Ok(_) => StatusCode::OK as c_int,
         Err(e) => e as c_int,
diff --git a/libs/binder/rust/tests/serialization.cpp b/libs/binder/rust/tests/serialization.cpp
new file mode 100644
index 0000000..ec780f2
--- /dev/null
+++ b/libs/binder/rust/tests/serialization.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2020 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/binder_ibinder_platform.h>
+#include <android/binder_libbinder.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/ProcessState.h>
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+#include "android-base/file.h"
+#include "serialization.hpp"
+
+#include <cmath>
+#include <cstdint>
+#include <iostream>
+#include <optional>
+
+using namespace std;
+using namespace android;
+using android::base::unique_fd;
+using android::os::ParcelFileDescriptor;
+
+// defined in Rust
+extern "C" AIBinder *rust_service();
+
+
+const int8_t TESTDATA_I8[4] = {-128, 0, 117, 127};
+const uint8_t TESTDATA_U8[4] = {0, 42, 117, 255};
+const char16_t TESTDATA_CHARS[4] = {0, 42, 117, numeric_limits<char16_t>::max()};
+const int32_t TESTDATA_I32[4] = {numeric_limits<int32_t>::min(), 0, 117, numeric_limits<int32_t>::max()};
+const int64_t TESTDATA_I64[4] = {numeric_limits<int64_t>::min(), 0, 117, numeric_limits<int64_t>::max()};
+const uint64_t TESTDATA_U64[4] = {0, 42, 117, numeric_limits<uint64_t>::max()};
+const float TESTDATA_FLOAT[4] = {
+        numeric_limits<float>::quiet_NaN(),
+        -numeric_limits<float>::infinity(),
+        117.0,
+        numeric_limits<float>::infinity(),
+};
+const double TESTDATA_DOUBLE[4] = {
+        numeric_limits<double>::quiet_NaN(),
+        -numeric_limits<double>::infinity(),
+        117.0,
+        numeric_limits<double>::infinity(),
+};
+const bool TESTDATA_BOOL[4] = {true, false, false, true};
+const char* const TESTDATA_STRS[4] = {"", nullptr, "test", ""};
+
+static ::testing::Environment* gEnvironment;
+
+class SerializationEnvironment : public ::testing::Environment {
+public:
+    void SetUp() override {
+        m_server = AIBinder_toPlatformBinder(rust_service());
+    }
+
+    sp<IBinder> getServer(void) { return m_server; }
+
+private:
+    sp<IBinder> m_server;
+};
+
+
+class SerializationTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        ASSERT_NE(gEnvironment, nullptr);
+        m_server = static_cast<SerializationEnvironment *>(gEnvironment)->getServer();
+    }
+
+    sp<IBinder> m_server;
+};
+
+
+TEST_F(SerializationTest, SerializeBool) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<bool> bools(begin(TESTDATA_BOOL), end(TESTDATA_BOOL));
+    ASSERT_EQ(data.writeBool(true), OK);
+    ASSERT_EQ(data.writeBool(false), OK);
+    ASSERT_EQ(data.writeBoolVector(bools), OK);
+    ASSERT_EQ(data.writeBoolVector(nullopt), OK);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_BOOL, data, &reply), OK);
+
+    vector<bool> read_bools;
+    optional<vector<bool>> maybe_bools;
+    ASSERT_EQ(reply.readBool(), true);
+    ASSERT_EQ(reply.readBool(), false);
+    ASSERT_EQ(reply.readBoolVector(&read_bools), OK);
+    ASSERT_EQ(read_bools, bools);
+    ASSERT_EQ(reply.readBoolVector(&maybe_bools), OK);
+    ASSERT_EQ(maybe_bools, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeByte) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<int8_t> i8s(begin(TESTDATA_I8), end(TESTDATA_I8));
+    vector<uint8_t> u8s(begin(TESTDATA_U8), end(TESTDATA_U8));
+    data.writeByte(0);
+    data.writeByte(1);
+    data.writeByte(numeric_limits<int8_t>::max());
+    data.writeByteVector(i8s);
+    data.writeByteVector(u8s);
+    data.writeByteVector(optional<vector<int8_t>>({}));
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_BYTE, data, &reply), OK);
+
+    vector<int8_t> read_i8s;
+    vector<uint8_t> read_u8s;
+    optional<vector<int8_t>> maybe_i8s;
+    ASSERT_EQ(reply.readByte(), 0);
+    ASSERT_EQ(reply.readByte(), 1);
+    ASSERT_EQ(reply.readByte(), numeric_limits<int8_t>::max());
+    ASSERT_EQ(reply.readByteVector(&read_i8s), OK);
+    ASSERT_EQ(read_i8s, i8s);
+    ASSERT_EQ(reply.readByteVector(&read_u8s), OK);
+    ASSERT_EQ(read_u8s, u8s);
+    ASSERT_EQ(reply.readByteVector(&maybe_i8s), OK);
+    ASSERT_EQ(maybe_i8s, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeU16) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<char16_t> chars(begin(TESTDATA_CHARS), end(TESTDATA_CHARS));
+    data.writeChar(0);
+    data.writeChar(1);
+    data.writeChar(numeric_limits<char16_t>::max());
+    data.writeCharVector(chars);
+    data.writeCharVector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_U16, data, &reply), OK);
+
+    vector<char16_t> read_chars;
+    optional<vector<char16_t>> maybe_chars;
+    ASSERT_EQ(reply.readChar(), 0);
+    ASSERT_EQ(reply.readChar(), 1);
+    ASSERT_EQ(reply.readChar(), numeric_limits<char16_t>::max());
+    ASSERT_EQ(reply.readCharVector(&read_chars), OK);
+    ASSERT_EQ(read_chars, chars);
+    ASSERT_EQ(reply.readCharVector(&maybe_chars), OK);
+    ASSERT_EQ(maybe_chars, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeI32) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<int32_t> i32s(begin(TESTDATA_I32), end(TESTDATA_I32));
+    data.writeInt32(0);
+    data.writeInt32(1);
+    data.writeInt32(numeric_limits<int32_t>::max());
+    data.writeInt32Vector(i32s);
+    data.writeInt32Vector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_I32, data, &reply), OK);
+
+    vector<int32_t> read_i32s;
+    optional<vector<int32_t>> maybe_i32s;
+    ASSERT_EQ(reply.readInt32(), 0);
+    ASSERT_EQ(reply.readInt32(), 1);
+    ASSERT_EQ(reply.readInt32(), numeric_limits<int32_t>::max());
+    ASSERT_EQ(reply.readInt32Vector(&read_i32s), OK);
+    ASSERT_EQ(read_i32s, i32s);
+    ASSERT_EQ(reply.readInt32Vector(&maybe_i32s), OK);
+    ASSERT_EQ(maybe_i32s, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeI64) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<int64_t> i64s(begin(TESTDATA_I64), end(TESTDATA_I64));
+    data.writeInt64(0);
+    data.writeInt64(1);
+    data.writeInt64(numeric_limits<int64_t>::max());
+    data.writeInt64Vector(i64s);
+    data.writeInt64Vector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_I64, data, &reply), OK);
+
+    vector<int64_t> read_i64s;
+    optional<vector<int64_t>> maybe_i64s;
+    ASSERT_EQ(reply.readInt64(), 0);
+    ASSERT_EQ(reply.readInt64(), 1);
+    ASSERT_EQ(reply.readInt64(), numeric_limits<int64_t>::max());
+    ASSERT_EQ(reply.readInt64Vector(&read_i64s), OK);
+    ASSERT_EQ(read_i64s, i64s);
+    ASSERT_EQ(reply.readInt64Vector(&maybe_i64s), OK);
+    ASSERT_EQ(maybe_i64s, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeU64) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<uint64_t> u64s(begin(TESTDATA_U64), end(TESTDATA_U64));
+    data.writeUint64(0);
+    data.writeUint64(1);
+    data.writeUint64(numeric_limits<uint64_t>::max());
+    data.writeUint64Vector(u64s);
+    data.writeUint64Vector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_U64, data, &reply), OK);
+
+    vector<uint64_t> read_u64s;
+    optional<vector<uint64_t>> maybe_u64s;
+    ASSERT_EQ(reply.readUint64(), 0);
+    ASSERT_EQ(reply.readUint64(), 1);
+    ASSERT_EQ(reply.readUint64(), numeric_limits<uint64_t>::max());
+    ASSERT_EQ(reply.readUint64Vector(&read_u64s), OK);
+    ASSERT_EQ(read_u64s, u64s);
+    ASSERT_EQ(reply.readUint64Vector(&maybe_u64s), OK);
+    ASSERT_EQ(maybe_u64s, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeF32) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<float> floats(begin(TESTDATA_FLOAT), end(TESTDATA_FLOAT));
+    data.writeFloat(0);
+    data.writeFloatVector(floats);
+    data.writeFloatVector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_F32, data, &reply), OK);
+
+    vector<float> read_floats;
+    optional<vector<float>> maybe_floats;
+    ASSERT_EQ(reply.readFloat(), 0);
+    ASSERT_EQ(reply.readFloatVector(&read_floats), OK);
+    ASSERT_TRUE(isnan(read_floats[0]));
+    ASSERT_EQ(read_floats[1], floats[1]);
+    ASSERT_EQ(read_floats[2], floats[2]);
+    ASSERT_EQ(read_floats[3], floats[3]);
+    ASSERT_EQ(reply.readFloatVector(&maybe_floats), OK);
+    ASSERT_EQ(maybe_floats, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeF64) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<double> doubles(begin(TESTDATA_DOUBLE), end(TESTDATA_DOUBLE));
+    data.writeDouble(0);
+    data.writeDoubleVector(doubles);
+    data.writeDoubleVector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_F64, data, &reply), OK);
+
+    vector<double> read_doubles;
+    optional<vector<double>> maybe_doubles;
+    ASSERT_EQ(reply.readDouble(), 0);
+    ASSERT_EQ(reply.readDoubleVector(&read_doubles), OK);
+    ASSERT_TRUE(isnan(read_doubles[0]));
+    ASSERT_EQ(read_doubles[1], doubles[1]);
+    ASSERT_EQ(read_doubles[2], doubles[2]);
+    ASSERT_EQ(read_doubles[3], doubles[3]);
+    ASSERT_EQ(reply.readDoubleVector(&maybe_doubles), OK);
+    ASSERT_EQ(maybe_doubles, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeString) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    vector<optional<String16>> strings;
+    for (auto I = begin(TESTDATA_STRS), E = end(TESTDATA_STRS); I != E; ++I) {
+        if (*I == nullptr) {
+            strings.push_back(optional<String16>());
+        } else {
+            strings.emplace_back(*I);
+        }
+    }
+    data.writeUtf8AsUtf16(string("testing"));
+    data.writeString16(nullopt);
+    data.writeString16Vector(strings);
+    data.writeString16Vector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_STRING, data, &reply), OK);
+
+    optional<String16> maybe_string;
+    optional<vector<optional<String16>>> read_strings;
+    ASSERT_EQ(reply.readString16(), String16("testing"));
+    ASSERT_EQ(reply.readString16(&maybe_string), OK);
+    ASSERT_EQ(maybe_string, nullopt);
+    ASSERT_EQ(reply.readString16Vector(&read_strings), OK);
+    ASSERT_EQ(read_strings, strings);
+    ASSERT_EQ(reply.readString16Vector(&read_strings), OK);
+    ASSERT_EQ(read_strings, nullopt);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeFileDescriptor) {
+    unique_fd out_file, in_file;
+    ASSERT_TRUE(base::Pipe(&out_file, &in_file));
+
+    vector<ParcelFileDescriptor> file_descriptors;
+    file_descriptors.push_back(ParcelFileDescriptor(std::move(out_file)));
+    file_descriptors.push_back(ParcelFileDescriptor(std::move(in_file)));
+
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    data.writeParcelable(file_descriptors[0]);
+    data.writeParcelable(file_descriptors[1]);
+    data.writeParcelableVector(file_descriptors);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_FILE_DESCRIPTOR, data, &reply), OK);
+
+    ParcelFileDescriptor returned_fd1, returned_fd2;
+    vector<ParcelFileDescriptor> returned_file_descriptors;
+    ASSERT_EQ(reply.readParcelable(&returned_fd1), OK);
+    ASSERT_EQ(reply.readParcelable(&returned_fd2), OK);
+    ASSERT_EQ(reply.readParcelableVector(&returned_file_descriptors), OK);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+
+    base::WriteStringToFd("Testing", returned_fd2.get());
+    base::WriteStringToFd("File", returned_file_descriptors[1].get());
+    base::WriteStringToFd("Descriptors", file_descriptors[1].get());
+
+    string expected = "TestingFileDescriptors";
+    vector<char> buf(expected.length());
+    base::ReadFully(file_descriptors[0].release(), buf.data(), buf.size());
+    ASSERT_EQ(expected, string(buf.data()));
+}
+
+TEST_F(SerializationTest, SerializeIBinder) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    data.writeStrongBinder(m_server);
+    data.writeStrongBinder(nullptr);
+    data.writeStrongBinderVector({m_server, nullptr});
+    data.writeStrongBinderVector(nullopt);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_IBINDER, data, &reply), OK);
+
+    optional<vector<sp<IBinder>>> binders;
+    ASSERT_TRUE(reply.readStrongBinder());
+    ASSERT_FALSE(reply.readStrongBinder());
+    ASSERT_EQ(reply.readStrongBinderVector(&binders), OK);
+    ASSERT_EQ(binders->size(), 2);
+    ASSERT_TRUE((*binders)[0]);
+    ASSERT_FALSE((*binders)[1]);
+    ASSERT_EQ(reply.readStrongBinderVector(&binders), OK);
+    ASSERT_FALSE(binders);
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+TEST_F(SerializationTest, SerializeStatus) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+
+    binder::Status::ok().writeToParcel(&data);
+    binder::Status::fromExceptionCode(binder::Status::EX_NULL_POINTER, "a status message")
+            .writeToParcel(&data);
+    binder::Status::fromServiceSpecificError(42, "a service-specific error").writeToParcel(&data);
+
+    android::Parcel reply;
+    ASSERT_EQ(m_server->transact(TEST_STATUS, data, &reply), OK);
+
+    binder::Status status;
+
+    ASSERT_EQ(status.readFromParcel(reply), OK);
+    ASSERT_TRUE(status.isOk());
+
+    ASSERT_EQ(status.readFromParcel(reply), OK);
+    ASSERT_EQ(status.exceptionCode(), binder::Status::EX_NULL_POINTER);
+    ASSERT_EQ(status.exceptionMessage(), "a status message");
+
+    ASSERT_EQ(status.readFromParcel(reply), OK);
+    ASSERT_EQ(status.serviceSpecificErrorCode(), 42);
+    ASSERT_EQ(status.exceptionMessage(), "a service-specific error");
+
+    int32_t end;
+    ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA);
+}
+
+// Test that failures from Rust properly propagate to C++
+TEST_F(SerializationTest, SerializeRustFail) {
+    android::Parcel data;
+    data.writeInterfaceToken(String16("read_parcel_test"));
+    ASSERT_EQ(m_server->transact(TEST_FAIL, data, nullptr), FAILED_TRANSACTION);
+}
+
+int main(int argc, char **argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    gEnvironment = AddGlobalTestEnvironment(new SerializationEnvironment());
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/libs/binder/rust/tests/serialization.hpp b/libs/binder/rust/tests/serialization.hpp
new file mode 100644
index 0000000..0041608
--- /dev/null
+++ b/libs/binder/rust/tests/serialization.hpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/IBinder.h>
+
+using namespace android;
+
+enum Transaction {
+    TEST_BOOL = IBinder::FIRST_CALL_TRANSACTION,
+    TEST_BYTE,
+    TEST_U16,
+    TEST_I32,
+    TEST_I64,
+    TEST_U64,
+    TEST_F32,
+    TEST_F64,
+    TEST_STRING,
+    TEST_FILE_DESCRIPTOR,
+    TEST_IBINDER,
+    TEST_STATUS,
+    TEST_FAIL,
+};
+
+extern const int8_t TESTDATA_I8[4];
+extern const uint8_t TESTDATA_U8[4];
+extern const char16_t TESTDATA_CHARS[4];
+extern const int32_t TESTDATA_I32[4];
+extern const int64_t TESTDATA_I64[4];
+extern const uint64_t TESTDATA_U64[4];
+extern const float TESTDATA_FLOAT[4];
+extern const double TESTDATA_DOUBLE[4];
+extern const bool TESTDATA_BOOL[4];
+extern const char* const TESTDATA_STRS[4];
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
new file mode 100644
index 0000000..66ba846
--- /dev/null
+++ b/libs/binder/rust/tests/serialization.rs
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+//! Included as a module in the binder crate internal tests for internal API
+//! access.
+
+use binder::declare_binder_interface;
+use binder::parcel::ParcelFileDescriptor;
+use binder::{
+    Binder, BinderFeatures, ExceptionCode, Interface, Parcel, Result, SpIBinder, Status,
+    StatusCode, TransactionCode,
+};
+
+use std::ffi::{c_void, CStr, CString};
+use std::sync::Once;
+
+#[allow(
+    non_camel_case_types,
+    non_snake_case,
+    non_upper_case_globals,
+    unused,
+    improper_ctypes,
+    missing_docs,
+    clippy::all
+)]
+mod bindings {
+    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
+}
+
+macro_rules! assert_eq {
+    ($left:expr, $right:expr $(,)?) => {
+        match (&$left, &$right) {
+            (left, right) => {
+                if *left != *right {
+                    eprintln!(
+                        "assertion failed: `{:?}` == `{:?}`, {}:{}:{}",
+                        &*left,
+                        &*right,
+                        file!(),
+                        line!(),
+                        column!()
+                    );
+                    return Err(StatusCode::FAILED_TRANSACTION);
+                }
+            }
+        }
+    };
+}
+
+macro_rules! assert {
+    ($expr:expr) => {
+        if !$expr {
+            eprintln!(
+                "assertion failed: `{:?}`, {}:{}:{}",
+                $expr,
+                file!(),
+                line!(),
+                column!()
+            );
+            return Err(StatusCode::FAILED_TRANSACTION);
+        }
+    };
+}
+
+static SERVICE_ONCE: Once = Once::new();
+static mut SERVICE: Option<SpIBinder> = None;
+
+/// Start binder service and return a raw AIBinder pointer to it.
+///
+/// Safe to call multiple times, only creates the service once.
+#[no_mangle]
+pub extern "C" fn rust_service() -> *mut c_void {
+    unsafe {
+        SERVICE_ONCE.call_once(|| {
+            SERVICE = Some(BnReadParcelTest::new_binder((), BinderFeatures::default()).as_binder());
+        });
+        SERVICE.as_ref().unwrap().as_raw().cast()
+    }
+}
+
+/// Empty interface just to use the declare_binder_interface macro
+pub trait ReadParcelTest: Interface {}
+
+declare_binder_interface! {
+    ReadParcelTest["read_parcel_test"] {
+        native: BnReadParcelTest(on_transact),
+        proxy: BpReadParcelTest,
+    }
+}
+
+impl ReadParcelTest for Binder<BnReadParcelTest> {}
+
+impl ReadParcelTest for BpReadParcelTest {}
+
+impl ReadParcelTest for () {}
+
+#[allow(clippy::float_cmp)]
+fn on_transact(
+    _service: &dyn ReadParcelTest,
+    code: TransactionCode,
+    parcel: &Parcel,
+    reply: &mut Parcel,
+) -> Result<()> {
+    match code {
+        bindings::Transaction_TEST_BOOL => {
+            assert_eq!(parcel.read::<bool>()?, true);
+            assert_eq!(parcel.read::<bool>()?, false);
+            assert_eq!(parcel.read::<Vec<bool>>()?, unsafe {
+                bindings::TESTDATA_BOOL
+            });
+            assert_eq!(parcel.read::<Option<Vec<bool>>>()?, None);
+
+            reply.write(&true)?;
+            reply.write(&false)?;
+            reply.write(&unsafe { bindings::TESTDATA_BOOL }[..])?;
+            reply.write(&(None as Option<Vec<bool>>))?;
+        }
+        bindings::Transaction_TEST_BYTE => {
+            assert_eq!(parcel.read::<i8>()?, 0);
+            assert_eq!(parcel.read::<i8>()?, 1);
+            assert_eq!(parcel.read::<i8>()?, i8::max_value());
+            assert_eq!(parcel.read::<Vec<i8>>()?, unsafe { bindings::TESTDATA_I8 });
+            assert_eq!(parcel.read::<Vec<u8>>()?, unsafe { bindings::TESTDATA_U8 });
+            assert_eq!(parcel.read::<Option<Vec<i8>>>()?, None);
+
+            reply.write(&0i8)?;
+            reply.write(&1i8)?;
+            reply.write(&i8::max_value())?;
+            reply.write(&unsafe { bindings::TESTDATA_I8 }[..])?;
+            reply.write(&unsafe { bindings::TESTDATA_U8 }[..])?;
+            reply.write(&(None as Option<Vec<i8>>))?;
+        }
+        bindings::Transaction_TEST_U16 => {
+            assert_eq!(parcel.read::<u16>()?, 0);
+            assert_eq!(parcel.read::<u16>()?, 1);
+            assert_eq!(parcel.read::<u16>()?, u16::max_value());
+            assert_eq!(parcel.read::<Vec<u16>>()?, unsafe {
+                bindings::TESTDATA_CHARS
+            });
+            assert_eq!(parcel.read::<Option<Vec<u16>>>()?, None);
+
+            reply.write(&0u16)?;
+            reply.write(&1u16)?;
+            reply.write(&u16::max_value())?;
+            reply.write(&unsafe { bindings::TESTDATA_CHARS }[..])?;
+            reply.write(&(None as Option<Vec<u16>>))?;
+        }
+        bindings::Transaction_TEST_I32 => {
+            assert_eq!(parcel.read::<i32>()?, 0);
+            assert_eq!(parcel.read::<i32>()?, 1);
+            assert_eq!(parcel.read::<i32>()?, i32::max_value());
+            assert_eq!(parcel.read::<Vec<i32>>()?, unsafe {
+                bindings::TESTDATA_I32
+            });
+            assert_eq!(parcel.read::<Option<Vec<i32>>>()?, None);
+
+            reply.write(&0i32)?;
+            reply.write(&1i32)?;
+            reply.write(&i32::max_value())?;
+            reply.write(&unsafe { bindings::TESTDATA_I32 }[..])?;
+            reply.write(&(None as Option<Vec<i32>>))?;
+        }
+        bindings::Transaction_TEST_I64 => {
+            assert_eq!(parcel.read::<i64>()?, 0);
+            assert_eq!(parcel.read::<i64>()?, 1);
+            assert_eq!(parcel.read::<i64>()?, i64::max_value());
+            assert_eq!(parcel.read::<Vec<i64>>()?, unsafe {
+                bindings::TESTDATA_I64
+            });
+            assert_eq!(parcel.read::<Option<Vec<i64>>>()?, None);
+
+            reply.write(&0i64)?;
+            reply.write(&1i64)?;
+            reply.write(&i64::max_value())?;
+            reply.write(&unsafe { bindings::TESTDATA_I64 }[..])?;
+            reply.write(&(None as Option<Vec<i64>>))?;
+        }
+        bindings::Transaction_TEST_U64 => {
+            assert_eq!(parcel.read::<u64>()?, 0);
+            assert_eq!(parcel.read::<u64>()?, 1);
+            assert_eq!(parcel.read::<u64>()?, u64::max_value());
+            assert_eq!(parcel.read::<Vec<u64>>()?, unsafe {
+                bindings::TESTDATA_U64
+            });
+            assert_eq!(parcel.read::<Option<Vec<u64>>>()?, None);
+
+            reply.write(&0u64)?;
+            reply.write(&1u64)?;
+            reply.write(&u64::max_value())?;
+            reply.write(&unsafe { bindings::TESTDATA_U64 }[..])?;
+            reply.write(&(None as Option<Vec<u64>>))?;
+        }
+        bindings::Transaction_TEST_F32 => {
+            assert_eq!(parcel.read::<f32>()?, 0f32);
+            let floats = parcel.read::<Vec<f32>>()?;
+            assert!(floats[0].is_nan());
+            assert_eq!(floats[1..], unsafe { bindings::TESTDATA_FLOAT }[1..]);
+            assert_eq!(parcel.read::<Option<Vec<f32>>>()?, None);
+
+            reply.write(&0f32)?;
+            reply.write(&unsafe { bindings::TESTDATA_FLOAT }[..])?;
+            reply.write(&(None as Option<Vec<f32>>))?;
+        }
+        bindings::Transaction_TEST_F64 => {
+            assert_eq!(parcel.read::<f64>()?, 0f64);
+            let doubles = parcel.read::<Vec<f64>>()?;
+            assert!(doubles[0].is_nan());
+            assert_eq!(doubles[1..], unsafe { bindings::TESTDATA_DOUBLE }[1..]);
+            assert_eq!(parcel.read::<Option<Vec<f64>>>()?, None);
+
+            reply.write(&0f64)?;
+            reply.write(&unsafe { bindings::TESTDATA_DOUBLE }[..])?;
+            reply.write(&(None as Option<Vec<f64>>))?;
+        }
+        bindings::Transaction_TEST_STRING => {
+            let s: Option<String> = parcel.read()?;
+            assert_eq!(s.as_deref(), Some("testing"));
+            let s: Option<String> = parcel.read()?;
+            assert_eq!(s, None);
+            let s: Option<Vec<Option<String>>> = parcel.read()?;
+            for (s, expected) in s
+                .unwrap()
+                .iter()
+                .zip(unsafe { bindings::TESTDATA_STRS }.iter())
+            {
+                let expected = unsafe {
+                    expected
+                        .as_ref()
+                        .and_then(|e| CStr::from_ptr(e).to_str().ok())
+                };
+                assert_eq!(s.as_deref(), expected);
+            }
+            let s: Option<Vec<Option<String>>> = parcel.read()?;
+            assert_eq!(s, None);
+
+            let strings: Vec<Option<String>> = unsafe {
+                bindings::TESTDATA_STRS
+                    .iter()
+                    .map(|s| {
+                        s.as_ref().map(|s| {
+                            CStr::from_ptr(s)
+                                .to_str()
+                                .expect("String was not UTF-8")
+                                .to_owned()
+                        })
+                    })
+                    .collect()
+            };
+
+            reply.write("testing")?;
+            reply.write(&(None as Option<String>))?;
+            reply.write(&strings)?;
+            reply.write(&(None as Option<Vec<String>>))?;
+        }
+        bindings::Transaction_TEST_FILE_DESCRIPTOR => {
+            let file1 = parcel.read::<ParcelFileDescriptor>()?;
+            let file2 = parcel.read::<ParcelFileDescriptor>()?;
+            let files = parcel.read::<Vec<Option<ParcelFileDescriptor>>>()?;
+
+            reply.write(&file1)?;
+            reply.write(&file2)?;
+            reply.write(&files)?;
+        }
+        bindings::Transaction_TEST_IBINDER => {
+            assert!(parcel.read::<Option<SpIBinder>>()?.is_some());
+            assert!(parcel.read::<Option<SpIBinder>>()?.is_none());
+            let ibinders = parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.unwrap();
+            assert_eq!(ibinders.len(), 2);
+            assert!(ibinders[0].is_some());
+            assert!(ibinders[1].is_none());
+            assert!(parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.is_none());
+
+            let service = unsafe {
+                SERVICE
+                    .as_ref()
+                    .expect("Global binder service not initialized")
+                    .clone()
+            };
+            reply.write(&service)?;
+            reply.write(&(None as Option<&SpIBinder>))?;
+            reply.write(&[Some(&service), None][..])?;
+            reply.write(&(None as Option<Vec<Option<&SpIBinder>>>))?;
+        }
+        bindings::Transaction_TEST_STATUS => {
+            let status: Status = parcel.read()?;
+            assert!(status.is_ok());
+            let status: Status = parcel.read()?;
+            assert_eq!(status.exception_code(), ExceptionCode::NULL_POINTER);
+            assert_eq!(
+                status.get_description(),
+                "Status(-4, EX_NULL_POINTER): 'a status message'"
+            );
+            let status: Status = parcel.read()?;
+            assert_eq!(status.service_specific_error(), 42);
+            assert_eq!(
+                status.get_description(),
+                "Status(-8, EX_SERVICE_SPECIFIC): '42: a service-specific error'"
+            );
+
+            reply.write(&Status::ok())?;
+            reply.write(&Status::new_exception(
+                ExceptionCode::NULL_POINTER,
+                Some(&CString::new("a status message").unwrap()),
+            ))?;
+            reply.write(&Status::new_service_specific_error(
+                42,
+                Some(&CString::new("a service-specific error").unwrap()),
+            ))?;
+        }
+        bindings::Transaction_TEST_FAIL => {
+            assert!(false);
+        }
+        _ => return Err(StatusCode::UNKNOWN_TRANSACTION),
+    }
+
+    assert_eq!(parcel.read::<i32>(), Err(StatusCode::NOT_ENOUGH_DATA));
+    Ok(())
+}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 87f1d45..ec231b2 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "binder_test_defaults",
     cflags: [
@@ -26,6 +35,7 @@
     name: "binderDriverInterfaceTest_IPC_32",
     defaults: ["binder_test_defaults"],
     srcs: ["binderDriverInterfaceTest.cpp"],
+    header_libs: ["libbinder_headers"],
     compile_multilib: "32",
     multilib: { lib32: { suffix: "" } },
     cflags: ["-DBINDER_IPC_32BIT=1"],
@@ -40,7 +50,7 @@
             cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
-
+    header_libs: ["libbinder_headers"],
     srcs: ["binderDriverInterfaceTest.cpp"],
     test_suites: ["device-tests", "vts"],
 }
@@ -53,6 +63,9 @@
         "libbinder",
         "libutils",
     ],
+    static_libs: [
+        "libgmock",
+    ],
     compile_multilib: "32",
     multilib: { lib32: { suffix: "" } },
     cflags: ["-DBINDER_IPC_32BIT=1"],
@@ -91,10 +104,81 @@
         "libbinder",
         "libutils",
     ],
+    static_libs: [
+        "libgmock",
+    ],
     test_suites: ["device-tests", "vts"],
     require_root: true,
 }
 
+aidl_interface {
+    name: "binderRpcTestIface",
+    host_supported: true,
+    unstable: true,
+    srcs: [
+        "IBinderRpcSession.aidl",
+        "IBinderRpcTest.aidl",
+    ],
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
+}
+
+cc_test {
+    name: "binderRpcTest",
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    defaults: [
+        "binder_test_defaults",
+        "libbinder_ndk_host_user",
+    ],
+
+    srcs: [
+        "binderRpcTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libbinder_ndk",
+        "libbase",
+        "libutils",
+        "libcutils",
+        "liblog",
+    ],
+    static_libs: [
+        "binderRpcTestIface-cpp",
+        "binderRpcTestIface-ndk_platform",
+    ],
+    test_suites: ["general-tests"],
+    require_root: true,
+}
+
+cc_benchmark {
+    name: "binderRpcBenchmark",
+    defaults: ["binder_test_defaults"],
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    srcs: [
+        "binderRpcBenchmark.cpp",
+        "IBinderRpcBenchmark.aidl",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
+
 cc_test {
     name: "binderThroughputTest",
     defaults: ["binder_test_defaults"],
@@ -157,12 +241,35 @@
     require_root: true,
 }
 
+cc_test {
+    name: "binderClearBufTest",
+    defaults: ["binder_test_defaults"],
+    srcs: [
+        "binderClearBufTest.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    test_suites: ["general-tests"],
+    require_root: true,
+}
+
 aidl_interface {
     name: "binderStabilityTestIface",
     unstable: true,
     srcs: [
         "IBinderStabilityTest.aidl",
     ],
+    backend: {
+        java: {
+            enabled: false,
+        },
+    },
 }
 
 cc_test {
@@ -202,3 +309,15 @@
     test_suites: ["device-tests"],
     require_root: true,
 }
+
+cc_benchmark {
+    name: "binderParcelBenchmark",
+    defaults: ["binder_test_defaults"],
+    srcs: ["binderParcelBenchmark.cpp"],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/IBinderRpcBenchmark.aidl
similarity index 69%
copy from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
copy to libs/binder/tests/IBinderRpcBenchmark.aidl
index b92a6a9..1457422 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/IBinderRpcBenchmark.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -14,11 +14,7 @@
  * limitations under the License.
  */
 
-#pragma once
-
-#include <binder/Parcel.h>
-#include <fuzzer/FuzzedDataProvider.h>
-
-namespace android {
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
-} // namespace android
+interface IBinderRpcBenchmark {
+    @utf8InCpp String repeatString(@utf8InCpp String str);
+    IBinder repeatBinder(IBinder binder);
+}
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/IBinderRpcSession.aidl
similarity index 75%
copy from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
copy to libs/binder/tests/IBinderRpcSession.aidl
index b92a6a9..cf5f318 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/IBinderRpcSession.aidl
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-#pragma once
-
-#include <binder/Parcel.h>
-#include <fuzzer/FuzzedDataProvider.h>
-
-namespace android {
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
-} // namespace android
+interface IBinderRpcSession {
+    @utf8InCpp String getName();
+}
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
new file mode 100644
index 0000000..ef4198d
--- /dev/null
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+interface IBinderRpcTest {
+    oneway void sendString(@utf8InCpp String str);
+    @utf8InCpp String doubleString(@utf8InCpp String str);
+
+    // number of known RPC binders to process, RpcState::countBinders by session
+    int[] countBinders();
+
+    // Caller sends server, callee pings caller's server and returns error code.
+    int pingMe(IBinder binder);
+    @nullable IBinder repeatBinder(@nullable IBinder binder);
+
+    void holdBinder(@nullable IBinder binder);
+    @nullable IBinder getHeldBinder();
+
+    // Idea is client creates its own instance of IBinderRpcTest and calls this,
+    // and the server calls 'binder' with (calls - 1) passing itself as 'binder',
+    // going back and forth until calls = 0
+    void nestMe(IBinderRpcTest binder, int calls);
+
+    // should always return the same binder
+    IBinder alwaysGiveMeTheSameBinder();
+
+    // Idea is that the server will not hold onto the session, the remote session
+    // object must. This is to test lifetimes of binder objects, and consequently, also
+    // identity (since by assigning sessions names, we can make sure a section always
+    // references the session it was originally opened with).
+    IBinderRpcSession openSession(@utf8InCpp String name);
+
+    // Decremented in ~IBinderRpcSession
+    int getNumOpenSessions();
+
+    // primitives to test threading behavior
+    void lock();
+    oneway void unlockInMsAsync(int ms);
+    void lockUnlock(); // locks and unlocks a mutex
+
+    // take up binder thread for some time
+    void sleepMs(int ms);
+    oneway void sleepMsAsync(int ms);
+
+    void die(boolean cleanup);
+}
diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp
new file mode 100644
index 0000000..2d30c8d
--- /dev/null
+++ b/libs/binder/tests/binderClearBufTest.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 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/logging.h>
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+#include <thread>
+
+using namespace android;
+
+const String16 kServerName = String16("binderClearBuf");
+
+std::string hexString(const void* bytes, size_t len) {
+    if (bytes == nullptr) return "<null>";
+
+    const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+    char chars[] = "0123456789abcdef";
+    std::string result;
+    result.resize(len * 2);
+
+    for (size_t i = 0; i < len; i++) {
+        result[2 * i] = chars[bytes8[i] >> 4];
+        result[2 * i + 1] = chars[bytes8[i] & 0xf];
+    }
+
+    return result;
+}
+
+class FooBar : public BBinder {
+ public:
+    enum {
+        TRANSACTION_REPEAT_STRING = IBinder::FIRST_CALL_TRANSACTION,
+    };
+
+    std::mutex foo;
+    std::string last;
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+        // not checking data, since there is no hook at the time this test is
+        // written to check values there are set to zero. Instead, we only check
+        // the reply parcel.
+
+        switch (code) {
+            case TRANSACTION_REPEAT_STRING: {
+                const char* str = data.readCString();
+                return reply->writeCString(str == nullptr ? "<null>" : str);
+            }
+        }
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+    static std::string RepeatString(const sp<IBinder> binder,
+                                    const std::string& repeat,
+                                    std::string* outBuffer) {
+        Parcel data;
+        data.writeCString(repeat.c_str());
+        std::string result;
+        const uint8_t* lastReply;
+        size_t lastReplySize;
+        {
+            Parcel reply;
+            binder->transact(TRANSACTION_REPEAT_STRING, data, &reply, FLAG_CLEAR_BUF);
+            result = reply.readCString();
+            lastReply = reply.data();
+            lastReplySize = reply.dataSize();
+        }
+        *outBuffer = hexString(lastReply, lastReplySize);
+        return result;
+    }
+};
+
+TEST(BinderClearBuf, ClearKernelBuffer) {
+    sp<IBinder> binder = defaultServiceManager()->getService(kServerName);
+    ASSERT_NE(nullptr, binder);
+
+    std::string replyBuffer;
+    std::string result = FooBar::RepeatString(binder, "foo", &replyBuffer);
+    EXPECT_EQ("foo", result);
+
+    // the buffer must have at least some length for the string, but we will
+    // just check it has some length, to avoid assuming anything about the
+    // format
+    EXPECT_GT(replyBuffer.size(), 0);
+
+    for (size_t i = 0; i < replyBuffer.size(); i++) {
+        EXPECT_EQ(replyBuffer[i], '0') << "reply buffer at " << i;
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    if (fork() == 0) {
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+        sp<IBinder> server = new FooBar;
+        android::defaultServiceManager()->addService(kServerName, server);
+
+        IPCThreadState::self()->joinThreadPool(true);
+        exit(1);  // should not reach
+    }
+
+    // This is not racey. Just giving these services some time to register before we call
+    // getService which sleeps for much longer. One alternative would be to
+    // start a threadpool + use waitForService, but we want to have as few
+    // binder things going on in this test as possible, since we are checking
+    // memory is zero'd which the kernel has a right to change.
+    usleep(100000);
+
+    return RUN_ALL_TESTS();
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index a5261e5..0c3fbcd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -21,24 +21,34 @@
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <thread>
 
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/ParcelRef.h>
 
-#include <private/binder/binder_module.h>
 #include <linux/sched.h>
 #include <sys/epoll.h>
 #include <sys/prctl.h>
 
+#include "../binder_module.h"
 #include "binderAbiHelper.h"
 
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
 
 using namespace android;
+using testing::Not;
+
+// e.g. EXPECT_THAT(expr, StatusEq(OK)) << "additional message";
+MATCHER_P(StatusEq, expected, (negation ? "not " : "") + statusToString(expected)) {
+    *result_listener << statusToString(arg);
+    return expected == arg;
+}
 
 static ::testing::AssertionResult IsPageAligned(void *buf) {
     if (((unsigned long)buf & ((unsigned long)PAGE_SIZE - 1)) == 0)
@@ -86,6 +96,7 @@
     BINDER_LIB_TEST_GETPID,
     BINDER_LIB_TEST_ECHO_VECTOR,
     BINDER_LIB_TEST_REJECT_BUF,
+    BINDER_LIB_TEST_CAN_GET_SID,
 };
 
 pid_t start_server_process(int arg2, bool usePoll = false)
@@ -202,19 +213,16 @@
     protected:
         sp<IBinder> addServerEtc(int32_t *idPtr, int code)
         {
-            int ret;
             int32_t id;
             Parcel data, reply;
             sp<IBinder> binder;
 
-            ret = m_server->transact(code, data, &reply);
-            EXPECT_EQ(NO_ERROR, ret);
+            EXPECT_THAT(m_server->transact(code, data, &reply), StatusEq(NO_ERROR));
 
             EXPECT_FALSE(binder != nullptr);
             binder = reply.readStrongBinder();
             EXPECT_TRUE(binder != nullptr);
-            ret = reply.readInt32(&id);
-            EXPECT_EQ(NO_ERROR, ret);
+            EXPECT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
             if (idPtr)
                 *idPtr = id;
             return binder;
@@ -398,29 +406,25 @@
 };
 
 TEST_F(BinderLibTest, NopTransaction) {
-    status_t ret;
     Parcel data, reply;
-    ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, NopTransactionOneway) {
-    status_t ret;
     Parcel data, reply;
-    ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY),
+                StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, NopTransactionClear) {
-    status_t ret;
     Parcel data, reply;
     // make sure it accepts the transaction flag
-    ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_CLEAR_BUF);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_CLEAR_BUF),
+                StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, Freeze) {
-    status_t ret;
     Parcel data, reply, replypid;
     std::ifstream freezer_file("/sys/fs/cgroup/freezer/cgroup.freeze");
 
@@ -439,9 +443,8 @@
         return;
     }
 
-    ret = m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid), StatusEq(NO_ERROR));
     int32_t pid = replypid.readInt32();
-    EXPECT_EQ(NO_ERROR, ret);
     for (int i = 0; i < 10; i++) {
         EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, data, &reply, TF_ONE_WAY));
     }
@@ -465,42 +468,36 @@
 TEST_F(BinderLibTest, SetError) {
     int32_t testValue[] = { 0, -123, 123 };
     for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) {
-        status_t ret;
         Parcel data, reply;
         data.writeInt32(testValue[i]);
-        ret = m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply);
-        EXPECT_EQ(testValue[i], ret);
+        EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply),
+                    StatusEq(testValue[i]));
     }
 }
 
 TEST_F(BinderLibTest, GetId) {
-    status_t ret;
     int32_t id;
     Parcel data, reply;
-    ret = m_server->transact(BINDER_LIB_TEST_GET_ID_TRANSACTION, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = reply.readInt32(&id);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GET_ID_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
+    EXPECT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
     EXPECT_EQ(0, id);
 }
 
 TEST_F(BinderLibTest, PtrSize) {
-    status_t ret;
     int32_t ptrsize;
     Parcel data, reply;
     sp<IBinder> server = addServer();
     ASSERT_TRUE(server != nullptr);
-    ret = server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = reply.readInt32(&ptrsize);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
+    EXPECT_THAT(reply.readInt32(&ptrsize), StatusEq(NO_ERROR));
     RecordProperty("TestPtrSize", sizeof(void *));
     RecordProperty("ServerPtrSize", sizeof(void *));
 }
 
 TEST_F(BinderLibTest, IndirectGetId2)
 {
-    status_t ret;
     int32_t id;
     int32_t count;
     Parcel data, reply;
@@ -518,22 +515,19 @@
         datai.appendTo(&data);
     }
 
-    ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
-    ASSERT_EQ(NO_ERROR, ret);
+    ASSERT_THAT(m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
 
-    ret = reply.readInt32(&id);
-    ASSERT_EQ(NO_ERROR, ret);
+    ASSERT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
     EXPECT_EQ(0, id);
 
-    ret = reply.readInt32(&count);
-    ASSERT_EQ(NO_ERROR, ret);
+    ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR));
     EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count);
 
     for (size_t i = 0; i < (size_t)count; i++) {
         BinderLibTestBundle replyi(&reply);
         EXPECT_TRUE(replyi.isValid());
-        ret = replyi.readInt32(&id);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(replyi.readInt32(&id), StatusEq(NO_ERROR));
         EXPECT_EQ(serverId[i], id);
         EXPECT_EQ(replyi.dataSize(), replyi.dataPosition());
     }
@@ -543,7 +537,6 @@
 
 TEST_F(BinderLibTest, IndirectGetId3)
 {
-    status_t ret;
     int32_t id;
     int32_t count;
     Parcel data, reply;
@@ -568,15 +561,13 @@
         datai.appendTo(&data);
     }
 
-    ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
-    ASSERT_EQ(NO_ERROR, ret);
+    ASSERT_THAT(m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
 
-    ret = reply.readInt32(&id);
-    ASSERT_EQ(NO_ERROR, ret);
+    ASSERT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
     EXPECT_EQ(0, id);
 
-    ret = reply.readInt32(&count);
-    ASSERT_EQ(NO_ERROR, ret);
+    ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR));
     EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count);
 
     for (size_t i = 0; i < (size_t)count; i++) {
@@ -584,18 +575,15 @@
 
         BinderLibTestBundle replyi(&reply);
         EXPECT_TRUE(replyi.isValid());
-        ret = replyi.readInt32(&id);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(replyi.readInt32(&id), StatusEq(NO_ERROR));
         EXPECT_EQ(serverId[i], id);
 
-        ret = replyi.readInt32(&counti);
-        ASSERT_EQ(NO_ERROR, ret);
+        ASSERT_THAT(replyi.readInt32(&counti), StatusEq(NO_ERROR));
         EXPECT_EQ(1, counti);
 
         BinderLibTestBundle replyi2(&replyi);
         EXPECT_TRUE(replyi2.isValid());
-        ret = replyi2.readInt32(&id);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(replyi2.readInt32(&id), StatusEq(NO_ERROR));
         EXPECT_EQ(0, id);
         EXPECT_EQ(replyi2.dataSize(), replyi2.dataPosition());
 
@@ -607,16 +595,13 @@
 
 TEST_F(BinderLibTest, CallBack)
 {
-    status_t ret;
     Parcel data, reply;
     sp<BinderLibTestCallBack> callBack = new BinderLibTestCallBack();
     data.writeStrongBinder(callBack);
-    ret = m_server->transact(BINDER_LIB_TEST_NOP_CALL_BACK, data, &reply, TF_ONE_WAY);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = callBack->waitEvent(5);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = callBack->getResult();
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_CALL_BACK, data, &reply, TF_ONE_WAY),
+                StatusEq(NO_ERROR));
+    EXPECT_THAT(callBack->waitEvent(5), StatusEq(NO_ERROR));
+    EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, AddServer)
@@ -627,7 +612,6 @@
 
 TEST_F(BinderLibTest, DeathNotificationStrongRef)
 {
-    status_t ret;
     sp<IBinder> sbinder;
 
     sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
@@ -635,20 +619,17 @@
     {
         sp<IBinder> binder = addServer();
         ASSERT_TRUE(binder != nullptr);
-        ret = binder->linkToDeath(testDeathRecipient);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(binder->linkToDeath(testDeathRecipient), StatusEq(NO_ERROR));
         sbinder = binder;
     }
     {
         Parcel data, reply;
-        ret = sbinder->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY);
-        EXPECT_EQ(0, ret);
+        EXPECT_THAT(sbinder->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY),
+                    StatusEq(OK));
     }
     IPCThreadState::self()->flushCommands();
-    ret = testDeathRecipient->waitEvent(5);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = sbinder->unlinkToDeath(testDeathRecipient);
-    EXPECT_EQ(DEAD_OBJECT, ret);
+    EXPECT_THAT(testDeathRecipient->waitEvent(5), StatusEq(NO_ERROR));
+    EXPECT_THAT(sbinder->unlinkToDeath(testDeathRecipient), StatusEq(DEAD_OBJECT));
 }
 
 TEST_F(BinderLibTest, DeathNotificationMultiple)
@@ -671,8 +652,9 @@
             callBack[i] = new BinderLibTestCallBack();
             data.writeStrongBinder(target);
             data.writeStrongBinder(callBack[i]);
-            ret = linkedclient[i]->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply, TF_ONE_WAY);
-            EXPECT_EQ(NO_ERROR, ret);
+            EXPECT_THAT(linkedclient[i]->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data,
+                                                  &reply, TF_ONE_WAY),
+                        StatusEq(NO_ERROR));
         }
         {
             Parcel data, reply;
@@ -680,8 +662,9 @@
             passiveclient[i] = addServer();
             ASSERT_TRUE(passiveclient[i] != nullptr);
             data.writeStrongBinder(target);
-            ret = passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data, &reply, TF_ONE_WAY);
-            EXPECT_EQ(NO_ERROR, ret);
+            EXPECT_THAT(passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data,
+                                                   &reply, TF_ONE_WAY),
+                        StatusEq(NO_ERROR));
         }
     }
     {
@@ -691,10 +674,8 @@
     }
 
     for (int i = 0; i < clientcount; i++) {
-        ret = callBack[i]->waitEvent(5);
-        EXPECT_EQ(NO_ERROR, ret);
-        ret = callBack[i]->getResult();
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(callBack[i]->waitEvent(5), StatusEq(NO_ERROR));
+        EXPECT_THAT(callBack[i]->getResult(), StatusEq(NO_ERROR));
     }
 }
 
@@ -709,8 +690,7 @@
 
     sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
 
-    ret = target->linkToDeath(testDeathRecipient);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(target->linkToDeath(testDeathRecipient), StatusEq(NO_ERROR));
 
     {
         Parcel data, reply;
@@ -747,14 +727,13 @@
         callback = new BinderLibTestCallBack();
         data.writeStrongBinder(target);
         data.writeStrongBinder(callback);
-        ret = client->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply, TF_ONE_WAY);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(client->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply,
+                                     TF_ONE_WAY),
+                    StatusEq(NO_ERROR));
     }
 
-    ret = callback->waitEvent(5);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = callback->getResult();
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(callback->waitEvent(5), StatusEq(NO_ERROR));
+    EXPECT_THAT(callback->getResult(), StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, PassFile) {
@@ -770,17 +749,14 @@
         Parcel data, reply;
         uint8_t writebuf[1] = { write_value };
 
-        ret = data.writeFileDescriptor(pipefd[1], true);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(data.writeFileDescriptor(pipefd[1], true), StatusEq(NO_ERROR));
 
-        ret = data.writeInt32(sizeof(writebuf));
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(data.writeInt32(sizeof(writebuf)), StatusEq(NO_ERROR));
 
-        ret = data.write(writebuf, sizeof(writebuf));
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(data.write(writebuf, sizeof(writebuf)), StatusEq(NO_ERROR));
 
-        ret = m_server->transact(BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, data, &reply);
-        EXPECT_EQ(NO_ERROR, ret);
+        EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, data, &reply),
+                    StatusEq(NO_ERROR));
     }
 
     ret = read(pipefd[0], buf, sizeof(buf));
@@ -861,11 +837,10 @@
 }
 
 TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
-    status_t ret;
     Parcel data, reply;
 
-    ret = m_server->transact(BINDER_LIB_TEST_GET_SELF_TRANSACTION, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GET_SELF_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
 
     const flat_binder_object *fb = reply.readObject(false);
     ASSERT_TRUE(fb != nullptr);
@@ -885,8 +860,8 @@
     wp<IBinder> keepFreedBinder;
     {
         Parcel data, reply;
-        ret = server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply);
-        ASSERT_EQ(NO_ERROR, ret);
+        ASSERT_THAT(server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply),
+                    StatusEq(NO_ERROR));
         struct flat_binder_object *freed = (struct flat_binder_object *)(reply.data());
         freedHandle = freed->handle;
         /* Add a weak ref to the freed binder so the driver does not
@@ -916,8 +891,37 @@
     }
 }
 
+TEST_F(BinderLibTest, ParcelAllocatedOnAnotherThread) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    Parcel data;
+    sp<ParcelRef> reply = ParcelRef::create();
+
+    // when we have a Parcel which is deleted on another thread, if it gets
+    // deleted, it will tell the kernel this, and it will drop strong references
+    // to binder, so that we can't BR_ACQUIRE would fail
+    IPCThreadState::self()->createTransactionReference(reply.get());
+    ASSERT_EQ(NO_ERROR, server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
+                                         data,
+                                         reply.get()));
+
+    // we have sp to binder, but it is not actually acquired by kernel, the
+    // transaction is sitting on an out buffer
+    sp<IBinder> binder = reply->readStrongBinder();
+
+    std::thread([&] {
+        // without the transaction reference, this would cause the Parcel to be
+        // deallocated before the first thread flushes BR_ACQUIRE
+        reply = nullptr;
+        IPCThreadState::self()->flushCommands();
+    }).join();
+
+    ASSERT_NE(nullptr, binder);
+    ASSERT_EQ(NO_ERROR, binder->pingBinder());
+}
+
 TEST_F(BinderLibTest, CheckNoHeaderMappedInUser) {
-    status_t ret;
     Parcel data, reply;
     sp<BinderLibTestCallBack> callBack = new BinderLibTestCallBack();
     for (int i = 0; i < 2; i++) {
@@ -931,13 +935,12 @@
 
         datai.appendTo(&data);
     }
-    ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply),
+                StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, OnewayQueueing)
 {
-    status_t ret;
     Parcel data, data2;
 
     sp<IBinder> pollServer = addPollServer();
@@ -950,25 +953,21 @@
     data2.writeStrongBinder(callBack2);
     data2.writeInt32(0); // delay in us
 
-    ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data, nullptr, TF_ONE_WAY);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data, nullptr, TF_ONE_WAY),
+                StatusEq(NO_ERROR));
 
     // The delay ensures that this second transaction will end up on the async_todo list
     // (for a single-threaded server)
-    ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data2, nullptr, TF_ONE_WAY);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data2, nullptr, TF_ONE_WAY),
+                StatusEq(NO_ERROR));
 
     // The server will ensure that the two transactions are handled in the expected order;
     // If the ordering is not as expected, an error will be returned through the callbacks.
-    ret = callBack->waitEvent(2);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = callBack->getResult();
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(callBack->waitEvent(2), StatusEq(NO_ERROR));
+    EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
 
-    ret = callBack2->waitEvent(2);
-    EXPECT_EQ(NO_ERROR, ret);
-    ret = callBack2->getResult();
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(callBack2->waitEvent(2), StatusEq(NO_ERROR));
+    EXPECT_THAT(callBack2->getResult(), StatusEq(NO_ERROR));
 }
 
 TEST_F(BinderLibTest, WorkSourceUnsetByDefault)
@@ -1087,8 +1086,8 @@
     ASSERT_TRUE(server != nullptr);
 
     Parcel data, reply;
-    status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply),
+                StatusEq(NO_ERROR));
 
     int policy = reply.readInt32();
     int priority = reply.readInt32();
@@ -1107,8 +1106,8 @@
     EXPECT_EQ(0, sched_setscheduler(getpid(), SCHED_RR, &param));
 
     Parcel data, reply;
-    status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply),
+                StatusEq(NO_ERROR));
 
     int policy = reply.readInt32();
     int priority = reply.readInt32();
@@ -1125,10 +1124,9 @@
     std::vector<uint64_t> const testValue = { std::numeric_limits<uint64_t>::max(), 0, 200 };
     data.writeUint64Vector(testValue);
 
-    status_t ret = server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply);
-    EXPECT_EQ(NO_ERROR, ret);
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply), StatusEq(NO_ERROR));
     std::vector<uint64_t> readValue;
-    ret = reply.readUint64Vector(&readValue);
+    EXPECT_THAT(reply.readUint64Vector(&readValue), StatusEq(OK));
     EXPECT_EQ(readValue, testValue);
 }
 
@@ -1153,11 +1151,18 @@
     memcpy(parcelData, &obj, sizeof(obj));
     data.setDataSize(sizeof(obj));
 
-    status_t ret = server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply);
     // Either the kernel should reject this transaction (if it's correct), but
     // if it's not, the server implementation should return an error if it
     // finds an object in the received Parcel.
-    EXPECT_NE(NO_ERROR, ret);
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply),
+                Not(StatusEq(NO_ERROR)));
+}
+
+TEST_F(BinderLibTest, GotSid) {
+    sp<IBinder> server = addServer();
+
+    Parcel data;
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr), StatusEq(OK));
 }
 
 class BinderLibTestService : public BBinder
@@ -1462,6 +1467,9 @@
             case BINDER_LIB_TEST_REJECT_BUF: {
                 return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR;
             }
+            case BINDER_LIB_TEST_CAN_GET_SID: {
+                return IPCThreadState::self()->getCallingSid() == nullptr ? BAD_VALUE : NO_ERROR;
+            }
             default:
                 return UNKNOWN_TRANSACTION;
             };
diff --git a/libs/binder/tests/binderParcelBenchmark.cpp b/libs/binder/tests/binderParcelBenchmark.cpp
new file mode 100644
index 0000000..26c50eb
--- /dev/null
+++ b/libs/binder/tests/binderParcelBenchmark.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2021 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 <binder/Parcel.h>
+#include <benchmark/benchmark.h>
+
+// Usage: atest binderParcelBenchmark
+
+// For static assert(false) we need a template version to avoid early failure.
+// See: https://stackoverflow.com/questions/51523965/template-dependent-false
+template <typename T>
+constexpr bool dependent_false_v = false;
+
+template <template <typename ...> class V, typename T, typename... Args>
+void writeVector(android::Parcel &p, const V<T, Args...> &v) {
+    if constexpr (std::is_same_v<T, bool>) {
+        p.writeBoolVector(v);
+    } else if constexpr (std::is_same_v<T, uint8_t>) {
+        p.writeByteVector(v);
+    } else if constexpr (std::is_same_v<T, char16_t>) {
+        p.writeCharVector(v);
+    } else if constexpr (std::is_same_v<T, int32_t>) {
+        p.writeInt32Vector(v);
+    } else if constexpr (std::is_same_v<T, int64_t>) {
+        p.writeInt64Vector(v);
+    } else {
+        static_assert(dependent_false_v<V<T>>);
+    }
+}
+
+template <template <typename ...> class V, typename T, typename... Args>
+void readVector(android::Parcel &p, V<T, Args...> *v) {
+    if constexpr (std::is_same_v<T, bool>) {
+        p.readBoolVector(v);
+    } else if constexpr (std::is_same_v<T, uint8_t>) {
+        p.readByteVector(v);
+    } else if constexpr (std::is_same_v<T, char16_t>) {
+        p.readCharVector(v);
+    } else if constexpr (std::is_same_v<T, int32_t>) {
+        p.readInt32Vector(v);
+    } else if constexpr (std::is_same_v<T, int64_t>) {
+        p.readInt64Vector(v);
+    } else {
+        static_assert(dependent_false_v<V<T>>);
+    }
+}
+
+// Construct a series of args { 1 << 0, 1 << 1, ..., 1 << 10 }
+static void VectorArgs(benchmark::internal::Benchmark* b) {
+    for (int i = 0; i < 10; ++i) {
+        b->Args({1 << i});
+    }
+}
+
+template <typename T>
+static void BM_ParcelVector(benchmark::State& state) {
+    const size_t elements = state.range(0);
+
+    std::vector<T> v1(elements);
+    std::vector<T> v2(elements);
+    android::Parcel p;
+    while (state.KeepRunning()) {
+        p.setDataPosition(0);
+        writeVector(p, v1);
+
+        p.setDataPosition(0);
+        readVector(p, &v2);
+
+        benchmark::DoNotOptimize(v2[0]);
+        benchmark::ClobberMemory();
+    }
+    state.SetComplexityN(elements);
+}
+
+/*
+  Parcel vector write than read.
+  The read and write vectors are fixed, no resizing required.
+
+  Results on Crosshatch Pixel 3XL
+
+  #BM_BoolVector/1         44 ns      44 ns     15630626
+  #BM_BoolVector/2         54 ns      54 ns     12900340
+  #BM_BoolVector/4         73 ns      72 ns      9749841
+  #BM_BoolVector/8        107 ns     107 ns      6503326
+  #BM_BoolVector/16       186 ns     185 ns      3773627
+  #BM_BoolVector/32       337 ns     336 ns      2083877
+  #BM_BoolVector/64       607 ns     605 ns      1154113
+  #BM_BoolVector/128     1155 ns    1151 ns       608128
+  #BM_BoolVector/256     2259 ns    2253 ns       310973
+  #BM_BoolVector/512     4469 ns    4455 ns       157277
+  #BM_ByteVector/1         41 ns      41 ns     16837425
+  #BM_ByteVector/2         41 ns      41 ns     16820726
+  #BM_ByteVector/4         38 ns      38 ns     18217813
+  #BM_ByteVector/8         38 ns      38 ns     18290298
+  #BM_ByteVector/16        38 ns      38 ns     18117817
+  #BM_ByteVector/32        38 ns      38 ns     18172385
+  #BM_ByteVector/64        41 ns      41 ns     16950055
+  #BM_ByteVector/128       53 ns      53 ns     13170749
+  #BM_ByteVector/256       69 ns      69 ns     10113626
+  #BM_ByteVector/512      106 ns     106 ns      6561936
+  #BM_CharVector/1         38 ns      38 ns     18074831
+  #BM_CharVector/2         40 ns      40 ns     17206266
+  #BM_CharVector/4         50 ns      50 ns     13785944
+  #BM_CharVector/8         67 ns      67 ns     10223316
+  #BM_CharVector/16        96 ns      96 ns      7297285
+  #BM_CharVector/32       156 ns     155 ns      4484845
+  #BM_CharVector/64       277 ns     276 ns      2536003
+  #BM_CharVector/128      520 ns     518 ns      1347070
+  #BM_CharVector/256     1006 ns    1003 ns       695952
+  #BM_CharVector/512     1976 ns    1970 ns       354673
+  #BM_Int32Vector/1        41 ns      41 ns     16951262
+  #BM_Int32Vector/2        41 ns      41 ns     16916883
+  #BM_Int32Vector/4        41 ns      41 ns     16761373
+  #BM_Int32Vector/8        42 ns      42 ns     16553179
+  #BM_Int32Vector/16       43 ns      43 ns     16200362
+  #BM_Int32Vector/32       55 ns      54 ns     12724454
+  #BM_Int32Vector/64       70 ns      69 ns     10049223
+  #BM_Int32Vector/128     107 ns     107 ns      6525796
+  #BM_Int32Vector/256     179 ns     178 ns      3922563
+  #BM_Int32Vector/512     324 ns     323 ns      2160653
+  #BM_Int64Vector/1        41 ns      41 ns     16909470
+  #BM_Int64Vector/2        41 ns      41 ns     16740788
+  #BM_Int64Vector/4        42 ns      42 ns     16564197
+  #BM_Int64Vector/8        43 ns      42 ns     16284082
+  #BM_Int64Vector/16       54 ns      54 ns     12839474
+  #BM_Int64Vector/32       69 ns      69 ns     10011010
+  #BM_Int64Vector/64      107 ns     106 ns      6557956
+  #BM_Int64Vector/128     177 ns     177 ns      3925618
+  #BM_Int64Vector/256     324 ns     323 ns      2163321
+  #BM_Int64Vector/512     613 ns     611 ns      1140418
+*/
+
+static void BM_BoolVector(benchmark::State& state) {
+    BM_ParcelVector<bool>(state);
+}
+
+static void BM_ByteVector(benchmark::State& state) {
+    BM_ParcelVector<uint8_t>(state);
+}
+
+static void BM_CharVector(benchmark::State& state) {
+    BM_ParcelVector<char16_t>(state);
+}
+
+static void BM_Int32Vector(benchmark::State& state) {
+    BM_ParcelVector<int32_t>(state);
+}
+
+static void BM_Int64Vector(benchmark::State& state) {
+    BM_ParcelVector<int64_t>(state);
+}
+
+BENCHMARK(BM_BoolVector)->Apply(VectorArgs);
+BENCHMARK(BM_ByteVector)->Apply(VectorArgs);
+BENCHMARK(BM_CharVector)->Apply(VectorArgs);
+BENCHMARK(BM_Int32Vector)->Apply(VectorArgs);
+BENCHMARK(BM_Int64Vector)->Apply(VectorArgs);
+
+BENCHMARK_MAIN();
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
new file mode 100644
index 0000000..a457e67
--- /dev/null
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 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 <BnBinderRpcBenchmark.h>
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+#include <binder/Binder.h>
+#include <binder/RpcServer.h>
+#include <binder/RpcSession.h>
+
+#include <thread>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+using android::BBinder;
+using android::IBinder;
+using android::interface_cast;
+using android::OK;
+using android::RpcServer;
+using android::RpcSession;
+using android::sp;
+using android::binder::Status;
+
+class MyBinderRpcBenchmark : public BnBinderRpcBenchmark {
+    Status repeatString(const std::string& str, std::string* out) override {
+        *out = str;
+        return Status::ok();
+    }
+    Status repeatBinder(const sp<IBinder>& str, sp<IBinder>* out) override {
+        *out = str;
+        return Status::ok();
+    }
+};
+
+static sp<RpcSession> gSession = RpcSession::make();
+
+void BM_getRootObject(benchmark::State& state) {
+    while (state.KeepRunning()) {
+        CHECK(gSession->getRootObject() != nullptr);
+    }
+}
+BENCHMARK(BM_getRootObject);
+
+void BM_pingTransaction(benchmark::State& state) {
+    sp<IBinder> binder = gSession->getRootObject();
+    CHECK(binder != nullptr);
+
+    while (state.KeepRunning()) {
+        CHECK_EQ(OK, binder->pingBinder());
+    }
+}
+BENCHMARK(BM_pingTransaction);
+
+void BM_repeatString(benchmark::State& state) {
+    sp<IBinder> binder = gSession->getRootObject();
+    CHECK(binder != nullptr);
+    sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
+    CHECK(iface != nullptr);
+
+    // Googlers might see go/another-look-at-aidl-hidl-perf
+    //
+    // When I checked in July 2019, 99.5% of AIDL transactions and 99.99% of HIDL
+    // transactions were less than one page in size (system wide during a test
+    // involving media and camera). This is why this diverges from
+    // binderThroughputTest and hwbinderThroughputTest. Future consideration - get
+    // this data on continuous integration. Here we are testing sending a
+    // transaction of twice this size. In other cases, we should focus on
+    // benchmarks of particular usecases. If individual binder transactions like
+    // the ones tested here are fast, then Android performance will be dominated
+    // by how many binder calls work together (and by factors like the scheduler,
+    // thermal throttling, core choice, etc..).
+    std::string str = std::string(getpagesize() * 2, 'a');
+    CHECK_EQ(str.size(), getpagesize() * 2);
+
+    while (state.KeepRunning()) {
+        std::string out;
+        Status ret = iface->repeatString(str, &out);
+        CHECK(ret.isOk()) << ret;
+    }
+}
+BENCHMARK(BM_repeatString);
+
+void BM_repeatBinder(benchmark::State& state) {
+    sp<IBinder> binder = gSession->getRootObject();
+    CHECK(binder != nullptr);
+    sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
+    CHECK(iface != nullptr);
+
+    while (state.KeepRunning()) {
+        // force creation of a new address
+        sp<IBinder> binder = sp<BBinder>::make();
+
+        sp<IBinder> out;
+        Status ret = iface->repeatBinder(binder, &out);
+        CHECK(ret.isOk()) << ret;
+    }
+}
+BENCHMARK(BM_repeatBinder);
+
+int main(int argc, char** argv) {
+    ::benchmark::Initialize(&argc, argv);
+    if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+
+    std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark";
+    (void)unlink(addr.c_str());
+
+    std::thread([addr]() {
+        sp<RpcServer> server = RpcServer::make();
+        server->setRootObject(sp<MyBinderRpcBenchmark>::make());
+        server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+        CHECK(server->setupUnixDomainServer(addr.c_str()));
+        server->join();
+    }).detach();
+
+    for (size_t tries = 0; tries < 5; tries++) {
+        usleep(10000);
+        if (gSession->setupUnixDomainClient(addr.c_str())) goto success;
+    }
+    LOG(FATAL) << "Could not connect.";
+success:
+
+    ::benchmark::RunSpecifiedBenchmarks();
+    return 0;
+}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
new file mode 100644
index 0000000..b3ce744
--- /dev/null
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -0,0 +1,938 @@
+/*
+ * Copyright (C) 2020 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 <BnBinderRpcSession.h>
+#include <BnBinderRpcTest.h>
+#include <aidl/IBinderRpcTest.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_libbinder.h>
+#include <binder/Binder.h>
+#include <binder/BpBinder.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/RpcServer.h>
+#include <binder/RpcSession.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <cstdlib>
+#include <iostream>
+#include <thread>
+
+#include <sys/prctl.h>
+#include <unistd.h>
+
+#include "../RpcState.h"   // for debugging
+#include "../vm_sockets.h" // for VMADDR_*
+
+namespace android {
+
+TEST(BinderRpcParcel, EntireParcelFormatted) {
+    Parcel p;
+    p.writeInt32(3);
+
+    EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "");
+}
+
+using android::binder::Status;
+
+#define EXPECT_OK(status)                 \
+    do {                                  \
+        Status stat = (status);           \
+        EXPECT_TRUE(stat.isOk()) << stat; \
+    } while (false)
+
+class MyBinderRpcSession : public BnBinderRpcSession {
+public:
+    static std::atomic<int32_t> gNum;
+
+    MyBinderRpcSession(const std::string& name) : mName(name) { gNum++; }
+    Status getName(std::string* name) override {
+        *name = mName;
+        return Status::ok();
+    }
+    ~MyBinderRpcSession() { gNum--; }
+
+private:
+    std::string mName;
+};
+std::atomic<int32_t> MyBinderRpcSession::gNum;
+
+class MyBinderRpcTest : public BnBinderRpcTest {
+public:
+    wp<RpcServer> server;
+
+    Status sendString(const std::string& str) override {
+        (void)str;
+        return Status::ok();
+    }
+    Status doubleString(const std::string& str, std::string* strstr) override {
+        *strstr = str + str;
+        return Status::ok();
+    }
+    Status countBinders(std::vector<int32_t>* out) override {
+        sp<RpcServer> spServer = server.promote();
+        if (spServer == nullptr) {
+            return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+        }
+        out->clear();
+        for (auto session : spServer->listSessions()) {
+            size_t count = session->state()->countBinders();
+            if (count != 1) {
+                // this is called when there is only one binder held remaining,
+                // so to aid debugging
+                session->state()->dump();
+            }
+            out->push_back(count);
+        }
+        return Status::ok();
+    }
+    Status pingMe(const sp<IBinder>& binder, int32_t* out) override {
+        if (binder == nullptr) {
+            std::cout << "Received null binder!" << std::endl;
+            return Status::fromExceptionCode(Status::EX_NULL_POINTER);
+        }
+        *out = binder->pingBinder();
+        return Status::ok();
+    }
+    Status repeatBinder(const sp<IBinder>& binder, sp<IBinder>* out) override {
+        *out = binder;
+        return Status::ok();
+    }
+    static sp<IBinder> mHeldBinder;
+    Status holdBinder(const sp<IBinder>& binder) override {
+        mHeldBinder = binder;
+        return Status::ok();
+    }
+    Status getHeldBinder(sp<IBinder>* held) override {
+        *held = mHeldBinder;
+        return Status::ok();
+    }
+    Status nestMe(const sp<IBinderRpcTest>& binder, int count) override {
+        if (count <= 0) return Status::ok();
+        return binder->nestMe(this, count - 1);
+    }
+    Status alwaysGiveMeTheSameBinder(sp<IBinder>* out) override {
+        static sp<IBinder> binder = new BBinder;
+        *out = binder;
+        return Status::ok();
+    }
+    Status openSession(const std::string& name, sp<IBinderRpcSession>* out) override {
+        *out = new MyBinderRpcSession(name);
+        return Status::ok();
+    }
+    Status getNumOpenSessions(int32_t* out) override {
+        *out = MyBinderRpcSession::gNum;
+        return Status::ok();
+    }
+
+    std::mutex blockMutex;
+    Status lock() override {
+        blockMutex.lock();
+        return Status::ok();
+    }
+    Status unlockInMsAsync(int32_t ms) override {
+        usleep(ms * 1000);
+        blockMutex.unlock();
+        return Status::ok();
+    }
+    Status lockUnlock() override {
+        std::lock_guard<std::mutex> _l(blockMutex);
+        return Status::ok();
+    }
+
+    Status sleepMs(int32_t ms) override {
+        usleep(ms * 1000);
+        return Status::ok();
+    }
+
+    Status sleepMsAsync(int32_t ms) override {
+        // In-process binder calls are asynchronous, but the call to this method
+        // is synchronous wrt its client. This in/out-process threading model
+        // diffentiation is a classic binder leaky abstraction (for better or
+        // worse) and is preserved here the way binder sockets plugs itself
+        // into BpBinder, as nothing is changed at the higher levels
+        // (IInterface) which result in this behavior.
+        return sleepMs(ms);
+    }
+
+    Status die(bool cleanup) override {
+        if (cleanup) {
+            exit(1);
+        } else {
+            _exit(1);
+        }
+    }
+};
+sp<IBinder> MyBinderRpcTest::mHeldBinder;
+
+class Pipe {
+public:
+    Pipe() { CHECK(android::base::Pipe(&mRead, &mWrite)); }
+    Pipe(Pipe&&) = default;
+    android::base::borrowed_fd readEnd() { return mRead; }
+    android::base::borrowed_fd writeEnd() { return mWrite; }
+
+private:
+    android::base::unique_fd mRead;
+    android::base::unique_fd mWrite;
+};
+
+class Process {
+public:
+    Process(Process&&) = default;
+    Process(const std::function<void(Pipe*)>& f) {
+        if (0 == (mPid = fork())) {
+            // racey: assume parent doesn't crash before this is set
+            prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+            f(&mPipe);
+        }
+    }
+    ~Process() {
+        if (mPid != 0) {
+            kill(mPid, SIGKILL);
+        }
+    }
+    Pipe* getPipe() { return &mPipe; }
+
+private:
+    pid_t mPid = 0;
+    Pipe mPipe;
+};
+
+static std::string allocateSocketAddress() {
+    static size_t id = 0;
+    std::string temp = getenv("TMPDIR") ?: "/tmp";
+    return temp + "/binderRpcTest_" + std::to_string(id++);
+};
+
+struct ProcessSession {
+    // reference to process hosting a socket server
+    Process host;
+
+    struct SessionInfo {
+        sp<RpcSession> session;
+        sp<IBinder> root;
+    };
+
+    // client session objects associated with other process
+    // each one represents a separate session
+    std::vector<SessionInfo> sessions;
+
+    ProcessSession(ProcessSession&&) = default;
+    ~ProcessSession() {
+        for (auto& session : sessions) {
+            session.root = nullptr;
+        }
+
+        for (auto& info : sessions) {
+            sp<RpcSession>& session = info.session;
+
+            EXPECT_NE(nullptr, session);
+            EXPECT_NE(nullptr, session->state());
+            EXPECT_EQ(0, session->state()->countBinders()) << (session->state()->dump(), "dump:");
+
+            wp<RpcSession> weakSession = session;
+            session = nullptr;
+            EXPECT_EQ(nullptr, weakSession.promote()) << "Leaked session";
+        }
+    }
+};
+
+// Process session where the process hosts IBinderRpcTest, the server used
+// for most testing here
+struct BinderRpcTestProcessSession {
+    ProcessSession proc;
+
+    // pre-fetched root object (for first session)
+    sp<IBinder> rootBinder;
+
+    // pre-casted root object (for first session)
+    sp<IBinderRpcTest> rootIface;
+
+    // whether session should be invalidated by end of run
+    bool expectInvalid = false;
+
+    BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
+    ~BinderRpcTestProcessSession() {
+        if (!expectInvalid) {
+            std::vector<int32_t> remoteCounts;
+            // calling over any sessions counts across all sessions
+            EXPECT_OK(rootIface->countBinders(&remoteCounts));
+            EXPECT_EQ(remoteCounts.size(), proc.sessions.size());
+            for (auto remoteCount : remoteCounts) {
+                EXPECT_EQ(remoteCount, 1);
+            }
+        }
+
+        rootIface = nullptr;
+        rootBinder = nullptr;
+    }
+};
+
+enum class SocketType {
+    UNIX,
+    VSOCK,
+    INET,
+};
+static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) {
+    switch (info.param) {
+        case SocketType::UNIX:
+            return "unix_domain_socket";
+        case SocketType::VSOCK:
+            return "vm_socket";
+        case SocketType::INET:
+            return "inet_socket";
+        default:
+            LOG_ALWAYS_FATAL("Unknown socket type");
+            return "";
+    }
+}
+class BinderRpc : public ::testing::TestWithParam<SocketType> {
+public:
+    // This creates a new process serving an interface on a certain number of
+    // threads.
+    ProcessSession createRpcTestSocketServerProcess(
+            size_t numThreads, size_t numSessions,
+            const std::function<void(const sp<RpcServer>&)>& configure) {
+        CHECK_GE(numSessions, 1) << "Must have at least one session to a server";
+
+        SocketType socketType = GetParam();
+
+        std::string addr = allocateSocketAddress();
+        unlink(addr.c_str());
+        static unsigned int vsockPort = 3456;
+        vsockPort++;
+
+        auto ret = ProcessSession{
+                .host = Process([&](Pipe* pipe) {
+                    sp<RpcServer> server = RpcServer::make();
+
+                    server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+                    server->setMaxThreads(numThreads);
+
+                    unsigned int outPort = 0;
+
+                    switch (socketType) {
+                        case SocketType::UNIX:
+                            CHECK(server->setupUnixDomainServer(addr.c_str())) << addr;
+                            break;
+                        case SocketType::VSOCK:
+                            CHECK(server->setupVsockServer(vsockPort));
+                            break;
+                        case SocketType::INET: {
+                            CHECK(server->setupInetServer(0, &outPort));
+                            CHECK_NE(0, outPort);
+                            break;
+                        }
+                        default:
+                            LOG_ALWAYS_FATAL("Unknown socket type");
+                    }
+
+                    CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort, sizeof(outPort)));
+
+                    configure(server);
+
+                    server->join();
+                }),
+        };
+
+        // always read socket, so that we have waited for the server to start
+        unsigned int outPort = 0;
+        CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &outPort, sizeof(outPort)));
+        if (socketType == SocketType::INET) {
+            CHECK_NE(0, outPort);
+        }
+
+        for (size_t i = 0; i < numSessions; i++) {
+            sp<RpcSession> session = RpcSession::make();
+            switch (socketType) {
+                case SocketType::UNIX:
+                    if (session->setupUnixDomainClient(addr.c_str())) goto success;
+                    break;
+                case SocketType::VSOCK:
+                    if (session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort)) goto success;
+                    break;
+                case SocketType::INET:
+                    if (session->setupInetClient("127.0.0.1", outPort)) goto success;
+                    break;
+                default:
+                    LOG_ALWAYS_FATAL("Unknown socket type");
+            }
+            LOG_ALWAYS_FATAL("Could not connect");
+        success:
+            ret.sessions.push_back({session, session->getRootObject()});
+        }
+        return ret;
+    }
+
+    BinderRpcTestProcessSession createRpcTestSocketServerProcess(size_t numThreads,
+                                                                 size_t numSessions = 1) {
+        BinderRpcTestProcessSession ret{
+                .proc = createRpcTestSocketServerProcess(numThreads, numSessions,
+                                                         [&](const sp<RpcServer>& server) {
+                                                             sp<MyBinderRpcTest> service =
+                                                                     new MyBinderRpcTest;
+                                                             server->setRootObject(service);
+                                                             service->server = server;
+                                                         }),
+        };
+
+        ret.rootBinder = ret.proc.sessions.at(0).root;
+        ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder);
+
+        return ret;
+    }
+};
+
+TEST_P(BinderRpc, RootObjectIsNull) {
+    auto proc = createRpcTestSocketServerProcess(1, 1, [](const sp<RpcServer>& server) {
+        // this is the default, but to be explicit
+        server->setRootObject(nullptr);
+    });
+
+    EXPECT_EQ(nullptr, proc.sessions.at(0).root);
+}
+
+TEST_P(BinderRpc, Ping) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    ASSERT_NE(proc.rootBinder, nullptr);
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+}
+
+TEST_P(BinderRpc, GetInterfaceDescriptor) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    ASSERT_NE(proc.rootBinder, nullptr);
+    EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor());
+}
+
+TEST_P(BinderRpc, MultipleSessions) {
+    auto proc = createRpcTestSocketServerProcess(1 /*threads*/, 5 /*sessions*/);
+    for (auto session : proc.proc.sessions) {
+        ASSERT_NE(nullptr, session.root);
+        EXPECT_EQ(OK, session.root->pingBinder());
+    }
+}
+
+TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    Parcel data;
+    Parcel reply;
+    EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0));
+}
+
+TEST_P(BinderRpc, AppendSeparateFormats) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    Parcel p1;
+    p1.markForBinder(proc.rootBinder);
+    p1.writeInt32(3);
+
+    Parcel p2;
+
+    EXPECT_EQ(BAD_TYPE, p1.appendFrom(&p2, 0, p2.dataSize()));
+    EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize()));
+}
+
+TEST_P(BinderRpc, UnknownTransaction) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    Parcel data;
+    data.markForBinder(proc.rootBinder);
+    Parcel reply;
+    EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0));
+}
+
+TEST_P(BinderRpc, SendSomethingOneway) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    EXPECT_OK(proc.rootIface->sendString("asdf"));
+}
+
+TEST_P(BinderRpc, SendAndGetResultBack) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    std::string doubled;
+    EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled));
+    EXPECT_EQ("cool cool ", doubled);
+}
+
+TEST_P(BinderRpc, SendAndGetResultBackBig) {
+    auto proc = createRpcTestSocketServerProcess(1);
+    std::string single = std::string(1024, 'a');
+    std::string doubled;
+    EXPECT_OK(proc.rootIface->doubleString(single, &doubled));
+    EXPECT_EQ(single + single, doubled);
+}
+
+TEST_P(BinderRpc, CallMeBack) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    int32_t pingResult;
+    EXPECT_OK(proc.rootIface->pingMe(new MyBinderRpcSession("foo"), &pingResult));
+    EXPECT_EQ(OK, pingResult);
+
+    EXPECT_EQ(0, MyBinderRpcSession::gNum);
+}
+
+TEST_P(BinderRpc, RepeatBinder) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> inBinder = new MyBinderRpcSession("foo");
+    sp<IBinder> outBinder;
+    EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder));
+    EXPECT_EQ(inBinder, outBinder);
+
+    wp<IBinder> weak = inBinder;
+    inBinder = nullptr;
+    outBinder = nullptr;
+
+    // Force reading a reply, to process any pending dec refs from the other
+    // process (the other process will process dec refs there before processing
+    // the ping here).
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+    EXPECT_EQ(nullptr, weak.promote());
+
+    EXPECT_EQ(0, MyBinderRpcSession::gNum);
+}
+
+TEST_P(BinderRpc, RepeatTheirBinder) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinderRpcSession> session;
+    EXPECT_OK(proc.rootIface->openSession("aoeu", &session));
+
+    sp<IBinder> inBinder = IInterface::asBinder(session);
+    sp<IBinder> outBinder;
+    EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder));
+    EXPECT_EQ(inBinder, outBinder);
+
+    wp<IBinder> weak = inBinder;
+    session = nullptr;
+    inBinder = nullptr;
+    outBinder = nullptr;
+
+    // Force reading a reply, to process any pending dec refs from the other
+    // process (the other process will process dec refs there before processing
+    // the ping here).
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+    EXPECT_EQ(nullptr, weak.promote());
+}
+
+TEST_P(BinderRpc, RepeatBinderNull) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> outBinder;
+    EXPECT_OK(proc.rootIface->repeatBinder(nullptr, &outBinder));
+    EXPECT_EQ(nullptr, outBinder);
+}
+
+TEST_P(BinderRpc, HoldBinder) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    IBinder* ptr = nullptr;
+    {
+        sp<IBinder> binder = new BBinder();
+        ptr = binder.get();
+        EXPECT_OK(proc.rootIface->holdBinder(binder));
+    }
+
+    sp<IBinder> held;
+    EXPECT_OK(proc.rootIface->getHeldBinder(&held));
+
+    EXPECT_EQ(held.get(), ptr);
+
+    // stop holding binder, because we test to make sure references are cleaned
+    // up
+    EXPECT_OK(proc.rootIface->holdBinder(nullptr));
+    // and flush ref counts
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+}
+
+// START TESTS FOR LIMITATIONS OF SOCKET BINDER
+// These are behavioral differences form regular binder, where certain usecases
+// aren't supported.
+
+TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketSessions) {
+    auto proc1 = createRpcTestSocketServerProcess(1);
+    auto proc2 = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> outBinder;
+    EXPECT_EQ(INVALID_OPERATION,
+              proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError());
+}
+
+TEST_P(BinderRpc, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+    auto proc = createRpcTestSocketServerProcess(1 /*threads*/, 2 /*sessions*/);
+
+    sp<IBinder> outBinder;
+    EXPECT_EQ(INVALID_OPERATION,
+              proc.rootIface->repeatBinder(proc.proc.sessions.at(1).root, &outBinder)
+                      .transactionError());
+}
+
+TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager());
+    sp<IBinder> outBinder;
+    EXPECT_EQ(INVALID_OPERATION,
+              proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError());
+}
+
+TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    // for historical reasons, IServiceManager interface only returns the
+    // exception code
+    EXPECT_EQ(binder::Status::EX_TRANSACTION_FAILED,
+              defaultServiceManager()->addService(String16("not_suspicious"), proc.rootBinder));
+}
+
+// END TESTS FOR LIMITATIONS OF SOCKET BINDER
+
+TEST_P(BinderRpc, RepeatRootObject) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> outBinder;
+    EXPECT_OK(proc.rootIface->repeatBinder(proc.rootBinder, &outBinder));
+    EXPECT_EQ(proc.rootBinder, outBinder);
+}
+
+TEST_P(BinderRpc, NestedTransactions) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    auto nastyNester = sp<MyBinderRpcTest>::make();
+    EXPECT_OK(proc.rootIface->nestMe(nastyNester, 10));
+
+    wp<IBinder> weak = nastyNester;
+    nastyNester = nullptr;
+    EXPECT_EQ(nullptr, weak.promote());
+}
+
+TEST_P(BinderRpc, SameBinderEquality) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> a;
+    EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a));
+
+    sp<IBinder> b;
+    EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b));
+
+    EXPECT_EQ(a, b);
+}
+
+TEST_P(BinderRpc, SameBinderEqualityWeak) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinder> a;
+    EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a));
+    wp<IBinder> weak = a;
+    a = nullptr;
+
+    sp<IBinder> b;
+    EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b));
+
+    // this is the wrong behavior, since BpBinder
+    // doesn't implement onIncStrongAttempted
+    // but make sure there is no crash
+    EXPECT_EQ(nullptr, weak.promote());
+
+    GTEST_SKIP() << "Weak binders aren't currently re-promotable for RPC binder.";
+
+    // In order to fix this:
+    // - need to have incStrongAttempted reflected across IPC boundary (wait for
+    //   response to promote - round trip...)
+    // - sendOnLastWeakRef, to delete entries out of RpcState table
+    EXPECT_EQ(b, weak.promote());
+}
+
+#define expectSessions(expected, iface)                   \
+    do {                                                  \
+        int session;                                      \
+        EXPECT_OK((iface)->getNumOpenSessions(&session)); \
+        EXPECT_EQ(expected, session);                     \
+    } while (false)
+
+TEST_P(BinderRpc, SingleSession) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    sp<IBinderRpcSession> session;
+    EXPECT_OK(proc.rootIface->openSession("aoeu", &session));
+    std::string out;
+    EXPECT_OK(session->getName(&out));
+    EXPECT_EQ("aoeu", out);
+
+    expectSessions(1, proc.rootIface);
+    session = nullptr;
+    expectSessions(0, proc.rootIface);
+}
+
+TEST_P(BinderRpc, ManySessions) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    std::vector<sp<IBinderRpcSession>> sessions;
+
+    for (size_t i = 0; i < 15; i++) {
+        expectSessions(i, proc.rootIface);
+        sp<IBinderRpcSession> session;
+        EXPECT_OK(proc.rootIface->openSession(std::to_string(i), &session));
+        sessions.push_back(session);
+    }
+    expectSessions(sessions.size(), proc.rootIface);
+    for (size_t i = 0; i < sessions.size(); i++) {
+        std::string out;
+        EXPECT_OK(sessions.at(i)->getName(&out));
+        EXPECT_EQ(std::to_string(i), out);
+    }
+    expectSessions(sessions.size(), proc.rootIface);
+
+    while (!sessions.empty()) {
+        sessions.pop_back();
+        expectSessions(sessions.size(), proc.rootIface);
+    }
+    expectSessions(0, proc.rootIface);
+}
+
+size_t epochMillis() {
+    using std::chrono::duration_cast;
+    using std::chrono::milliseconds;
+    using std::chrono::seconds;
+    using std::chrono::system_clock;
+    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+}
+
+TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) {
+    constexpr size_t kNumThreads = 10;
+
+    auto proc = createRpcTestSocketServerProcess(kNumThreads);
+
+    EXPECT_OK(proc.rootIface->lock());
+
+    // block all but one thread taking locks
+    std::vector<std::thread> ts;
+    for (size_t i = 0; i < kNumThreads - 1; i++) {
+        ts.push_back(std::thread([&] { proc.rootIface->lockUnlock(); }));
+    }
+
+    usleep(100000); // give chance for calls on other threads
+
+    // other calls still work
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+    constexpr size_t blockTimeMs = 500;
+    size_t epochMsBefore = epochMillis();
+    // after this, we should never see a response within this time
+    EXPECT_OK(proc.rootIface->unlockInMsAsync(blockTimeMs));
+
+    // this call should be blocked for blockTimeMs
+    EXPECT_EQ(OK, proc.rootBinder->pingBinder());
+
+    size_t epochMsAfter = epochMillis();
+    EXPECT_GE(epochMsAfter, epochMsBefore + blockTimeMs) << epochMsBefore;
+
+    for (auto& t : ts) t.join();
+}
+
+TEST_P(BinderRpc, ThreadPoolOverSaturated) {
+    constexpr size_t kNumThreads = 10;
+    constexpr size_t kNumCalls = kNumThreads + 3;
+    constexpr size_t kSleepMs = 500;
+
+    auto proc = createRpcTestSocketServerProcess(kNumThreads);
+
+    size_t epochMsBefore = epochMillis();
+
+    std::vector<std::thread> ts;
+    for (size_t i = 0; i < kNumCalls; i++) {
+        ts.push_back(std::thread([&] { proc.rootIface->sleepMs(kSleepMs); }));
+    }
+
+    for (auto& t : ts) t.join();
+
+    size_t epochMsAfter = epochMillis();
+
+    EXPECT_GE(epochMsAfter, epochMsBefore + 2 * kSleepMs);
+
+    // Potential flake, but make sure calls are handled in parallel.
+    EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs);
+}
+
+TEST_P(BinderRpc, ThreadingStressTest) {
+    constexpr size_t kNumClientThreads = 10;
+    constexpr size_t kNumServerThreads = 10;
+    constexpr size_t kNumCalls = 100;
+
+    auto proc = createRpcTestSocketServerProcess(kNumServerThreads);
+
+    std::vector<std::thread> threads;
+    for (size_t i = 0; i < kNumClientThreads; i++) {
+        threads.push_back(std::thread([&] {
+            for (size_t j = 0; j < kNumCalls; j++) {
+                sp<IBinder> out;
+                EXPECT_OK(proc.rootIface->repeatBinder(proc.rootBinder, &out));
+                EXPECT_EQ(proc.rootBinder, out);
+            }
+        }));
+    }
+
+    for (auto& t : threads) t.join();
+}
+
+TEST_P(BinderRpc, OnewayStressTest) {
+    constexpr size_t kNumClientThreads = 10;
+    constexpr size_t kNumServerThreads = 10;
+    constexpr size_t kNumCalls = 100;
+
+    auto proc = createRpcTestSocketServerProcess(kNumServerThreads);
+
+    std::vector<std::thread> threads;
+    for (size_t i = 0; i < kNumClientThreads; i++) {
+        threads.push_back(std::thread([&] {
+            for (size_t j = 0; j < kNumCalls; j++) {
+                EXPECT_OK(proc.rootIface->sendString("a"));
+            }
+
+            // check threads are not stuck
+            EXPECT_OK(proc.rootIface->sleepMs(250));
+        }));
+    }
+
+    for (auto& t : threads) t.join();
+}
+
+TEST_P(BinderRpc, OnewayCallDoesNotWait) {
+    constexpr size_t kReallyLongTimeMs = 100;
+    constexpr size_t kSleepMs = kReallyLongTimeMs * 5;
+
+    // more than one thread, just so this doesn't deadlock
+    auto proc = createRpcTestSocketServerProcess(2);
+
+    size_t epochMsBefore = epochMillis();
+
+    EXPECT_OK(proc.rootIface->sleepMsAsync(kSleepMs));
+
+    size_t epochMsAfter = epochMillis();
+    EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
+}
+
+TEST_P(BinderRpc, OnewayCallQueueing) {
+    constexpr size_t kNumSleeps = 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(1 + kNumExtraServerThreads);
+
+    EXPECT_OK(proc.rootIface->lock());
+
+    for (size_t i = 0; i < kNumSleeps; i++) {
+        // these should be processed serially
+        proc.rootIface->sleepMsAsync(kSleepMs);
+    }
+    // should also be processesed serially
+    EXPECT_OK(proc.rootIface->unlockInMsAsync(kSleepMs));
+
+    size_t epochMsBefore = epochMillis();
+    EXPECT_OK(proc.rootIface->lockUnlock());
+    size_t epochMsAfter = epochMillis();
+
+    EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps);
+}
+
+TEST_P(BinderRpc, Die) {
+    for (bool doDeathCleanup : {true, false}) {
+        auto proc = createRpcTestSocketServerProcess(1);
+
+        // make sure there is some state during crash
+        // 1. we hold their binder
+        sp<IBinderRpcSession> session;
+        EXPECT_OK(proc.rootIface->openSession("happy", &session));
+        // 2. they hold our binder
+        sp<IBinder> binder = new BBinder();
+        EXPECT_OK(proc.rootIface->holdBinder(binder));
+
+        EXPECT_EQ(DEAD_OBJECT, proc.rootIface->die(doDeathCleanup).transactionError())
+                << "Do death cleanup: " << doDeathCleanup;
+
+        proc.expectInvalid = true;
+    }
+}
+
+TEST_P(BinderRpc, WorksWithLibbinderNdkPing) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(proc.rootBinder));
+    ASSERT_NE(binder, nullptr);
+
+    ASSERT_EQ(STATUS_OK, AIBinder_ping(binder.get()));
+}
+
+TEST_P(BinderRpc, WorksWithLibbinderNdkUserTransaction) {
+    auto proc = createRpcTestSocketServerProcess(1);
+
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(proc.rootBinder));
+    ASSERT_NE(binder, nullptr);
+
+    auto ndkBinder = aidl::IBinderRpcTest::fromBinder(binder);
+    ASSERT_NE(ndkBinder, nullptr);
+
+    std::string out;
+    ndk::ScopedAStatus status = ndkBinder->doubleString("aoeu", &out);
+    ASSERT_TRUE(status.isOk()) << status.getDescription();
+    ASSERT_EQ("aoeuaoeu", out);
+}
+
+ssize_t countFds() {
+    DIR* dir = opendir("/proc/self/fd/");
+    if (dir == nullptr) return -1;
+    ssize_t ret = 0;
+    dirent* ent;
+    while ((ent = readdir(dir)) != nullptr) ret++;
+    closedir(dir);
+    return ret;
+}
+
+TEST_P(BinderRpc, Fds) {
+    ssize_t beforeFds = countFds();
+    ASSERT_GE(beforeFds, 0);
+    {
+        auto proc = createRpcTestSocketServerProcess(10);
+        ASSERT_EQ(OK, proc.rootBinder->pingBinder());
+    }
+    ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?");
+}
+
+INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
+                        ::testing::ValuesIn({
+                                SocketType::UNIX,
+// TODO(b/185269356): working on host
+#ifdef __BIONIC__
+                                SocketType::VSOCK,
+#endif
+                                SocketType::INET,
+                        }),
+                        PrintSocketType);
+
+} // namespace android
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter);
+    return RUN_ALL_TESTS();
+}
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index ffb3ef2..c857d62 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -226,7 +226,7 @@
         IncrementNativeHandle,
         IncrementNoCopyNoMove,
         IncrementParcelableVector,
-        ToUpper,
+        DoubleString,
         CallMeBack,
         IncrementInt32,
         IncrementUint32,
@@ -256,7 +256,7 @@
     virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
     virtual status_t increment(const std::vector<TestParcelable>& a,
                                std::vector<TestParcelable>* aPlusOne) const = 0;
-    virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
+    virtual status_t doubleString(const String8& str, String8* doubleStr) const = 0;
     // As mentioned above, sp<IBinder> is already tested by setDeathToken
     virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
     virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
@@ -329,9 +329,10 @@
                                                            std::vector<TestParcelable>*);
         return callRemote<Signature>(Tag::IncrementParcelableVector, a, aPlusOne);
     }
-    status_t toUpper(const String8& str, String8* upperStr) const override {
+    status_t doubleString(const String8& str, String8* doubleStr) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
-        return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
+        return callRemote<decltype(&ISafeInterfaceTest::doubleString)>(Tag::DoubleString, str,
+                                                                       doubleStr);
     }
     void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
@@ -454,10 +455,9 @@
         }
         return NO_ERROR;
     }
-    status_t toUpper(const String8& str, String8* upperStr) const override {
+    status_t doubleString(const String8& str, String8* doubleStr) const override {
         ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
-        *upperStr = str;
-        upperStr->toUpper();
+        *doubleStr = str + str;
         return NO_ERROR;
     }
     void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
@@ -548,8 +548,8 @@
                                                          std::vector<TestParcelable>*) const;
                 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
             }
-            case ISafeInterfaceTest::Tag::ToUpper: {
-                return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
+            case ISafeInterfaceTest::Tag::DoubleString: {
+                return callLocal(data, reply, &ISafeInterfaceTest::doubleString);
             }
             case ISafeInterfaceTest::Tag::CallMeBack: {
                 return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
@@ -726,12 +726,12 @@
     }
 }
 
-TEST_F(SafeInterfaceTest, TestToUpper) {
-    const String8 str{"Hello, world!"};
-    String8 upperStr;
-    status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
+TEST_F(SafeInterfaceTest, TestDoubleString) {
+    const String8 str{"asdf"};
+    String8 doubleStr;
+    status_t result = mSafeInterfaceTest->doubleString(str, &doubleStr);
     ASSERT_EQ(NO_ERROR, result);
-    ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
+    ASSERT_TRUE(doubleStr == String8{"asdfasdf"});
 }
 
 TEST_F(SafeInterfaceTest, TestCallMeBack) {
diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp
index 1f2779a..2ce13df 100644
--- a/libs/binder/tests/binderStabilityTest.cpp
+++ b/libs/binder/tests/binderStabilityTest.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android/binder_libbinder.h>
 #include <android/binder_manager.h>
 #include <android/binder_stability.h>
 #include <binder/Binder.h>
@@ -131,6 +132,55 @@
     EXPECT_TRUE(Stability::requiresVintfDeclaration(BadStableBinder::vintf()));
 }
 
+TEST(BinderStability, ForceDowngradeToLocalStability) {
+    sp<IBinder> someBinder = BadStableBinder::vintf();
+
+    EXPECT_TRUE(Stability::requiresVintfDeclaration(someBinder));
+
+    // silly to do this after already using the binder, but it's for the test
+    Stability::forceDowngradeToLocalStability(someBinder);
+
+    EXPECT_FALSE(Stability::requiresVintfDeclaration(someBinder));
+}
+
+TEST(BinderStability, NdkForceDowngradeToLocalStability) {
+    sp<IBinder> someBinder = BadStableBinder::vintf();
+
+    EXPECT_TRUE(Stability::requiresVintfDeclaration(someBinder));
+
+    // silly to do this after already using the binder, but it's for the test
+    AIBinder_forceDowngradeToLocalStability(AIBinder_fromPlatformBinder(someBinder));
+
+    EXPECT_FALSE(Stability::requiresVintfDeclaration(someBinder));
+}
+
+TEST(BinderStability, ForceDowngradeToVendorStability) {
+    sp<IBinder> serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer);
+    auto server = interface_cast<IBinderStabilityTest>(serverBinder);
+
+    ASSERT_NE(nullptr, server.get());
+    ASSERT_NE(nullptr, IInterface::asBinder(server)->remoteBinder());
+
+    {
+        sp<BadStableBinder> binder = BadStableBinder::vintf();
+
+        EXPECT_TRUE(Stability::requiresVintfDeclaration(binder));
+        EXPECT_TRUE(server->sendAndCallBinder(binder).isOk());
+        EXPECT_TRUE(binder->gotUserTransaction);
+    }
+    {
+        sp<BadStableBinder> binder = BadStableBinder::vintf();
+
+        // This method should never be called directly. This is done only for the test.
+        Stability::forceDowngradeToVendorStability(binder);
+
+        // Binder downgraded to vendor stability, cannot be called from system context
+        EXPECT_FALSE(Stability::requiresVintfDeclaration(binder));
+        EXPECT_EQ(BAD_TYPE, server->sendAndCallBinder(binder).exceptionCode());
+        EXPECT_FALSE(binder->gotUserTransaction);
+    }
+}
+
 TEST(BinderStability, VintfStabilityServerMustBeDeclaredInManifest) {
     sp<IBinder> vintfServer = BadStableBinder::vintf();
 
@@ -142,6 +192,8 @@
         EXPECT_EQ(Status::EX_ILLEGAL_ARGUMENT,
             android::defaultServiceManager()->addService(String16("."), vintfServer)) << instance8;
         EXPECT_FALSE(android::defaultServiceManager()->isDeclared(instance)) << instance8;
+        EXPECT_EQ(std::nullopt, android::defaultServiceManager()->updatableViaApex(instance))
+                << instance8;
     }
 }
 
diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp
index ce99f59..b37030e 100644
--- a/libs/binder/tests/binderTextOutputTest.cpp
+++ b/libs/binder/tests/binderTextOutputTest.cpp
@@ -26,7 +26,6 @@
 
 #include <binder/Parcel.h>
 #include <binder/TextOutput.h>
-#include <binder/Debug.h>
 
 static void CheckMessage(CapturedStderr& cap,
                          const char* expected,
diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
similarity index 82%
rename from libs/binder/parcel_fuzzer/Android.bp
rename to libs/binder/tests/parcel_fuzzer/Android.bp
index 3e6fe99..74b8eb8 100644
--- a/libs/binder/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_fuzz {
     name: "binder_parcel_fuzzer",
     defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.cpp
rename to libs/binder/tests/parcel_fuzzer/binder.cpp
diff --git a/libs/binder/parcel_fuzzer/binder.h b/libs/binder/tests/parcel_fuzzer/binder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.h
rename to libs/binder/tests/parcel_fuzzer/binder.h
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder_ndk.cpp
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.h b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
similarity index 97%
rename from libs/binder/parcel_fuzzer/binder_ndk.h
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.h
index e69d9c1..cf24ab9 100644
--- a/libs/binder/parcel_fuzzer/binder_ndk.h
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
@@ -23,7 +23,7 @@
 
 // libbinder_ndk doesn't export this header which breaks down its API for NDK
 // and APEX users, but we need access to it to fuzz.
-#include "../ndk/parcel_internal.h"
+#include "../../ndk/parcel_internal.h"
 
 class NdkParcelAdapter {
 public:
diff --git a/libs/binder/parcel_fuzzer/hwbinder.cpp b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.cpp
rename to libs/binder/tests/parcel_fuzzer/hwbinder.cpp
diff --git a/libs/binder/parcel_fuzzer/hwbinder.h b/libs/binder/tests/parcel_fuzzer/hwbinder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.h
rename to libs/binder/tests/parcel_fuzzer/hwbinder.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
similarity index 80%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
index b92a6a9..749bf21 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
@@ -20,5 +20,12 @@
 #include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
+/**
+ * Fill parcel data, including some random binder objects and FDs
+ */
 void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
+/**
+ * Fill parcel data, but don't fill any objects.
+ */
+void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider);
 } // namespace android
diff --git a/libs/binder/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
similarity index 89%
rename from libs/binder/parcel_fuzzer/main.cpp
rename to libs/binder/tests/parcel_fuzzer/main.cpp
index 78606cc..a47b753 100644
--- a/libs/binder/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -23,6 +23,7 @@
 #include <iostream>
 
 #include <android-base/logging.h>
+#include <binder/RpcSession.h>
 #include <fuzzbinder/random_parcel.h>
 #include <fuzzer/FuzzedDataProvider.h>
 
@@ -32,6 +33,8 @@
 #include <sys/time.h>
 
 using android::fillRandomParcel;
+using android::RpcSession;
+using android::sp;
 
 void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) {
     // TODO: functionality to create random parcels for libhwbinder parcels
@@ -56,7 +59,18 @@
             provider.ConsumeIntegralInRange<size_t>(0, maxInstructions));
 
     P p;
-    fillRandomParcel(&p, std::move(provider));
+    if constexpr (std::is_same_v<P, android::Parcel>) {
+        if (provider.ConsumeBool()) {
+            auto session = sp<RpcSession>::make();
+            CHECK(session->addNullDebuggingClient());
+            p.markForRpc(session);
+            fillRandomParcelData(&p, std::move(provider));
+        } else {
+            fillRandomParcel(&p, std::move(provider));
+        }
+    } else {
+        fillRandomParcel(&p, std::move(provider));
+    }
 
     // since we are only using a byte to index
     CHECK(reads.size() <= 255) << reads.size();
diff --git a/libs/binder/parcel_fuzzer/parcel_fuzzer.h b/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/parcel_fuzzer.h
rename to libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
diff --git a/libs/binder/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/random_fd.cpp
rename to libs/binder/tests/parcel_fuzzer/random_fd.cpp
diff --git a/libs/binder/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
similarity index 93%
rename from libs/binder/parcel_fuzzer/random_parcel.cpp
rename to libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 9ca4c8a..b045a22 100644
--- a/libs/binder/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -75,4 +75,9 @@
     }
 }
 
+void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) {
+    std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes());
+    CHECK(OK == p->write(data.data(), data.size()));
+}
+
 } // namespace android
diff --git a/libs/binder/parcel_fuzzer/util.cpp b/libs/binder/tests/parcel_fuzzer/util.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.cpp
rename to libs/binder/tests/parcel_fuzzer/util.cpp
diff --git a/libs/binder/parcel_fuzzer/util.h b/libs/binder/tests/parcel_fuzzer/util.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.h
rename to libs/binder/tests/parcel_fuzzer/util.h
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
similarity index 71%
rename from libs/binder/tests/fuzzers/Android.bp
rename to libs/binder/tests/unit_fuzzers/Android.bp
index c465bed..b1263e8 100644
--- a/libs/binder/tests/fuzzers/Android.bp
+++ b/libs/binder/tests/unit_fuzzers/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "binder_fuzz_defaults",
     host_supported: true,
@@ -69,3 +78,18 @@
     defaults: ["binder_fuzz_defaults"],
     srcs: ["TextOutputFuzz.cpp"],
 }
+
+cc_fuzz {
+    name: "binder_bufferedTextOutputFuzz",
+    include_dirs: [
+        "frameworks/native/libs/binder",
+    ],
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["BufferedTextOutputFuzz.cpp"],
+}
+
+cc_fuzz {
+    name: "binder_memoryDealerFuzz",
+    defaults: ["binder_fuzz_defaults"],
+    srcs: ["MemoryDealerFuzz.cpp"],
+}
diff --git a/libs/binder/tests/fuzzers/BinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
diff --git a/libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
new file mode 100644
index 0000000..09cb216
--- /dev/null
+++ b/libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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 <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <string>
+#include <vector>
+#include "BufferedTextOutput.h"
+
+namespace android {
+
+class FuzzBufferedTextOutput : public BufferedTextOutput {
+public:
+    FuzzBufferedTextOutput(uint32_t flags) : BufferedTextOutput(flags) {}
+    virtual status_t writeLines(const struct iovec& buf, size_t) {
+        size_t len = buf.iov_len;
+        void* tmp_buf = malloc(len);
+
+        if (tmp_buf == NULL) {
+            return status_t();
+        }
+
+        // This will attempt to read data from iov_base to ensure valid params were passed.
+        memcpy(tmp_buf, buf.iov_base, len);
+        free(tmp_buf);
+        return status_t();
+    }
+};
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+    uint32_t flags = fdp.ConsumeIntegral<uint32_t>();
+    size_t push_count = 0;
+    std::shared_ptr<BufferedTextOutput> bTextOutput(new FuzzBufferedTextOutput(flags));
+
+    while (fdp.remaining_bytes() > 0) {
+        fdp.PickValueInArray<std::function<void()>>({
+                [&]() -> void {
+                    bTextOutput->pushBundle();
+                    push_count++;
+                },
+                [&]() -> void {
+                    std::string txt = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+                    size_t len = fdp.ConsumeIntegralInRange<size_t>(0, txt.length());
+                    bTextOutput->print(txt.c_str(), len);
+                },
+                [&]() -> void {
+                    if (push_count == 0) return;
+
+                    bTextOutput->popBundle();
+                    push_count--;
+                },
+        })();
+    }
+
+    return 0;
+}
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/IBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
diff --git a/libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp b/libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
new file mode 100644
index 0000000..f9dda8c
--- /dev/null
+++ b/libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 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 <binder/MemoryDealer.h>
+#include <commonFuzzHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <string>
+#include <unordered_set>
+
+namespace android {
+
+static constexpr size_t kMaxBufferSize = 10000;
+static constexpr size_t kMaxDealerSize = 1024 * 512;
+static constexpr size_t kMaxAllocSize = 1024;
+
+// Fuzzer entry point.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (size > kMaxBufferSize) {
+        return 0;
+    }
+
+    FuzzedDataProvider fdp(data, size);
+    size_t dSize = fdp.ConsumeIntegralInRange<size_t>(0, kMaxDealerSize);
+    std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+    uint32_t flags = fdp.ConsumeIntegral<uint32_t>();
+    sp<MemoryDealer> dealer = new MemoryDealer(dSize, name.c_str(), flags);
+
+    // This is used to track offsets that have been freed already to avoid an expected fatal log.
+    std::unordered_set<size_t> free_list;
+
+    while (fdp.remaining_bytes() > 0) {
+        fdp.PickValueInArray<std::function<void()>>({
+                [&]() -> void { dealer->getAllocationAlignment(); },
+                [&]() -> void { dealer->getMemoryHeap(); },
+                [&]() -> void {
+                    size_t offset = fdp.ConsumeIntegral<size_t>();
+
+                    // Offset has already been freed, so return instead.
+                    if (free_list.find(offset) != free_list.end()) return;
+
+                    dealer->deallocate(offset);
+                    free_list.insert(offset);
+                },
+                [&]() -> void {
+                    std::string randString = fdp.ConsumeRandomLengthString(fdp.remaining_bytes());
+                    dealer->dump(randString.c_str());
+                },
+                [&]() -> void {
+                    size_t allocSize = fdp.ConsumeIntegralInRange<size_t>(0, kMaxAllocSize);
+                    sp<IMemory> allocated = dealer->allocate(allocSize);
+                    // If the allocation was successful, try to write to it
+                    if (allocated != nullptr && allocated->unsecurePointer() != nullptr) {
+                        memset(allocated->unsecurePointer(), 1, allocated->size());
+
+                        // Clear the address from freelist since it has been allocated over again.
+                        free_list.erase(allocated->offset());
+                    }
+                },
+        })();
+    }
+
+    return 0;
+}
+} // namespace android
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StabilityFuzz.cpp b/libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StatusFuzz.cpp b/libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StatusFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
similarity index 98%
rename from libs/binder/tests/fuzzers/TextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
index c950020..5e3502a 100644
--- a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp
+++ b/libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
@@ -16,7 +16,6 @@
 
 #include <fuzzer/FuzzedDataProvider.h>
 
-#include <binder/Debug.h>
 #include <binder/Parcel.h>
 #include <binder/TextOutput.h>
 #include "android-base/file.h"
diff --git a/libs/binder/tests/fuzzers/commonFuzzHelpers.h b/libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
similarity index 100%
rename from libs/binder/tests/fuzzers/commonFuzzHelpers.h
rename to libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
diff --git a/libs/binder/vm_sockets.h b/libs/binder/vm_sockets.h
new file mode 100644
index 0000000..7d9732b
--- /dev/null
+++ b/libs/binder/vm_sockets.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   Copied and modified from bionic/libc/kernel/uapi/linux/vm_sockets.h
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#pragma once
+
+#ifdef __BIONIC__
+#include <linux/vm_sockets.h>
+#else
+
+#ifndef _UAPI_VM_SOCKETS_H
+#define _UAPI_VM_SOCKETS_H
+#define SO_VM_SOCKETS_BUFFER_SIZE 0
+#define SO_VM_SOCKETS_BUFFER_MIN_SIZE 1
+#define SO_VM_SOCKETS_BUFFER_MAX_SIZE 2
+#define SO_VM_SOCKETS_PEER_HOST_VM_ID 3
+#define SO_VM_SOCKETS_TRUSTED 5
+#define SO_VM_SOCKETS_CONNECT_TIMEOUT 6
+#define SO_VM_SOCKETS_NONBLOCK_TXRX 7
+#define VMADDR_CID_ANY (-1U)
+#define VMADDR_PORT_ANY (-1U)
+#define VMADDR_CID_HYPERVISOR 0
+#define VMADDR_CID_LOCAL 1
+#define VMADDR_CID_HOST 2
+#define VM_SOCKETS_INVALID_VERSION (-1U)
+#define VM_SOCKETS_VERSION_EPOCH(_v) (((_v)&0xFF000000) >> 24)
+#define VM_SOCKETS_VERSION_MAJOR(_v) (((_v)&0x00FF0000) >> 16)
+#define VM_SOCKETS_VERSION_MINOR(_v) (((_v)&0x0000FFFF))
+struct sockaddr_vm {
+    sa_family_t svm_family;
+    // NOLINTNEXTLINE(google-runtime-int)
+    unsigned short svm_reserved1;
+    unsigned int svm_port;
+    unsigned int svm_cid;
+    // NOLINTNEXTLINE(google-runtime-int)
+    unsigned char svm_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - sizeof(unsigned short) -
+                           sizeof(unsigned int) - sizeof(unsigned int)];
+};
+#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
+#ifndef AF_VSOCK
+#define AF_VSOCK 40
+#endif
+#endif
+
+#endif
diff --git a/libs/binderdebug/Android.bp b/libs/binderdebug/Android.bp
index 343246a..3eeaf3e 100644
--- a/libs/binderdebug/Android.bp
+++ b/libs/binderdebug/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libbinderdebug",
     vendor_available: true,
diff --git a/libs/binderdebug/tests/Android.bp b/libs/binderdebug/tests/Android.bp
index 4c06b1d..d141a05 100644
--- a/libs/binderdebug/tests/Android.bp
+++ b/libs/binderdebug/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "libbinderdebug_test",
     test_suites: ["general-tests"],
diff --git a/libs/binderthreadstate/1.0/Android.bp b/libs/binderthreadstate/1.0/Android.bp
index ebdc932..99477d8 100644
--- a/libs/binderthreadstate/1.0/Android.bp
+++ b/libs/binderthreadstate/1.0/Android.bp
@@ -1,5 +1,14 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 hidl_interface {
     name: "binderthreadstateutilstest@1.0",
     root: "binderthreadstateutilstest",
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index 08c62df..0a82463 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -14,6 +14,15 @@
 
 // DO NOT ADD NEW USAGES OF THIS
 // See comments in header file.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libbinderthreadstateutils",
     double_loadable: true,
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index bab2674..c5d3a32 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libbufferqueueconverter_headers",
     vendor_available: true,
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index e3cd085..570af71 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libtimeinstate",
     srcs: ["cputimeinstate.cpp"],
@@ -35,4 +44,3 @@
     ],
     require_root: true,
 }
-
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 4209dc5..7e9bb7d 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -56,6 +56,7 @@
 static std::vector<std::vector<uint32_t>> gPolicyFreqs;
 static std::vector<std::vector<uint32_t>> gPolicyCpus;
 static std::set<uint32_t> gAllFreqs;
+static unique_fd gTisTotalMapFd;
 static unique_fd gTisMapFd;
 static unique_fd gConcurrentMapFd;
 static unique_fd gUidLastUpdateMapFd;
@@ -98,7 +99,7 @@
     struct dirent **dirlist;
     const char basepath[] = "/sys/devices/system/cpu/cpufreq";
     int ret = scandir(basepath, &dirlist, isPolicyFile, comparePolicyFiles);
-    if (ret == -1) return false;
+    if (ret == -1 || ret == 0) return false;
     gNPolicies = ret;
 
     std::vector<std::string> policyFileNames;
@@ -129,6 +130,10 @@
         gPolicyCpus.emplace_back(*cpus);
     }
 
+    gTisTotalMapFd =
+            unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_total_time_in_state_map")};
+    if (gTisTotalMapFd < 0) return false;
+
     gTisMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_time_in_state_map")};
     if (gTisMapFd < 0) return false;
 
@@ -150,10 +155,14 @@
     return true;
 }
 
-static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
     std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
                                     eventType.c_str(), eventName.c_str());
-    int prog_fd = retrieveProgram(path.c_str());
+    return retrieveProgram(path.c_str());
+}
+
+static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+    int prog_fd = retrieveProgramFd(eventType, eventName);
     if (prog_fd < 0) return false;
     return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
 }
@@ -169,6 +178,17 @@
     return {};
 }
 
+// Check if tracking is expected to work without activating it.
+bool isTrackingUidTimesSupported() {
+    auto freqs = getCpuFreqs();
+    if (!freqs || freqs->empty()) return false;
+    if (gTracking) return true;
+    if (retrieveProgramFd("sched", "sched_switch") < 0) return false;
+    if (retrieveProgramFd("power", "cpu_frequency") < 0) return false;
+    if (retrieveProgramFd("sched", "sched_process_free") < 0) return false;
+    return true;
+}
+
 // Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
 // Returns true on success, false otherwise.
 // Tracking is active only once a live process has successfully called this function; if the calling
@@ -239,6 +259,31 @@
     return gPolicyFreqs;
 }
 
+std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes() {
+    if (!gInitialized && !initGlobals()) return {};
+
+    std::vector<std::vector<uint64_t>> out;
+    uint32_t maxFreqCount = 0;
+    for (const auto &freqList : gPolicyFreqs) {
+        if (freqList.size() > maxFreqCount) maxFreqCount = freqList.size();
+        out.emplace_back(freqList.size(), 0);
+    }
+
+    std::vector<uint64_t> vals(gNCpus);
+    const uint32_t freqCount = maxFreqCount <= MAX_FREQS_FOR_TOTAL ? maxFreqCount :
+            MAX_FREQS_FOR_TOTAL;
+    for (uint32_t freqIdx = 0; freqIdx < freqCount; ++freqIdx) {
+        if (findMapEntry(gTisTotalMapFd, &freqIdx, vals.data())) return {};
+        for (uint32_t policyIdx = 0; policyIdx < gNPolicies; ++policyIdx) {
+            if (freqIdx >= gPolicyFreqs[policyIdx].size()) continue;
+            for (const auto &cpu : gPolicyCpus[policyIdx]) {
+                out[policyIdx][freqIdx] += vals[cpu];
+            }
+        }
+    }
+
+    return out;
+}
 // Retrieve the times in ns that uid spent running at each CPU frequency.
 // Return contains no value on error, otherwise it contains a vector of vectors using the format:
 // [[t0_0, t0_1, ...],
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 87a328a..4145374 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -22,7 +22,9 @@
 namespace android {
 namespace bpf {
 
+bool isTrackingUidTimesSupported();
 bool startTrackingUidTimes();
+std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
 std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
 std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>>
     getUidsCpuFreqTimes();
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 519689b..2112b10 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,17 @@
 
 using std::vector;
 
+TEST(TimeInStateTest, IsTrackingSupported) {
+    isTrackingUidTimesSupported();
+    SUCCEED();
+}
+
+TEST(TimeInStateTest, TotalTimeInState) {
+    auto times = getTotalCpuFreqTimes();
+    ASSERT_TRUE(times.has_value());
+    EXPECT_FALSE(times->empty());
+}
+
 TEST(TimeInStateTest, SingleUidTimeInState) {
     auto times = getUidCpuFreqTimes(0);
     ASSERT_TRUE(times.has_value());
@@ -186,6 +197,31 @@
     }
 }
 
+TEST(TimeInStateTest, TotalAndAllUidTimeInStateConsistent) {
+    auto allUid = getUidsCpuFreqTimes();
+    auto total = getTotalCpuFreqTimes();
+
+    ASSERT_TRUE(allUid.has_value() && total.has_value());
+
+    // Check the number of policies.
+    ASSERT_EQ(allUid->at(0).size(), total->size());
+
+    for (uint32_t policyIdx = 0; policyIdx < total->size(); ++policyIdx) {
+        std::vector<uint64_t> totalTimes = total->at(policyIdx);
+        uint32_t totalFreqsCount = totalTimes.size();
+        std::vector<uint64_t> allUidTimes(totalFreqsCount, 0);
+        for (auto const &[uid, uidTimes]: *allUid) {
+            for (uint32_t freqIdx = 0; freqIdx < uidTimes[policyIdx].size(); ++freqIdx) {
+                allUidTimes[std::min(freqIdx, totalFreqsCount - 1)] += uidTimes[policyIdx][freqIdx];
+            }
+        }
+
+        for (uint32_t freqIdx = 0; freqIdx < totalFreqsCount; ++freqIdx) {
+            ASSERT_LE(allUidTimes[freqIdx], totalTimes[freqIdx]);
+        }
+    }
+}
+
 TEST(TimeInStateTest, SingleAndAllUidTimeInStateConsistent) {
     uint64_t zero = 0;
     auto maps = {getUidsCpuFreqTimes(), getUidsUpdatedCpuFreqTimes(&zero)};
@@ -292,6 +328,22 @@
     ASSERT_LE(after - before, NSEC_PER_SEC * 2 * get_nprocs_conf());
 }
 
+TEST(TimeInStateTest, TotalTimeInStateMonotonic) {
+    auto before = getTotalCpuFreqTimes();
+    ASSERT_TRUE(before.has_value());
+    sleep(1);
+    auto after = getTotalCpuFreqTimes();
+    ASSERT_TRUE(after.has_value());
+
+    for (uint32_t policyIdx = 0; policyIdx < after->size(); ++policyIdx) {
+        auto timesBefore = before->at(policyIdx);
+        auto timesAfter = after->at(policyIdx);
+        for (uint32_t freqIdx = 0; freqIdx < timesAfter.size(); ++freqIdx) {
+            ASSERT_NO_FATAL_FAILURE(TestCheckDelta(timesBefore[freqIdx], timesAfter[freqIdx]));
+        }
+    }
+}
+
 TEST(TimeInStateTest, AllUidTimeInStateMonotonic) {
     auto map1 = getUidsCpuFreqTimes();
     ASSERT_TRUE(map1.has_value());
diff --git a/libs/diskusage/Android.bp b/libs/diskusage/Android.bp
index a826306..8684061 100644
--- a/libs/diskusage/Android.bp
+++ b/libs/diskusage/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libdiskusage",
     srcs: ["dirsize.c"],
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index e403d36..acda402 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libdumputils",
 
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 3faf792..b52ec39 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -46,13 +46,13 @@
 
 // Native processes to dump on debuggable builds.
 static const char* debuggable_native_processes_to_dump[] = {
+        "/system/bin/keystore2",
         "/system/bin/vold",
         NULL,
 };
 
 /* list of hal interface to dump containing process during native dumps */
 static const char* hal_interfaces_to_dump[] {
-        "android.hardware.audio@2.0::IDevicesFactory",
         "android.hardware.audio@4.0::IDevicesFactory",
         "android.hardware.audio@5.0::IDevicesFactory",
         "android.hardware.audio@6.0::IDevicesFactory",
diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp
index 76518c1..47c0657 100644
--- a/libs/fakeservicemanager/Android.bp
+++ b/libs/fakeservicemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "fakeservicemanager_defaults",
     host_supported: true,
diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp
index 4ecbe53..761e45c 100644
--- a/libs/fakeservicemanager/ServiceManager.cpp
+++ b/libs/fakeservicemanager/ServiceManager.cpp
@@ -73,4 +73,9 @@
     return out;
 }
 
+std::optional<String16> ServiceManager::updatableViaApex(const String16& name) {
+    (void)name;
+    return std::nullopt;
+}
+
 }  // namespace android
diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h
index 4ef47fb..e26c21b 100644
--- a/libs/fakeservicemanager/ServiceManager.h
+++ b/libs/fakeservicemanager/ServiceManager.h
@@ -19,6 +19,7 @@
 #include <binder/IServiceManager.h>
 
 #include <map>
+#include <optional>
 
 namespace android {
 
@@ -48,6 +49,8 @@
 
     Vector<String16> getDeclaredInstances(const String16& iface) override;
 
+    std::optional<String16> updatableViaApex(const String16& name) override;
+
 private:
     std::map<String16, sp<IBinder>> mNameToService;
 };
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 243d7f1..a0032ae 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libgralloctypes",
     defaults: ["libbinder_ndk_host_user"],
@@ -43,14 +52,14 @@
     ],
 
     shared_libs: [
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.mapper@4.0",
         "libhidlbase",
         "liblog",
     ],
 
     export_shared_lib_headers: [
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.mapper@4.0",
         "libhidlbase",
     ],
diff --git a/libs/gralloc/types/fuzzer/Android.bp b/libs/gralloc/types/fuzzer/Android.bp
index 8933dc3..6689771 100644
--- a/libs/gralloc/types/fuzzer/Android.bp
+++ b/libs/gralloc/types/fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_fuzz {
     name: "libgralloctypes_fuzzer",
     defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/gralloc/types/tests/Android.bp b/libs/gralloc/types/tests/Android.bp
index b939c1d..66eb0aa 100644
--- a/libs/gralloc/types/tests/Android.bp
+++ b/libs/gralloc/types/tests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "GrallocTypes_test",
     shared_libs: [
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index 642c5f2..a96a07a 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libgraphicsenv",
 
diff --git a/libs/graphicsenv/OWNERS b/libs/graphicsenv/OWNERS
index c0bb75f..8c28464 100644
--- a/libs/graphicsenv/OWNERS
+++ b/libs/graphicsenv/OWNERS
@@ -1,6 +1,4 @@
 chrisforbes@google.com
 cnorthrop@google.com
-courtneygo@google.com
 lpy@google.com
 timvp@google.com
-zzyiwei@google.com
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 4a4510e..8398794 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -11,6 +11,15 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libgui_headers",
     vendor_available: true,
@@ -32,9 +41,10 @@
 
 cc_library_shared {
     name: "libgui",
-    vendor_available: false,
+    vendor_available: true,
     vndk: {
         enabled: true,
+        private: true,
     },
     double_loadable: true,
 
@@ -122,7 +132,16 @@
 
     aidl: {
         export_aidl_headers: true,
-    }
+    },
+
+    pgo: {
+        sampling: true,
+        profile_file: "libgui/libgui.profdata",
+    },
+
+    lto: {
+        thin: true,
+    },
 }
 
 // Used by media codec services exclusively as a static lib for
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index 1667fb0..45c958e 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -1,5 +1,4 @@
 adyabr@google.com
-akrulec@google.com
 alecmouri@google.com
 chaviw@google.com
 chrisforbes@google.com
@@ -7,7 +6,6 @@
 lpy@google.com
 mathias@google.com
 racarr@google.com
-stoza@google.com
 vishnun@google.com
 
 per-file EndToEndNativeInputTest.cpp = svv@google.com
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
index 64b1eac..bddb0ac 100644
--- a/libs/gui/sysprop/Android.bp
+++ b/libs/gui/sysprop/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sysprop_library {
     name: "LibGuiProperties",
     srcs: ["*.sysprop"],
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index a6bcd10..6077b4e 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -2,6 +2,15 @@
 
 // Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
 // to integrate with auto-test framework.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "libgui_test",
     test_suites: ["device-tests"],
diff --git a/libs/incidentcompanion/Android.bp b/libs/incidentcompanion/Android.bp
index 63411b9..ef7f523 100644
--- a/libs/incidentcompanion/Android.bp
+++ b/libs/incidentcompanion/Android.bp
@@ -14,6 +14,15 @@
  * limitations under the License.
  */
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 filegroup {
     name: "incidentcompanion_aidl",
     srcs: [
@@ -49,4 +58,3 @@
         "-Wunused-parameter",
     ],
 }
-
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 6a5d434..393c0f6 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -14,6 +14,15 @@
 
 // libinput is partially built for the host (used by build time keymap validation tool)
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libinput",
     host_supported: true,
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 3b57146..cacce92 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -1,4 +1,13 @@
 // Build the unit tests.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "libinput_tests",
     srcs: [
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 3b1edcb..5595587 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_native_libs_math_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_math_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_static {
     name: "libmath",
     host_supported: true,
diff --git a/libs/math/OWNERS b/libs/math/OWNERS
index 6fb149a..72d33bc 100644
--- a/libs/math/OWNERS
+++ b/libs/math/OWNERS
@@ -1,6 +1,3 @@
-jaesoo@google.com
-jiyong@google.com
 mathias@google.com
-pawin@google.com
 randolphs@google.com
 romainguy@google.com
diff --git a/libs/math/tests/Android.bp b/libs/math/tests/Android.bp
index 0184f56..4a7c4dd 100644
--- a/libs/math/tests/Android.bp
+++ b/libs/math/tests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_libs_math_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_libs_math_license"],
+}
+
 cc_test {
     name: "vec_test",
     srcs: ["vec_test.cpp"],
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
index 8399e8c..1a4729c 100644
--- a/libs/nativebase/Android.bp
+++ b/libs/nativebase/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_native_libs_nativebase_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_nativebase_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_headers {
     name: "libnativebase_headers",
     vendor_available: true,
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index b431cbb..62a4d7f 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -21,7 +21,7 @@
 #include <gui/DisplayEventDispatcher.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
 #include <private/android/choreographer.h>
 #include <utils/Looper.h>
 #include <utils/Timers.h>
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index f56b3a2..6e9c999 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_native_libs_nativedisplay_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_nativedisplay_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_headers {
     name: "libnativedisplay_headers",
     export_include_dirs: ["include",],
@@ -53,15 +72,12 @@
         "libcutils",
         "libEGL",
         "libGLESv2",
-        "libnativehelper",
-    ],
-
-    export_shared_lib_headers: [
-        "libnativehelper",
     ],
 
     header_libs: [
         "libnativedisplay_headers",
+        "libnativehelper_header_only",
     ],
 
+    export_header_lib_headers: ["libnativehelper_header_only"],
 }
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index 2164930..c00ce4e 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -18,7 +18,7 @@
 
 #include <apex/choreographer.h>
 #include <inttypes.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
 
 namespace android {
 
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index f371667..85fe42f 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
 #include <system/graphics.h>
 
 // This file provides a facade API on top of SurfaceTexture, which avoids using
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index ebe4484..c214ab7 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -29,8 +29,7 @@
 #include <mutex>
 
 #include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_local_ref.h>
 
 struct ASurfaceTexture {
     android::sp<android::SurfaceTexture> consumer;
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 1ec73ce..3030068 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -51,13 +51,13 @@
             std::string("AHardwareBuffer pid [") + std::to_string(getpid()) + "]"));
 
     status_t err = gbuffer->initCheck();
-    if (err != 0 || gbuffer->handle == 0) {
+    if (err != 0 || gbuffer->handle == nullptr) {
         if (err == NO_MEMORY) {
             GraphicBuffer::dumpAllocationsToSystemLog();
         }
         ALOGE("GraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
                 desc->width, desc->height, desc->layers, strerror(-err), gbuffer->handle);
-        return err;
+        return err == 0 ? UNKNOWN_ERROR : err;
     }
 
     *outBuffer = AHardwareBuffer_from_GraphicBuffer(gbuffer.get());
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 07e5d86..9286009 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -12,6 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: [
+        "frameworks_native_libs_nativewindow_license",
+    ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_nativewindow_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 ndk_headers {
     name: "libnativewindow_ndk_headers",
     from: "include/android",
@@ -28,6 +47,7 @@
     // TODO(b/153609531): remove when no longer needed.
     native_bridge_supported: true,
     min_sdk_version: "29",
+    host_supported: true,
 }
 
 ndk_library {
@@ -40,7 +60,13 @@
 
 cc_library {
     name: "libnativewindow",
-    llndk_stubs: "libnativewindow.llndk",
+    llndk: {
+        symbol_file: "libnativewindow.map.txt",
+        unversioned: true,
+        override_export_include_dirs: [
+            "include"
+        ],
+    },
     export_include_dirs: [
         "include",
         "include-private",
@@ -95,11 +121,4 @@
     },
 }
 
-llndk_library {
-    name: "libnativewindow.llndk",
-    symbol_file: "libnativewindow.map.txt",
-    unversioned: true,
-    export_include_dirs: ["include"],
-}
-
 subdirs = ["tests"]
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ae5e47b..dcb05b5 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -332,8 +332,6 @@
  */
 typedef struct AHardwareBuffer AHardwareBuffer;
 
-#if __ANDROID_API__ >= 26
-
 /**
  * Allocates a buffer that matches the passed AHardwareBuffer_Desc.
  *
@@ -501,10 +499,6 @@
  */
 int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
 
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 29
-
 /**
  * Test whether the given format and usage flag combination is
  * allocatable.
@@ -540,7 +534,6 @@
 int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
         int32_t fence, const ARect* rect, void** outVirtualAddress,
         int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
 
 __END_DECLS
 
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 36aad2e..a3a45e3 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -185,8 +185,6 @@
  */
 int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
 
-#if __ANDROID_API__ >= 26
-
 /**
  * Set a transform that will be applied to future buffers posted to the window.
  *
@@ -197,10 +195,6 @@
  */
 int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26);
 
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 28
-
 /**
  * All buffers queued after this call will be associated with the dataSpace
  * parameter specified.
@@ -229,10 +223,6 @@
  */
 int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
 
-#endif // __ANDROID_API__ >= 28
-
-#if __ANDROID_API__ >= 30
-
 /** Compatibility value for ANativeWindow_setFrameRate. */
 enum ANativeWindow_FrameRateCompatibility {
     /**
@@ -301,8 +291,6 @@
  */
 void ANativeWindow_tryAllocateBuffers(ANativeWindow* window);
 
-#endif // __ANDROID_API__ >= 30
-
 #ifdef __cplusplus
 };
 #endif
diff --git a/libs/nativewindow/tests/Android.bp b/libs/nativewindow/tests/Android.bp
index cdb3d20..2744458 100644
--- a/libs/nativewindow/tests/Android.bp
+++ b/libs/nativewindow/tests/Android.bp
@@ -14,6 +14,17 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_libs_nativewindow_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_native_libs_nativewindow_license",
+    ],
+}
+
 cc_test {
     name: "libnativewindow_test",
     test_suites: [
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
new file mode 100644
index 0000000..a5712b3
--- /dev/null
+++ b/libs/permission/Android.bp
@@ -0,0 +1,23 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_library_shared {
+    name: "libpermission",
+    srcs: [
+        "AppOpsManager.cpp",
+        "IAppOpsCallback.cpp",
+        "IAppOpsService.cpp",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/libs/binder/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp
similarity index 98%
rename from libs/binder/AppOpsManager.cpp
rename to libs/permission/AppOpsManager.cpp
index 1c6b491..f3ea1a7 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/permission/AppOpsManager.cpp
@@ -36,7 +36,7 @@
 
     pthread_mutex_lock(&gClientIdMutex);
     if (gClientId == nullptr) {
-        gClientId = new BBinder();
+        gClientId = sp<BBinder>::make();
     }
     pthread_mutex_unlock(&gClientIdMutex);
     return gClientId;
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/permission/IAppOpsCallback.cpp
similarity index 100%
rename from libs/binder/IAppOpsCallback.cpp
rename to libs/permission/IAppOpsCallback.cpp
diff --git a/libs/binder/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
similarity index 100%
rename from libs/binder/IAppOpsService.cpp
rename to libs/permission/IAppOpsService.cpp
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
similarity index 100%
rename from libs/binder/include/binder/AppOpsManager.h
rename to libs/permission/include/binder/AppOpsManager.h
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/permission/include/binder/IAppOpsCallback.h
similarity index 100%
rename from libs/binder/include/binder/IAppOpsCallback.h
rename to libs/permission/include/binder/IAppOpsCallback.h
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
similarity index 100%
rename from libs/binder/include/binder/IAppOpsService.h
rename to libs/permission/include/binder/IAppOpsService.h
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index eb6080f..aae1e31 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "renderengine_defaults",
     cflags: [
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
index b44456b..c478506 100644
--- a/libs/renderengine/OWNERS
+++ b/libs/renderengine/OWNERS
@@ -1,4 +1,5 @@
 alecmouri@google.com
+djsollen@google.com
 jreck@google.com
 lpy@google.com
-stoza@google.com
+scroggo@google.com
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index e98babc..fdb3a6f 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "librenderengine_test",
     defaults: ["surfaceflinger_defaults"],
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index e8154a6..edd453a 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libsensor",
 
@@ -39,11 +48,10 @@
         "libutils",
         "liblog",
         "libhardware",
+        "libpermission",
     ],
 
     export_include_dirs: ["include"],
 
-    export_shared_lib_headers: ["libbinder", "libhardware"],
+    export_shared_lib_headers: ["libbinder", "libpermission", "libhardware"],
 }
-
-subdirs = ["tests"]
diff --git a/libs/sensor/tests/Android.bp b/libs/sensor/tests/Android.bp
index c9a7668..8fdb003 100644
--- a/libs/sensor/tests/Android.bp
+++ b/libs/sensor/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "libsensor_test",
 
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index 4a606ff..00514c4 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libsensorprivacy",
 
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 47eb59f..07760ab 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_libs_ui_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_shared {
     name: "libui",
     vendor_available: true,
@@ -72,7 +89,7 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.allocator@3.0",
         "android.hardware.graphics.allocator@4.0",
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
@@ -89,7 +106,7 @@
 
     export_shared_lib_headers: [
         "android.hardware.graphics.common@1.2",
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.mapper@4.0",
         "libgralloctypes",
     ],
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
index b1317b1..a0b5fe7 100644
--- a/libs/ui/OWNERS
+++ b/libs/ui/OWNERS
@@ -1,7 +1,7 @@
+adyabr@google.com
 alecmouri@google.com
 chrisforbes@google.com
 jreck@google.com
 lpy@google.com
 mathias@google.com
 romainguy@google.com
-stoza@google.com
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b53342c..bc53346 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_libs_ui_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
 cc_test {
     name: "Region_test",
     shared_libs: ["libui"],
diff --git a/libs/ui/tools/Android.bp b/libs/ui/tools/Android.bp
index fb46c2b..c28c303 100644
--- a/libs/ui/tools/Android.bp
+++ b/libs/ui/tools/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_libs_ui_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
 cc_defaults {
     name: "libui_tools_default",
     clang_cflags: [
diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp
index 33ab8ba..11b09bd 100644
--- a/libs/vibrator/Android.bp
+++ b/libs/vibrator/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libvibrator",
 
diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp
index 8020151..f2a313c 100644
--- a/libs/vibrator/fuzzer/Android.bp
+++ b/libs/vibrator/fuzzer/Android.bp
@@ -17,6 +17,15 @@
  *****************************************************************************
  */
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_fuzz {
     name: "vibrator_fuzzer",
 
diff --git a/libs/vr/Android.bp b/libs/vr/Android.bp
index e8176cf..b308895 100644
--- a/libs/vr/Android.bp
+++ b/libs/vr/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    //   legacy_notice
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 subdirs = [
     "*",
 ]
diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp
index 13af470..2eb2f9f 100644
--- a/libs/vr/libbroadcastring/Android.bp
+++ b/libs/vr/libbroadcastring/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libbroadcastring",
     clang: true,
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 37c19d4..45bdd35 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libbufferhub_headers",
     export_include_dirs: ["include"],
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 77c7911..f372bd7 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sourceFiles = [
     "buffer_hub_queue_client.cpp",
     "buffer_hub_queue_parcelable.cpp",
diff --git a/libs/vr/libbufferhubqueue/benchmarks/Android.bp b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
index ef1eed6..fc1f376 100644
--- a/libs/vr/libbufferhubqueue/benchmarks/Android.bp
+++ b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
@@ -1,4 +1,15 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_benchmark {
     srcs: ["buffer_transport_benchmark.cpp"],
     shared_libs: [
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index a337921..e883916 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -1,4 +1,15 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 header_libraries = [
     "libdvr_headers",
 ]
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 8c354fb..365a676 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sourceFiles = [
     "display_client.cpp",
     "display_manager_client.cpp",
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index d5a19d3..83c30d7 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -13,6 +13,17 @@
 // limitations under the License.
 
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libdvr_headers",
     export_include_dirs: ["include"],
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index 3260447..4ed80a4 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     srcs: [
         "dvr_display_manager-test.cpp",
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index e751768..9e1e516 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 localIncludeFiles = [
     "include",
 ]
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 24ba830..c1f6da3 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libpdx_headers",
     export_include_dirs: ["private"],
diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp
index b36e0de..cc32b18 100644
--- a/libs/vr/libpdx/fuzz/Android.bp
+++ b/libs/vr/libpdx/fuzz/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_fuzz {
     name: "libpdx_service_dispatcher_fuzzer",
     clang: true,
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index b3534de..ea73d7a 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "pdx_default_transport_compiler_defaults",
     clang: true,
@@ -75,4 +86,3 @@
         "libpdx_default_transport",
     ],
 }
-
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index 1d6eea2..532d1a7 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libpdx_uds",
     clang: true,
diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp
index 35d3dea..5beee35 100644
--- a/libs/vr/libperformance/Android.bp
+++ b/libs/vr/libperformance/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sourceFiles = [
     "performance_client.cpp",
     "performance_rpc.cpp",
diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp
index 2cd6a28..6f2ada4 100644
--- a/libs/vr/libvr_manager/Android.bp
+++ b/libs/vr/libvr_manager/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libvr_manager",
     srcs: [
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index abc64bd..8aca9a5 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sourceFiles = [
     "acquired_buffer.cpp",
     "epoll_event_dispatcher.cpp",
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
index 7fafd3b..dafd354 100644
--- a/libs/vr/libvrflinger/tests/Android.bp
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 shared_libs = [
     "android.hardware.configstore-utils",
     "android.hardware.configstore@1.0",
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index 8542790..8f566a0 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sourceFiles = [
     "pose_client.cpp",
     "latency_model.cpp",
@@ -52,4 +63,3 @@
     header_libs: ["libdvr_headers"],
     name: "libvrsensor",
 }
-
diff --git a/opengl/Android.bp b/opengl/Android.bp
index 48abdce..16ce15b 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -12,6 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    //   SPDX-license-identifier-MIT
+    //   legacy_notice
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 ndk_headers {
     name: "libEGL_headers",
     from: "include",
@@ -56,11 +68,9 @@
     name: "gl_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
-}
-
-llndk_headers {
-    name: "gl_llndk_headers",
-    export_include_dirs: ["include"],
+    llndk: {
+        llndk_headers: true,
+    },
 }
 
 subdirs = [
diff --git a/opengl/OWNERS b/opengl/OWNERS
index b505712..a9bd4bb 100644
--- a/opengl/OWNERS
+++ b/opengl/OWNERS
@@ -1,7 +1,6 @@
 chrisforbes@google.com
 cnorthrop@google.com
-courtneygo@google.com
 ianelliott@google.com
 jessehall@google.com
 lpy@google.com
-zzyiwei@google.com
+timvp@google.com
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index ed2ed83..daaaf88 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -1,4 +1,13 @@
 // Build the ETC1 library
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library {
     name: "libETC1",
     srcs: ["ETC1/etc1.cpp"],
@@ -133,7 +142,12 @@
 cc_library_shared {
     name: "libEGL",
     defaults: ["egl_libs_defaults"],
-    llndk_stubs: "libEGL.llndk",
+    llndk: {
+        symbol_file: "libEGL.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: [
         "EGL/egl_tls.cpp",
         "EGL/egl_cache.cpp",
@@ -199,7 +213,12 @@
 cc_library_shared {
     name: "libGLESv1_CM",
     defaults: ["gles_libs_defaults"],
-    llndk_stubs: "libGLESv1_CM.llndk",
+    llndk: {
+        symbol_file: "libGLESv1_CM.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: ["GLES_CM/gl.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv1\""],
     version_script: "libGLESv1_CM.map.txt",
@@ -211,7 +230,12 @@
 cc_library_shared {
     name: "libGLESv2",
     defaults: ["gles_libs_defaults"],
-    llndk_stubs: "libGLESv2.llndk",
+    llndk: {
+        symbol_file: "libGLESv2.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: ["GLES2/gl2.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv2\""],
 
@@ -226,31 +250,12 @@
 cc_library_shared {
     name: "libGLESv3",
     defaults: ["gles_libs_defaults"],
-    llndk_stubs: "libGLESv3.llndk",
+    llndk: {
+        symbol_file: "libGLESv3.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: ["GLES2/gl2.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv3\""],
 }
-
-llndk_library {
-    name: "libEGL.llndk",
-    symbol_file: "libEGL.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
-    name: "libGLESv1_CM.llndk",
-    symbol_file: "libGLESv1_CM.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
-    name: "libGLESv2.llndk",
-    symbol_file: "libGLESv2.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
-    name: "libGLESv3.llndk",
-    symbol_file: "libGLESv3.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index f82c2a4..4f85eff 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -24,16 +24,16 @@
 #include <EGL/Platform.h>
 #pragma GCC diagnostic pop
 
+#include <android-base/properties.h>
 #include <android/dlext.h>
 #include <dlfcn.h>
 #include <graphicsenv/GraphicsEnv.h>
-#include <time.h>
 #include <log/log.h>
+#include <time.h>
 #include <vndksupport/linker.h>
 
 namespace angle {
 
-constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so";
 constexpr int kAngleDlFlags = RTLD_LOCAL | RTLD_NOW;
 
 static GetDisplayPlatformFunc angleGetDisplayPlatform = nullptr;
@@ -107,18 +107,36 @@
     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
     void* so = nullptr;
     if (ns) {
+        // Loading from an APK, so hard-code the suffix to "_angle".
+        constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so";
         const android_dlextinfo dlextinfo = {
                 .flags = ANDROID_DLEXT_USE_NAMESPACE,
                 .library_namespace = ns,
         };
         so = android_dlopen_ext(kAngleEs2Lib, kAngleDlFlags, &dlextinfo);
+        if (so) {
+            ALOGD("dlopen_ext from APK (%s) success at %p", kAngleEs2Lib, so);
+        } else {
+            ALOGE("dlopen_ext(\"%s\") failed: %s", kAngleEs2Lib, dlerror());
+            return false;
+        }
     } else {
         // If we are here, ANGLE is loaded as built-in gl driver in the sphal.
-        so = android_load_sphal_library(kAngleEs2Lib, kAngleDlFlags);
-    }
-    if (!so) {
-        ALOGE("%s failed to dlopen %s!", __FUNCTION__, kAngleEs2Lib);
-        return false;
+        // Get the specified ANGLE library filename suffix.
+        std::string angleEs2LibSuffix = android::base::GetProperty("ro.hardware.egl", "");
+        if (angleEs2LibSuffix.empty()) {
+            ALOGE("%s failed to get valid ANGLE library filename suffix!", __FUNCTION__);
+            return false;
+        }
+
+        std::string angleEs2LibName = "libGLESv2_" + angleEs2LibSuffix + ".so";
+        so = android_load_sphal_library(angleEs2LibName.c_str(), kAngleDlFlags);
+        if (so) {
+            ALOGD("dlopen (%s) success at %p", angleEs2LibName.c_str(), so);
+        } else {
+            ALOGE("%s failed to dlopen %s!", __FUNCTION__, angleEs2LibName.c_str());
+            return false;
+        }
     }
 
     angleGetDisplayPlatform =
@@ -130,8 +148,7 @@
     }
 
     angleResetDisplayPlatform =
-            reinterpret_cast<ResetDisplayPlatformFunc>(
-                    eglGetProcAddress("ANGLEResetDisplayPlatform"));
+            reinterpret_cast<ResetDisplayPlatformFunc>(dlsym(so, "ANGLEResetDisplayPlatform"));
 
     PlatformMethods* platformMethods = nullptr;
     if (!((angleGetDisplayPlatform)(dpy, g_PlatformMethodNames,
diff --git a/opengl/tests/Android.bp b/opengl/tests/Android.bp
index 639f351..da717bd 100644
--- a/opengl/tests/Android.bp
+++ b/opengl/tests/Android.bp
@@ -1,4 +1,16 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-BSD
+    //   SPDX-license-identifier-MIT
+    //   legacy_notice
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 subdirs = [
     "angeles",
     "configdump",
@@ -16,4 +28,3 @@
     "hwc",
     "lib",
 ]
-
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index e3912a8..51c9376 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -1,4 +1,13 @@
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
 
     name: "EGL_test",
diff --git a/opengl/tests/angeles/Android.bp b/opengl/tests/angeles/Android.bp
index 5c398a6..5b81501 100644
--- a/opengl/tests/angeles/Android.bp
+++ b/opengl/tests/angeles/Android.bp
@@ -1,5 +1,50 @@
 // Copyright 2006 The Android Open Source Project
 
+package {
+    default_applicable_licenses: [
+        "frameworks_native_opengl_tests_angeles_license",
+    ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change included anything that looked like it might be a license
+// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
+//
+// Please consider removing redundant or irrelevant files from 'license_text:'.
+//
+// large-scale-change filtered out the below license kinds as false-positives:
+//   SPDX-license-identifier-LGPL
+//   SPDX-license-identifier-LGPL-2.1
+//   SPDX-license-identifier-LGPL-3.0
+// See: http://go/android-license-faq
+license {
+    name: "frameworks_native_opengl_tests_angeles_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-MIT",
+        "legacy_notice",
+    ],
+    license_text: [
+        "license-BSD.txt",
+        "license-LGPL.txt",
+        "license.txt",
+    ],
+}
+
 cc_test {
     name: "angeles",
 
diff --git a/opengl/tests/configdump/Android.bp b/opengl/tests/configdump/Android.bp
index ee967970..ffb0c1f 100644
--- a/opengl/tests/configdump/Android.bp
+++ b/opengl/tests/configdump/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-configdump",
 
diff --git a/opengl/tests/fillrate/Android.bp b/opengl/tests/fillrate/Android.bp
index 689cee4..e4bff01 100644
--- a/opengl/tests/fillrate/Android.bp
+++ b/opengl/tests/fillrate/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-fillrate",
 
diff --git a/opengl/tests/filter/Android.bp b/opengl/tests/filter/Android.bp
index 23241e1..3b92b37 100644
--- a/opengl/tests/filter/Android.bp
+++ b/opengl/tests/filter/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-filter",
 
diff --git a/opengl/tests/finish/Android.bp b/opengl/tests/finish/Android.bp
index be20851..c2dfbc3 100644
--- a/opengl/tests/finish/Android.bp
+++ b/opengl/tests/finish/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-finish",
 
diff --git a/opengl/tests/gl2_basic/Android.bp b/opengl/tests/gl2_basic/Android.bp
index f4538ad..c54bdf3 100644
--- a/opengl/tests/gl2_basic/Android.bp
+++ b/opengl/tests/gl2_basic/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gl2_basic",
 
diff --git a/opengl/tests/gl2_cameraeye/Android.bp b/opengl/tests/gl2_cameraeye/Android.bp
index 00e00df..6b8ee85 100644
--- a/opengl/tests/gl2_cameraeye/Android.bp
+++ b/opengl/tests/gl2_cameraeye/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "GL2CameraEye",
     // Only compile source java files in this apk.
diff --git a/opengl/tests/gl2_copyTexImage/Android.bp b/opengl/tests/gl2_copyTexImage/Android.bp
index 87fa7ea..0a84d25 100644
--- a/opengl/tests/gl2_copyTexImage/Android.bp
+++ b/opengl/tests/gl2_copyTexImage/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gl2_copyTexImage",
 
diff --git a/opengl/tests/gl2_java/Android.bp b/opengl/tests/gl2_java/Android.bp
index a8e5d7d..a33075e 100644
--- a/opengl/tests/gl2_java/Android.bp
+++ b/opengl/tests/gl2_java/Android.bp
@@ -1,6 +1,15 @@
 //########################################################################
 // OpenGL ES 2.0 Java sample
 //########################################################################
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "GL2Java",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/gl2_jni/Android.bp b/opengl/tests/gl2_jni/Android.bp
index 8d4323f..79773cb 100644
--- a/opengl/tests/gl2_jni/Android.bp
+++ b/opengl/tests/gl2_jni/Android.bp
@@ -3,6 +3,15 @@
 // This makefile builds both an activity and a shared library.
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "GL2JNI",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/gl2_yuvtex/Android.bp b/opengl/tests/gl2_yuvtex/Android.bp
index b64d94d..fadf0e8 100644
--- a/opengl/tests/gl2_yuvtex/Android.bp
+++ b/opengl/tests/gl2_yuvtex/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gl2_yuvtex",
 
diff --git a/opengl/tests/gl_basic/Android.bp b/opengl/tests/gl_basic/Android.bp
index 5eed17e..f777401 100644
--- a/opengl/tests/gl_basic/Android.bp
+++ b/opengl/tests/gl_basic/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gl_basic",
 
diff --git a/opengl/tests/gl_jni/Android.bp b/opengl/tests/gl_jni/Android.bp
index 0cb129a..dc46483 100644
--- a/opengl/tests/gl_jni/Android.bp
+++ b/opengl/tests/gl_jni/Android.bp
@@ -4,6 +4,15 @@
 //########################################################################
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "GLJNI",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/gl_perf/Android.bp b/opengl/tests/gl_perf/Android.bp
index 25a317c..ca0f7e8 100644
--- a/opengl/tests/gl_perf/Android.bp
+++ b/opengl/tests/gl_perf/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gl2_perf",
 
diff --git a/opengl/tests/gl_perfapp/Android.bp b/opengl/tests/gl_perfapp/Android.bp
index 66afb6a..2f62346 100644
--- a/opengl/tests/gl_perfapp/Android.bp
+++ b/opengl/tests/gl_perfapp/Android.bp
@@ -2,6 +2,15 @@
 // OpenGL ES Perf App
 // This makefile builds both an activity and a shared library.
 //########################################################################
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "GLPerf",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/gl_yuvtex/Android.bp b/opengl/tests/gl_yuvtex/Android.bp
index 9b4924a..7844186 100644
--- a/opengl/tests/gl_yuvtex/Android.bp
+++ b/opengl/tests/gl_yuvtex/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gl_yuvtex",
 
diff --git a/opengl/tests/gldual/Android.bp b/opengl/tests/gldual/Android.bp
index 1006d44..3d6e677 100644
--- a/opengl/tests/gldual/Android.bp
+++ b/opengl/tests/gldual/Android.bp
@@ -4,6 +4,15 @@
 //########################################################################
 // Build activity
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "GLDual",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/gralloc/Android.bp b/opengl/tests/gralloc/Android.bp
index 33c3dba..5fb4556 100644
--- a/opengl/tests/gralloc/Android.bp
+++ b/opengl/tests/gralloc/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "test-opengl-gralloc",
 
diff --git a/opengl/tests/hwc/Android.bp b/opengl/tests/hwc/Android.bp
index 55f058f..719eb11 100644
--- a/opengl/tests/hwc/Android.bp
+++ b/opengl/tests/hwc/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
 
     name: "hwc_tests_defaults",
diff --git a/opengl/tests/lib/Android.bp b/opengl/tests/lib/Android.bp
index 2f6095d..05c9397 100644
--- a/opengl/tests/lib/Android.bp
+++ b/opengl/tests/lib/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
 
     name: "libglTest",
diff --git a/opengl/tests/lighting1709/Android.bp b/opengl/tests/lighting1709/Android.bp
index e734dd1..79daa26 100644
--- a/opengl/tests/lighting1709/Android.bp
+++ b/opengl/tests/lighting1709/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_test {
     name: "LightingTest",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/linetex/Android.bp b/opengl/tests/linetex/Android.bp
index dbc2cdb..61976e5 100644
--- a/opengl/tests/linetex/Android.bp
+++ b/opengl/tests/linetex/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-opengl-linetex",
     srcs: ["linetex.cpp"],
diff --git a/opengl/tests/swapinterval/Android.bp b/opengl/tests/swapinterval/Android.bp
index eed4dff..a76f4cf 100644
--- a/opengl/tests/swapinterval/Android.bp
+++ b/opengl/tests/swapinterval/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-opengl-swapinterval",
     srcs: ["swapinterval.cpp"],
diff --git a/opengl/tests/testFramerate/Android.bp b/opengl/tests/testFramerate/Android.bp
index 5aa83b0..4334d88 100644
--- a/opengl/tests/testFramerate/Android.bp
+++ b/opengl/tests/testFramerate/Android.bp
@@ -2,6 +2,15 @@
 // Test framerate and look for hiccups
 //########################################################################
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "TestFramerate",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/testLatency/Android.bp b/opengl/tests/testLatency/Android.bp
index c516dc3..473cb42 100644
--- a/opengl/tests/testLatency/Android.bp
+++ b/opengl/tests/testLatency/Android.bp
@@ -1,6 +1,15 @@
 //########################################################################
 // Test end-to-end latency.
 //########################################################################
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "TestLatency",
     sdk_version: "8",
diff --git a/opengl/tests/testPauseResume/Android.bp b/opengl/tests/testPauseResume/Android.bp
index 810e895..8171e1f 100644
--- a/opengl/tests/testPauseResume/Android.bp
+++ b/opengl/tests/testPauseResume/Android.bp
@@ -1,4 +1,13 @@
 // OpenGL ES JNI sample
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "TestEGL",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/testViewport/Android.bp b/opengl/tests/testViewport/Android.bp
index 629b573..13ce3ad 100644
--- a/opengl/tests/testViewport/Android.bp
+++ b/opengl/tests/testViewport/Android.bp
@@ -2,6 +2,15 @@
 // OpenGL ES JNI sample
 // This makefile builds both an activity and a shared library.
 //########################################################################
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 android_app {
     name: "TestViewport",
     srcs: ["**/*.java"],
diff --git a/opengl/tests/textures/Android.bp b/opengl/tests/textures/Android.bp
index 84adda2..f113ff7 100644
--- a/opengl/tests/textures/Android.bp
+++ b/opengl/tests/textures/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-opengl-textures",
     srcs: ["textures.cpp"],
diff --git a/opengl/tests/tritex/Android.bp b/opengl/tests/tritex/Android.bp
index 390397b..759582c 100644
--- a/opengl/tests/tritex/Android.bp
+++ b/opengl/tests/tritex/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-opengl-tritex",
     srcs: ["tritex.cpp"],
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index 12ad47e..e6fb2c3 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libaudiomanager",
 
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp
index c3da216..72bd292 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "android.frameworks.automotive.display@1.0-service",
     defaults: ["hidl_defaults"],
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 66ee8ff..1e37991 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libbatteryservice_headers",
     vendor_available: true,
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
index 4d2d873..8681784 100644
--- a/services/displayservice/Android.bp
+++ b/services/displayservice/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libdisplayservicehidl",
 
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 9a9bca1..b9b6a19 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "gpuservice_defaults",
     cflags: [
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
index 5d02839..ac300d0 100644
--- a/services/gpuservice/OWNERS
+++ b/services/gpuservice/OWNERS
@@ -1,3 +1,2 @@
 chrisforbes@google.com
 lpy@google.com
-zzyiwei@google.com
diff --git a/services/gpuservice/bpfprogs/Android.bp b/services/gpuservice/bpfprogs/Android.bp
index b875814..9842ed7 100644
--- a/services/gpuservice/bpfprogs/Android.bp
+++ b/services/gpuservice/bpfprogs/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 bpf {
     name: "gpu_mem.o",
     srcs: ["gpu_mem.c"],
diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp
index b2230b6..830e53d 100644
--- a/services/gpuservice/gpumem/Android.bp
+++ b/services/gpuservice/gpumem/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libgpumem",
     srcs: [
diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp
index f52602a..54291ad 100644
--- a/services/gpuservice/gpustats/Android.bp
+++ b/services/gpuservice/gpustats/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libgfxstats",
     srcs: [
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 940a26b..6d87c45 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "gpuservice_unittest",
     test_suites: ["device-tests"],
@@ -20,6 +29,7 @@
     },
     srcs: [
         "GpuMemTest.cpp",
+        "GpuMemTracerTest.cpp",
         "GpuStatsTest.cpp",
     ],
     shared_libs: [
@@ -29,14 +39,19 @@
         "libcutils",
         "libgfxstats",
         "libgpumem",
+        "libgpumemtracer",
         "libgraphicsenv",
         "liblog",
+        "libprotobuf-cpp-lite",
+        "libprotoutil",
         "libstatslog",
         "libstatspull",
         "libutils",
     ],
     static_libs: [
         "libgmock",
+        "libperfetto_client_experimental",
+        "perfetto_trace_protos",
     ],
     require_root: true,
 }
diff --git a/services/gpuservice/tests/unittests/GpuMemTest.cpp b/services/gpuservice/tests/unittests/GpuMemTest.cpp
index c5f8859..e916221 100644
--- a/services/gpuservice/tests/unittests/GpuMemTest.cpp
+++ b/services/gpuservice/tests/unittests/GpuMemTest.cpp
@@ -59,7 +59,6 @@
     }
 
     void SetUp() override {
-        SKIP_IF_BPF_NOT_SUPPORTED;
         bpf::setrlimitForTest();
 
         mGpuMem = std::make_unique<GpuMem>();
@@ -87,8 +86,6 @@
 };
 
 TEST_F(GpuMemTest, validGpuMemTotalBpfPaths) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
-
     EXPECT_EQ(mTestableGpuMem.getGpuMemTraceGroup(), "gpu_mem");
     EXPECT_EQ(mTestableGpuMem.getGpuMemTotalTracepoint(), "gpu_mem_total");
     EXPECT_EQ(mTestableGpuMem.getGpuMemTotalProgPath(),
@@ -97,20 +94,16 @@
 }
 
 TEST_F(GpuMemTest, bpfInitializationFailed) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
-
     EXPECT_EQ(dumpsys(), "Failed to initialize GPU memory eBPF\n");
 }
 
 TEST_F(GpuMemTest, gpuMemTotalMapEmpty) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
 
     EXPECT_EQ(dumpsys(), "GPU memory total usage map is empty\n");
 }
 
 TEST_F(GpuMemTest, globalMemTotal) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY));
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
 
@@ -118,7 +111,6 @@
 }
 
 TEST_F(GpuMemTest, missingGlobalMemTotal) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
 
@@ -126,7 +118,6 @@
 }
 
 TEST_F(GpuMemTest, procMemTotal) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY));
     mTestableGpuMem.setGpuMemTotalMap(mTestMap);
@@ -146,7 +137,6 @@
 }
 
 TEST_F(GpuMemTest, traverseGpuMemTotals) {
-    SKIP_IF_BPF_NOT_SUPPORTED;
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY));
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
     ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY));
diff --git a/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp b/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp
new file mode 100644
index 0000000..d76f039
--- /dev/null
+++ b/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "gpuservice_unittest"
+
+#include <bpf/BpfMap.h>
+#include <gpumem/GpuMem.h>
+#include <gtest/gtest.h>
+#include <perfetto/trace/trace.pb.h>
+#include <tracing/GpuMemTracer.h>
+
+#include "TestableGpuMem.h"
+
+namespace android {
+
+constexpr uint32_t TEST_MAP_SIZE = 10;
+constexpr uint64_t TEST_GLOBAL_KEY = 0;
+constexpr uint32_t TEST_GLOBAL_PID = 0;
+constexpr uint64_t TEST_GLOBAL_VAL = 123;
+constexpr uint32_t TEST_GLOBAL_GPU_ID = 0;
+constexpr uint64_t TEST_PROC_KEY_1 = 1;
+constexpr uint32_t TEST_PROC_PID_1 = 1;
+constexpr uint64_t TEST_PROC_VAL_1 = 234;
+constexpr uint32_t TEST_PROC_1_GPU_ID = 0;
+constexpr uint64_t TEST_PROC_KEY_2 = 4294967298; // (1 << 32) + 2
+constexpr uint32_t TEST_PROC_PID_2 = 2;
+constexpr uint64_t TEST_PROC_VAL_2 = 345;
+constexpr uint32_t TEST_PROC_2_GPU_ID = 1;
+
+class GpuMemTracerTest : public testing::Test {
+public:
+    GpuMemTracerTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+
+    ~GpuMemTracerTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+
+    void SetUp() override {
+        bpf::setrlimitForTest();
+
+        mGpuMem = std::make_shared<GpuMem>();
+        mGpuMemTracer = std::make_unique<GpuMemTracer>();
+        mGpuMemTracer->initializeForTest(mGpuMem);
+        mTestableGpuMem = TestableGpuMem(mGpuMem.get());
+
+        errno = 0;
+        mTestMap = bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE,
+                                                   BPF_F_NO_PREALLOC);
+
+        EXPECT_EQ(0, errno);
+        EXPECT_LE(0, mTestMap.getMap().get());
+        EXPECT_TRUE(mTestMap.isValid());
+    }
+
+    int getTracerThreadCount() { return mGpuMemTracer->tracerThreadCount; }
+
+    std::vector<perfetto::protos::TracePacket> readGpuMemTotalPacketsBlocking(
+            perfetto::TracingSession* tracingSession) {
+        std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+        perfetto::protos::Trace trace;
+        trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()));
+
+        std::vector<perfetto::protos::TracePacket> packets;
+        for (const auto& packet : trace.packet()) {
+            if (!packet.has_gpu_mem_total_event()) {
+                continue;
+            }
+            packets.emplace_back(packet);
+        }
+        return packets;
+    }
+
+    std::shared_ptr<GpuMem> mGpuMem;
+    TestableGpuMem mTestableGpuMem;
+    std::unique_ptr<GpuMemTracer> mGpuMemTracer;
+    bpf::BpfMap<uint64_t, uint64_t> mTestMap;
+};
+
+static constexpr uint64_t getSizeForPid(uint32_t pid) {
+    switch (pid) {
+        case TEST_GLOBAL_PID:
+            return TEST_GLOBAL_VAL;
+        case TEST_PROC_PID_1:
+            return TEST_PROC_VAL_1;
+        case TEST_PROC_PID_2:
+            return TEST_PROC_VAL_2;
+    }
+    return 0;
+}
+
+static constexpr uint32_t getGpuIdForPid(uint32_t pid) {
+    switch (pid) {
+        case TEST_GLOBAL_PID:
+            return TEST_GLOBAL_GPU_ID;
+        case TEST_PROC_PID_1:
+            return TEST_PROC_1_GPU_ID;
+        case TEST_PROC_PID_2:
+            return TEST_PROC_2_GPU_ID;
+    }
+    return 0;
+}
+
+TEST_F(GpuMemTracerTest, traceInitialCountersAfterGpuMemInitialize) {
+    ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY));
+    ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY));
+    ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY));
+    mTestableGpuMem.setGpuMemTotalMap(mTestMap);
+    mTestableGpuMem.setInitialized();
+
+    // Only 1 tracer thread should be existing for test.
+    EXPECT_EQ(getTracerThreadCount(), 1);
+    auto tracingSession = mGpuMemTracer->getTracingSessionForTest();
+
+    tracingSession->StartBlocking();
+    // Sleep for a short time to let the tracer thread finish its work
+    sleep(1);
+    tracingSession->StopBlocking();
+
+    // The test tracer thread should have finished its execution by now.
+    EXPECT_EQ(getTracerThreadCount(), 0);
+
+    auto packets = readGpuMemTotalPacketsBlocking(tracingSession.get());
+    EXPECT_EQ(packets.size(), 3);
+
+    const auto& packet0 = packets[0];
+    ASSERT_TRUE(packet0.has_timestamp());
+    ASSERT_TRUE(packet0.has_gpu_mem_total_event());
+    const auto& gpuMemEvent0 = packet0.gpu_mem_total_event();
+    ASSERT_TRUE(gpuMemEvent0.has_pid());
+    const auto& pid0 = gpuMemEvent0.pid();
+    ASSERT_TRUE(gpuMemEvent0.has_size());
+    EXPECT_EQ(gpuMemEvent0.size(), getSizeForPid(pid0));
+    ASSERT_TRUE(gpuMemEvent0.has_gpu_id());
+    EXPECT_EQ(gpuMemEvent0.gpu_id(), getGpuIdForPid(pid0));
+
+    const auto& packet1 = packets[1];
+    ASSERT_TRUE(packet1.has_timestamp());
+    ASSERT_TRUE(packet1.has_gpu_mem_total_event());
+    const auto& gpuMemEvent1 = packet1.gpu_mem_total_event();
+    ASSERT_TRUE(gpuMemEvent1.has_pid());
+    const auto& pid1 = gpuMemEvent1.pid();
+    ASSERT_TRUE(gpuMemEvent1.has_size());
+    EXPECT_EQ(gpuMemEvent1.size(), getSizeForPid(pid1));
+    ASSERT_TRUE(gpuMemEvent1.has_gpu_id());
+    EXPECT_EQ(gpuMemEvent1.gpu_id(), getGpuIdForPid(pid1));
+
+    const auto& packet2 = packets[2];
+    ASSERT_TRUE(packet2.has_timestamp());
+    ASSERT_TRUE(packet2.has_gpu_mem_total_event());
+    const auto& gpuMemEvent2 = packet2.gpu_mem_total_event();
+    ASSERT_TRUE(gpuMemEvent2.has_pid());
+    const auto& pid2 = gpuMemEvent2.pid();
+    ASSERT_TRUE(gpuMemEvent2.has_size());
+    EXPECT_EQ(gpuMemEvent2.size(), getSizeForPid(pid2));
+    ASSERT_TRUE(gpuMemEvent2.has_gpu_id());
+    EXPECT_EQ(gpuMemEvent2.gpu_id(), getGpuIdForPid(pid2));
+}
+
+TEST_F(GpuMemTracerTest, noTracingWithoutGpuMemInitialize) {
+    // Only 1 tracer thread should be existing for test.
+    EXPECT_EQ(getTracerThreadCount(), 1);
+
+    auto tracingSession = mGpuMemTracer->getTracingSessionForTest();
+
+    tracingSession->StartBlocking();
+    // Sleep for a short time to let the tracer thread finish its work
+    sleep(1);
+    tracingSession->StopBlocking();
+
+    // The test tracer thread should have finished its execution by now.
+    EXPECT_EQ(getTracerThreadCount(), 0);
+
+    auto packets = readGpuMemTotalPacketsBlocking(tracingSession.get());
+    EXPECT_EQ(packets.size(), 0);
+}
+} // namespace android
diff --git a/services/gpuservice/tracing/Android.bp b/services/gpuservice/tracing/Android.bp
index 919fed3..a1bc1ed 100644
--- a/services/gpuservice/tracing/Android.bp
+++ b/services/gpuservice/tracing/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libgpumemtracer",
     srcs: [
diff --git a/services/gpuservice/tracing/GpuMemTracer.cpp b/services/gpuservice/tracing/GpuMemTracer.cpp
index 6366e1d..44a30ea 100644
--- a/services/gpuservice/tracing/GpuMemTracer.cpp
+++ b/services/gpuservice/tracing/GpuMemTracer.cpp
@@ -44,9 +44,35 @@
     args.backends = perfetto::kSystemBackend;
     perfetto::Tracing::Initialize(args);
     registerDataSource();
-    std::thread tracerThread(&GpuMemTracer::threadLoop, this);
+    std::thread tracerThread(&GpuMemTracer::threadLoop, this, true);
     pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread");
     tracerThread.detach();
+    tracerThreadCount++;
+}
+
+void GpuMemTracer::initializeForTest(std::shared_ptr<GpuMem> gpuMem) {
+    mGpuMem = gpuMem;
+    perfetto::TracingInitArgs args;
+    args.backends = perfetto::kInProcessBackend;
+    perfetto::Tracing::Initialize(args);
+    registerDataSource();
+    std::thread tracerThread(&GpuMemTracer::threadLoop, this, false);
+    pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThreadForTest");
+    tracerThread.detach();
+    tracerThreadCount++;
+}
+
+// Each tracing session can be used for a single block of Start -> Stop.
+std::unique_ptr<perfetto::TracingSession> GpuMemTracer::getTracingSessionForTest() {
+    perfetto::TraceConfig cfg;
+    cfg.set_duration_ms(500);
+    cfg.add_buffers()->set_size_kb(1024);
+    auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+    ds_cfg->set_name(GpuMemTracer::kGpuMemDataSource);
+
+    auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+    tracingSession->Setup(cfg);
+    return tracingSession;
 }
 
 void GpuMemTracer::registerDataSource() {
@@ -55,8 +81,8 @@
     GpuMemDataSource::Register(dsd);
 }
 
-void GpuMemTracer::threadLoop() {
-    while (true) {
+void GpuMemTracer::threadLoop(bool infiniteLoop) {
+    do {
         {
             std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex);
             while (!sTraceStarted) {
@@ -68,7 +94,11 @@
             std::lock_guard<std::mutex> lock(GpuMemTracer::sTraceMutex);
             sTraceStarted = false;
         }
-    }
+    } while (infiniteLoop);
+
+    // Thread loop is exiting. Reduce the tracerThreadCount to reflect the number of active threads
+    // in the wait loop.
+    tracerThreadCount--;
 }
 
 void GpuMemTracer::traceInitialCounters() {
diff --git a/services/gpuservice/tracing/include/tracing/GpuMemTracer.h b/services/gpuservice/tracing/include/tracing/GpuMemTracer.h
index 40deb4c..ae871f1 100644
--- a/services/gpuservice/tracing/include/tracing/GpuMemTracer.h
+++ b/services/gpuservice/tracing/include/tracing/GpuMemTracer.h
@@ -20,6 +20,10 @@
 
 #include <mutex>
 
+namespace perfetto::protos {
+class TracePacket;
+}
+
 namespace android {
 
 class GpuMem;
@@ -45,16 +49,37 @@
     // perfetto::kInProcessBackend in tests.
     void registerDataSource();
 
+    // TODO(b/175904796): Refactor gpuservice lib to include perfetto lib and move the test
+    // functions into the unittests.
+    // Functions only used for testing with in-process backend. These functions require the static
+    // perfetto lib to be linked. If the tests have a perfetto linked, while libgpumemtracer.so also
+    // has one linked, they will both use different static states maintained in perfetto. Since the
+    // static perfetto states are not shared, tracing sessions created in the unit test are not
+    // recognized by GpuMemTracer. As a result, we cannot use any of the perfetto functions from
+    // this class, which defeats the purpose of the unit test. To solve this, we restrict all
+    // tracing functionality to this class, while the unit test validates the data.
+    // Sets up the perfetto in-process backend and calls into registerDataSource.
+    void initializeForTest(std::shared_ptr<GpuMem>);
+    // Creates a tracing session with in process backend, for testing.
+    std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest();
+    // Read and filter the gpu memory packets from the created trace.
+    std::vector<perfetto::protos::TracePacket> readGpuMemTotalPacketsForTestBlocking(
+            perfetto::TracingSession* tracingSession);
+
     static constexpr char kGpuMemDataSource[] = "android.gpu.memory";
     static std::condition_variable sCondition;
     static std::mutex sTraceMutex;
     static bool sTraceStarted;
 
 private:
-    void traceInitialCounters();
-    void threadLoop();
+    // Friend class for testing
+    friend class GpuMemTracerTest;
 
+    void threadLoop(bool infiniteLoop);
+    void traceInitialCounters();
     std::shared_ptr<GpuMem> mGpuMem;
+    // Count of how many tracer threads are currently active. Useful for testing.
+    std::atomic<int32_t> tracerThreadCount = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index f67c9d0..8610737 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Default flags to be used throughout all libraries in inputflinger.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "inputflinger_defaults",
     cflags: [
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 066a816..67d85d6 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_benchmark {
     name: "inputflinger_benchmarks",
     srcs: [
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 390c6b8..40c2409 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libinputdispatcher_headers",
     export_include_dirs: [
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 2517060..6ea64b4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -58,6 +58,7 @@
 #include <sstream>
 
 #include <android-base/chrono_utils.h>
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <binder/Binder.h>
 #include <input/InputDevice.h>
@@ -72,13 +73,14 @@
 #define INDENT3 "      "
 #define INDENT4 "        "
 
+using android::base::HwTimeoutMultiplier;
 using android::base::StringPrintf;
 
 namespace android::inputdispatcher {
 
 // Default input dispatching timeout if there is no focused application or paused window
 // from which to determine an appropriate dispatching timeout.
-constexpr std::chrono::nanoseconds DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5s;
+const std::chrono::nanoseconds DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5s * HwTimeoutMultiplier();
 
 // Amount of time to allow for all pending events to be processed when an app switch
 // key is on the way.  This is used to preempt input dispatch and drop input events
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index b56f356..f0151c9 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libinputflingerhost",
 
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 83a610f..dadbd0e 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libinputreader_headers",
     export_include_dirs: [
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 4b19e5e..3347ba6 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -84,12 +84,13 @@
     bumpGeneration();
 }
 
-void InputDevice::dump(std::string& dump) {
+void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) {
     InputDeviceInfo deviceInfo;
     getDeviceInfo(&deviceInfo);
 
     dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
                          deviceInfo.getDisplayName().c_str());
+    dump += StringPrintf(INDENT "%s", eventHubDevStr.c_str());
     dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
     dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
     dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
@@ -101,6 +102,7 @@
     dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
     dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
     dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
+    dump += StringPrintf(INDENT2 "ControllerNum: %d\n", deviceInfo.getControllerNumber());
 
     const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
     if (!ranges.empty()) {
@@ -200,6 +202,8 @@
 
     // insert the context into the devices set
     mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+    // Must change generation to flag this device as changed
+    bumpGeneration();
 }
 
 void InputDevice::removeEventHubDevice(int32_t eventHubId) {
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 06e3743..dff830c 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -206,6 +206,14 @@
     }
 
     mDevices.emplace(eventHubId, device);
+    // Add device to device to EventHub ids map.
+    const auto mapIt = mDeviceToEventHubIdsMap.find(device);
+    if (mapIt == mDeviceToEventHubIdsMap.end()) {
+        std::vector<int32_t> ids = {eventHubId};
+        mDeviceToEventHubIdsMap.emplace(device, ids);
+    } else {
+        mapIt->second.push_back(eventHubId);
+    }
     bumpGenerationLocked();
 
     if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
@@ -222,6 +230,17 @@
 
     std::shared_ptr<InputDevice> device = std::move(deviceIt->second);
     mDevices.erase(deviceIt);
+    // Erase device from device to EventHub ids map.
+    auto mapIt = mDeviceToEventHubIdsMap.find(device);
+    if (mapIt != mDeviceToEventHubIdsMap.end()) {
+        std::vector<int32_t>& eventHubIds = mapIt->second;
+        eventHubIds.erase(std::remove_if(eventHubIds.begin(), eventHubIds.end(),
+                                         [eventHubId](int32_t eId) { return eId == eventHubId; }),
+                          eventHubIds.end());
+        if (eventHubIds.size() == 0) {
+            mDeviceToEventHubIdsMap.erase(mapIt);
+        }
+    }
     bumpGenerationLocked();
 
     if (device->isIgnored()) {
@@ -450,8 +469,7 @@
 void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
     outInputDevices.clear();
 
-    for (auto& devicePair : mDevices) {
-        std::shared_ptr<InputDevice>& device = devicePair.second;
+    for (const auto& [device, eventHubIds] : mDeviceToEventHubIdsMap) {
         if (!device->isIgnored()) {
             InputDeviceInfo info;
             device->getDeviceInfo(&info);
@@ -622,11 +640,17 @@
     mEventHub->dump(dump);
     dump += "\n";
 
-    dump += "Input Reader State:\n";
+    dump += StringPrintf("Input Reader State (Nums of device: %zu):\n",
+                         mDeviceToEventHubIdsMap.size());
 
-    for (const auto& devicePair : mDevices) {
-        const std::shared_ptr<InputDevice>& device = devicePair.second;
-        device->dump(dump);
+    for (const auto& devicePair : mDeviceToEventHubIdsMap) {
+        const std::shared_ptr<InputDevice>& device = devicePair.first;
+        std::string eventHubDevStr = INDENT "EventHub Devices: [ ";
+        for (const auto& eId : devicePair.second) {
+            eventHubDevStr += StringPrintf("%d ", eId);
+        }
+        eventHubDevStr += "] \n";
+        device->dump(dump, eventHubDevStr);
     }
 
     dump += INDENT "Configuration:\n";
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 7c17102..d2bb4f4 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -66,7 +66,7 @@
     bool isEnabled();
     void setEnabled(bool enabled, nsecs_t when);
 
-    void dump(std::string& dump);
+    void dump(std::string& dump, const std::string& eventHubDevStr);
     void addEventHubDevice(int32_t eventHubId, bool populateMappers = true);
     void removeEventHubDevice(int32_t eventHubId);
     void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 108b9c2..2773f70 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -143,6 +143,11 @@
     // to lookup the input device instance from the EventHub device id.
     std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices;
 
+    // An input device contains one or more eventHubId, this map provides a way to lookup the
+    // EventHubIds contained in the input device from the input device instance.
+    std::unordered_map<std::shared_ptr<InputDevice>, std::vector<int32_t> /*eventHubId*/>
+            mDeviceToEventHubIdsMap;
+
     // low-level input event decoding and device management
     void processEventsLocked(const RawEvent* rawEvents, size_t count);
 
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 0b541fb..cbdb1d0 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -3673,6 +3673,9 @@
     const float xScaled = float(x - mRawPointerAxes.x.minValue) * mXScale;
     const float yScaled = float(y - mRawPointerAxes.y.minValue) * mYScale;
 
+    const float xScaledMax = float(mRawPointerAxes.x.maxValue - x) * mXScale;
+    const float yScaledMax = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+
     // Rotate to surface coordinate.
     // 0 - no swap and reverse.
     // 90 - swap x/y and reverse y.
@@ -3684,16 +3687,16 @@
             y = yScaled + mYTranslate;
             break;
         case DISPLAY_ORIENTATION_90:
-            y = mSurfaceRight - xScaled;
+            y = xScaledMax - (mRawSurfaceWidth - mSurfaceRight);
             x = yScaled + mYTranslate;
             break;
         case DISPLAY_ORIENTATION_180:
-            x = mSurfaceRight - xScaled;
-            y = mSurfaceBottom - yScaled;
+            x = xScaledMax - (mRawSurfaceWidth - mSurfaceRight);
+            y = yScaledMax - (mRawSurfaceHeight - mSurfaceBottom);
             break;
         case DISPLAY_ORIENTATION_270:
             y = xScaled + mXTranslate;
-            x = mSurfaceBottom - yScaled;
+            x = yScaledMax - (mRawSurfaceHeight - mSurfaceBottom);
             break;
         default:
             assert(false);
diff --git a/services/inputflinger/reporter/Android.bp b/services/inputflinger/reporter/Android.bp
index fbc51da..7430731 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/inputflinger/reporter/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "libinputreporter_headers",
     export_include_dirs: ["."],
@@ -46,4 +55,3 @@
         "libinputreporter_headers",
     ],
 }
-
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index a0d2f4f..86ed60d 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "inputflinger_tests",
     defaults: [
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 58f83b5..e9bb169 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -7449,8 +7449,8 @@
         configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
 
-    void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xInside, int32_t yInside,
-                                  int32_t xOutside, int32_t yOutside, int32_t xExpected,
+    void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xOutside, int32_t yOutside,
+                                  int32_t xInside, int32_t yInside, int32_t xExpected,
                                   int32_t yExpected) {
         // touch on outside area should not work.
         processPosition(mapper, toRawX(xOutside), toRawY(yOutside));
@@ -7532,6 +7532,34 @@
     processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
 }
 
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner) {
+    addConfigurationProperty("touch.deviceType", "touchScreen");
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+    const int32_t x = 0;
+    const int32_t y = 0;
+
+    const int32_t xExpected = x;
+    const int32_t yExpected = y;
+    processPositionAndVerify(mapper, x - 1, y, x, y, xExpected, yExpected);
+
+    clearViewports();
+    prepareDisplay(DISPLAY_ORIENTATION_90);
+    // expect x/y = swap x/y then reverse y.
+    const int32_t xExpected90 = y;
+    const int32_t yExpected90 = DISPLAY_WIDTH - 1;
+    processPositionAndVerify(mapper, x - 1, y, x, y, xExpected90, yExpected90);
+
+    clearViewports();
+    prepareDisplay(DISPLAY_ORIENTATION_270);
+    // expect x/y = swap x/y then reverse x.
+    const int32_t xExpected270 = DISPLAY_HEIGHT - 1;
+    const int32_t yExpected270 = x;
+    processPositionAndVerify(mapper, x - 1, y, x, y, xExpected270, yExpected270);
+}
+
 TEST_F(MultiTouchInputMapperTest, Process_TouchpadCapture) {
     // we need a pointer controller for mouse mode of touchpad (start pointer at 0,0)
     std::shared_ptr<FakePointerController> fakePointerController =
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
new file mode 100644
index 0000000..2a90a08
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -0,0 +1,121 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_defaults {
+    name: "inputflinger_fuzz_defaults",
+    defaults: [
+        "inputflinger_defaults",
+    ],
+    include_dirs: [
+        "frameworks/native/services/inputflinger",
+    ],
+    shared_libs: [
+        "android.hardware.input.classifier@1.0",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libui",
+        "libinput",
+        "libinputflinger",
+        "libinputreader",
+        "libinputflinger_base",
+        "libstatslog",
+    ],
+    header_libs: [
+        "libinputreader_headers",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_cursor_input_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "CursorInputFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_keyboard_input_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "KeyboardInputFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_multitouch_input_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "MultiTouchInputFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_switch_input_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "SwitchInputFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_input_reader_device_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "InputReaderDeviceFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_blocking_queue_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "BlockingQueueFuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "inputflinger_input_classifier_fuzzer",
+    defaults: [
+        "inputflinger_fuzz_defaults",
+    ],
+    srcs: [
+        "InputClassifierFuzzer.cpp",
+    ],
+}
diff --git a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
new file mode 100644
index 0000000..6a136cf
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>
+#include <thread>
+#include "BlockingQueue.h"
+
+// Chosen to be a number large enough for variation in fuzzer runs, but not consume too much memory.
+static constexpr size_t MAX_CAPACITY = 1024;
+
+namespace android {
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+    size_t capacity = fdp.ConsumeIntegralInRange<size_t>(1, MAX_CAPACITY);
+    size_t filled = 0;
+    BlockingQueue<int32_t> queue(capacity);
+
+    while (fdp.remaining_bytes() > 0) {
+        fdp.PickValueInArray<std::function<void()>>({
+                [&]() -> void {
+                    size_t numPushes = fdp.ConsumeIntegralInRange<size_t>(0, capacity + 1);
+                    for (size_t i = 0; i < numPushes; i++) {
+                        queue.push(fdp.ConsumeIntegral<int32_t>());
+                    }
+                    filled = std::min(capacity, filled + numPushes);
+                },
+                [&]() -> void {
+                    // Pops blocks if it is empty, so only pop up to num elements inserted.
+                    size_t numPops = fdp.ConsumeIntegralInRange<size_t>(0, filled);
+                    for (size_t i = 0; i < numPops; i++) {
+                        queue.pop();
+                    }
+                    filled > numPops ? filled -= numPops : filled = 0;
+                },
+                [&]() -> void {
+                    queue.clear();
+                    filled = 0;
+                },
+                [&]() -> void {
+                    int32_t eraseElement = fdp.ConsumeIntegral<int32_t>();
+                    queue.erase([&](int32_t element) {
+                        if (element == eraseElement) {
+                            filled--;
+                            return true;
+                        }
+                        return false;
+                    });
+                },
+        })();
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
new file mode 100644
index 0000000..8aa7434
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2020 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 <CursorInputMapper.h>
+#include <FuzzContainer.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+    // Pick a random property to set for the mapper to have set.
+    fdp->PickValueInArray<std::function<void()>>(
+            {[&]() -> void { fuzzer.addProperty(String8("cursor.mode"), String8("pointer")); },
+             [&]() -> void { fuzzer.addProperty(String8("cursor.mode"), String8("navigation")); },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("cursor.mode"),
+                                    String8(fdp->ConsumeRandomLengthString(100).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("cursor.orientationAware"),
+                                    String8(fdp->ConsumeRandomLengthString(100).data()));
+             }})();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    FuzzContainer fuzzer = FuzzContainer(fdp);
+
+    CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>();
+    auto policyConfig = fuzzer.getPolicyConfig();
+
+    // Loop through mapper operations until randomness is exhausted.
+    while (fdp->remaining_bytes() > 0) {
+        fdp->PickValueInArray<std::function<void()>>({
+                [&]() -> void { addProperty(fuzzer, fdp); },
+                [&]() -> void {
+                    std::string dump;
+                    mapper.dump(dump);
+                },
+                [&]() -> void { mapper.getSources(); },
+                [&]() -> void {
+                    mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+                                     fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    // Need to reconfigure with 0 or you risk a NPE.
+                    mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+                    InputDeviceInfo info;
+                    mapper.populateDeviceInfo(&info);
+                },
+                [&]() -> void {
+                    // Need to reconfigure with 0 or you risk a NPE.
+                    mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+                    RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>()};
+                    mapper.process(&rawEvent);
+                },
+                [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); },
+                [&]() -> void {
+                    mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
+                                            fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    // Need to reconfigure with 0 or you risk a NPE.
+                    mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0);
+                    mapper.getAssociatedDisplayId();
+                },
+        })();
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h
new file mode 100644
index 0000000..84f0566
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <InputDevice.h>
+#include <InputMapper.h>
+#include <InputReader.h>
+#include <MapperHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+class FuzzContainer {
+    int32_t meventID;
+    std::shared_ptr<FuzzEventHub> mFuzzEventHub;
+    sp<FuzzInputReaderPolicy> mFuzzPolicy;
+    sp<FuzzInputListener> mFuzzListener;
+    std::unique_ptr<FuzzInputReaderContext> mFuzzContext;
+    std::unique_ptr<InputDevice> mFuzzDevice;
+    InputReaderConfiguration mPolicyConfig;
+    std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+    FuzzContainer(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {
+        // Setup parameters.
+        std::string deviceName = fdp->ConsumeRandomLengthString(16);
+        std::string deviceLocation = fdp->ConsumeRandomLengthString(12);
+        int32_t deviceID = fdp->ConsumeIntegralInRange<int32_t>(0, 5);
+        int32_t deviceGeneration = fdp->ConsumeIntegralInRange<int32_t>(0, 5);
+        meventID = fdp->ConsumeIntegral<int32_t>();
+
+        // Create mocked objects.
+        mFuzzEventHub = std::make_shared<FuzzEventHub>(fdp);
+        mFuzzPolicy = new FuzzInputReaderPolicy(fdp);
+        mFuzzListener = new FuzzInputListener();
+        mFuzzContext = std::make_unique<FuzzInputReaderContext>(mFuzzEventHub, mFuzzPolicy,
+                                                                mFuzzListener, fdp);
+
+        InputDeviceIdentifier identifier;
+        identifier.name = deviceName;
+        identifier.location = deviceLocation;
+        mFuzzDevice = std::make_unique<InputDevice>(mFuzzContext.get(), deviceID, deviceGeneration,
+                                                    identifier);
+        mFuzzPolicy->getReaderConfiguration(&mPolicyConfig);
+    }
+
+    ~FuzzContainer() {}
+
+    void configureDevice() {
+        nsecs_t arbitraryTime = fdp->ConsumeIntegral<nsecs_t>();
+        mFuzzDevice->configure(arbitraryTime, &mPolicyConfig, 0);
+        mFuzzDevice->reset(arbitraryTime);
+    }
+
+    void addProperty(const String8& key, const String8& value) {
+        mFuzzEventHub->addProperty(key, value);
+        configureDevice();
+    }
+
+    InputReaderConfiguration& getPolicyConfig() { return mPolicyConfig; }
+
+    template <class T, typename... Args>
+    T& getMapper(Args... args) {
+        T& mapper = mFuzzDevice->addMapper<T>(fdp->ConsumeIntegral<int32_t>(), args...);
+        configureDevice();
+        return mapper;
+    }
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
new file mode 100644
index 0000000..7f91000
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2020 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 <MapperHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include "InputClassifier.h"
+#include "InputClassifierConverter.h"
+
+namespace android {
+
+static constexpr int32_t MAX_AXES = 64;
+
+// Used by two fuzz operations and a bit lengthy, so pulled out into a function.
+NotifyMotionArgs generateFuzzedMotionArgs(FuzzedDataProvider &fdp) {
+    // Create a basic motion event for testing
+    PointerProperties properties;
+    properties.id = 0;
+    properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+    PointerCoords coords;
+    coords.clear();
+    for (int32_t i = 0; i < fdp.ConsumeIntegralInRange<int32_t>(0, MAX_AXES); i++) {
+        coords.setAxisValue(fdp.ConsumeIntegral<int32_t>(), fdp.ConsumeFloatingPoint<float>());
+    }
+
+    nsecs_t downTime = 2;
+    NotifyMotionArgs motionArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+                                downTime /*eventTime*/, fdp.ConsumeIntegral<int32_t>() /*deviceId*/,
+                                AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT,
+                                fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/,
+                                AMOTION_EVENT_ACTION_DOWN,
+                                fdp.ConsumeIntegral<int32_t>() /*actionButton*/,
+                                fdp.ConsumeIntegral<int32_t>() /*flags*/, AMETA_NONE,
+                                fdp.ConsumeIntegral<int32_t>() /*buttonState*/,
+                                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+                                1 /*pointerCount*/, &properties, &coords,
+                                fdp.ConsumeFloatingPoint<float>() /*xPrecision*/,
+                                fdp.ConsumeFloatingPoint<float>() /*yPrecision*/,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                                AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime,
+                                {} /*videoFrames*/);
+    return motionArgs;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+
+    sp<FuzzInputListener> mFuzzListener = new FuzzInputListener();
+    sp<InputClassifierInterface> mClassifier = new InputClassifier(mFuzzListener);
+
+    while (fdp.remaining_bytes() > 0) {
+        fdp.PickValueInArray<std::function<void()>>({
+                [&]() -> void {
+                    // SendToNextStage_NotifyConfigurationChangedArgs
+                    NotifyConfigurationChangedArgs
+                            args(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+                                 fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/);
+                    mClassifier->notifyConfigurationChanged(&args);
+                },
+                [&]() -> void {
+                    // SendToNextStage_NotifyKeyArgs
+                    NotifyKeyArgs keyArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+                                          fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/,
+                                          fdp.ConsumeIntegral<int32_t>() /*deviceId*/,
+                                          AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT,
+                                          fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/,
+                                          AKEY_EVENT_ACTION_DOWN,
+                                          fdp.ConsumeIntegral<int32_t>() /*flags*/, AKEYCODE_HOME,
+                                          fdp.ConsumeIntegral<int32_t>() /*scanCode*/, AMETA_NONE,
+                                          fdp.ConsumeIntegral<nsecs_t>() /*downTime*/);
+
+                    mClassifier->notifyKey(&keyArgs);
+                },
+                [&]() -> void {
+                    // SendToNextStage_NotifyMotionArgs
+                    NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp);
+                    mClassifier->notifyMotion(&motionArgs);
+                },
+                [&]() -> void {
+                    // SendToNextStage_NotifySwitchArgs
+                    NotifySwitchArgs switchArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+                                                fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/,
+                                                fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/,
+                                                fdp.ConsumeIntegral<uint32_t>() /*switchValues*/,
+                                                fdp.ConsumeIntegral<uint32_t>() /*switchMask*/);
+
+                    mClassifier->notifySwitch(&switchArgs);
+                },
+                [&]() -> void {
+                    // SendToNextStage_NotifyDeviceResetArgs
+                    NotifyDeviceResetArgs resetArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/,
+                                                    fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/,
+                                                    fdp.ConsumeIntegral<int32_t>() /*deviceId*/);
+
+                    mClassifier->notifyDeviceReset(&resetArgs);
+                },
+                [&]() -> void {
+                    // InputClassifierConverterTest
+                    const NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp);
+                    hardware::input::common::V1_0::MotionEvent motionEvent =
+                            notifyMotionArgsToHalMotionEvent(motionArgs);
+                },
+        })();
+    }
+    return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp
new file mode 100644
index 0000000..9194891
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2020 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 <InputReader.h>
+#include <MapperHelpers.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+
+    sp<FuzzInputListener> fuzzListener = new FuzzInputListener();
+    sp<FuzzInputReaderPolicy> fuzzPolicy = new FuzzInputReaderPolicy(fdp);
+    std::shared_ptr<FuzzEventHub> fuzzEventHub = std::make_shared<FuzzEventHub>(fdp);
+    std::unique_ptr<InputReader> reader =
+            std::make_unique<InputReader>(fuzzEventHub, fuzzPolicy, fuzzListener);
+
+    fuzzEventHub->addEvents(fdp);
+    reader->start();
+
+    // Loop through mapper operations until randomness is exhausted.
+    while (fdp->remaining_bytes() > 0) {
+        fdp->PickValueInArray<std::function<void()>>({
+                [&]() -> void {
+                    std::string dump;
+                    reader->dump(dump);
+                },
+                [&]() -> void { reader->monitor(); },
+                [&]() -> void { fuzzEventHub->addEvents(fdp); },
+                [&]() -> void {
+                    std::vector<InputDeviceInfo> inputDevices;
+                    reader->getInputDevices(inputDevices);
+                },
+                [&]() -> void { reader->isInputDeviceEnabled(fdp->ConsumeIntegral<int32_t>()); },
+                [&]() -> void {
+                    reader->getScanCodeState(fdp->ConsumeIntegral<int32_t>(),
+                                             fdp->ConsumeIntegral<uint32_t>(),
+                                             fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    reader->getKeyCodeState(fdp->ConsumeIntegral<int32_t>(),
+                                            fdp->ConsumeIntegral<uint32_t>(),
+                                            fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    reader->getSwitchState(fdp->ConsumeIntegral<int32_t>(),
+                                           fdp->ConsumeIntegral<uint32_t>(),
+                                           fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void { reader->toggleCapsLockState(fdp->ConsumeIntegral<int32_t>()); },
+                [&]() -> void {
+                    size_t count = fdp->ConsumeIntegralInRange<size_t>(1, 1024);
+                    uint8_t* outFlags = new uint8_t[count];
+                    reader->hasKeys(fdp->ConsumeIntegral<int32_t>(),
+                                    fdp->ConsumeIntegral<uint32_t>(), count, nullptr, outFlags);
+                    delete[] outFlags;
+                },
+                [&]() -> void {
+                    reader->requestRefreshConfiguration(fdp->ConsumeIntegral<uint32_t>());
+                },
+                [&]() -> void {
+                    // 260 is slightly higher than the maximum intended size of 256.
+                    size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 260);
+                    nsecs_t pattern[count];
+
+                    for (size_t i = 0; i < count; i++) pattern[i] = fdp->ConsumeIntegral<nsecs_t>();
+
+                    reader->vibrate(fdp->ConsumeIntegral<int32_t>(), pattern, count,
+                                    fdp->ConsumeIntegral<ssize_t>(),
+                                    fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    reader->cancelVibrate(fdp->ConsumeIntegral<int32_t>(),
+                                          fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    reader->canDispatchToDisplay(fdp->ConsumeIntegral<int32_t>(),
+                                                 fdp->ConsumeIntegral<int32_t>());
+                },
+        })();
+    }
+
+    reader->stop();
+    return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
new file mode 100644
index 0000000..854e2fd
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2020 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 <FuzzContainer.h>
+#include <KeyboardInputMapper.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+    // Pick a random property to set for the mapper to have set.
+    fdp->PickValueInArray<std::function<void()>>(
+            {[&]() -> void {
+                 fuzzer.addProperty(String8("keyboard.orientationAware"), String8("1"));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("keyboard.orientationAware"),
+                                    String8(fdp->ConsumeRandomLengthString(100).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("keyboard.doNotWakeByDefault"),
+                                    String8(fdp->ConsumeRandomLengthString(100).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("keyboard.handlesKeyRepeat"),
+                                    String8(fdp->ConsumeRandomLengthString(100).data()));
+             }})();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    FuzzContainer fuzzer = FuzzContainer(fdp);
+
+    KeyboardInputMapper& mapper =
+            fuzzer.getMapper<KeyboardInputMapper>(fdp->ConsumeIntegral<uint32_t>(),
+                                                  fdp->ConsumeIntegral<int32_t>());
+    auto policyConfig = fuzzer.getPolicyConfig();
+
+    // Loop through mapper operations until randomness is exhausted.
+    while (fdp->remaining_bytes() > 0) {
+        fdp->PickValueInArray<std::function<void()>>({
+                [&]() -> void { addProperty(fuzzer, fdp); },
+                [&]() -> void {
+                    std::string dump;
+                    mapper.dump(dump);
+                },
+                [&]() -> void {
+                    InputDeviceInfo info;
+                    mapper.populateDeviceInfo(&info);
+                },
+                [&]() -> void { mapper.getSources(); },
+                [&]() -> void {
+                    mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+                                     fdp->ConsumeIntegral<uint32_t>());
+                },
+                [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); },
+                [&]() -> void {
+                    RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>()};
+                    mapper.process(&rawEvent);
+                },
+                [&]() -> void {
+                    mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
+                                           fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
+                                            fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(),
+                                                 fdp->ConsumeIntegral<size_t>(), nullptr, nullptr);
+                },
+                [&]() -> void { mapper.getMetaState(); },
+                [&]() -> void { mapper.updateMetaState(fdp->ConsumeIntegral<int32_t>()); },
+                [&]() -> void { mapper.getAssociatedDisplayId(); },
+        })();
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
new file mode 100644
index 0000000..edfb68d
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <InputDevice.h>
+#include <InputMapper.h>
+#include <InputReader.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+class FuzzEventHub : public EventHubInterface {
+    InputDeviceIdentifier mIdentifier;
+    std::vector<TouchVideoFrame> mVideoFrames;
+    PropertyMap mFuzzConfig;
+    std::mutex mEventLock;
+    size_t mCount = 0;
+    RawEvent mBuf[256];
+    std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+    FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {}
+    ~FuzzEventHub() {}
+    void addProperty(const String8& key, const String8 value) {
+        mFuzzConfig.addProperty(key, value);
+    }
+    void addEvents(std::shared_ptr<FuzzedDataProvider> fdp) {
+        std::lock_guard<std::mutex> guard(mEventLock);
+        mCount = fdp->ConsumeIntegralInRange<size_t>(0, 256);
+
+        for (size_t i = 0; i < mCount; i++)
+            mBuf[i] = {fdp->ConsumeIntegral<nsecs_t>(), fdp->ConsumeIntegral<int32_t>(),
+                       fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(),
+                       fdp->ConsumeIntegral<int32_t>()};
+    }
+    uint32_t getDeviceClasses(int32_t deviceId) const override {
+        return fdp->ConsumeIntegral<uint32_t>();
+    }
+    InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
+        return mIdentifier;
+    }
+    int32_t getDeviceControllerNumber(int32_t deviceId) const override {
+        return fdp->ConsumeIntegral<int32_t>();
+    }
+    void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override {
+        *outConfiguration = mFuzzConfig;
+    }
+    status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+                                 RawAbsoluteAxisInfo* outAxisInfo) const override {
+        return fdp->ConsumeIntegral<status_t>();
+    }
+    bool hasRelativeAxis(int32_t deviceId, int axis) const override { return fdp->ConsumeBool(); }
+    bool hasInputProperty(int32_t deviceId, int property) const override {
+        return fdp->ConsumeBool();
+    }
+    status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
+                    int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
+        return fdp->ConsumeIntegral<status_t>();
+    }
+    status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override {
+        return fdp->ConsumeIntegral<status_t>();
+    }
+    void setExcludedDevices(const std::vector<std::string>& devices) override {}
+    size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override {
+        std::lock_guard<std::mutex> guard(mEventLock);
+        for (size_t i = 0; i < mCount; i++) buffer[i] = mBuf[i];
+
+        return mCount;
+    }
+    std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; }
+    int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
+        return fdp->ConsumeIntegral<int32_t>();
+    }
+    int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
+        return fdp->ConsumeIntegral<int32_t>();
+    }
+    int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
+        return fdp->ConsumeIntegral<int32_t>();
+    }
+    status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
+                                  int32_t* outValue) const override {
+        return fdp->ConsumeIntegral<status_t>();
+    }
+    bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+                               uint8_t* outFlags) const override {
+        return fdp->ConsumeBool();
+    }
+    bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
+        return fdp->ConsumeBool();
+    }
+    bool hasLed(int32_t deviceId, int32_t led) const override { return fdp->ConsumeBool(); }
+    void setLedState(int32_t deviceId, int32_t led, bool on) override {}
+    void getVirtualKeyDefinitions(
+            int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {}
+    sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override { return nullptr; }
+    bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) override {
+        return fdp->ConsumeBool();
+    }
+    void vibrate(int32_t deviceId, nsecs_t duration) override {}
+    void cancelVibrate(int32_t deviceId) override {}
+    void requestReopenDevices() override {}
+    void wake() override {}
+    void dump(std::string& dump) override {}
+    void monitor() override {}
+    bool isDeviceEnabled(int32_t deviceId) override { return fdp->ConsumeBool(); }
+    status_t enableDevice(int32_t deviceId) override { return fdp->ConsumeIntegral<status_t>(); }
+    status_t disableDevice(int32_t deviceId) override { return fdp->ConsumeIntegral<status_t>(); }
+};
+
+class FuzzPointerController : public PointerControllerInterface {
+    std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+    FuzzPointerController(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {}
+    ~FuzzPointerController() {}
+    bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
+        return fdp->ConsumeBool();
+    }
+    void move(float deltaX, float deltaY) override {}
+    void setButtonState(int32_t buttonState) override {}
+    int32_t getButtonState() const override { return fdp->ConsumeIntegral<int32_t>(); }
+    void setPosition(float x, float y) override {}
+    void getPosition(float* outX, float* outY) const override {}
+    void fade(Transition transition) override {}
+    void unfade(Transition transition) override {}
+    void setPresentation(Presentation presentation) override {}
+    void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
+                  BitSet32 spotIdBits, int32_t displayId) override {}
+    void clearSpots() override {}
+    int32_t getDisplayId() const override { return fdp->ConsumeIntegral<int32_t>(); }
+    void setDisplayViewport(const DisplayViewport& displayViewport) override {}
+};
+
+class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
+    TouchAffineTransformation mTransform;
+    std::shared_ptr<FuzzPointerController> mPointerController;
+    std::shared_ptr<FuzzedDataProvider> fdp;
+
+protected:
+    ~FuzzInputReaderPolicy() {}
+
+public:
+    FuzzInputReaderPolicy(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {
+        mPointerController = std::make_shared<FuzzPointerController>(fdp);
+    }
+    void getReaderConfiguration(InputReaderConfiguration* outConfig) override {}
+    std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
+        return mPointerController;
+    }
+    void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {}
+    sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) override {
+        return nullptr;
+    }
+    std::string getDeviceAlias(const InputDeviceIdentifier& identifier) {
+        return fdp->ConsumeRandomLengthString(32);
+    }
+    TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
+                                                           int32_t surfaceRotation) override {
+        return mTransform;
+    }
+    void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; }
+};
+
+class FuzzInputListener : public virtual InputListenerInterface {
+protected:
+    ~FuzzInputListener() {}
+
+public:
+    FuzzInputListener() {}
+    void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override {}
+    void notifyKey(const NotifyKeyArgs* args) override {}
+    void notifyMotion(const NotifyMotionArgs* args) override {}
+    void notifySwitch(const NotifySwitchArgs* args) override {}
+    void notifyDeviceReset(const NotifyDeviceResetArgs* args) override {}
+};
+
+class FuzzInputReaderContext : public InputReaderContext {
+    std::shared_ptr<EventHubInterface> mEventHub;
+    sp<InputReaderPolicyInterface> mPolicy;
+    sp<InputListenerInterface> mListener;
+    std::shared_ptr<FuzzedDataProvider> fdp;
+
+public:
+    FuzzInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
+                           const sp<InputReaderPolicyInterface>& policy,
+                           const sp<InputListenerInterface>& listener,
+                           std::shared_ptr<FuzzedDataProvider> fdp)
+          : mEventHub(eventHub), mPolicy(policy), mListener(listener), fdp(fdp) {}
+    ~FuzzInputReaderContext() {}
+    void updateGlobalMetaState() override {}
+    int32_t getGlobalMetaState() { return fdp->ConsumeIntegral<int32_t>(); }
+    void disableVirtualKeysUntil(nsecs_t time) override {}
+    bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override {
+        return fdp->ConsumeBool();
+    }
+    void fadePointer() override {}
+    std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override {
+        return mPolicy->obtainPointerController(0);
+    }
+    void requestTimeoutAtTime(nsecs_t when) override {}
+    int32_t bumpGeneration() override { return fdp->ConsumeIntegral<int32_t>(); }
+    void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {}
+    void dispatchExternalStylusState(const StylusState& outState) override {}
+    InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); }
+    InputListenerInterface* getListener() override { return mListener.get(); }
+    EventHubInterface* getEventHub() override { return mEventHub.get(); }
+    int32_t getNextId() override { return fdp->ConsumeIntegral<int32_t>(); }
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
new file mode 100644
index 0000000..336ecb6
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2020 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 <FuzzContainer.h>
+#include <MultiTouchInputMapper.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) {
+    // Pick a random property to set for the mapper to have set.
+    fdp->PickValueInArray<std::function<void()>>(
+            {[&]() -> void {
+                 fuzzer.addProperty(String8("touch.deviceType"), String8("touchScreen"));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.deviceType"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.size.scale"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.size.bias"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.size.isSummed"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.size.calibration"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.pressure.scale"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.size.calibration"),
+                                    fdp->ConsumeBool() ? String8("diameter") : String8("area"));
+             },
+             [&]() -> void {
+                 fuzzer.addProperty(String8("touch.pressure.calibration"),
+                                    String8(fdp->ConsumeRandomLengthString(8).data()));
+             }})();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    FuzzContainer fuzzer = FuzzContainer(fdp);
+
+    MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>();
+    auto policyConfig = fuzzer.getPolicyConfig();
+
+    // Loop through mapper operations until randomness is exhausted.
+    while (fdp->remaining_bytes() > 0) {
+        fdp->PickValueInArray<std::function<void()>>({
+                [&]() -> void { addProperty(fuzzer, fdp); },
+                [&]() -> void {
+                    std::string dump;
+                    mapper.dump(dump);
+                },
+                [&]() -> void {
+                    InputDeviceInfo info;
+                    mapper.populateDeviceInfo(&info);
+                },
+                [&]() -> void { mapper.getSources(); },
+                [&]() -> void {
+                    mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig,
+                                     fdp->ConsumeIntegral<uint32_t>());
+                },
+                [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); },
+                [&]() -> void {
+                    RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>()};
+                    mapper.process(&rawEvent);
+                },
+                [&]() -> void {
+                    mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(),
+                                           fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(),
+                                            fdp->ConsumeIntegral<int32_t>());
+                },
+                [&]() -> void {
+                    mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(),
+                                                 fdp->ConsumeIntegral<size_t>(), nullptr, nullptr);
+                },
+                [&]() -> void { mapper.cancelTouch(fdp->ConsumeIntegral<nsecs_t>()); },
+                [&]() -> void { mapper.timeoutExpired(fdp->ConsumeIntegral<nsecs_t>()); },
+                [&]() -> void {
+                    StylusState state{fdp->ConsumeIntegral<nsecs_t>(),
+                                      fdp->ConsumeFloatingPoint<float>(),
+                                      fdp->ConsumeIntegral<uint32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>()};
+                    mapper.updateExternalStylusState(state);
+                },
+                [&]() -> void { mapper.getAssociatedDisplayId(); },
+        })();
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
new file mode 100644
index 0000000..ae7429c
--- /dev/null
+++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020 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 <FuzzContainer.h>
+#include <SwitchInputMapper.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
+    std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size);
+    FuzzContainer fuzzer = FuzzContainer(fdp);
+
+    SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>();
+    auto policyConfig = fuzzer.getPolicyConfig();
+
+    // Loop through mapper operations until randomness is exhausted.
+    while (fdp->remaining_bytes() > 0) {
+        fdp->PickValueInArray<std::function<void()>>({
+                [&]() -> void {
+                    std::string dump;
+                    mapper.dump(dump);
+                },
+                [&]() -> void { mapper.getSources(); },
+                [&]() -> void {
+                    RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>(),
+                                      fdp->ConsumeIntegral<int32_t>()};
+                    mapper.process(&rawEvent);
+                },
+                [&]() -> void {
+                    mapper.getSwitchState(fdp->ConsumeIntegral<uint32_t>(),
+                                          fdp->ConsumeIntegral<int32_t>());
+                },
+        })();
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/services/memtrackproxy/Android.bp b/services/memtrackproxy/Android.bp
new file mode 100644
index 0000000..7d78f3b
--- /dev/null
+++ b/services/memtrackproxy/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_library_shared {
+    name: "libmemtrackproxy",
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libbinder",
+        "libhidlbase",
+        "liblog",
+        "libcutils",
+        "libutils",
+        "android.hardware.memtrack@1.0",
+        "android.hardware.memtrack-V1-ndk_platform",
+    ],
+    srcs: [
+        "MemtrackProxy.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    local_include_dirs: [
+        "include/memtrackproxy",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.memtrack@1.0",
+        "android.hardware.memtrack-V1-ndk_platform",
+    ],
+}
diff --git a/services/memtrackproxy/MemtrackProxy.cpp b/services/memtrackproxy/MemtrackProxy.cpp
new file mode 100644
index 0000000..4676167
--- /dev/null
+++ b/services/memtrackproxy/MemtrackProxy.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2021 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 "MemtrackProxy.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <private/android_filesystem_config.h>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+// Check Memtrack Flags
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SMAPS_ACCOUNTED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SMAPS_ACCOUNTED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SMAPS_UNACCOUNTED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SMAPS_UNACCOUNTED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SHARED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SHARED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SHARED_PSS) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SHARED_PSS));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::PRIVATE) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_PRIVATE));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SYSTEM) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SYSTEM));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::DEDICATED) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_DEDICATED));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::NONSECURE) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_NONSECURE));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackFlag::SECURE) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackRecord::FLAG_SECURE));
+
+// Check Memtrack Types
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::OTHER) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::OTHER));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::GL) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::GL));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::GRAPHICS) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::GRAPHICS));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::MULTIMEDIA) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::MULTIMEDIA));
+static_assert(static_cast<uint32_t>(V1_0_hidl::MemtrackType::CAMERA) ==
+              static_cast<uint32_t>(V1_aidl::MemtrackType::CAMERA));
+
+__attribute__((warn_unused_result)) bool translate(const V1_0_hidl::MemtrackRecord& in,
+                                                   V1_aidl::MemtrackRecord* out) {
+    // Convert uint64_t to int64_t (long in AIDL). AIDL doesn't support unsigned types.
+    if (in.sizeInBytes > std::numeric_limits<int64_t>::max() || in.sizeInBytes < 0) {
+        return false;
+    }
+    out->sizeInBytes = static_cast<int64_t>(in.sizeInBytes);
+
+    // It's ok to just assign directly, since this is a bitmap.
+    out->flags = in.flags;
+    return true;
+}
+
+sp<V1_0_hidl::IMemtrack> MemtrackProxy::MemtrackHidlInstance() {
+    return V1_0_hidl::IMemtrack::getService();
+}
+
+std::shared_ptr<V1_aidl::IMemtrack> MemtrackProxy::MemtrackAidlInstance() {
+    const auto instance = std::string() + V1_aidl::IMemtrack::descriptor + "/default";
+    bool declared = AServiceManager_isDeclared(instance.c_str());
+    if (!declared) {
+        return nullptr;
+    }
+    ndk::SpAIBinder memtrack_binder =
+            ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str()));
+    return V1_aidl::IMemtrack::fromBinder(memtrack_binder);
+}
+
+bool MemtrackProxy::CheckUid(uid_t calling_uid) {
+    // Allow AID_SHELL for adb shell dumpsys meminfo
+    return calling_uid == AID_SYSTEM || calling_uid == AID_ROOT || calling_uid == AID_SHELL;
+}
+
+bool MemtrackProxy::CheckPid(pid_t calling_pid, pid_t request_pid) {
+    return calling_pid == request_pid;
+}
+
+MemtrackProxy::MemtrackProxy()
+      : memtrack_hidl_instance_(MemtrackProxy::MemtrackHidlInstance()),
+        memtrack_aidl_instance_(MemtrackProxy::MemtrackAidlInstance()) {}
+
+ndk::ScopedAStatus MemtrackProxy::getMemory(int pid, MemtrackType type,
+                                            std::vector<MemtrackRecord>* _aidl_return) {
+    if (pid < 0) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    if (!MemtrackProxy::CheckPid(AIBinder_getCallingPid(), pid) &&
+        !MemtrackProxy::CheckUid(AIBinder_getCallingUid())) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                EX_SECURITY,
+                "Only AID_ROOT, AID_SYSTEM and AID_SHELL can request getMemory() for PIDs other "
+                "than the calling PID");
+    }
+
+    if (type != MemtrackType::OTHER && type != MemtrackType::GL && type != MemtrackType::GRAPHICS &&
+        type != MemtrackType::MULTIMEDIA && type != MemtrackType::CAMERA) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+    }
+
+    _aidl_return->clear();
+
+    if (memtrack_aidl_instance_) {
+        return memtrack_aidl_instance_->getMemory(pid, type, _aidl_return);
+    } else if (memtrack_hidl_instance_) {
+        ndk::ScopedAStatus aidl_status;
+
+        Return<void> ret = memtrack_hidl_instance_->getMemory(
+                pid, static_cast<V1_0_hidl::MemtrackType>(type),
+                [&_aidl_return, &aidl_status](V1_0_hidl::MemtrackStatus status,
+                                              hidl_vec<V1_0_hidl::MemtrackRecord> records) {
+                    switch (status) {
+                        case V1_0_hidl::MemtrackStatus::SUCCESS:
+                            aidl_status = ndk::ScopedAStatus::ok();
+                            break;
+                        case V1_0_hidl::MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
+                            [[fallthrough]];
+                        case V1_0_hidl::MemtrackStatus::TYPE_NOT_SUPPORTED:
+                            [[fallthrough]];
+                        default:
+                            aidl_status =
+                                    ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+                            return;
+                    }
+
+                    _aidl_return->resize(records.size());
+                    for (size_t i = 0; i < records.size(); i++) {
+                        if (!translate(records[i], &(*_aidl_return)[i])) {
+                            aidl_status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                                    EX_SERVICE_SPECIFIC,
+                                    "Failed to convert HIDL MemtrackRecord to AIDL");
+                            return;
+                        }
+                    }
+                });
+
+        // Check HIDL return
+        if (!ret.isOk()) {
+            const char* err_msg = "HIDL Memtrack::getMemory() failed";
+            aidl_status =
+                    ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC, err_msg);
+            LOG(ERROR) << err_msg << ": " << ret.description();
+        }
+
+        return aidl_status;
+    }
+
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+                                                            "Memtrack HAL service not available");
+}
+
+ndk::ScopedAStatus MemtrackProxy::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
+    if (!MemtrackProxy::CheckUid(AIBinder_getCallingUid())) {
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SECURITY,
+                "Only AID_ROOT, AID_SYSTEM and AID_SHELL can request getGpuDeviceInfo()");
+    }
+
+    _aidl_return->clear();
+
+    if (memtrack_aidl_instance_ ||
+        (memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance())) {
+        return memtrack_aidl_instance_->getGpuDeviceInfo(_aidl_return);
+    }
+
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+                                                            "Memtrack HAL service not available");
+}
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/services/memtrackproxy/include/memtrackproxy/MemtrackProxy.h b/services/memtrackproxy/include/memtrackproxy/MemtrackProxy.h
new file mode 100644
index 0000000..5ac1fbf
--- /dev/null
+++ b/services/memtrackproxy/include/memtrackproxy/MemtrackProxy.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/memtrack/BnMemtrack.h>
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/IMemtrack.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+
+using ::android::sp;
+
+namespace V1_0_hidl = ::android::hardware::memtrack::V1_0;
+namespace V1_aidl = ::aidl::android::hardware::memtrack;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+__attribute__((warn_unused_result)) bool translate(const V1_0_hidl::MemtrackRecord& in,
+                                                   V1_aidl::MemtrackRecord* out);
+
+class MemtrackProxy : public BnMemtrack {
+public:
+    MemtrackProxy();
+    ndk::ScopedAStatus getMemory(int pid, MemtrackType type,
+                                 std::vector<MemtrackRecord>* _aidl_return) override;
+    ndk::ScopedAStatus getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) override;
+
+private:
+    static sp<V1_0_hidl::IMemtrack> MemtrackHidlInstance();
+    static std::shared_ptr<V1_aidl::IMemtrack> MemtrackAidlInstance();
+    static bool CheckUid(uid_t calling_uid);
+    static bool CheckPid(pid_t calling_pid, pid_t request_pid);
+
+    sp<V1_0_hidl::IMemtrack> memtrack_hidl_instance_;
+    std::shared_ptr<V1_aidl::IMemtrack> memtrack_aidl_instance_;
+};
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/services/memtrackproxy/test/Android.bp b/services/memtrackproxy/test/Android.bp
new file mode 100644
index 0000000..f943761
--- /dev/null
+++ b/services/memtrackproxy/test/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_test {
+    name: "memtrackproxy_test",
+    srcs: [
+        "MemtrackProxyTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libmemtrackproxy",
+        "android.hardware.memtrack-V1-ndk_platform",
+    ],
+    test_suites: ["general-tests"],
+    require_root: true,
+}
diff --git a/services/memtrackproxy/test/MemtrackProxyTest.cpp b/services/memtrackproxy/test/MemtrackProxyTest.cpp
new file mode 100644
index 0000000..16dfba0
--- /dev/null
+++ b/services/memtrackproxy/test/MemtrackProxyTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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 <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/IMemtrack.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+using aidl::android::hardware::memtrack::DeviceInfo;
+using aidl::android::hardware::memtrack::IMemtrack;
+using aidl::android::hardware::memtrack::MemtrackRecord;
+using aidl::android::hardware::memtrack::MemtrackType;
+
+class MemtrackProxyTest : public ::testing::Test {
+public:
+    virtual void SetUp() override {
+        const char* kMemtrackProxyService = "memtrack.proxy";
+        auto memtrackProxyBinder =
+                ndk::SpAIBinder(AServiceManager_waitForService(kMemtrackProxyService));
+        memtrack_proxy_ = IMemtrack::fromBinder(memtrackProxyBinder);
+        ASSERT_NE(memtrack_proxy_, nullptr);
+    }
+
+    std::shared_ptr<IMemtrack> memtrack_proxy_;
+};
+
+TEST_F(MemtrackProxyTest, GetMemoryForInvalidPid) {
+    int pid = -1;
+
+    for (MemtrackType type : ndk::enum_range<MemtrackType>()) {
+        std::vector<MemtrackRecord> records;
+
+        auto status = memtrack_proxy_->getMemory(pid, type, &records);
+
+        EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+    }
+}
+
+TEST_F(MemtrackProxyTest, GetMemoryForCallingPid) {
+    int pid = getpid();
+
+    for (MemtrackType type : ndk::enum_range<MemtrackType>()) {
+        std::vector<MemtrackRecord> records;
+
+        auto status = memtrack_proxy_->getMemory(pid, type, &records);
+
+        EXPECT_TRUE(status.isOk());
+    }
+}
+
+TEST_F(MemtrackProxyTest, GetMemoryForOtherPid) {
+    int pid = 1;
+
+    for (MemtrackType type : ndk::enum_range<MemtrackType>()) {
+        std::vector<MemtrackRecord> records;
+
+        auto status = memtrack_proxy_->getMemory(pid, type, &records);
+
+        // Test is run as root
+        EXPECT_TRUE(status.isOk());
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index b0d3e3b..19b6a0f 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libpowermanager",
 
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 73802db..4ef72d0 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libschedulerservicehidl",
     srcs: [
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 532a2e5..4151b45 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -1,6 +1,12 @@
-subdirs = [
-    "hidl"
-]
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libsensorservice",
 
@@ -43,9 +49,12 @@
         "libhardware_legacy",
         "libutils",
         "liblog",
+        "libactivitymanager_aidl",
+        "libbatterystats_aidl",
         "libbinder",
         "libsensor",
         "libsensorprivacy",
+        "libpermission",
         "libprotoutil",
         "libcrypto",
         "libbase",
@@ -62,8 +71,12 @@
 
     generated_headers: ["framework-cppstream-protos"],
 
-    // our public headers depend on libsensor and libsensorprivacy
-    export_shared_lib_headers: ["libsensor", "libsensorprivacy"],
+    export_shared_lib_headers: [
+        "libactivitymanager_aidl",
+        "libsensor",
+        "libsensorprivacy",
+        "libpermission",
+    ],
 }
 
 cc_binary {
diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h
index 43a750c..09eb2c1 100644
--- a/services/sensorservice/BatteryService.h
+++ b/services/sensorservice/BatteryService.h
@@ -17,7 +17,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <binder/IBatteryStats.h>
+#include <batterystats/IBatteryStats.h>
 #include <utils/Singleton.h>
 
 namespace android {
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index e355594..4d4cac5 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -689,9 +689,9 @@
         ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%zd", info.batchParams.indexOfKey(ident));
 
         if (isClientDisabledLocked(ident)) {
-            ALOGE("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
+            ALOGW("SensorDevice::activate, isClientDisabledLocked(%p):true, handle:%d",
                     ident, handle);
-            return INVALID_OPERATION;
+            return NO_ERROR;
         }
 
         if (info.batchParams.indexOfKey(ident) >= 0) {
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index d14a301..3cccaf9 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <log/log.h>
 #include <sys/socket.h>
 #include <utils/threads.h>
 
@@ -53,20 +54,13 @@
 SensorService::SensorEventConnection::~SensorEventConnection() {
     ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
     destroy();
-}
-
-void SensorService::SensorEventConnection::destroy() {
-    Mutex::Autolock _l(mDestroyLock);
-
-    // destroy once only
-    if (mDestroyed) {
-        return;
-    }
-
     mService->cleanupConnection(this);
     if (mEventCache != nullptr) {
         delete[] mEventCache;
     }
+}
+
+void SensorService::SensorEventConnection::destroy() {
     mDestroyed = true;
 }
 
@@ -679,6 +673,11 @@
         int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
         int reservedFlags)
 {
+    if (mDestroyed) {
+        android_errorWriteLog(0x534e4554, "168211968");
+        return DEAD_OBJECT;
+    }
+
     status_t err;
     if (enabled) {
         err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
@@ -693,10 +692,19 @@
 status_t SensorService::SensorEventConnection::setEventRate(
         int handle, nsecs_t samplingPeriodNs)
 {
+    if (mDestroyed) {
+        android_errorWriteLog(0x534e4554, "168211968");
+        return DEAD_OBJECT;
+    }
+
     return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
 }
 
 status_t  SensorService::SensorEventConnection::flush() {
+    if (mDestroyed) {
+        return DEAD_OBJECT;
+    }
+
     return  mService->flushSensor(this, mOpPackageName);
 }
 
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 8f2d5db..9487a39 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SENSOR_EVENT_CONNECTION_H
 #define ANDROID_SENSOR_EVENT_CONNECTION_H
 
+#include <atomic>
 #include <stdint.h>
 #include <sys/types.h>
 #include <unordered_map>
@@ -182,8 +183,8 @@
     int mTotalAcksNeeded, mTotalAcksReceived;
 #endif
 
-    mutable Mutex mDestroyLock;
-    bool mDestroyed;
+    // Used to track if this object was inappropriately used after destroy().
+    std::atomic_bool mDestroyed;
 
     // Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
     // valid mapping for sensors that require a permission in order to reduce the lookup time.
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index 0e1af59..9bafb3c 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libsensorservicehidl",
     srcs: [
diff --git a/services/sensorservice/tests/Android.bp b/services/sensorservice/tests/Android.bp
index d33c0ca..ddc03a1 100644
--- a/services/sensorservice/tests/Android.bp
+++ b/services/sensorservice/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-sensorservice",
     srcs: ["sensorservicetest.cpp"],
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 1ce0524..58e5993 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libstatshidl",
     srcs: [
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index bdd04db..6b3bf8d 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "surfaceflinger_defaults",
     cflags: [
@@ -20,7 +29,6 @@
         "-DEGL_EGLEXT_PROTOTYPES",
     ],
     shared_libs: [
-        "android.frameworks.vr.composer@2.0",
         "android.hardware.configstore-utils",
         "android.hardware.configstore@1.0",
         "android.hardware.configstore@1.1",
@@ -33,7 +41,7 @@
         "android.hardware.graphics.composer@2.4",
         "android.hardware.power@1.0",
         "android.hardware.power@1.3",
-        "android.hardware.power-cpp",
+        "android.hardware.power-V1-cpp",
         "libbase",
         "libbinder",
         "libbufferhubqueue",
@@ -58,21 +66,12 @@
         "libutils",
         "libSurfaceFlingerProp",
     ],
-    // VrComposer is not used when building surfaceflinger for vendors
-    target: {
-        vendor: {
-            exclude_shared_libs: [
-                "android.frameworks.vr.composer@2.0",
-            ],
-        },
-    },
     static_libs: [
         "libcompositionengine",
         "libperfetto_client_experimental",
         "librenderengine",
         "libserviceutils",
         "libtrace_proto",
-        "libvrflinger",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
@@ -113,6 +112,10 @@
         thin: true,
     },
     whole_program_vtables: true, // Requires ThinLTO
+    pgo: {
+        sampling: true,
+        profile_file: "surfaceflinger/surfaceflinger.profdata",
+    },
     // TODO(b/131771163): Fix broken fuzzer support with LTO.
     sanitize: {
         fuzzer: false,
@@ -198,17 +201,6 @@
         // can be easily replaced.
         "SurfaceFlingerFactory.cpp",
     ],
-    cflags: [
-        "-DUSE_VR_COMPOSER=1",
-    ],
-    // VrComposer is not used when building surfaceflinger for vendors
-    target: {
-        vendor: {
-            cflags: [
-                "-DUSE_VR_COMPOSER=0",
-            ],
-        },
-    },
     logtags: ["EventLog/EventLogTags.logtags"],
 }
 
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f0b0200..082356d 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -176,10 +176,17 @@
         if (!holes.isEmpty()) {
             targetSettings.clearRegion.orSelf(holes);
         }
-        return std::nullopt;
+
+        if (mSidebandStream != nullptr) {
+            // For surfaceview of tv sideband, there is no activeBuffer
+            // in bufferqueue, we need return LayerSettings.
+            return result;
+        } else {
+            return std::nullopt;
+        }
     }
     bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
-            (isSecure() && !targetSettings.isSecure);
+            ((isSecure() || isProtected()) && !targetSettings.isSecure);
     compositionengine::LayerFE::LayerSettings& layer = *result;
     if (blackOutLayer) {
         prepareClearClientComposition(layer, true /* blackout */);
@@ -204,8 +211,8 @@
     layer.frameNumber = mCurrentFrameNumber;
     layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
 
-    // TODO: we could be more subtle with isFixedSize()
-    const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || isFixedSize();
+    const bool useFiltering =
+            targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
 
     // Query the texture matrix given our current filtering mode.
     float textureMatrix[16];
@@ -840,6 +847,36 @@
     }
 }
 
+bool BufferLayer::bufferNeedsFiltering() const {
+    // Layers that don't resize along with their buffer, don't need filtering.
+    if (!isFixedSize()) {
+        return false;
+    }
+
+    if (!mBufferInfo.mBuffer) {
+        return false;
+    }
+
+    uint32_t bufferWidth = mBufferInfo.mBuffer->width;
+    uint32_t bufferHeight = mBufferInfo.mBuffer->height;
+
+    // Undo any transformations on the buffer and return the result.
+    const State& s(getDrawingState());
+    if (s.transform & ui::Transform::ROT_90) {
+        std::swap(bufferWidth, bufferHeight);
+    }
+
+    if (s.transformToDisplayInverse) {
+        uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+        if (invTransform & ui::Transform::ROT_90) {
+            std::swap(bufferWidth, bufferHeight);
+        }
+    }
+
+    const Rect layerSize{getBounds()};
+    return layerSize.width() != bufferWidth || layerSize.height() != bufferHeight;
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 26bfb49..c7e8ad7 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -118,6 +118,10 @@
 
     ui::Transform::RotationFlags getTransformHint() const override { return mTransformHint; }
 
+    // Returns true if the transformed buffer size does not match the layer size and we need
+    // to apply filtering.
+    bool bufferNeedsFiltering() const;
+
     // -----------------------------------------------------------------------
     // Functions that must be implemented by derived classes
     // -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index ec73b9d..d94347a 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -825,6 +825,7 @@
                                         static_cast<float>(s.active.transform.ty() + s.active.h)),
                               radius);
 }
+
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index b37ca33..3f63951 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "libcompositionengine_defaults",
     defaults: ["surfaceflinger_defaults"],
@@ -6,7 +15,6 @@
         "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
     ],
     shared_libs: [
-        "android.frameworks.vr.composer@2.0",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index b4ed92f..77400eb 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -130,16 +130,6 @@
     Rect geomContentCrop;
     Rect geomCrop;
 
-    /*
-     * Extra metadata
-     */
-
-    // The type for this layer
-    int type{0};
-
-    // The appId for this layer
-    int appId{0};
-
     GenericLayerMetadataMap metadata;
 
     /*
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
index 02e3a45..1338538 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
@@ -75,10 +75,6 @@
     dumpVal(out, "alpha", alpha);
     dumpVal(out, "backgroundBlurRadius", backgroundBlurRadius);
 
-    out.append("\n      ");
-    dumpVal(out, "type", type);
-    dumpVal(out, "appId", appId);
-
     if (!metadata.empty()) {
         out.append("\n      metadata {");
         for (const auto& [key, entry] : metadata) {
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 34dc536..d3247e1 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -835,6 +835,8 @@
             needsProtected == renderEngine.isProtected()) {
             mRenderSurface->setProtected(needsProtected);
         }
+    } else if (!outputState.isSecure && renderEngine.isProtected()) {
+        renderEngine.useProtectedContext(false);
     }
 
     base::unique_fd fd;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 1faf775..3aed7f5 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -402,13 +402,6 @@
               outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error));
     }
 
-    if (auto error = hwcLayer->setInfo(static_cast<uint32_t>(outputIndependentState.type),
-                                       static_cast<uint32_t>(outputIndependentState.appId));
-        error != hal::Error::NONE) {
-        ALOGE("[%s] Failed to set info %s (%d)", getLayerFE().getDebugName(),
-              to_string(error).c_str(), static_cast<int32_t>(error));
-    }
-
     for (const auto& [name, entry] : outputIndependentState.metadata) {
         if (auto error = hwcLayer->setLayerGenericMetadata(name, entry.mandatory, entry.value);
             error != hal::Error::NONE) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 09f37fb..29fd4b9 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -159,6 +159,7 @@
         EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
         EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
         EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+        EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     }
 
     DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() {
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index d21b97e..87911cc 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -66,7 +66,6 @@
     MOCK_METHOD1(setTransform, Error(hal::Transform));
     MOCK_METHOD1(setVisibleRegion, Error(const android::Region&));
     MOCK_METHOD1(setZOrder, Error(uint32_t));
-    MOCK_METHOD2(setInfo, Error(uint32_t, uint32_t));
 
     MOCK_METHOD1(setColorTransform, Error(const android::mat4&));
     MOCK_METHOD3(setLayerGenericMetadata,
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 020f93a..c32ef11 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -676,8 +676,6 @@
     static constexpr Hwc2::IComposerClient::BlendMode kBlendMode =
             static_cast<Hwc2::IComposerClient::BlendMode>(41);
     static constexpr float kAlpha = 51.f;
-    static constexpr uint32_t kType = 61u;
-    static constexpr uint32_t kAppId = 62u;
     static constexpr ui::Dataspace kDataspace = static_cast<ui::Dataspace>(71);
     static constexpr int kSupportedPerFrameMetadata = 101;
     static constexpr int kExpectedHwcSlot = 0;
@@ -711,8 +709,6 @@
 
         mLayerFEState.blendMode = kBlendMode;
         mLayerFEState.alpha = kAlpha;
-        mLayerFEState.type = kType;
-        mLayerFEState.appId = kAppId;
         mLayerFEState.colorTransform = kColorTransform;
         mLayerFEState.color = kColor;
         mLayerFEState.surfaceDamage = kSurfaceDamage;
@@ -746,7 +742,6 @@
 
         EXPECT_CALL(*mHwcLayer, setBlendMode(kBlendMode)).WillOnce(Return(kError));
         EXPECT_CALL(*mHwcLayer, setPlaneAlpha(kAlpha)).WillOnce(Return(kError));
-        EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError));
     }
 
     void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 7a06400..8f76afa 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -2871,6 +2871,7 @@
     mOutput.mState.usesClientComposition = false;
 
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
 
@@ -2883,6 +2884,7 @@
     mOutput.mState.flipClientTarget = true;
 
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
@@ -2892,6 +2894,7 @@
 
 TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) {
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
 
@@ -2904,6 +2907,7 @@
     mOutput.mState.flipClientTarget = true;
 
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
 
@@ -2914,6 +2918,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -2936,6 +2941,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -2963,6 +2969,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -2991,6 +2998,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -3019,6 +3027,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -3050,6 +3059,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r2}))
             .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r3}));
@@ -3072,6 +3082,7 @@
 struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComposeSurfacesTest {
     OutputComposeSurfacesTest_UsesExpectedDisplaySettings() {
         EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+        EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
         EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
                 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
         EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -3219,6 +3230,8 @@
     mOutput.mState.isSecure = false;
     mLayer2.mLayerFEState.hasProtectedContent = true;
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
+    EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
+    EXPECT_CALL(mRenderEngine, useProtectedContext(false)).WillOnce(Return(true));
 
     mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
@@ -3311,6 +3324,7 @@
         EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
         EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
         EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+        EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
         EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
                 .WillRepeatedly(Return());
         EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index a3f1b52..1bf43da 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -117,63 +117,7 @@
 
 namespace impl {
 
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize)
-    : CommandWriterBase(initialMaxSize) {}
-
-Composer::CommandWriter::~CommandWriter()
-{
-}
-
-void Composer::CommandWriter::setLayerInfo(uint32_t type, uint32_t appId)
-{
-    constexpr uint16_t kSetLayerInfoLength = 2;
-    beginCommand(static_cast<V2_1::IComposerClient::Command>(
-                         IVrComposerClient::VrCommand::SET_LAYER_INFO),
-                 kSetLayerInfoLength);
-    write(type);
-    write(appId);
-    endCommand();
-}
-
-void Composer::CommandWriter::setClientTargetMetadata(
-        const IVrComposerClient::BufferMetadata& metadata)
-{
-    constexpr uint16_t kSetClientTargetMetadataLength = 7;
-    beginCommand(static_cast<V2_1::IComposerClient::Command>(
-                         IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA),
-                 kSetClientTargetMetadataLength);
-    writeBufferMetadata(metadata);
-    endCommand();
-}
-
-void Composer::CommandWriter::setLayerBufferMetadata(
-        const IVrComposerClient::BufferMetadata& metadata)
-{
-    constexpr uint16_t kSetLayerBufferMetadataLength = 7;
-    beginCommand(static_cast<V2_1::IComposerClient::Command>(
-                         IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA),
-                 kSetLayerBufferMetadataLength);
-    writeBufferMetadata(metadata);
-    endCommand();
-}
-
-void Composer::CommandWriter::writeBufferMetadata(
-        const IVrComposerClient::BufferMetadata& metadata)
-{
-    write(metadata.width);
-    write(metadata.height);
-    write(metadata.stride);
-    write(metadata.layerCount);
-    writeSigned(static_cast<int32_t>(metadata.format));
-    write64(metadata.usage);
-}
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-
-Composer::Composer(const std::string& serviceName)
-    : mWriter(kWriterInitialSize),
-      mIsUsingVrComposer(serviceName == std::string("vr"))
-{
+Composer::Composer(const std::string& serviceName) : mWriter(kWriterInitialSize) {
     mComposer = V2_1::IComposer::getService(serviceName);
 
     if (mComposer == nullptr) {
@@ -215,15 +159,6 @@
     if (mClient == nullptr) {
         LOG_ALWAYS_FATAL("failed to create composer client");
     }
-
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-    if (mIsUsingVrComposer) {
-        sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient);
-        if (vrClient == nullptr) {
-            LOG_ALWAYS_FATAL("failed to create vr composer client");
-        }
-    }
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 }
 
 Composer::~Composer() = default;
@@ -262,10 +197,6 @@
     }
 }
 
-bool Composer::isRemote() {
-    return mClient->isRemote();
-}
-
 void Composer::resetCommands() {
     mWriter.reset();
 }
@@ -587,20 +518,6 @@
 {
     mWriter.selectDisplay(display);
 
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-    if (mIsUsingVrComposer && target.get()) {
-        IVrComposerClient::BufferMetadata metadata = {
-                .width = target->getWidth(),
-                .height = target->getHeight(),
-                .stride = target->getStride(),
-                .layerCount = target->getLayerCount(),
-                .format = static_cast<types::V1_2::PixelFormat>(target->getPixelFormat()),
-                .usage = target->getUsage(),
-        };
-        mWriter.setClientTargetMetadata(metadata);
-    }
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-
     const native_handle_t* handle = nullptr;
     if (target.get()) {
         handle = target->getNativeBuffer()->handle;
@@ -720,20 +637,6 @@
     mWriter.selectDisplay(display);
     mWriter.selectLayer(layer);
 
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-    if (mIsUsingVrComposer && buffer.get()) {
-        IVrComposerClient::BufferMetadata metadata = {
-                .width = buffer->getWidth(),
-                .height = buffer->getHeight(),
-                .stride = buffer->getStride(),
-                .layerCount = buffer->getLayerCount(),
-                .format = static_cast<types::V1_2::PixelFormat>(buffer->getPixelFormat()),
-                .usage = buffer->getUsage(),
-        };
-        mWriter.setLayerBufferMetadata(metadata);
-    }
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-
     const native_handle_t* handle = nullptr;
     if (buffer.get()) {
         handle = buffer->getNativeBuffer()->handle;
@@ -850,27 +753,6 @@
     return Error::NONE;
 }
 
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-Error Composer::setLayerInfo(Display display, Layer layer, uint32_t type,
-                             uint32_t appId)
-{
-    if (mIsUsingVrComposer) {
-        mWriter.selectDisplay(display);
-        mWriter.selectLayer(layer);
-        mWriter.setLayerInfo(type, appId);
-    }
-    return Error::NONE;
-}
-#else
-Error Composer::setLayerInfo(Display display, Layer layer, uint32_t, uint32_t) {
-    if (mIsUsingVrComposer) {
-        mWriter.selectDisplay(display);
-        mWriter.selectLayer(layer);
-    }
-    return Error::NONE;
-}
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-
 Error Composer::execute()
 {
     // prepare input command queue
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 00ef782..5b66809 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -27,9 +27,6 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wconversion"
 
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-#include <android/frameworks/vr/composer/2.0/IVrComposerClient.h>
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 #include <android/hardware/graphics/common/1.1/types.h>
 #include <android/hardware/graphics/composer/2.4/IComposer.h>
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
@@ -47,10 +44,6 @@
 
 namespace Hwc2 {
 
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-using frameworks::vr::composer::V2_0::IVrComposerClient;
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-
 namespace types = hardware::graphics::common;
 
 namespace V2_1 = hardware::graphics::composer::V2_1;
@@ -91,11 +84,6 @@
 
     virtual void registerCallback(const sp<IComposerCallback>& callback) = 0;
 
-    // Returns true if the connected composer service is running in a remote
-    // process, false otherwise. This will return false if the service is
-    // configured in passthrough mode, for example.
-    virtual bool isRemote() = 0;
-
     // Reset all pending commands in the command buffer. Useful if you want to
     // skip a frame but have already queued some commands.
     virtual void resetCommands() = 0;
@@ -104,7 +92,6 @@
     virtual Error executeCommands() = 0;
 
     virtual uint32_t getMaxVirtualDisplayCount() = 0;
-    virtual bool isUsingVrComposer() const = 0;
     virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
                                        Display* outDisplay) = 0;
     virtual Error destroyVirtualDisplay(Display display) = 0;
@@ -188,7 +175,6 @@
     virtual Error setLayerVisibleRegion(Display display, Layer layer,
                                         const std::vector<IComposerClient::Rect>& visible) = 0;
     virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0;
-    virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0;
 
     // Composer HAL 2.2
     virtual Error setLayerPerFrameMetadata(
@@ -344,11 +330,6 @@
 
     void registerCallback(const sp<IComposerCallback>& callback) override;
 
-    // Returns true if the connected composer service is running in a remote
-    // process, false otherwise. This will return false if the service is
-    // configured in passthrough mode, for example.
-    bool isRemote() override;
-
     // Reset all pending commands in the command buffer. Useful if you want to
     // skip a frame but have already queued some commands.
     void resetCommands() override;
@@ -357,7 +338,6 @@
     Error executeCommands() override;
 
     uint32_t getMaxVirtualDisplayCount() override;
-    bool isUsingVrComposer() const override { return mIsUsingVrComposer; }
     Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
                                Display* outDisplay) override;
     Error destroyVirtualDisplay(Display display) override;
@@ -436,7 +416,6 @@
     Error setLayerVisibleRegion(Display display, Layer layer,
                                 const std::vector<IComposerClient::Rect>& visible) override;
     Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
-    Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override;
 
     // Composer HAL 2.2
     Error setLayerPerFrameMetadata(
@@ -490,29 +469,11 @@
             IComposerClient::ClientTargetProperty* outClientTargetProperty) override;
 
 private:
-#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
-    class CommandWriter : public CommandWriterBase {
-    public:
-        explicit CommandWriter(uint32_t initialMaxSize);
-        ~CommandWriter() override;
-
-        void setLayerInfo(uint32_t type, uint32_t appId);
-        void setClientTargetMetadata(
-                const IVrComposerClient::BufferMetadata& metadata);
-        void setLayerBufferMetadata(
-                const IVrComposerClient::BufferMetadata& metadata);
-
-    private:
-        void writeBufferMetadata(
-                const IVrComposerClient::BufferMetadata& metadata);
-    };
-#else
     class CommandWriter : public CommandWriterBase {
     public:
         explicit CommandWriter(uint32_t initialMaxSize) : CommandWriterBase(initialMaxSize) {}
         ~CommandWriter() override {}
     };
-#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 
     // Many public functions above simply write a command into the command
     // queue to batch the calls.  validateDisplay and presentDisplay will call
@@ -531,10 +492,6 @@
         64 * 1024 / sizeof(uint32_t) - 16;
     CommandWriter mWriter;
     CommandReader mReader;
-
-    // When true, the we attach to the vr_hwcomposer service instead of the
-    // hwcomposer. This allows us to redirect surfaces to 3d surfaces in vr.
-    const bool mIsUsingVrComposer;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 08559bd..e6bff04 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -977,12 +977,6 @@
     return static_cast<Error>(intError);
 }
 
-Error Layer::setInfo(uint32_t type, uint32_t appId)
-{
-  auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId);
-  return static_cast<Error>(intError);
-}
-
 // Composer HAL 2.3
 Error Layer::setColorTransform(const android::mat4& matrix) {
     if (matrix == mColorMatrix) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 6819ff4..8bd6ea8 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -380,7 +380,6 @@
     [[clang::warn_unused_result]] virtual hal::Error setVisibleRegion(
             const android::Region& region) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setZOrder(uint32_t z) = 0;
-    [[clang::warn_unused_result]] virtual hal::Error setInfo(uint32_t type, uint32_t appId) = 0;
 
     // Composer HAL 2.3
     [[clang::warn_unused_result]] virtual hal::Error setColorTransform(
@@ -422,7 +421,6 @@
     hal::Error setTransform(hal::Transform transform) override;
     hal::Error setVisibleRegion(const android::Region& region) override;
     hal::Error setZOrder(uint32_t z) override;
-    hal::Error setInfo(uint32_t type, uint32_t appId) override;
 
     // Composer HAL 2.3
     hal::Error setColorTransform(const android::mat4& matrix) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7a2f0f3..7db9359 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -815,10 +815,6 @@
             });
 }
 
-bool HWComposer::isUsingVrComposer() const {
-    return getComposer()->isUsingVrComposer();
-}
-
 status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) {
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
     const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
@@ -883,11 +879,6 @@
 
 bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId,
                                             bool hasDisplayIdentificationData) const {
-    if (isUsingVrComposer() && mInternalHwcDisplayId) {
-        ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
-        return true;
-    }
-
     if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
         ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
               hwcDisplayId);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index c355ebd..e05e41a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -195,8 +195,6 @@
     virtual status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
                                         ui::RenderIntent renderIntent) = 0;
 
-    virtual bool isUsingVrComposer() const = 0;
-
     // Composer 2.4
     virtual DisplayConnectionType getDisplayConnectionType(DisplayId) const = 0;
     virtual bool isVsyncPeriodSwitchSupported(DisplayId displayId) const = 0;
@@ -336,8 +334,6 @@
     status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
                                 ui::RenderIntent renderIntent) override;
 
-    bool isUsingVrComposer() const override;
-
     // Composer 2.4
     DisplayConnectionType getDisplayConnectionType(DisplayId) const override;
     bool isVsyncPeriodSwitchSupported(DisplayId displayId) const override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 55af849..3282a5a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -492,9 +492,6 @@
     compositionState->geomUsesSourceCrop = usesSourceCrop();
     compositionState->isSecure = isSecure();
 
-    compositionState->type = type;
-    compositionState->appId = appId;
-
     compositionState->metadata.clear();
     const auto& supportedMetadata = mFlinger->getHwComposer().getSupportedLayerGenericMetadata();
     for (const auto& [key, mandatory] : supportedMetadata) {
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index f273725..43a6e55 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -1,8 +1,6 @@
 adyabr@google.com
-akrulec@google.com
 alecmouri@google.com
 chaviw@google.com
 lpy@google.com
 racarr@google.com
-stoza@google.com
 vishnun@google.com
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 61f3fbb..708a5b8 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -78,8 +78,12 @@
 
     if (!validate(timestamp)) {
         // VSR could elect to ignore the incongruent timestamp or resetModel(). If ts is ignored,
-        // don't insert this ts into mTimestamps ringbuffer.
-        if (!mTimestamps.empty()) {
+        // don't insert this ts into mTimestamps ringbuffer. If we are still
+        // in the learning phase we should just clear all timestamps and start
+        // over.
+        if (mTimestamps.size() < kMinimumSamplesForPrediction) {
+            clearTimestamps();
+        } else if (!mTimestamps.empty()) {
             mKnownTimestamp =
                     std::max(timestamp, *std::max_element(mTimestamps.begin(), mTimestamps.end()));
         } else {
diff --git a/services/surfaceflinger/StartPropertySetThread.cpp b/services/surfaceflinger/StartPropertySetThread.cpp
index db82772..f42cd53 100644
--- a/services/surfaceflinger/StartPropertySetThread.cpp
+++ b/services/surfaceflinger/StartPropertySetThread.cpp
@@ -31,6 +31,7 @@
     property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
     // Clear BootAnimation exit flag
     property_set("service.bootanim.exit", "0");
+    property_set("service.bootanim.progress", "0");
     // Start BootAnimation if not started
     property_set("ctl.start", "bootanim");
     // Exit immediately
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 39f923f..4698ac6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -46,7 +46,6 @@
 #include <cutils/compiler.h>
 #include <cutils/properties.h>
 #include <dlfcn.h>
-#include <dvr/vr_flinger.h>
 #include <errno.h>
 #include <gui/BufferQueue.h>
 #include <gui/DebugEGLImageTracker.h>
@@ -267,7 +266,6 @@
 bool SurfaceFlinger::useHwcForRgbToYuv;
 uint64_t SurfaceFlinger::maxVirtualDisplaySize;
 bool SurfaceFlinger::hasSyncFramework;
-bool SurfaceFlinger::useVrFlinger;
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
 uint32_t SurfaceFlinger::maxGraphicsWidth;
 uint32_t SurfaceFlinger::maxGraphicsHeight;
@@ -332,9 +330,6 @@
 
     maxVirtualDisplaySize = max_virtual_display_dimension(0);
 
-    // Vr flinger is only enabled on Daydream ready devices.
-    useVrFlinger = use_vr_flinger(false);
-
     maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2);
 
     maxGraphicsWidth = std::max(max_graphics_width(0), 0);
@@ -601,17 +596,6 @@
     if (mWindowManager != 0) {
         mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
     }
-    sp<IBinder> input(defaultServiceManager()->getService(
-            String16("inputflinger")));
-    if (input == nullptr) {
-        ALOGE("Failed to link to input service");
-    } else {
-        mInputFlinger = interface_cast<IInputFlinger>(input);
-    }
-
-    if (mVrFlinger) {
-      mVrFlinger->OnBootFinished();
-    }
 
     // stop boot animation
     // formerly we would just kill the process, but we now ask it to exit so it
@@ -622,7 +606,15 @@
     LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                    ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
 
-    static_cast<void>(schedule([this] {
+    sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));
+
+    static_cast<void>(schedule([=] {
+        if (input == nullptr) {
+            ALOGE("Failed to link to input service");
+        } else {
+            mInputFlinger = interface_cast<IInputFlinger>(input);
+        }
+
         readPersistentProperties();
         mPowerAdvisor.onBootFinished();
         mBootStage = BootStage::FINISHED;
@@ -688,9 +680,6 @@
                         : renderengine::RenderEngine::ContextPriority::MEDIUM)
                 .build()));
     mCompositionEngine->setTimeStats(mTimeStats);
-
-    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
-            "Starting with vr flinger active is not currently supported.");
     mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
     mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId);
     // Process any initial hotplug and resulting display changes.
@@ -700,30 +689,6 @@
     LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
                         "Internal display is disconnected.");
 
-    if (useVrFlinger) {
-        auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
-            // This callback is called from the vr flinger dispatch thread. We
-            // need to call signalTransaction(), which requires holding
-            // mStateLock when we're not on the main thread. Acquiring
-            // mStateLock from the vr flinger dispatch thread might trigger a
-            // deadlock in surface flinger (see b/66916578), so post a message
-            // to be handled on the main thread instead.
-            static_cast<void>(schedule([=] {
-                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
-                mVrFlingerRequestsDisplay = requestDisplay;
-                signalTransaction();
-            }));
-        };
-        mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
-                                            getHwComposer()
-                                                    .fromPhysicalDisplayId(*display->getId())
-                                                    .value_or(0),
-                                            vrFlingerRequestDisplayCallback);
-        if (!mVrFlinger) {
-            ALOGE("Failed to start vrflinger");
-        }
-    }
-
     // initialize our drawing state
     mDrawingState = mCurrentState;
 
@@ -1700,98 +1665,6 @@
     }
 }
 
-void SurfaceFlinger::resetDisplayState() {
-    mScheduler->disableHardwareVsync(true);
-    // Clear the drawing state so that the logic inside of
-    // handleTransactionLocked will fire. It will determine the delta between
-    // mCurrentState and mDrawingState and re-apply all changes when we make the
-    // transition.
-    mDrawingState.displays.clear();
-    mDisplays.clear();
-}
-
-void SurfaceFlinger::updateVrFlinger() {
-    ATRACE_CALL();
-    if (!mVrFlinger)
-        return;
-    bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay;
-    if (vrFlingerRequestsDisplay == getHwComposer().isUsingVrComposer()) {
-        return;
-    }
-
-    if (vrFlingerRequestsDisplay && !getHwComposer().getComposer()->isRemote()) {
-        ALOGE("Vr flinger is only supported for remote hardware composer"
-              " service connections. Ignoring request to transition to vr"
-              " flinger.");
-        mVrFlingerRequestsDisplay = false;
-        return;
-    }
-
-    Mutex::Autolock _l(mStateLock);
-
-    sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
-    LOG_ALWAYS_FATAL_IF(!display);
-
-    const hal::PowerMode currentDisplayPowerMode = display->getPowerMode();
-
-    // Clear out all the output layers from the composition engine for all
-    // displays before destroying the hardware composer interface. This ensures
-    // any HWC layers are destroyed through that interface before it becomes
-    // invalid.
-    for (const auto& [token, displayDevice] : mDisplays) {
-        displayDevice->getCompositionDisplay()->clearOutputLayers();
-    }
-
-    // This DisplayDevice will no longer be relevant once resetDisplayState() is
-    // called below. Clear the reference now so we don't accidentally use it
-    // later.
-    display.clear();
-
-    if (!vrFlingerRequestsDisplay) {
-        mVrFlinger->SeizeDisplayOwnership();
-    }
-
-    resetDisplayState();
-    // Delete the current instance before creating the new one
-    mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
-    mCompositionEngine->setHwComposer(getFactory().createHWComposer(
-            vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName));
-    mCompositionEngine->getHwComposer().setConfiguration(this, ++getBE().mComposerSequenceId);
-
-    LOG_ALWAYS_FATAL_IF(!getHwComposer().getComposer()->isRemote(),
-                        "Switched to non-remote hardware composer");
-
-    if (vrFlingerRequestsDisplay) {
-        mVrFlinger->GrantDisplayOwnership();
-    }
-
-    mVisibleRegionsDirty = true;
-    invalidateHwcGeometry();
-
-    // Re-enable default display.
-    display = getDefaultDisplayDeviceLocked();
-    LOG_ALWAYS_FATAL_IF(!display);
-    setPowerModeInternal(display, currentDisplayPowerMode);
-
-    // Reset the timing values to account for the period of the swapped in HWC
-    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
-    mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
-
-    // The present fences returned from vr_hwc are not an accurate
-    // representation of vsync times.
-    mScheduler->setIgnorePresentFences(getHwComposer().isUsingVrComposer() || !hasSyncFramework);
-
-    // Use phase of 0 since phase is not known.
-    // Use latency of 0, which will snap to the ideal latency.
-    DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
-    setCompositorTimingSnapped(stats, 0);
-
-    mScheduler->resyncToHardwareVsync(false, vsyncPeriod);
-
-    mRepaintEverything = true;
-    setTransactionFlags(eDisplayTransactionNeeded);
-}
-
 sp<Fence> SurfaceFlinger::previousFrameFence() {
     // We are storing the last 2 present fences. If sf's phase offset is to be
     // woken up before the actual vsync but targeting the next vsync, we need to check
@@ -1853,8 +1726,14 @@
     // calculate the expected present time once and use the cached
     // value throughout this frame to make sure all layers are
     // seeing this same value.
-    const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load();
-    mExpectedPresentTime = expectedVSyncTime;
+    if (expectedVSyncTime >= frameStart) {
+        mExpectedPresentTime = expectedVSyncTime;
+    } else {
+        mExpectedPresentTime = mScheduler->getDispSyncExpectedPresentTime(frameStart);
+    }
+
+    const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
+    mScheduledPresentTime = expectedVSyncTime;
 
     // When Backpressure propagation is enabled we want to give a small grace period
     // for the present fence to fire instead of just giving up on this frame to handle cases
@@ -1884,7 +1763,7 @@
     const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed",
                                              framePending ||
                                                      (previousPresentTime >= 0 &&
-                                                      (lastExpectedPresentTime <
+                                                      (lastScheduledPresentTime <
                                                        previousPresentTime - frameMissedSlop))};
     const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed",
                                                 mHadDeviceComposition && frameMissed};
@@ -1960,11 +1839,6 @@
         }
     }
 
-    // Now that we're going to make it to the handleMessageTransaction()
-    // call below it's safe to call updateVrFlinger(), which will
-    // potentially trigger a display handoff.
-    updateVrFlinger();
-
     if (mTracingEnabledChanged) {
         mTracingEnabled = mTracing.isEnabled();
         mTracingEnabledChanged = false;
@@ -2611,7 +2485,7 @@
     builder.setIsSecure(state.isSecure);
     builder.setLayerStackId(state.layerStack);
     builder.setPowerAdvisor(&mPowerAdvisor);
-    builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer());
+    builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays);
     builder.setName(state.displayName);
     const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
 
@@ -4501,12 +4375,9 @@
 
 void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) {
     result.append("Layer frame timestamps:\n");
-
-    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
-    const size_t count = currentLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        currentLayers[i]->dumpFrameEvents(result);
-    }
+    // Traverse all layers to dump frame-events for each layer
+    mCurrentState.traverseInZOrder(
+        [&] (Layer* layer) { layer->dumpFrameEvents(result); });
 }
 
 void SurfaceFlinger::dumpBufferingStats(std::string& result) const {
@@ -4835,15 +4706,6 @@
     const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
     alloc.dump(result);
 
-    /*
-     * Dump VrFlinger state if in use.
-     */
-    if (mVrFlingerRequestsDisplay && mVrFlinger) {
-        result.append("VrFlinger state:\n");
-        result.append(mVrFlinger->Dump());
-        result.append("\n");
-    }
-
     result.append(mTimeStats->miniDump());
     result.append("\n");
 }
@@ -5226,11 +5088,8 @@
                 }
                 return NO_ERROR;
             }
-            // Is VrFlinger active?
-            case 1028: {
-                Mutex::Autolock _l(mStateLock);
-                reply->writeBool(getHwComposer().isUsingVrComposer());
-                return NO_ERROR;
+            case 1028: { // Unused.
+                return NAME_NOT_FOUND;
             }
             // Set buffer size for SF tracing (value in KB)
             case 1029: {
@@ -6209,9 +6068,6 @@
     // on the work to remove the table in that bug rather than adding more to
     // it.
     static const std::unordered_map<std::string, uint32_t> genericLayerMetadataKeyMap{
-            // Note: METADATA_OWNER_UID and METADATA_WINDOW_TYPE are officially
-            // supported, and exposed via the
-            // IVrComposerClient::VrCommand::SET_LAYER_INFO command.
             {"org.chromium.arc.V1_0.TaskId", METADATA_TASK_ID},
             {"org.chromium.arc.V1_0.CursorInfo", METADATA_MOUSE_CURSOR},
     };
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c727574..90ac856 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -109,10 +109,6 @@
 class RenderEngine;
 } // namespace renderengine
 
-namespace dvr {
-class VrFlinger;
-} // namespace dvr
-
 enum {
     eTransactionNeeded = 0x01,
     eTraversalNeeded = 0x02,
@@ -798,8 +794,7 @@
     // The following thread safety rules apply when accessing mHwc, either
     // directly or via getHwComposer():
     //
-    // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc
-    //    only when switching into and out of vr. Recreating mHwc must only be
+    // 1. When recreating mHwc, acquire mStateLock. Recreating mHwc must only be
     //    done on the main thread.
     //
     // 2. When accessing mHwc on the main thread, it's not necessary to acquire
@@ -983,14 +978,6 @@
 
     void onFrameRateFlexibilityTokenReleased();
 
-    /* ------------------------------------------------------------------------
-     * VrFlinger
-     */
-    void resetDisplayState() REQUIRES(mStateLock);
-
-    // Check to see if we should handoff to vr flinger.
-    void updateVrFlinger();
-
     void updateColorMatrixLocked();
 
     /* ------------------------------------------------------------------------
@@ -1175,9 +1162,6 @@
     // to mWindowManager or mInputFlinger
     std::atomic<bool> mBootFinished = false;
 
-    std::unique_ptr<dvr::VrFlinger> mVrFlinger;
-    std::atomic<bool> mVrFlingerRequestsDisplay = false;
-    static bool useVrFlinger;
     std::thread::id mMainThreadId = std::this_thread::get_id();
 
     DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::kEnhanced;
@@ -1215,6 +1199,7 @@
     std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
 
     std::atomic<nsecs_t> mExpectedPresentTime = 0;
+    nsecs_t mScheduledPresentTime = 0;
     hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE;
 
     /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 3901757..d6d0cb8 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libtimestats",
     srcs: [
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
index 1441f91..ded3ebb 100644
--- a/services/surfaceflinger/TimeStats/OWNERS
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -1,2 +1 @@
 alecmouri@google.com
-zzyiwei@google.com
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
index b937f41..4743098 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libtimestats_proto",
     export_include_dirs: ["include"],
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index d03cb7b..7f8da5a 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "liblayers_proto",
     export_include_dirs: ["include"],
diff --git a/services/surfaceflinger/sysprop/Android.bp b/services/surfaceflinger/sysprop/Android.bp
index 7721d7d2..f579119 100644
--- a/services/surfaceflinger/sysprop/Android.bp
+++ b/services/surfaceflinger/sysprop/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sysprop_library {
     name: "SurfaceFlingerProperties",
     srcs: ["*.sysprop"],
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 1532855..15744a1 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "SurfaceFlinger_test",
     defaults: ["surfaceflinger_defaults"],
@@ -44,7 +53,7 @@
         "libtrace_proto",
     ],
     shared_libs: [
-        "android.hardware.graphics.common-unstable-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.composer@2.1",
         "libandroid",
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 3535fbb..2551a19 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "sffakehwc_test",
     defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 1bbc3f8..e00c3da 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "libsurfaceflinger_unittest",
     defaults: ["libsurfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 32d722e..faa619e 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -577,8 +577,6 @@
                     .Times(1);
             // TODO: Coverage of other values
             EXPECT_CALL(*test->mComposer, setLayerZOrder(HWC_DISPLAY, HWC_LAYER, 0u)).Times(1);
-            // TODO: Coverage of other values
-            EXPECT_CALL(*test->mComposer, setLayerInfo(HWC_DISPLAY, HWC_LAYER, 0u, 0u)).Times(1);
 
             // These expectations retire on saturation as the code path these
             // expectations are for appears to make an extra call to them.
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 06bdcdc..0323778 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -1298,55 +1298,6 @@
 }
 
 /* ------------------------------------------------------------------------
- * SurfaceFlinger::resetDisplayState
- */
-
-TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) {
-    using Case = NonHwcVirtualDisplayCase;
-
-    // --------------------------------------------------------------------
-    // Preconditions
-
-    // vsync is enabled and available
-    mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = true;
-    mFlinger.scheduler()->mutableHWVsyncAvailable() = true;
-
-    // A display exists
-    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
-    existing.inject();
-
-    // --------------------------------------------------------------------
-    // Call Expectations
-
-    // The call disable vsyncs
-    EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1);
-
-    // The call ends any display resyncs
-    EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1);
-
-    // --------------------------------------------------------------------
-    // Invocation
-
-    mFlinger.resetDisplayState();
-
-    // --------------------------------------------------------------------
-    // Postconditions
-
-    // vsyncs should be off and not available.
-    EXPECT_FALSE(mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled());
-    EXPECT_FALSE(mFlinger.scheduler()->mutableHWVsyncAvailable());
-
-    // The display should have been removed from the display map.
-    EXPECT_FALSE(hasDisplayDevice(existing.token()));
-
-    // The display should still exist in the current state
-    EXPECT_TRUE(hasCurrentDisplayState(existing.token()));
-
-    // The display should have been removed from the drawing state
-    EXPECT_FALSE(hasDrawingDisplayState(existing.token()));
-}
-
-/* ------------------------------------------------------------------------
  * DisplayDevice::GetBestColorMode
  */
 class GetBestColorModeTest : public DisplayTransactionTest {
@@ -2019,8 +1970,6 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillOnce(Return(false));
-
     setupCommonCallExpectationsForConnectProcessing<Case>();
 
     // --------------------------------------------------------------------
@@ -2082,7 +2031,6 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _))
             .Times(0);
 
@@ -2139,20 +2087,9 @@
                             SetArgPointee<2>(TertiaryDisplay::GET_IDENTIFICATION_DATA()),
                             Return(Error::NONE)));
 
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
-
     ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>();
 }
 
-TEST_F(HandleTransactionLockedTest, ignoresHotplugConnectIfExternalForVrComposer) {
-    // Inject a primary display.
-    PrimaryDisplayVariant::injectHwcDisplay(this);
-
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(true));
-
-    ignoresHotplugConnectCommon<SimpleExternalDisplayCase>();
-}
-
 TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) {
     processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>();
 }
@@ -2177,8 +2114,6 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
-
     setupCommonCallExpectationsForConnectProcessing<Case>();
     setupCommonCallExpectationsForDisconnectProcessing<Case>();
 
@@ -2225,8 +2160,6 @@
     // --------------------------------------------------------------------
     // Call Expectations
 
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
-
     setupCommonCallExpectationsForConnectProcessing<Case>();
     setupCommonCallExpectationsForDisconnectProcessing<Case>();
 
@@ -2385,11 +2318,6 @@
     mFlinger.mutableCurrentState().displays.removeItem(existing.token());
 
     // --------------------------------------------------------------------
-    // Call Expectations
-
-    EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
-
-    // --------------------------------------------------------------------
     // Invocation
 
     mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index afd2b71..536207d 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -120,7 +120,8 @@
 
 namespace {
 
-TEST_F(LayerHistoryTestV2, oneLayer) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(LayerHistoryTestV2, DISABLED_oneLayer) {
     const auto layer = createLayer();
     EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
     EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
@@ -631,7 +632,8 @@
     EXPECT_EQ(1, animatingLayerCount(time));
 }
 
-TEST_F(LayerHistoryTestV2, heuristicLayer60Hz) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(LayerHistoryTestV2, DISABLED_heuristicLayer60Hz) {
     const auto layer = createLayer();
     EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
     EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
diff --git a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index 0208728..0b1b8ad 100644
--- a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -80,7 +80,8 @@
     mIdleTimer->stop();
 }
 
-TEST_F(OneShotTimerTest, resetTest) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(OneShotTimerTest, DISABLED_resetTest) {
     mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
                                                            mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
@@ -105,7 +106,8 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(OneShotTimerTest, resetBackToBackTest) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(OneShotTimerTest, DISABLED_resetBackToBackTest) {
     mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
                                                            mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
@@ -136,7 +138,8 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(OneShotTimerTest, startNotCalledTest) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(OneShotTimerTest, DISABLED_startNotCalledTest) {
     mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
                                                            mExpiredTimerCallback.getInvocable());
     // The start hasn't happened, so the callback does not happen.
@@ -148,7 +151,8 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(OneShotTimerTest, idleTimerIdlesTest) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(OneShotTimerTest, DISABLED_idleTimerIdlesTest) {
     mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
                                                            mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
@@ -168,7 +172,8 @@
     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
 }
 
-TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) {
+// TODO(b/186417847) This test is flaky. Reenable once fixed.
+TEST_F(OneShotTimerTest, DISABLED_timeoutCallbackExecutionTest) {
     mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
                                                            mExpiredTimerCallback.getInvocable());
     mIdleTimer->start();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index cbf264d..cd2a482 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -289,8 +289,6 @@
         return mFlinger->destroyDisplay(displayToken);
     }
 
-    auto resetDisplayState() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->resetDisplayState(); }
-
     auto setupNewDisplayDeviceInternal(
             const wp<IBinder>& displayToken,
             std::shared_ptr<compositionengine::Display> compositionDisplay,
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index d4cd11d..5e5d51c 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -450,6 +450,20 @@
     EXPECT_THAT(intercept, Eq(0));
 }
 
+TEST_F(VSyncPredictorTest, InconsistentVsyncValueIsFlushedEventually) {
+    EXPECT_TRUE(tracker.addVsyncTimestamp(600));
+    EXPECT_TRUE(tracker.needsMoreSamples());
+
+    EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod));
+
+    for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
+        EXPECT_TRUE(tracker.needsMoreSamples());
+        EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
+    }
+
+    EXPECT_FALSE(tracker.needsMoreSamples());
+}
+
 } // namespace android::scheduler
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index c2c5072..cd9b87a 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -52,11 +52,9 @@
     MOCK_METHOD0(getCapabilities, std::vector<IComposer::Capability>());
     MOCK_METHOD0(dumpDebugInfo, std::string());
     MOCK_METHOD1(registerCallback, void(const sp<IComposerCallback>&));
-    MOCK_METHOD0(isRemote, bool());
     MOCK_METHOD0(resetCommands, void());
     MOCK_METHOD0(executeCommands, Error());
     MOCK_METHOD0(getMaxVirtualDisplayCount, uint32_t());
-    MOCK_CONST_METHOD0(isUsingVrComposer, bool());
     MOCK_METHOD4(createVirtualDisplay, Error(uint32_t, uint32_t, PixelFormat*, Display*));
     MOCK_METHOD1(destroyVirtualDisplay, Error(Display));
     MOCK_METHOD1(acceptDisplayChanges, Error(Display));
@@ -110,7 +108,6 @@
     MOCK_METHOD3(setLayerVisibleRegion,
                  Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
     MOCK_METHOD3(setLayerZOrder, Error(Display, Layer, uint32_t));
-    MOCK_METHOD4(setLayerInfo, Error(Display, Layer, uint32_t, uint32_t));
     MOCK_METHOD3(getRenderIntents, Error(Display, ColorMode, std::vector<RenderIntent>*));
     MOCK_METHOD3(setLayerColorTransform, Error(Display, Layer, const float*));
     MOCK_METHOD4(getDisplayedContentSamplingAttributes,
diff --git a/services/surfaceflinger/tests/vsync/Android.bp b/services/surfaceflinger/tests/vsync/Android.bp
index 6a89945..bae9796 100644
--- a/services/surfaceflinger/tests/vsync/Android.bp
+++ b/services/surfaceflinger/tests/vsync/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-vsync-events",
     defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.bp b/services/surfaceflinger/tests/waitforvsync/Android.bp
index cb6d0fd..ffed4d7 100644
--- a/services/surfaceflinger/tests/waitforvsync/Android.bp
+++ b/services/surfaceflinger/tests/waitforvsync/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_binary {
     name: "test-waitforvsync",
     cflags: [
diff --git a/services/utils/Android.bp b/services/utils/Android.bp
index f3d2bc9..81e1232 100644
--- a/services/utils/Android.bp
+++ b/services/utils/Android.bp
@@ -15,6 +15,15 @@
 //
 // Static library used in testing and executables
 //
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libserviceutils",
 
diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp
index f21254c..54cf5b7 100644
--- a/services/utils/tests/Android.bp
+++ b/services/utils/tests/Android.bp
@@ -14,6 +14,15 @@
 
 // Build unit tests.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_test {
     name: "prioritydumper_test",
     test_suites: ["device-tests"],
diff --git a/services/vr/Android.bp b/services/vr/Android.bp
index 80df479..980dcf4 100644
--- a/services/vr/Android.bp
+++ b/services/vr/Android.bp
@@ -1,3 +1,13 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 subdirs = [
   "*",
 ]
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 7097e7a..8523bb2 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -12,6 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 sharedLibraries = [
     "libbase",
     "libcutils",
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 3728731..80e9a3c 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libvr_hwc-hal",
 
@@ -97,41 +106,6 @@
     ],
 }
 
-cc_binary {
-    name: "vr_hwc",
-    system_ext_specific: true,
-    vintf_fragments: ["manifest_vr_hwc.xml"],
-    srcs: [
-        "vr_hardware_composer_service.cpp",
-    ],
-    static_libs: [
-        "libvr_hwc-impl",
-        // NOTE: This needs to be included after the *-impl lib otherwise the
-        // symbols in the *-binder library get optimized out.
-        "libvr_hwc-binder",
-    ],
-    shared_libs: [
-        "android.frameworks.vr.composer@2.0",
-        "android.hardware.graphics.composer@2.3",
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libhardware",
-        "libhidlbase",
-        "libui",
-        "libutils",
-        "libvr_hwc-hal",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"vr_hwc\"",
-        "-Wall",
-        "-Werror",
-    ],
-    init_rc: [
-        "vr_hwc.rc",
-    ],
-}
-
 cc_test {
     name: "vr_hwc_test",
     gtest: true,
diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp
index a1d5392..98afdec 100644
--- a/services/vr/hardware_composer/aidl/Android.bp
+++ b/services/vr/hardware_composer/aidl/Android.bp
@@ -1,3 +1,14 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    //   SPDX-license-identifier-Unicode-DFS
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_static {
     name: "libvr_hwc-binder",
     srcs: [
diff --git a/services/vr/hardware_composer/manifest_vr_hwc.xml b/services/vr/hardware_composer/manifest_vr_hwc.xml
deleted file mode 100644
index 1068cac..0000000
--- a/services/vr/hardware_composer/manifest_vr_hwc.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="framework">
-    <hal>
-      <name>android.hardware.graphics.composer</name>
-      <transport>hwbinder</transport>
-      <version>2.1</version>
-      <interface>
-          <name>IComposer</name>
-          <instance>vr</instance>
-      </interface>
-    </hal>
-</manifest>
diff --git a/services/vr/hardware_composer/vr_hardware_composer_service.cpp b/services/vr/hardware_composer/vr_hardware_composer_service.cpp
deleted file mode 100644
index 7701847..0000000
--- a/services/vr/hardware_composer/vr_hardware_composer_service.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2017 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 <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <hwbinder/IPCThreadState.h>
-#include <impl/vr_hwc.h>
-#include <inttypes.h>
-
-#include "vr_composer.h"
-
-int main() {
-  android::ProcessState::self()->startThreadPool();
-
-  // Register the hwbinder HWC HAL service used by SurfaceFlinger while in VR
-  // mode.
-  android::sp<android::dvr::VrHwc> service = new android::dvr::VrHwc();
-
-  LOG_ALWAYS_FATAL_IF(!service.get(), "Failed to get service");
-  LOG_ALWAYS_FATAL_IF(service->isRemote(), "Service is remote");
-
-  const char instance[] = "vr";
-  LOG_ALWAYS_FATAL_IF(service->registerAsService(instance) != android::OK,
-                      "Failed to register service");
-
-  android::sp<android::dvr::VrComposer> composer =
-      new android::dvr::VrComposer(service.get());
-
-  android::sp<android::IServiceManager> sm(android::defaultServiceManager());
-
-  // Register the binder service used by VR Window Manager service to receive
-  // frame information from VR HWC HAL.
-  android::status_t status = sm->addService(
-      android::dvr::VrComposer::SERVICE_NAME(), composer.get(),
-      false /* allowIsolated */);
-  LOG_ALWAYS_FATAL_IF(status != android::OK,
-                      "VrDisplay service failed to start: %" PRId32, status);
-
-  android::hardware::ProcessState::self()->startThreadPool();
-  android::hardware::IPCThreadState::self()->joinThreadPool();
-
-  return 0;
-}
diff --git a/services/vr/hardware_composer/vr_hwc.rc b/services/vr/hardware_composer/vr_hwc.rc
deleted file mode 100644
index 645ab80..0000000
--- a/services/vr/hardware_composer/vr_hwc.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service vr_hwc /system/bin/vr_hwc
-  class hal animation
-  user system
-  group system graphics
-  onrestart restart surfaceflinger
-  writepid /dev/cpuset/system-background/tasks
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
index 0ef8cc4..5eca88b 100644
--- a/services/vr/performanced/Android.bp
+++ b/services/vr/performanced/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-MIT
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_defaults {
     name: "performanced_defaults",
     static_libs: [
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 9cf4905..f2ec5a4 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -2,6 +2,15 @@
 
 // Touchpad implementation.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 src = [
     "EvdevInjector.cpp",
     "VirtualTouchpadEvdev.cpp",
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 4934970..33599ea 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -14,6 +14,16 @@
 
 // This module makes the Vulkan libhardware HAL headers available, for
 // the loader and for HAL/driver implementations.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    //   SPDX-license-identifier-MIT
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_headers {
     name: "hwvulkan_headers",
     vendor_available: true,
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 1d29bab..440c5b1 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -13,6 +13,15 @@
 // limitations under the License.
 
 // Headers module is in external/vulkan-headers/Android.bp.
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 ndk_library {
     name: "libvulkan",
     symbol_file: "libvulkan.map.txt",
@@ -20,17 +29,14 @@
     unversioned_until: "current",
 }
 
-llndk_library {
-    name: "libvulkan.llndk",
-    symbol_file: "libvulkan.map.txt",
-    export_llndk_headers: [
-        "vulkan_headers_llndk",
-    ],
-}
-
 cc_library_shared {
     name: "libvulkan",
-    llndk_stubs: "libvulkan.llndk",
+    llndk: {
+        symbol_file: "libvulkan.map.txt",
+        export_llndk_headers: [
+            "vulkan_headers",
+        ],
+    },
     clang: true,
     sanitize: {
         misc_undefined: ["integer"],
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 5b9affd..9aaac5f 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -33,6 +33,7 @@
 #include <unordered_set>
 #include <utility>
 
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <cutils/properties.h>
 #include <log/log.h>
@@ -134,7 +135,7 @@
         // If no layers specified via Settings, check legacy properties
         if (implicit_layers_.count <= 0) {
             ParseDebugVulkanLayers();
-            property_list(ParseDebugVulkanLayer, this);
+            ParseDebugVulkanLayer();
 
             // sort by priorities
             auto& arr = implicit_layers_;
@@ -181,30 +182,39 @@
             AddImplicitLayer(prio, p, strlen(p));
     }
 
-    static void ParseDebugVulkanLayer(const char* key,
-                                      const char* val,
-                                      void* user_data) {
+    void ParseDebugVulkanLayer() {
+        // Checks for consecutive debug.vulkan.layer.<priority> system
+        // properties after always checking an initial fixed range.
         static const char prefix[] = "debug.vulkan.layer.";
-        const size_t prefix_len = sizeof(prefix) - 1;
+        static constexpr int kFixedRangeBeginInclusive = 0;
+        static constexpr int kFixedRangeEndInclusive = 9;
 
-        if (strncmp(key, prefix, prefix_len) || val[0] == '\0')
-            return;
-        key += prefix_len;
+        bool logged = false;
 
-        // debug.vulkan.layer.<priority>
-        int priority = -1;
-        if (key[0] >= '0' && key[0] <= '9')
-            priority = atoi(key);
+        int priority = kFixedRangeBeginInclusive;
+        while (true) {
+            const std::string prop_key =
+                std::string(prefix) + std::to_string(priority);
+            const std::string prop_val =
+                android::base::GetProperty(prop_key, "");
 
-        if (priority < 0) {
-            ALOGW("Ignored implicit layer %s with invalid priority %s", val,
-                  key);
-            return;
+            if (!prop_val.empty()) {
+                if (!logged) {
+                    ALOGI(
+                        "Detected Vulkan layers configured with "
+                        "debug.vulkan.layer.<priority>. Checking for "
+                        "debug.vulkan.layer.<priority> in the range [%d, %d] "
+                        "followed by a consecutive scan.",
+                        kFixedRangeBeginInclusive, kFixedRangeEndInclusive);
+                    logged = true;
+                }
+                AddImplicitLayer(priority, prop_val.c_str(), prop_val.length());
+            } else if (priority >= kFixedRangeEndInclusive) {
+                return;
+            }
+
+            ++priority;
         }
-
-        OverrideLayerNames& override_layers =
-            *reinterpret_cast<OverrideLayerNames*>(user_data);
-        override_layers.AddImplicitLayer(priority, val, strlen(val));
     }
 
     void AddImplicitLayer(int priority, const char* name, size_t len) {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 55d80fb..5d47172 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -149,8 +149,8 @@
 Hal Hal::hal_;
 
 const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
-    "ro.hardware.vulkan",
-    "ro.board.platform",
+    "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
+    "ro.board.platform"
 }};
 constexpr int LIB_DL_FLAGS = RTLD_LOCAL | RTLD_NOW;
 
@@ -184,8 +184,9 @@
         if (so)
             break;
     }
-    if (!so)
+    if (!so) {
         return -ENOENT;
+    }
 
     auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
     if (!hmi) {
@@ -230,7 +231,6 @@
 
 bool Hal::Open() {
     ATRACE_CALL();
-
     const nsecs_t openTime = systemTime();
 
     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
@@ -248,16 +248,16 @@
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
             android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
-        ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
         return true;
     }
 
-
     hwvulkan_device_t* device;
     ATRACE_BEGIN("hwvulkan module open");
     result =
         module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
                                      reinterpret_cast<hw_device_t**>(&device));
+
+
     ATRACE_END();
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 6b51817..2913850 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -606,44 +606,9 @@
 VKAPI_ATTR
 VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
                                             uint32_t /*queue_family*/,
-                                            VkSurfaceKHR surface_handle,
+                                            VkSurfaceKHR /*surface_handle*/,
                                             VkBool32* supported) {
-    ATRACE_CALL();
-
-    const Surface* surface = SurfaceFromHandle(surface_handle);
-    if (!surface) {
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-    const ANativeWindow* window = surface->window.get();
-
-    int query_value;
-    int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
-    if (err != android::OK || query_value < 0) {
-        ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
-              strerror(-err), err, query_value);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-
-    android_pixel_format native_format =
-        static_cast<android_pixel_format>(query_value);
-
-    bool format_supported = false;
-    switch (native_format) {
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_RGBA_FP16:
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-            format_supported = true;
-            break;
-        default:
-            break;
-    }
-
-    *supported = static_cast<VkBool32>(
-        format_supported || (surface->consumer_usage &
-                             (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
-                              AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
-
+    *supported = VK_TRUE;
     return VK_SUCCESS;
 }
 
@@ -1123,20 +1088,14 @@
     ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)",
              strerror(-err), err);
 
-    err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, -1);
+    err =
+        window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1});
     if (err != android::OK) {
         ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)",
               strerror(-err), err);
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    err = native_window_set_buffer_count(window, 0);
-    if (err != android::OK) {
-        ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
-              strerror(-err), err);
-        return VK_ERROR_SURFACE_LOST_KHR;
-    }
-
     int swap_interval =
         create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
     err = window->setSwapInterval(window, swap_interval);
@@ -1744,7 +1703,7 @@
                 if (err != android::OK) {
                     ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
                     swapchain_result = WorstPresentResult(
-                        swapchain_result, VK_ERROR_OUT_OF_DATE_KHR);
+                        swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
                 } else {
                     if (img.dequeue_fence >= 0) {
                         close(img.dequeue_fence);
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index ba02504..0daad9c 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     // Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM)
     name: "vulkan.default",
diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp
index 8528898..fa0258b 100644
--- a/vulkan/vkjson/Android.bp
+++ b/vulkan/vkjson/Android.bp
@@ -1,3 +1,12 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_native_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_native_license"],
+}
+
 cc_library_shared {
     name: "libvkjson",
     srcs: [
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index bfc240e..438e5dd 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -842,6 +842,8 @@
   bool ret = true;
   switch (device->properties.apiVersion ^
           VK_VERSION_PATCH(device->properties.apiVersion)) {
+    case VK_API_VERSION_1_2:
+      FALLTHROUGH_INTENDED;
     case VK_API_VERSION_1_1:
       ret &=
           visitor->Visit("subgroupProperties", &device->subgroup_properties) &&
@@ -896,6 +898,8 @@
 inline bool Iterate(Visitor* visitor, VkJsonInstance* instance) {
   bool ret = true;
   switch (instance->api_version ^ VK_VERSION_PATCH(instance->api_version)) {
+    case VK_API_VERSION_1_2:
+      FALLTHROUGH_INTENDED;
     case VK_API_VERSION_1_1:
       ret &= visitor->Visit("deviceGroups", &instance->device_groups);
       FALLTHROUGH_INTENDED;
@@ -1196,10 +1200,10 @@
                                           std::string* errors) {
   *t = T();
   Json::Value object(Json::objectValue);
-  Json::Reader reader;
-  reader.parse(json, object, false);
-  if (!object) {
-    if (errors) errors->assign(reader.getFormatedErrorMessages());
+  Json::CharReaderBuilder builder;
+  builder["collectComments"] = false;
+  std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+  if (!reader->parse(json.data(), json.data() + json.size(), &object, errors)) {
     return false;
   }
   return AsValue(&object, t);
diff --git a/vulkan/vkjson/vkjson_info.cc b/vulkan/vkjson/vkjson_info.cc
deleted file mode 100644
index 3c4b08b..0000000
--- a/vulkan/vkjson/vkjson_info.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2015-2016 The Khronos Group Inc.
-// Copyright (c) 2015-2016 Valve Corporation
-// Copyright (c) 2015-2016 LunarG, Inc.
-// Copyright (c) 2015-2016 Google, Inc.
-//
-// 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.
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef VK_PROTOTYPES
-#define VK_PROTOTYPES
-#endif
-
-#include "vkjson.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <iostream>
-#include <vector>
-
-const uint32_t unsignedNegOne = (uint32_t)(-1);
-
-struct Options {
-  bool instance = false;
-  uint32_t device_index = unsignedNegOne;
-  std::string device_name;
-  std::string output_file;
-};
-
-bool ParseOptions(int argc, char* argv[], Options* options) {
-  for (int i = 1; i < argc; ++i) {
-    std::string arg(argv[i]);
-    if (arg == "--instance" || arg == "-i") {
-      options->instance = true;
-    } else if (arg == "--first" || arg == "-f") {
-      options->device_index = 0;
-    } else {
-      ++i;
-      if (i >= argc) {
-        std::cerr << "Missing parameter after: " << arg << std::endl;
-        return false;
-      }
-      std::string arg2(argv[i]);
-      if (arg == "--device-index" || arg == "-d") {
-        int result = sscanf(arg2.c_str(), "%u", &options->device_index);
-        if (result != 1) {
-          options->device_index = static_cast<uint32_t>(-1);
-          std::cerr << "Unable to parse index: " << arg2 << std::endl;
-          return false;
-        }
-      } else if (arg == "--device-name" || arg == "-n") {
-        options->device_name = arg2;
-      } else if (arg == "--output" || arg == "-o") {
-        options->output_file = arg2;
-      } else {
-        std::cerr << "Unknown argument: " << arg << std::endl;
-        return false;
-      }
-    }
-  }
-  if (options->instance && (options->device_index != unsignedNegOne ||
-                            !options->device_name.empty())) {
-    std::cerr << "Specifying a specific device is incompatible with dumping "
-                 "the whole instance." << std::endl;
-    return false;
-  }
-  if (options->device_index != unsignedNegOne && !options->device_name.empty()) {
-    std::cerr << "Must specify only one of device index and device name."
-              << std::endl;
-    return false;
-  }
-  if (options->instance && options->output_file.empty()) {
-    std::cerr << "Must specify an output file when dumping the whole instance."
-              << std::endl;
-    return false;
-  }
-  if (!options->output_file.empty() && !options->instance &&
-      options->device_index == unsignedNegOne && options->device_name.empty()) {
-    std::cerr << "Must specify instance, device index, or device name when "
-                 "specifying "
-                 "output file." << std::endl;
-    return false;
-  }
-  return true;
-}
-
-bool Dump(const VkJsonInstance& instance, const Options& options) {
-  const VkJsonDevice* out_device = nullptr;
-  if (options.device_index != unsignedNegOne) {
-    if (static_cast<uint32_t>(options.device_index) >=
-        instance.devices.size()) {
-      std::cerr << "Error: device " << options.device_index
-                << " requested but only " << instance.devices.size()
-                << " devices found." << std::endl;
-      return false;
-    }
-    out_device = &instance.devices[options.device_index];
-  } else if (!options.device_name.empty()) {
-    for (const auto& device : instance.devices) {
-      if (device.properties.deviceName == options.device_name) {
-        out_device = &device;
-      }
-    }
-    if (!out_device) {
-      std::cerr << "Error: device '" << options.device_name
-                << "' requested but not found." << std::endl;
-      return false;
-    }
-  }
-
-  std::string output_file;
-  if (options.output_file.empty()) {
-    assert(out_device);
-#if defined(ANDROID)
-    output_file.assign("/sdcard/Android/" + std::string(out_device->properties.deviceName));
-#else
-    output_file.assign(out_device->properties.deviceName);
-#endif
-    output_file.append(".json");
-  } else {
-    output_file = options.output_file;
-  }
-  FILE* file = nullptr;
-  if (output_file == "-") {
-    file = stdout;
-  } else {
-    file = fopen(output_file.c_str(), "w");
-    if (!file) {
-      std::cerr << "Unable to open file " << output_file << "." << std::endl;
-      return false;
-    }
-  }
-
-  std::string json = out_device ? VkJsonDeviceToJson(*out_device)
-                                : VkJsonInstanceToJson(instance);
-  fwrite(json.data(), 1, json.size(), file);
-  fputc('\n', file);
-
-  if (output_file != "-") {
-    fclose(file);
-    std::cout << "Wrote file " << output_file;
-    if (out_device)
-      std::cout << " for device " << out_device->properties.deviceName;
-    std::cout << "." << std::endl;
-  }
-  return true;
-}
-
-int main(int argc, char* argv[]) {
-#if defined(ANDROID)
-  int vulkanSupport = InitVulkan();
-  if (vulkanSupport == 0)
-    return 1;
-#endif
-  Options options;
-  if (!ParseOptions(argc, argv, &options))
-    return 1;
-
-  VkJsonInstance instance = VkJsonGetInstance();
-  if (options.instance || options.device_index != unsignedNegOne ||
-      !options.device_name.empty()) {
-    Dump(instance, options);
-  } else {
-    for (uint32_t i = 0, n = static_cast<uint32_t>(instance.devices.size()); i < n; i++) {
-      options.device_index = i;
-      Dump(instance, options);
-    }
-  }
-
-  return 0;
-}
diff --git a/vulkan/vkjson/vkjson_instance.cc b/vulkan/vkjson/vkjson_instance.cc
index 73586d4..c3f4963 100644
--- a/vulkan/vkjson/vkjson_instance.cc
+++ b/vulkan/vkjson/vkjson_instance.cc
@@ -433,6 +433,10 @@
     VkJsonDeviceGroup device_group;
     std::vector<VkPhysicalDeviceGroupProperties> group_properties;
     group_properties.resize(count);
+    for (auto& properties : group_properties) {
+      properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
+      properties.pNext = nullptr;
+    }
     result = (*vkpEnumeratePhysicalDeviceGroups)(vkinstance, &count,
                                                  group_properties.data());
     if (result != VK_SUCCESS) {
diff --git a/vulkan/vkjson/vkjson_unittest.cc b/vulkan/vkjson/vkjson_unittest.cc
deleted file mode 100644
index de765cd..0000000
--- a/vulkan/vkjson/vkjson_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2015-2016 The Khronos Group Inc.
-// Copyright (c) 2015-2016 Valve Corporation
-// Copyright (c) 2015-2016 LunarG, Inc.
-// Copyright (c) 2015-2016 Google, Inc.
-//
-// 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 "vkjson.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <iostream>
-
-#define EXPECT(X) if (!(X)) \
-  ReportFailure(__FILE__, __LINE__, #X);
-
-#define ASSERT(X) if (!(X)) { \
-  ReportFailure(__FILE__, __LINE__, #X); \
-  return 2; \
-}
-
-int g_failures;
-
-void ReportFailure(const char* file, int line, const char* assertion) {
-  std::cout << file << ":" << line << ": \"" << assertion << "\" failed."
-            << std::endl;
-  ++g_failures;
-}
-
-int main(int argc, char* argv[]) {
-  std::string errors;
-  bool result = false;
-
-  VkJsonInstance instance;
-  instance.devices.resize(1);
-  VkJsonDevice& device = instance.devices[0];
-
-  const char name[] = "Test device";
-  memcpy(device.properties.deviceName, name, sizeof(name));
-  device.properties.limits.maxImageDimension1D = 3;
-  device.properties.limits.maxSamplerLodBias = 3.5f;
-  device.properties.limits.bufferImageGranularity = 0x1ffffffffull;
-  device.properties.limits.maxViewportDimensions[0] = 1;
-  device.properties.limits.maxViewportDimensions[1] = 2;
-  VkFormatProperties format_props = {
-      VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,
-      VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT,
-      VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT};
-  device.formats.insert(std::make_pair(VK_FORMAT_R8_UNORM, format_props));
-  device.formats.insert(std::make_pair(VK_FORMAT_R8G8_UNORM, format_props));
-
-  std::string json = VkJsonInstanceToJson(instance);
-  std::cout << json << std::endl;
-
-  VkJsonInstance instance2;
-  result = VkJsonInstanceFromJson(json, &instance2, &errors);
-  EXPECT(result);
-  if (!result)
-    std::cout << "Error: " << errors << std::endl;
-  const VkJsonDevice& device2 = instance2.devices.at(0);
-
-  EXPECT(!memcmp(&device.properties, &device2.properties,
-                 sizeof(device.properties)));
-  for (auto& kv : device.formats) {
-    auto it = device2.formats.find(kv.first);
-    EXPECT(it != device2.formats.end());
-    EXPECT(!memcmp(&kv.second, &it->second, sizeof(kv.second)));
-  }
-
-  VkImageFormatProperties props = {};
-  json = VkJsonImageFormatPropertiesToJson(props);
-  VkImageFormatProperties props2 = {};
-  result = VkJsonImageFormatPropertiesFromJson(json, &props2, &errors);
-  EXPECT(result);
-  if (!result)
-    std::cout << "Error: " << errors << std::endl;
-
-  EXPECT(!memcmp(&props, &props2, sizeof(props)));
-
-  if (g_failures) {
-    std::cout << g_failures << " failures." << std::endl;
-    return 1;
-  } else {
-    std::cout << "Success." << std::endl;
-    return 0;
-  }
-}