Merge "Don't check synthetic package name on dir removal."
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 8da1352..34ccb21 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -11,286 +11,6 @@
 
 # Grant unix world read/write permissions to kernel tracepoints.
 # Access control to these files is now entirely in selinux policy.
-    chmod 0755 /sys/kernel/debug/tracing/events
-    chmod 0755 /sys/kernel/debug/tracing/events/binder
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_lock
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_locked
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_set_priority
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction_alloc_buf
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction_received
-    chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_unlock
-    chmod 0755 /sys/kernel/debug/tracing/events/block
-    chmod 0755 /sys/kernel/debug/tracing/events/block/block_rq_complete
-    chmod 0755 /sys/kernel/debug/tracing/events/block/block_rq_issue
-    chmod 0755 /sys/kernel/debug/tracing/events/cgroup
-    chmod 0755 /sys/kernel/debug/tracing/events/clk
-    chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_disable
-    chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_enable
-    chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_set_rate
-    chmod 0755 /sys/kernel/debug/tracing/events/cpufreq_interactive
-    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp
-    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_enter
-    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_pause
-    chmod 0755 /sys/kernel/debug/tracing/events/dma_fence
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_enter
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_load_inode
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter
-    chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_get_data_block
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_iget
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin
-    chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end
-    chmod 0755 /sys/kernel/debug/tracing/events/fence
-    chmod 0755 /sys/kernel/debug/tracing/events/filemap
-    chmod 0755 /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache
-    chmod 0755 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache
-    chmod 0755 /sys/kernel/debug/tracing/events/gpu_mem
-    chmod 0755 /sys/kernel/debug/tracing/events/gpu_mem/gpu_mem_total
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_read
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_reply
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_result
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_write
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_read
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_reply
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_result
-    chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_write
-    chmod 0755 /sys/kernel/debug/tracing/events/ion
-    chmod 0755 /sys/kernel/debug/tracing/events/ion/ion_stat
-    chmod 0755 /sys/kernel/debug/tracing/events/ipi
-    chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_entry
-    chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_raise
-    chmod 0755 /sys/kernel/debug/tracing/events/irq
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/irq_handler_entry
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/irq_handler_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_entry
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_raise
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_entry
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_hi_entry
-    chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_hi_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/kmem
-    chmod 0755 /sys/kernel/debug/tracing/events/kmem/ion_heap_grow
-    chmod 0755 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink
-    chmod 0755 /sys/kernel/debug/tracing/events/kmem/rss_stat
-    chmod 0755 /sys/kernel/debug/tracing/events/lowmemorykiller
-    chmod 0755 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill
-    chmod 0755 /sys/kernel/debug/tracing/events/mm_event
-    chmod 0755 /sys/kernel/debug/tracing/events/mm_event/mm_event_record
-    chmod 0755 /sys/kernel/debug/tracing/events/oom
-    chmod 0755 /sys/kernel/debug/tracing/events/oom/mark_victim
-    chmod 0755 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update
-    chmod 0755 /sys/kernel/debug/tracing/events/power
-    chmod 0755 /sys/kernel/debug/tracing/events/power/clock_disable
-    chmod 0755 /sys/kernel/debug/tracing/events/power/clock_enable
-    chmod 0755 /sys/kernel/debug/tracing/events/power/clock_set_rate
-    chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_frequency
-    chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits
-    chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_idle
-    chmod 0755 /sys/kernel/debug/tracing/events/power/gpu_frequency
-    chmod 0755 /sys/kernel/debug/tracing/events/power/suspend_resume
-    chmod 0755 /sys/kernel/debug/tracing/events/sched
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_pi_setprio
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_process_exit
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_process_free
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_switch
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_wakeup
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new
-    chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_waking
-    chmod 0755 /sys/kernel/debug/tracing/events/signal
-    chmod 0755 /sys/kernel/debug/tracing/events/signal/signal_deliver
-    chmod 0755 /sys/kernel/debug/tracing/events/signal/signal_generate
-    chmod 0755 /sys/kernel/debug/tracing/events/sync
-    chmod 0755 /sys/kernel/debug/tracing/events/task
-    chmod 0755 /sys/kernel/debug/tracing/events/task/task_newtask
-    chmod 0755 /sys/kernel/debug/tracing/events/task/task_rename
-    chmod 0755 /sys/kernel/debug/tracing/events/thermal
-    chmod 0755 /sys/kernel/debug/tracing/events/thermal/cdev_update
-    chmod 0755 /sys/kernel/debug/tracing/events/thermal/thermal_temperature
-    chmod 0755 /sys/kernel/debug/tracing/events/vmscan
-    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin
-    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end
-    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep
-    chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake
-    chmod 0755 /sys/kernel/debug/tracing/options
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu0
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu1
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu2
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu3
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu4
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu5
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu6
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu7
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu8
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu9
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu10
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu11
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu12
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu13
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu14
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu15
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu16
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu17
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu18
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu19
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu20
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu21
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu22
-    chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu23
-    chmod 0755 /sys/kernel/tracing/events
-    chmod 0755 /sys/kernel/tracing/events/binder
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_lock
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_locked
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_set_priority
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction_alloc_buf
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction_received
-    chmod 0755 /sys/kernel/tracing/events/binder/binder_unlock
-    chmod 0755 /sys/kernel/tracing/events/block
-    chmod 0755 /sys/kernel/tracing/events/block/block_rq_complete
-    chmod 0755 /sys/kernel/tracing/events/block/block_rq_issue
-    chmod 0755 /sys/kernel/tracing/events/cgroup
-    chmod 0755 /sys/kernel/tracing/events/clk
-    chmod 0755 /sys/kernel/tracing/events/clk/clk_disable
-    chmod 0755 /sys/kernel/tracing/events/clk/clk_enable
-    chmod 0755 /sys/kernel/tracing/events/clk/clk_set_rate
-    chmod 0755 /sys/kernel/tracing/events/cpufreq_interactive
-    chmod 0755 /sys/kernel/tracing/events/cpuhp
-    chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_enter
-    chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_exit
-    chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_pause
-    chmod 0755 /sys/kernel/tracing/events/dma_fence
-    chmod 0755 /sys/kernel/tracing/events/ext4
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_da_write_begin
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_da_write_end
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_enter
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_exit
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_load_inode
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter
-    chmod 0755 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit
-    chmod 0755 /sys/kernel/tracing/events/f2fs
-    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block
-    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_iget
-    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter
-    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit
-    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_write_begin
-    chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_write_end
-    chmod 0755 /sys/kernel/tracing/events/fence
-    chmod 0755 /sys/kernel/tracing/events/filemap
-    chmod 0755 /sys/kernel/tracing/events/filemap/mm_filemap_add_to_page_cache
-    chmod 0755 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache
-    chmod 0755 /sys/kernel/tracing/events/gpu_mem
-    chmod 0755 /sys/kernel/tracing/events/gpu_mem/gpu_mem_total
-    chmod 0755 /sys/kernel/tracing/events/i2c
-    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_read
-    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_reply
-    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_result
-    chmod 0755 /sys/kernel/tracing/events/i2c/i2c_write
-    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_read
-    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_reply
-    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_result
-    chmod 0755 /sys/kernel/tracing/events/i2c/smbus_write
-    chmod 0755 /sys/kernel/tracing/events/ion
-    chmod 0755 /sys/kernel/tracing/events/ion/ion_stat
-    chmod 0755 /sys/kernel/tracing/events/ipi
-    chmod 0755 /sys/kernel/tracing/events/ipi/ipi_entry
-    chmod 0755 /sys/kernel/tracing/events/ipi/ipi_exit
-    chmod 0755 /sys/kernel/tracing/events/ipi/ipi_raise
-    chmod 0755 /sys/kernel/tracing/events/irq
-    chmod 0755 /sys/kernel/tracing/events/irq/irq_handler_entry
-    chmod 0755 /sys/kernel/tracing/events/irq/irq_handler_exit
-    chmod 0755 /sys/kernel/tracing/events/irq/softirq_entry
-    chmod 0755 /sys/kernel/tracing/events/irq/softirq_exit
-    chmod 0755 /sys/kernel/tracing/events/irq/softirq_raise
-    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_entry
-    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_exit
-    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_hi_entry
-    chmod 0755 /sys/kernel/tracing/events/irq/tasklet_hi_exit
-    chmod 0755 /sys/kernel/tracing/events/kmem
-    chmod 0755 /sys/kernel/tracing/events/kmem/ion_heap_grow
-    chmod 0755 /sys/kernel/tracing/events/kmem/ion_heap_shrink
-    chmod 0755 /sys/kernel/tracing/events/kmem/rss_stat
-    chmod 0755 /sys/kernel/tracing/events/lowmemorykiller
-    chmod 0755 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill
-    chmod 0755 /sys/kernel/tracing/events/mm_event
-    chmod 0755 /sys/kernel/tracing/events/mm_event/mm_event_record
-    chmod 0755 /sys/kernel/tracing/events/oom
-    chmod 0755 /sys/kernel/tracing/events/oom/mark_victim
-    chmod 0755 /sys/kernel/tracing/events/oom/oom_score_adj_update
-    chmod 0755 /sys/kernel/tracing/events/power
-    chmod 0755 /sys/kernel/tracing/events/power/clock_disable
-    chmod 0755 /sys/kernel/tracing/events/power/clock_enable
-    chmod 0755 /sys/kernel/tracing/events/power/clock_set_rate
-    chmod 0755 /sys/kernel/tracing/events/power/cpu_frequency
-    chmod 0755 /sys/kernel/tracing/events/power/cpu_frequency_limits
-    chmod 0755 /sys/kernel/tracing/events/power/cpu_idle
-    chmod 0755 /sys/kernel/tracing/events/power/gpu_frequency
-    chmod 0755 /sys/kernel/tracing/events/power/suspend_resume
-    chmod 0755 /sys/kernel/tracing/events/sched
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_blocked_reason
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_cpu_hotplug
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_pi_setprio
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_process_exit
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_process_free
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_switch
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_wakeup
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_wakeup_new
-    chmod 0755 /sys/kernel/tracing/events/sched/sched_waking
-    chmod 0755 /sys/kernel/tracing/events/signal
-    chmod 0755 /sys/kernel/tracing/events/signal/signal_deliver
-    chmod 0755 /sys/kernel/tracing/events/signal/signal_generate
-    chmod 0755 /sys/kernel/tracing/events/sync
-    chmod 0755 /sys/kernel/tracing/events/task
-    chmod 0755 /sys/kernel/tracing/events/task/task_newtask
-    chmod 0755 /sys/kernel/tracing/events/task/task_rename
-    chmod 0755 /sys/kernel/tracing/events/thermal
-    chmod 0755 /sys/kernel/tracing/events/thermal/cdev_update
-    chmod 0755 /sys/kernel/tracing/events/thermal/thermal_temperature
-    chmod 0755 /sys/kernel/tracing/events/vmscan
-    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin
-    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_end
-    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_sleep
-    chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_wake
-    chmod 0755 /sys/kernel/tracing/options
-    chmod 0755 /sys/kernel/tracing/per_cpu
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu0
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu1
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu2
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu3
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu4
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu5
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu6
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu7
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu8
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu9
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu10
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu11
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu12
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu13
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu14
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu15
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu16
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu17
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu18
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu19
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu20
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu21
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu22
-    chmod 0755 /sys/kernel/tracing/per_cpu/cpu23
     chmod 0666 /sys/kernel/debug/tracing/trace_clock
     chmod 0666 /sys/kernel/tracing/trace_clock
     chmod 0666 /sys/kernel/debug/tracing/buffer_size_kb
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index faa8485..00babc3 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -28,6 +28,7 @@
         "dexopt.cpp",
         "execv_helper.cpp",
         "globals.cpp",
+        "restorable_file.cpp",
         "run_dex2oat.cpp",
         "unique_file.cpp",
         "utils.cpp",
@@ -80,7 +81,7 @@
         "-cert-err58-cpp",
     ],
     tidy_flags: [
-        "-warnings-as-errors=clang-analyzer-security*,cert-*"
+        "-warnings-as-errors=clang-analyzer-security*,cert-*",
     ],
 }
 
@@ -132,7 +133,10 @@
         "unique_file.cpp",
         "execv_helper.cpp",
     ],
-    cflags: ["-Wall", "-Werror"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
     shared_libs: [
         "libbase",
         "server_configurable_flags",
@@ -170,7 +174,7 @@
 
     // Needs to be wherever installd is as it's execed by
     // installd.
-    required: [ "migrate_legacy_obb_data.sh" ],
+    required: ["migrate_legacy_obb_data.sh"],
 }
 
 // OTA chroot tool
@@ -194,7 +198,7 @@
         "libutils",
     ],
     required: [
-      "apexd"
+        "apexd",
     ],
 }
 
@@ -213,7 +217,7 @@
     name: "libotapreoptparameters",
     cflags: [
         "-Wall",
-        "-Werror"
+        "-Werror",
     ],
 
     srcs: ["otapreopt_parameters.cpp"],
@@ -237,7 +241,7 @@
     name: "otapreopt",
     cflags: [
         "-Wall",
-        "-Werror"
+        "-Werror",
     ],
 
     srcs: [
@@ -246,6 +250,7 @@
         "globals.cpp",
         "otapreopt.cpp",
         "otapreopt_utils.cpp",
+        "restorable_file.cpp",
         "run_dex2oat.cpp",
         "unique_file.cpp",
         "utils.cpp",
@@ -296,5 +301,5 @@
 // Script to migrate legacy obb data.
 sh_binary {
     name: "migrate_legacy_obb_data.sh",
-    src: "migrate_legacy_obb_data.sh"
+    src: "migrate_legacy_obb_data.sh",
 }
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index effee98..d4c17fe 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -419,10 +419,17 @@
     int res = 0;
     char* before = nullptr;
     char* after = nullptr;
+    if (!existing) {
+        if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
+                SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
+            PLOG(ERROR) << "Failed recursive restorecon for " << path;
+            goto fail;
+        }
+        return res;
+    }
 
     // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by
     // libselinux. Not needed here.
-
     if (lgetfilecon(path.c_str(), &before) < 0) {
         PLOG(ERROR) << "Failed before getfilecon for " << path;
         goto fail;
@@ -459,12 +466,6 @@
     return res;
 }
 
-static int restorecon_app_data_lazy(const std::string& parent, const char* name,
-        const std::string& seInfo, uid_t uid, bool existing) {
-    return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid,
-            existing);
-}
-
 static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
     if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
         PLOG(ERROR) << "Failed to prepare " << path;
@@ -610,8 +611,14 @@
         int32_t uid, int32_t* previousUid, int32_t cacheGid,
         const std::string& seInfo, mode_t targetMode) {
     struct stat st{};
-    bool existing = (stat(path.c_str(), &st) == 0);
-    if (existing) {
+    bool parent_dir_exists = (stat(path.c_str(), &st) == 0);
+
+    auto cache_path = StringPrintf("%s/%s", path.c_str(), "cache");
+    auto code_cache_path = StringPrintf("%s/%s", path.c_str(), "code_cache");
+    bool cache_exists = (access(cache_path.c_str(), F_OK) == 0);
+    bool code_cache_exists = (access(code_cache_path.c_str(), F_OK) == 0);
+
+    if (parent_dir_exists) {
         if (*previousUid < 0) {
             // If previousAppId is -1 in CreateAppDataArgs, we will assume the current owner
             // of the directory as previousUid. This is required because it is not always possible
@@ -625,6 +632,7 @@
         }
     }
 
+    // Prepare only the parent app directory
     if (prepare_app_dir(path, targetMode, uid) ||
             prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
             prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
@@ -632,12 +640,23 @@
     }
 
     // Consider restorecon over contents if label changed
-    if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
-            restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
-            restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
+    if (restorecon_app_data_lazy(path, seInfo, uid, parent_dir_exists)) {
         return error("Failed to restorecon " + path);
     }
 
+    // If the parent dir exists, the restorecon would already have been done
+    // as a part of the recursive restorecon above
+    if (parent_dir_exists && !cache_exists
+            && restorecon_app_data_lazy(cache_path, seInfo, uid, false)) {
+        return error("Failed to restorecon " + cache_path);
+    }
+
+    // If the parent dir exists, the restorecon would already have been done
+    // as a part of the recursive restorecon above
+    if (parent_dir_exists && !code_cache_exists
+            && restorecon_app_data_lazy(code_cache_path, seInfo, uid, false)) {
+        return error("Failed to restorecon " + code_cache_path);
+    }
     return ok();
 }
 
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 2bcf2d4..b6f42ad 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -58,9 +58,10 @@
 #include "dexopt_return_codes.h"
 #include "execv_helper.h"
 #include "globals.h"
-#include "installd_deps.h"
 #include "installd_constants.h"
+#include "installd_deps.h"
 #include "otapreopt_utils.h"
+#include "restorable_file.h"
 #include "run_dex2oat.h"
 #include "unique_file.h"
 #include "utils.h"
@@ -309,12 +310,6 @@
     return profile_boot_class_path == "true";
 }
 
-static void UnlinkIgnoreResult(const std::string& path) {
-    if (unlink(path.c_str()) < 0) {
-        PLOG(ERROR) << "Failed to unlink " << path;
-    }
-}
-
 /*
  * Whether dexopt should use a swap file when compiling an APK.
  *
@@ -988,42 +983,34 @@
 }
 
 // (re)Creates the app image if needed.
-UniqueFile maybe_open_app_image(const std::string& out_oat_path,
-        bool generate_app_image, bool is_public, int uid, bool is_secondary_dex) {
-
+RestorableFile maybe_open_app_image(const std::string& out_oat_path, bool generate_app_image,
+                                    bool is_public, int uid, bool is_secondary_dex) {
     const std::string image_path = create_image_filename(out_oat_path);
     if (image_path.empty()) {
         // Happens when the out_oat_path has an unknown extension.
-        return UniqueFile();
+        return RestorableFile();
     }
 
-    // In case there is a stale image, remove it now. Ignore any error.
-    unlink(image_path.c_str());
-
     // Not enabled, exit.
     if (!generate_app_image) {
-        return UniqueFile();
+        RestorableFile::RemoveAllFiles(image_path);
+        return RestorableFile();
     }
     std::string app_image_format = GetProperty("dalvik.vm.appimageformat", "");
     if (app_image_format.empty()) {
-        return UniqueFile();
+        RestorableFile::RemoveAllFiles(image_path);
+        return RestorableFile();
     }
-    // Recreate is true since we do not want to modify a mapped image. If the app is
-    // already running and we modify the image file, it can cause crashes (b/27493510).
-    UniqueFile image_file(
-            open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
-            image_path,
-            UnlinkIgnoreResult);
+    // If the app is already running and we modify the image file, it can cause crashes
+    // (b/27493510).
+    RestorableFile image_file = RestorableFile::CreateWritableFile(image_path,
+                                                                   /*permissions*/ 0600);
     if (image_file.fd() < 0) {
         // Could not create application image file. Go on since we can compile without it.
         LOG(ERROR) << "installd could not create '" << image_path
                 << "' for image file during dexopt";
-         // If we have a valid image file path but no image fd, explicitly erase the image file.
-        if (unlink(image_path.c_str()) < 0) {
-            if (errno != ENOENT) {
-                PLOG(ERROR) << "Couldn't unlink image file " << image_path;
-            }
-        }
+        // If we have a valid image file path but cannot create tmp file, reset it.
+        image_file.reset();
     } else if (!set_permissions_and_ownership(
                 image_file.fd(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
         ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
@@ -1097,9 +1084,9 @@
 // Opens the vdex files and assigns the input fd to in_vdex_wrapper and the output fd to
 // out_vdex_wrapper. Returns true for success or false in case of errors.
 bool open_vdex_files_for_dex2oat(const char* apk_path, const char* out_oat_path, int dexopt_needed,
-        const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
-        bool profile_guided, UniqueFile* in_vdex_wrapper,
-        UniqueFile* out_vdex_wrapper) {
+                                 const char* instruction_set, bool is_public, int uid,
+                                 bool is_secondary_dex, bool profile_guided,
+                                 UniqueFile* in_vdex_wrapper, RestorableFile* out_vdex_wrapper) {
     CHECK(in_vdex_wrapper != nullptr);
     CHECK(out_vdex_wrapper != nullptr);
     // Open the existing VDEX. We do this before creating the new output VDEX, which will
@@ -1114,6 +1101,14 @@
         return false;
     }
 
+    // Create work file first. All files will be deleted when it fails.
+    *out_vdex_wrapper = RestorableFile::CreateWritableFile(out_vdex_path_str,
+                                                           /*permissions*/ 0644);
+    if (out_vdex_wrapper->fd() < 0) {
+        ALOGE("installd cannot open vdex '%s' during dexopt\n", out_vdex_path_str.c_str());
+        return false;
+    }
+
     bool update_vdex_in_place = false;
     if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
         // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
@@ -1145,41 +1140,19 @@
             (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
             !profile_guided;
         if (update_vdex_in_place) {
+            // dex2oat marks it invalid anyway. So delete it and set work file fd.
+            unlink(in_vdex_path_str.c_str());
             // Open the file read-write to be able to update it.
-            in_vdex_wrapper->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0),
-                                   in_vdex_path_str);
-            if (in_vdex_wrapper->fd() == -1) {
-                // If we failed to open the file, we cannot update it in place.
-                update_vdex_in_place = false;
-            }
+            in_vdex_wrapper->reset(out_vdex_wrapper->fd(), in_vdex_path_str);
+            // Disable auto close for the in wrapper fd (it will be done when destructing the out
+            // wrapper).
+            in_vdex_wrapper->DisableAutoClose();
         } else {
             in_vdex_wrapper->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0),
                                    in_vdex_path_str);
         }
     }
 
-    // If we are updating the vdex in place, we do not need to recreate a vdex,
-    // and can use the same existing one.
-    if (update_vdex_in_place) {
-        // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
-        // have bogus stale vdex files.
-        out_vdex_wrapper->reset(
-              in_vdex_wrapper->fd(),
-              out_vdex_path_str,
-              UnlinkIgnoreResult);
-        // Disable auto close for the in wrapper fd (it will be done when destructing the out
-        // wrapper).
-        in_vdex_wrapper->DisableAutoClose();
-    } else {
-        out_vdex_wrapper->reset(
-              open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
-              out_vdex_path_str,
-              UnlinkIgnoreResult);
-        if (out_vdex_wrapper->fd() < 0) {
-            ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
-            return false;
-        }
-    }
     if (!set_permissions_and_ownership(out_vdex_wrapper->fd(), is_public, uid,
             out_vdex_path_str.c_str(), is_secondary_dex)) {
         ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
@@ -1191,16 +1164,13 @@
 }
 
 // Opens the output oat file for the given apk.
-UniqueFile open_oat_out_file(const char* apk_path, const char* oat_dir,
-        bool is_public, int uid, const char* instruction_set, bool is_secondary_dex) {
+RestorableFile open_oat_out_file(const char* apk_path, const char* oat_dir, bool is_public, int uid,
+                                 const char* instruction_set, bool is_secondary_dex) {
     char out_oat_path[PKG_PATH_MAX];
     if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
-        return UniqueFile();
+        return RestorableFile();
     }
-    UniqueFile oat(
-            open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
-            out_oat_path,
-            UnlinkIgnoreResult);
+    RestorableFile oat = RestorableFile::CreateWritableFile(out_oat_path, /*permissions*/ 0644);
     if (oat.fd() < 0) {
         PLOG(ERROR) << "installd cannot open output during dexopt" <<  out_oat_path;
     } else if (!set_permissions_and_ownership(
@@ -1839,6 +1809,7 @@
         if (sec_dex_result == kSecondaryDexOptProcessOk) {
             oat_dir = oat_dir_str.c_str();
             if (dexopt_needed == NO_DEXOPT_NEEDED) {
+                *completed = true;
                 return 0;  // Nothing to do, report success.
             }
         } else if (sec_dex_result == kSecondaryDexOptProcessCancelled) {
@@ -1874,8 +1845,8 @@
     }
 
     // Create the output OAT file.
-    UniqueFile out_oat = open_oat_out_file(dex_path, oat_dir, is_public, uid,
-            instruction_set, is_secondary_dex);
+    RestorableFile out_oat =
+            open_oat_out_file(dex_path, oat_dir, is_public, uid, instruction_set, is_secondary_dex);
     if (out_oat.fd() < 0) {
         *error_msg = "Could not open out oat file.";
         return -1;
@@ -1883,7 +1854,7 @@
 
     // Open vdex files.
     UniqueFile in_vdex;
-    UniqueFile out_vdex;
+    RestorableFile out_vdex;
     if (!open_vdex_files_for_dex2oat(dex_path, out_oat.path().c_str(), dexopt_needed,
             instruction_set, is_public, uid, is_secondary_dex, profile_guided, &in_vdex,
             &out_vdex)) {
@@ -1919,8 +1890,8 @@
     }
 
     // Create the app image file if needed.
-    UniqueFile out_image = maybe_open_app_image(
-            out_oat.path(), generate_app_image, is_public, uid, is_secondary_dex);
+    RestorableFile out_image = maybe_open_app_image(out_oat.path(), generate_app_image, is_public,
+                                                    uid, is_secondary_dex);
 
     UniqueFile dex_metadata;
     if (dex_metadata_path != nullptr) {
@@ -1953,30 +1924,18 @@
     LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
 
     RunDex2Oat runner(dex2oat_bin, execv_helper.get());
-    runner.Initialize(out_oat,
-                      out_vdex,
-                      out_image,
-                      in_dex,
-                      in_vdex,
-                      dex_metadata,
-                      reference_profile,
-                      class_loader_context,
-                      join_fds(context_input_fds),
-                      swap_fd.get(),
-                      instruction_set,
-                      compiler_filter,
-                      debuggable,
-                      boot_complete,
-                      for_restore,
-                      target_sdk_version,
-                      enable_hidden_api_checks,
-                      generate_compact_dex,
-                      use_jitzygote_image,
+    runner.Initialize(out_oat.GetUniqueFile(), out_vdex.GetUniqueFile(), out_image.GetUniqueFile(),
+                      in_dex, in_vdex, dex_metadata, reference_profile, class_loader_context,
+                      join_fds(context_input_fds), swap_fd.get(), instruction_set, compiler_filter,
+                      debuggable, boot_complete, for_restore, target_sdk_version,
+                      enable_hidden_api_checks, generate_compact_dex, use_jitzygote_image,
                       compilation_reason);
 
     bool cancelled = false;
     pid_t pid = dexopt_status_->check_cancellation_and_fork(&cancelled);
     if (cancelled) {
+        *completed = false;
+        reference_profile.DisableCleanup();
         return 0;
     }
     if (pid == 0) {
@@ -2004,6 +1963,7 @@
                 LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- cancelled";
                 // cancelled, not an error
                 *completed = false;
+                reference_profile.DisableCleanup();
                 return 0;
             }
             LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- status=0x"
@@ -2013,13 +1973,42 @@
         }
     }
 
-    // TODO(b/156537504) Implement SWAP of completed files
-    // We've been successful, don't delete output.
-    out_oat.DisableCleanup();
-    out_vdex.DisableCleanup();
-    out_image.DisableCleanup();
+    // dex2oat ran successfully, so profile is safe to keep.
     reference_profile.DisableCleanup();
 
+    // We've been successful, commit work files.
+    // If committing (=renaming tmp to regular) fails, try to restore backup files.
+    // If restoring fails as well, as a last resort, remove all files.
+    if (!out_oat.CreateBackupFile() || !out_vdex.CreateBackupFile() ||
+        !out_image.CreateBackupFile()) {
+        // Renaming failure can mean that the original file may not be accessible from installd.
+        LOG(ERROR) << "Cannot create backup file from existing file, file in wrong state?"
+                   << ", out_oat:" << out_oat.path() << " ,out_vdex:" << out_vdex.path()
+                   << " ,out_image:" << out_image.path();
+        out_oat.ResetAndRemoveAllFiles();
+        out_vdex.ResetAndRemoveAllFiles();
+        out_image.ResetAndRemoveAllFiles();
+        return -1;
+    }
+    if (!out_oat.CommitWorkFile() || !out_vdex.CommitWorkFile() || !out_image.CommitWorkFile()) {
+        LOG(ERROR) << "Cannot commit, out_oat:" << out_oat.path()
+                   << " ,out_vdex:" << out_vdex.path() << " ,out_image:" << out_image.path();
+        if (!out_oat.RestoreBackupFile() || !out_vdex.RestoreBackupFile() ||
+            !out_image.RestoreBackupFile()) {
+            LOG(ERROR) << "Cannot cancel commit, out_oat:" << out_oat.path()
+                       << " ,out_vdex:" << out_vdex.path() << " ,out_image:" << out_image.path();
+            // Restoring failed.
+            out_oat.ResetAndRemoveAllFiles();
+            out_vdex.ResetAndRemoveAllFiles();
+            out_image.ResetAndRemoveAllFiles();
+        }
+        return -1;
+    }
+    // Now remove remaining backup files.
+    out_oat.RemoveBackupFile();
+    out_vdex.RemoveBackupFile();
+    out_image.RemoveBackupFile();
+
     *completed = true;
     return 0;
 }
diff --git a/cmds/installd/restorable_file.cpp b/cmds/installd/restorable_file.cpp
new file mode 100644
index 0000000..fd54a23
--- /dev/null
+++ b/cmds/installd/restorable_file.cpp
@@ -0,0 +1,161 @@
+/*
+ * 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 "restorable_file.h"
+
+#include <string>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+namespace {
+
+constexpr char kTmpFileSuffix[] = ".tmp";
+constexpr char kBackupFileSuffix[] = ".backup";
+
+std::string GetTmpFilePath(const std::string& path) {
+    return android::base::StringPrintf("%s%s", path.c_str(), kTmpFileSuffix);
+}
+
+std::string GetBackupFilePath(const std::string& path) {
+    return android::base::StringPrintf("%s%s", path.c_str(), kBackupFileSuffix);
+}
+
+void UnlinkPossiblyNonExistingFile(const std::string& path) {
+    if (unlink(path.c_str()) < 0) {
+        if (errno != ENOENT && errno != EROFS) { // EROFS reported even if it does not exist.
+            PLOG(ERROR) << "Cannot unlink: " << path;
+        }
+    }
+}
+
+// Check if file for the given path exists
+bool FileExists(const std::string& path) {
+    struct stat st;
+    return ::stat(path.c_str(), &st) == 0;
+}
+
+} // namespace
+
+namespace android {
+namespace installd {
+
+RestorableFile::RestorableFile() : RestorableFile(-1, "") {}
+
+RestorableFile::RestorableFile(int value, const std::string& path) : unique_file_(value, path) {
+    // As cleanup is null, this does not make much difference but use unique_file_ only for closing
+    // tmp file.
+    unique_file_.DisableCleanup();
+}
+
+RestorableFile::~RestorableFile() {
+    reset();
+}
+
+void RestorableFile::reset() {
+    // need to copy before reset clears it.
+    std::string path(unique_file_.path());
+    unique_file_.reset();
+    if (!path.empty()) {
+        UnlinkPossiblyNonExistingFile(GetTmpFilePath(path));
+    }
+}
+
+bool RestorableFile::CreateBackupFile() {
+    if (path().empty() || !FileExists(path())) {
+        return true;
+    }
+    std::string backup = GetBackupFilePath(path());
+    UnlinkPossiblyNonExistingFile(backup);
+    if (rename(path().c_str(), backup.c_str()) < 0) {
+        PLOG(ERROR) << "Cannot rename " << path() << " to " << backup;
+        return false;
+    }
+    return true;
+}
+
+bool RestorableFile::CommitWorkFile() {
+    std::string path(unique_file_.path());
+    // Keep the path with Commit for debugging purpose.
+    unique_file_.reset(-1, path);
+    if (!path.empty()) {
+        if (rename(GetTmpFilePath(path).c_str(), path.c_str()) < 0) {
+            PLOG(ERROR) << "Cannot rename " << GetTmpFilePath(path) << " to " << path;
+            // Remove both files as renaming can fail due to the original file as well.
+            UnlinkPossiblyNonExistingFile(path);
+            UnlinkPossiblyNonExistingFile(GetTmpFilePath(path));
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool RestorableFile::RestoreBackupFile() {
+    std::string backup = GetBackupFilePath(path());
+    if (path().empty() || !FileExists(backup)) {
+        return true;
+    }
+    UnlinkPossiblyNonExistingFile(path());
+    if (rename(backup.c_str(), path().c_str()) < 0) {
+        PLOG(ERROR) << "Cannot rename " << backup << " to " << path();
+        return false;
+    }
+    return true;
+}
+
+void RestorableFile::RemoveBackupFile() {
+    UnlinkPossiblyNonExistingFile(GetBackupFilePath(path()));
+}
+
+const UniqueFile& RestorableFile::GetUniqueFile() const {
+    return unique_file_;
+}
+
+void RestorableFile::ResetAndRemoveAllFiles() {
+    std::string path(unique_file_.path());
+    reset();
+    RemoveAllFiles(path);
+}
+
+RestorableFile RestorableFile::CreateWritableFile(const std::string& path, int permissions) {
+    std::string tmp_file_path = GetTmpFilePath(path);
+    // If old tmp file exists, delete it.
+    UnlinkPossiblyNonExistingFile(tmp_file_path);
+    int fd = -1;
+    if (!path.empty()) {
+        fd = open(tmp_file_path.c_str(), O_RDWR | O_CREAT, permissions);
+        if (fd < 0) {
+            PLOG(ERROR) << "Cannot create file: " << tmp_file_path;
+        }
+    }
+    RestorableFile rf(fd, path);
+    return rf;
+}
+
+void RestorableFile::RemoveAllFiles(const std::string& path) {
+    UnlinkPossiblyNonExistingFile(GetTmpFilePath(path));
+    UnlinkPossiblyNonExistingFile(GetBackupFilePath(path));
+    UnlinkPossiblyNonExistingFile(path);
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/restorable_file.h b/cmds/installd/restorable_file.h
new file mode 100644
index 0000000..eda2292
--- /dev/null
+++ b/cmds/installd/restorable_file.h
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_INSTALLD_RESTORABLE_FILE_H
+#define ANDROID_INSTALLD_RESTORABLE_FILE_H
+
+#include <functional>
+#include <string>
+
+#include "unique_file.h"
+
+namespace android {
+namespace installd {
+
+// This is a file abstraction which allows restoring to the original file while temporary work
+// file is updated.
+//
+// Typical flow for this API will be:
+// RestorableFile rf =  RestorableFile::CreateWritableFile(...)
+// write to file using file descriptor acquired from: rf.fd()
+// Make work file into a regular file with: rf.CommitWorkFile()
+// Or throw away the work file by destroying the instance without calling CommitWorkFile().
+// The temporary work file is closed / removed when an instance is destroyed without calling
+// CommitWorkFile(). The original file, if CommitWorkFile() is not called, will be kept.
+//
+// For safer restoration of original file when commit fails, following 3 steps can be taken:
+// 1. CreateBackupFile(): This renames an existing regular file into a separate backup file.
+// 2. CommitWorkFile(): Rename the work file into the regular file.
+// 3. RemoveBackupFile(): Removes the backup file
+// If CommitWorkFile fails, client can call RestoreBackupFile() which will restore regular file from
+// the backup.
+class RestorableFile {
+public:
+    // Creates invalid instance with no fd (=-1) and empty path.
+    RestorableFile();
+    RestorableFile(RestorableFile&& other) = default;
+    ~RestorableFile();
+
+    // Passes all contents of other file into the current file.
+    // Files kept for the current file will be either deleted or committed depending on
+    // CommitWorkFile() and DisableCleanUp() calls made before this.
+    RestorableFile& operator=(RestorableFile&& other) = default;
+
+    // Gets file descriptor for backing work (=temporary) file. If work file does not exist, it will
+    // return -1.
+    int fd() const { return unique_file_.fd(); }
+
+    // Gets the path name for the regular file (not temporary file).
+    const std::string& path() const { return unique_file_.path(); }
+
+    // Closes work file, deletes it and resets all internal states into default states.
+    void reset();
+
+    // Closes work file and closes all files including work file, backup file and regular file.
+    void ResetAndRemoveAllFiles();
+
+    // Creates a backup file by renaming existing regular file. This will return false if renaming
+    // fails. If regular file for renaming does not exist, it will return true.
+    bool CreateBackupFile();
+
+    // Closes existing work file and makes it a regular file.
+    // Note that the work file is closed and fd() will return -1 after this. path() will still
+    // return the original path.
+    // This will return false when committing fails (=cannot rename). Both the regular file and tmp
+    // file will be deleted when it fails.
+    bool CommitWorkFile();
+
+    // Cancels the commit and restores the backup file into the regular one. If renaming fails,
+    // it will return false. This returns true if the backup file does not exist.
+    bool RestoreBackupFile();
+
+    // Removes the backup file.
+    void RemoveBackupFile();
+
+    // Gets UniqueFile with the same path and fd() pointing to the work file.
+    const UniqueFile& GetUniqueFile() const;
+
+    // Creates writable RestorableFile. This involves creating tmp file for writing.
+    static RestorableFile CreateWritableFile(const std::string& path, int permissions);
+
+    // Removes the specified file together with tmp file generated as RestorableFile.
+    static void RemoveAllFiles(const std::string& path);
+
+private:
+    RestorableFile(int value, const std::string& path);
+
+    // Used as a storage for work file fd and path string.
+    UniqueFile unique_file_;
+};
+
+} // namespace installd
+} // namespace android
+
+#endif // ANDROID_INSTALLD_RESTORABLE_FILE_H
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 4cde7e3..51f7716 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -188,3 +188,23 @@
         "libotapreoptparameters",
     ],
 }
+
+cc_test {
+    name: "installd_file_test",
+    test_suites: ["device-tests"],
+    clang: true,
+    srcs: ["installd_file_test.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libutils",
+    ],
+    static_libs: [
+        "libinstalld",
+        "liblog",
+    ],
+}
diff --git a/cmds/installd/tests/installd_file_test.cpp b/cmds/installd/tests/installd_file_test.cpp
new file mode 100644
index 0000000..00fb308
--- /dev/null
+++ b/cmds/installd/tests/installd_file_test.cpp
@@ -0,0 +1,521 @@
+/*
+ * 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 <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "restorable_file.h"
+#include "unique_file.h"
+#include "utils.h"
+
+#undef LOG_TAG
+#define LOG_TAG "installd_file_test"
+
+namespace {
+
+constexpr char kFileTestDir[] = "/data/local/tmp/installd_file_test_data";
+constexpr char kTmpFileSuffix[] = ".tmp";
+constexpr char kBackupFileSuffix[] = ".backup";
+
+void UnlinkWithAssert(const std::string& path) {
+    ASSERT_EQ(0, unlink(path.c_str()));
+}
+
+} // namespace
+
+namespace android {
+namespace installd {
+
+// Add these as macros as functions make it hard to tell where the failure has happened.
+#define ASSERT_FILE_NOT_EXISTING(path)           \
+    {                                            \
+        struct stat st;                          \
+        ASSERT_NE(0, ::stat(path.c_str(), &st)); \
+    }
+#define ASSERT_FILE_EXISTING(path)               \
+    {                                            \
+        struct stat st;                          \
+        ASSERT_EQ(0, ::stat(path.c_str(), &st)); \
+    }
+#define ASSERT_FILE_CONTENT(path, expectedContent) ASSERT_EQ(expectedContent, ReadTestFile(path))
+#define ASSERT_FILE_OPEN(path, fd)       \
+    {                                    \
+        fd = open(path.c_str(), O_RDWR); \
+        ASSERT_TRUE(fd >= 0);            \
+    }
+#define ASSERT_WRITE_TO_FD(fd, content) \
+    ASSERT_TRUE(android::base::WriteStringToFd(content, android::base::borrowed_fd(fd)))
+
+class FileTest : public testing::Test {
+protected:
+    virtual void SetUp() {
+        setenv("ANDROID_LOG_TAGS", "*:v", 1);
+        android::base::InitLogging(nullptr);
+
+        ASSERT_EQ(0, create_dir_if_needed(kFileTestDir, 0777));
+    }
+
+    virtual void TearDown() {
+        system(android::base::StringPrintf("rm -rf %s", kFileTestDir).c_str());
+    }
+
+    std::string GetTestFilePath(const std::string& fileName) {
+        return android::base::StringPrintf("%s/%s", kFileTestDir, fileName.c_str());
+    }
+
+    void CreateTestFileWithContents(const std::string& path, const std::string& content) {
+        ALOGI("CreateTestFileWithContents:%s", path.c_str());
+        ASSERT_TRUE(android::base::WriteStringToFile(content, path));
+    }
+
+    std::string GetTestName() {
+        std::string name(testing::UnitTest::GetInstance()->current_test_info()->name());
+        return name;
+    }
+
+    std::string ReadTestFile(const std::string& path) {
+        std::string content;
+        bool r = android::base::ReadFileToString(path, &content);
+        if (!r) {
+            PLOG(ERROR) << "Cannot read file:" << path;
+        }
+        return content;
+    }
+};
+
+TEST_F(FileTest, TestUniqueFileMoveConstruction) {
+    const int fd = 101;
+    std::string testFile = GetTestFilePath(GetTestName());
+    UniqueFile uf1(fd, testFile);
+    uf1.DisableAutoClose();
+
+    UniqueFile uf2(std::move(uf1));
+
+    ASSERT_EQ(fd, uf2.fd());
+    ASSERT_EQ(testFile, uf2.path());
+}
+
+TEST_F(FileTest, TestUniqueFileAssignment) {
+    const int fd1 = 101;
+    const int fd2 = 102;
+    std::string testFile1 = GetTestFilePath(GetTestName());
+    std::string testFile2 = GetTestFilePath(GetTestName() + "2");
+
+    UniqueFile uf1(fd1, testFile1);
+    uf1.DisableAutoClose();
+
+    UniqueFile uf2(fd2, testFile2);
+    uf2.DisableAutoClose();
+
+    ASSERT_EQ(fd2, uf2.fd());
+    ASSERT_EQ(testFile2, uf2.path());
+
+    uf2 = std::move(uf1);
+
+    ASSERT_EQ(fd1, uf2.fd());
+    ASSERT_EQ(testFile1, uf2.path());
+}
+
+TEST_F(FileTest, TestUniqueFileCleanup) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    int fd;
+    ASSERT_FILE_OPEN(testFile, fd);
+
+    { UniqueFile uf = UniqueFile(fd, testFile, UnlinkWithAssert); }
+
+    ASSERT_FILE_NOT_EXISTING(testFile);
+}
+
+TEST_F(FileTest, TestUniqueFileNoCleanup) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    int fd;
+    ASSERT_FILE_OPEN(testFile, fd);
+
+    {
+        UniqueFile uf = UniqueFile(fd, testFile, UnlinkWithAssert);
+        uf.DisableCleanup();
+    }
+
+    ASSERT_FILE_CONTENT(testFile, "OriginalContent");
+}
+
+TEST_F(FileTest, TestUniqueFileFd) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    int fd;
+    ASSERT_FILE_OPEN(testFile, fd);
+
+    UniqueFile uf(fd, testFile, UnlinkWithAssert);
+
+    ASSERT_EQ(fd, uf.fd());
+
+    uf.reset();
+
+    ASSERT_EQ(-1, uf.fd());
+}
+
+TEST_F(FileTest, TestRestorableFileMoveConstruction) {
+    std::string testFile = GetTestFilePath(GetTestName());
+
+    RestorableFile rf1 = RestorableFile::CreateWritableFile(testFile, 0600);
+    int fd = rf1.fd();
+
+    RestorableFile rf2(std::move(rf1));
+
+    ASSERT_EQ(fd, rf2.fd());
+    ASSERT_EQ(testFile, rf2.path());
+}
+
+TEST_F(FileTest, TestRestorableFileAssignment) {
+    std::string testFile1 = GetTestFilePath(GetTestName());
+    std::string testFile2 = GetTestFilePath(GetTestName() + "2");
+
+    RestorableFile rf1 = RestorableFile::CreateWritableFile(testFile1, 0600);
+    int fd1 = rf1.fd();
+
+    RestorableFile rf2 = RestorableFile::CreateWritableFile(testFile2, 0600);
+    int fd2 = rf2.fd();
+
+    ASSERT_EQ(fd2, rf2.fd());
+    ASSERT_EQ(testFile2, rf2.path());
+
+    rf2 = std::move(rf1);
+
+    ASSERT_EQ(fd1, rf2.fd());
+    ASSERT_EQ(testFile1, rf2.path());
+}
+
+TEST_F(FileTest, TestRestorableFileVerifyUniqueFileWithReset) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+        ASSERT_FILE_EXISTING(tmpFile);
+
+        const UniqueFile& uf = rf.GetUniqueFile();
+
+        ASSERT_EQ(rf.fd(), uf.fd());
+        ASSERT_EQ(rf.path(), uf.path());
+
+        rf.reset();
+
+        ASSERT_EQ(rf.fd(), uf.fd());
+        ASSERT_EQ(rf.path(), uf.path());
+        ASSERT_EQ(-1, rf.fd());
+        ASSERT_TRUE(rf.path().empty());
+    }
+}
+
+TEST_F(FileTest, TestRestorableFileVerifyUniqueFileWithCommit) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+        ASSERT_FILE_EXISTING(tmpFile);
+
+        const UniqueFile& uf = rf.GetUniqueFile();
+
+        ASSERT_EQ(rf.fd(), uf.fd());
+        ASSERT_EQ(rf.path(), uf.path());
+
+        ASSERT_TRUE(rf.CreateBackupFile());
+
+        ASSERT_FILE_NOT_EXISTING(backupFile);
+
+        rf.CommitWorkFile();
+
+        ASSERT_EQ(rf.fd(), uf.fd());
+        ASSERT_EQ(rf.path(), uf.path());
+        ASSERT_EQ(-1, rf.fd());
+        ASSERT_EQ(testFile, rf.path());
+    }
+}
+
+TEST_F(FileTest, TestRestorableFileNewFileNotCommitted) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+        ASSERT_FILE_EXISTING(tmpFile);
+        ASSERT_FILE_NOT_EXISTING(testFile);
+
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+        ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(testFile);
+}
+
+TEST_F(FileTest, TestRestorableFileNotCommittedWithOriginal) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+        ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+        ASSERT_FILE_EXISTING(testFile);
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_CONTENT(testFile, "OriginalContent");
+}
+
+TEST_F(FileTest, TestRestorableFileNotCommittedWithOriginalAndOldTmp) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+    CreateTestFileWithContents(testFile + kTmpFileSuffix, "OldTmp");
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+        ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+        ASSERT_FILE_EXISTING(testFile);
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_CONTENT(testFile, "OriginalContent");
+}
+
+TEST_F(FileTest, TestRestorableFileNewFileCommitted) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+        ASSERT_FILE_EXISTING(tmpFile);
+        ASSERT_FILE_NOT_EXISTING(testFile);
+
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+        ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+
+        ASSERT_TRUE(rf.CreateBackupFile());
+
+        ASSERT_FILE_NOT_EXISTING(backupFile);
+
+        ASSERT_TRUE(rf.CommitWorkFile());
+        rf.RemoveBackupFile();
+
+        ASSERT_FILE_CONTENT(testFile, "NewContent");
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(backupFile);
+    ASSERT_FILE_CONTENT(testFile, "NewContent");
+}
+
+TEST_F(FileTest, TestRestorableFileCommittedWithOriginal) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+        ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+
+        ASSERT_TRUE(rf.CreateBackupFile());
+
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_EXISTING(backupFile);
+
+        ASSERT_TRUE(rf.CommitWorkFile());
+
+        ASSERT_FILE_EXISTING(backupFile);
+        ASSERT_FILE_CONTENT(testFile, "NewContent");
+
+        rf.RemoveBackupFile();
+
+        ASSERT_FILE_NOT_EXISTING(backupFile);
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_CONTENT(testFile, "NewContent");
+}
+
+TEST_F(FileTest, TestRestorableFileCommittedWithOriginalAndOldTmp) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+    CreateTestFileWithContents(testFile + kTmpFileSuffix, "OldTmp");
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+        ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+
+        ASSERT_TRUE(rf.CommitWorkFile());
+
+        ASSERT_FILE_CONTENT(testFile, "NewContent");
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_CONTENT(testFile, "NewContent");
+}
+
+TEST_F(FileTest, TestRestorableFileCommitFailureNoOriginal) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+        ASSERT_TRUE(rf.CreateBackupFile());
+
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_NOT_EXISTING(backupFile);
+
+        // Now remove tmp file to force commit failure.
+        close(rf.fd());
+        ASSERT_EQ(0, unlink(tmpFile.c_str()));
+        ASSERT_FILE_NOT_EXISTING(tmpFile);
+
+        ASSERT_FALSE(rf.CommitWorkFile());
+
+        ASSERT_EQ(-1, rf.fd());
+        ASSERT_EQ(testFile, rf.path());
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_NOT_EXISTING(tmpFile);
+
+        ASSERT_TRUE(rf.RestoreBackupFile());
+    }
+
+    ASSERT_FILE_NOT_EXISTING(testFile);
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileCommitFailureAndRollback) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+        ASSERT_TRUE(rf.CreateBackupFile());
+
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_EXISTING(backupFile);
+
+        // Now remove tmp file to force commit failure.
+        close(rf.fd());
+        ASSERT_EQ(0, unlink(tmpFile.c_str()));
+        ASSERT_FILE_NOT_EXISTING(tmpFile);
+
+        ASSERT_FALSE(rf.CommitWorkFile());
+
+        ASSERT_EQ(-1, rf.fd());
+        ASSERT_EQ(testFile, rf.path());
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_NOT_EXISTING(tmpFile);
+        ASSERT_FILE_EXISTING(backupFile);
+
+        ASSERT_TRUE(rf.RestoreBackupFile());
+    }
+
+    ASSERT_FILE_EXISTING(testFile);
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileResetAndRemoveAllFiles) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    {
+        RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+        ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+        ASSERT_TRUE(rf.CreateBackupFile());
+
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_EXISTING(backupFile);
+
+        rf.ResetAndRemoveAllFiles();
+
+        ASSERT_EQ(-1, rf.fd());
+        ASSERT_FILE_NOT_EXISTING(tmpFile);
+        ASSERT_FILE_NOT_EXISTING(testFile);
+        ASSERT_FILE_NOT_EXISTING(backupFile);
+    }
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(testFile);
+    ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileRemoveFileAndTmpFileWithContentFile) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+
+    RestorableFile::RemoveAllFiles(testFile);
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(testFile);
+    ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileRemoveFileAndTmpFileWithContentAndTmpFile) {
+    std::string testFile = GetTestFilePath(GetTestName());
+    std::string tmpFile = testFile + kTmpFileSuffix;
+    std::string backupFile = testFile + kBackupFileSuffix;
+    CreateTestFileWithContents(testFile, "OriginalContent");
+    CreateTestFileWithContents(testFile + kTmpFileSuffix, "TmpContent");
+
+    RestorableFile::RemoveAllFiles(testFile);
+
+    ASSERT_FILE_NOT_EXISTING(tmpFile);
+    ASSERT_FILE_NOT_EXISTING(testFile);
+    ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/tests/installd_file_test.xml b/cmds/installd/tests/installd_file_test.xml
new file mode 100644
index 0000000..5ec6e3f
--- /dev/null
+++ b/cmds/installd/tests/installd_file_test.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<!-- Note: this is derived from the autogenerated configuration. We require
+           root support. -->
+<configuration description="Runs installd_file_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push"
+                value="installd_file_test->/data/local/tmp/installd_file_test" />
+    </target_preparer>
+
+    <!-- The test requires root for file access (rollback. -->
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="installd_file_test" />
+    </test>
+</configuration>
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 0dd29e0..e5d689f 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -6,8 +6,8 @@
     onrestart restart apexd
     onrestart restart audioserver
     onrestart restart gatekeeperd
-    onrestart class_restart main
-    onrestart class_restart hal
-    onrestart class_restart early_hal
+    onrestart class_restart --only-enabled main
+    onrestart class_restart --only-enabled hal
+    onrestart class_restart --only-enabled early_hal
     task_profiles ServiceCapacityLow
     shutdown critical
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 059bc41..3a13104 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -595,6 +595,15 @@
                                                bool enableBackPressure)
                                                __INTRODUCED_IN(31);
 
+/**
+ * Sets the frame timeline to use.
+ *
+ * \param vsyncId The vsync ID received from AChoreographer, setting the frame's present target to
+ * the corresponding expected present time and deadline from the frame to be rendered.
+ */
+void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* transaction,
+                                          int64_t vsyncId) __INTRODUCED_IN(33);
+
 __END_DECLS
 
 #endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h
index 2c6eacb..dfb0ff5 100644
--- a/include/powermanager/PowerHalWrapper.h
+++ b/include/powermanager/PowerHalWrapper.h
@@ -201,10 +201,8 @@
     std::array<std::atomic<HalSupport>,
                static_cast<int32_t>(hardware::power::Boost::DISPLAY_UPDATE_IMMINENT) + 1>
             mBoostSupportedArray GUARDED_BY(mBoostMutex) = {HalSupport::UNKNOWN};
-    // Android framework only sends mode upto DISPLAY_INACTIVE.
-    // Need to increase the array if more mode supported.
     std::array<std::atomic<HalSupport>,
-               static_cast<int32_t>(hardware::power::Mode::DISPLAY_INACTIVE) + 1>
+               static_cast<int32_t>(*(android::enum_range<hardware::power::Mode>().end() - 1)) + 1>
             mModeSupportedArray GUARDED_BY(mModeMutex) = {HalSupport::UNKNOWN};
 };
 
diff --git a/libs/battery/MultiStateCounter.h b/libs/battery/MultiStateCounter.h
index a2b59a8..0caf005 100644
--- a/libs/battery/MultiStateCounter.h
+++ b/libs/battery/MultiStateCounter.h
@@ -63,12 +63,24 @@
     void setValue(state_t state, const T& value);
 
     /**
-     * Updates the value for the current state and returns the delta from the previously
-     * set value.
+     * Updates the value by distributing the delta from the previously set value
+     * among states according to their respective time-in-state.
+     * Returns the delta from the previously set value.
      */
     const T& updateValue(const T& value, time_t timestamp);
 
-    void addValue(const T& value);
+    /**
+     * Updates the value by distributing the specified increment among states according
+     * to their respective time-in-state.
+     */
+    void incrementValue(const T& increment, time_t timestamp);
+
+    /**
+     * Adds the specified increment to the value for the current state, without affecting
+     * the last updated value or timestamp.  Ignores partial time-in-state: the entirety of
+     * the increment is given to the current state.
+     */
+    void addValue(const T& increment);
 
     void reset();
 
@@ -216,11 +228,17 @@
 }
 
 template <class T>
+void MultiStateCounter<T>::incrementValue(const T& increment, time_t timestamp) {
+    T newValue = lastValue;
+    add(&newValue, increment, 1 /* numerator */, 1 /* denominator */);
+    updateValue(newValue, timestamp);
+}
+
+template <class T>
 void MultiStateCounter<T>::addValue(const T& value) {
     if (!isEnabled) {
         return;
     }
-
     add(&states[currentState].counter, value, 1 /* numerator */, 1 /* denominator */);
 }
 
diff --git a/libs/battery/MultiStateCounterTest.cpp b/libs/battery/MultiStateCounterTest.cpp
index 876bf74..cb11a54 100644
--- a/libs/battery/MultiStateCounterTest.cpp
+++ b/libs/battery/MultiStateCounterTest.cpp
@@ -210,6 +210,26 @@
     EXPECT_DOUBLE_EQ(3.0, delta);
 }
 
+TEST_F(MultiStateCounterTest, incrementValue) {
+    DoubleMultiStateCounter testCounter(2, 0);
+    testCounter.updateValue(0, 0);
+    testCounter.setState(0, 0);
+    testCounter.updateValue(6.0, 2000);
+
+    testCounter.setState(1, 3000);
+
+    testCounter.incrementValue(8.0, 6000);
+
+    // The total accumulated count is:
+    //  6.0             // For the period 0-2000
+    //  +(8.0 * 0.25)   // For the period 3000-4000
+    EXPECT_DOUBLE_EQ(8.0, testCounter.getCount(0));
+
+    // 0                // For the period 0-3000
+    // +(8.0 * 0.75)    // For the period 3000-4000
+    EXPECT_DOUBLE_EQ(6.0, testCounter.getCount(1));
+}
+
 TEST_F(MultiStateCounterTest, addValue) {
     DoubleMultiStateCounter testCounter(1, 0);
     testCounter.updateValue(0, 0);
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 9670d7b..8dbdc1d 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <array>
 #include <map> // for legacy reasons
 #include <string>
 #include <type_traits>
@@ -224,6 +225,15 @@
         return writeData(val);
     }
 
+    template <typename T, size_t N>
+    status_t writeFixedArray(const std::array<T, N>& val) {
+        return writeData(val);
+    }
+    template <typename T, size_t N>
+    status_t writeFixedArray(const std::optional<std::array<T, N>>& val) {
+        return writeData(val);
+    }
+
     // 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>
@@ -487,6 +497,15 @@
                             std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const __attribute__((deprecated("use std::optional version instead")));
     status_t            readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
 
+    template <typename T, size_t N>
+    status_t readFixedArray(std::array<T, N>* val) const {
+        return readData(val);
+    }
+    template <typename T, size_t N>
+    status_t readFixedArray(std::optional<std::array<T, N>>* val) const {
+        return readData(val);
+    }
+
     template<typename T>
     status_t            read(Flattenable<T>& val) const;
 
@@ -818,6 +837,16 @@
             || is_specialization_v<T, std::unique_ptr>
             || is_specialization_v<T, std::shared_ptr>;
 
+    // Tells if T is a fixed-size array.
+    template <typename T>
+    struct is_fixed_array : std::false_type {};
+
+    template <typename T, size_t N>
+    struct is_fixed_array<std::array<T, N>> : std::true_type {};
+
+    template <typename T>
+    static inline constexpr bool is_fixed_array_v = is_fixed_array<T>::value;
+
     // 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;
@@ -922,7 +951,9 @@
             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.
+        } else if constexpr (is_fixed_array_v<T>) {
+            if (!c) return writeData(static_cast<int32_t>(kNullVectorSize));
+        } else /* constexpr */ { // could define this, but raise as error.
             static_assert(dependent_false_v<CT>);
         }
         return writeData(*c);
@@ -961,6 +992,23 @@
         return OK;
     }
 
+    template <typename T, size_t N>
+    status_t writeData(const std::array<T, N>& val) {
+        static_assert(N <= std::numeric_limits<int32_t>::max());
+        status_t status = writeData(static_cast<int32_t>(N));
+        if (status != OK) return status;
+        if constexpr (is_pointer_equivalent_array_v<T>) {
+            static_assert(N <= std::numeric_limits<size_t>::max() / sizeof(T));
+            return write(val.data(), val.size() * sizeof(T));
+        } else /* constexpr */ {
+            for (const auto& t : val) {
+                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.
@@ -1053,9 +1101,8 @@
         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 constexpr (is_specialization_v<T, std::vector> || is_fixed_array_v<T> ||
+                      std::is_same_v<T, String16> || std::is_same_v<T, std::string>) {
             if (peek == kNullVectorSize) {
                 c->reset();
                 return OK;
@@ -1065,12 +1112,15 @@
                 c->reset();
                 return OK;
             }
-        } else /* constexpr */ {  // could define this, but raise as error.
+        } 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();
+            // Call default constructor explicitly
+            // - Clang bug: https://bugs.llvm.org/show_bug.cgi?id=35748
+            //   std::optional::emplace() doesn't work with nested types.
+            c->emplace(T());
         } else /* constexpr */ {
             T* const t = new (std::nothrow) T;  // contents read from Parcel below.
             if (t == nullptr) return NO_MEMORY;
@@ -1079,7 +1129,7 @@
         // 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>) {
+        if constexpr (is_specialization_v<T, std::vector> || is_fixed_array_v<T>) {
             return readData(&**c, READ_FLAG_SP_NULLABLE);  // nullable sp<> allowed now
         } else {
             return readData(&**c);
@@ -1142,6 +1192,41 @@
         return OK;
     }
 
+    template <typename T, size_t N>
+    status_t readData(std::array<T, N>* val, ReadFlags readFlags = READ_FLAG_NONE) const {
+        static_assert(N <= std::numeric_limits<int32_t>::max());
+        int32_t size;
+        status_t status = readInt32(&size);
+        if (status != OK) return status;
+        if (size < 0) return UNEXPECTED_NULL;
+        if (size != static_cast<int32_t>(N)) return BAD_VALUE;
+        if constexpr (is_pointer_equivalent_array_v<T>) {
+            auto data = reinterpret_cast<const T*>(readInplace(N * sizeof(T)));
+            if (data == nullptr) return BAD_VALUE;
+            memcpy(val->data(), data, N * sizeof(T));
+        } else if constexpr (is_specialization_v<T, sp>) {
+            for (auto& t : *val) {
+                if (readFlags & READ_FLAG_SP_NULLABLE) {
+                    status = readNullableStrongBinder(&t); // allow nullable
+                } else {
+                    status = readStrongBinder(&t);
+                }
+                if (status != OK) return status;
+            }
+        } else if constexpr (is_fixed_array_v<T>) { // pass readFlags down to nested arrays
+            for (auto& t : *val) {
+                status = readData(&t, readFlags);
+                if (status != OK) return status;
+            }
+        } else /* constexpr */ {
+            for (auto& t : *val) {
+                status = readData(&t);
+                if (status != OK) return status;
+            }
+        }
+        return OK;
+    }
+
     //-----------------------------------------------------------------------------
     private:
 
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index ee46fcb..4289574 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -38,7 +38,7 @@
         host: {
             cflags: [
                 "-D__INTRODUCED_IN(n)=",
-                "-D__assert(a,b,c)=",
+                "-D__assert(a,b,c)=do { syslog(LOG_ERR, a \": \" c); abort(); } while(false)",
                 // We want all the APIs to be available on the host.
                 "-D__ANDROID_API__=10000",
             ],
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 67623a6..0bf1e3d 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -31,6 +31,7 @@
 #include <android/binder_internal_logging.h>
 #include <android/binder_parcel.h>
 
+#include <array>
 #include <optional>
 #include <string>
 #include <type_traits>
@@ -86,9 +87,87 @@
                                                         (is_specialization_v<T, std::optional> ||
                                                          is_specialization_v<T, std::unique_ptr>);
 
+// Tells if T is a fixed-size array.
+template <typename T>
+struct is_fixed_array : std::false_type {};
+
+template <typename T, size_t N>
+struct is_fixed_array<std::array<T, N>> : std::true_type {};
+
+template <typename T>
+static inline constexpr bool is_fixed_array_v = is_fixed_array<T>::value;
+
+template <typename T>
+static inline constexpr bool dependent_false_v = false;
 }  // namespace
 
 /**
+ * This checks the length against the array size and retrieves the buffer. No allocation required.
+ */
+template <typename T, size_t N>
+static inline bool AParcel_stdArrayAllocator(void* arrayData, int32_t length, T** outBuffer) {
+    if (length < 0) return false;
+
+    if (length != static_cast<int32_t>(N)) {
+        return false;
+    }
+
+    std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData);
+    *outBuffer = arr->data();
+    return true;
+}
+
+/**
+ * This checks the length against the array size and retrieves the buffer. No allocation required.
+ */
+template <typename T, size_t N>
+static inline bool AParcel_nullableStdArrayAllocator(void* arrayData, int32_t length,
+                                                     T** outBuffer) {
+    std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData);
+    if (length < 0) {
+        *arr = std::nullopt;
+        return true;
+    }
+
+    if (length != static_cast<int32_t>(N)) {
+        return false;
+    }
+
+    arr->emplace();
+    *outBuffer = (*arr)->data();
+    return true;
+}
+
+/**
+ * This checks the length against the array size. No allocation required.
+ */
+template <size_t N>
+static inline bool AParcel_stdArrayExternalAllocator(void* arrayData, int32_t length) {
+    (void)arrayData;
+    return length == static_cast<int32_t>(N);
+}
+
+/**
+ * This checks the length against the array size. No allocation required.
+ */
+template <typename T, size_t N>
+static inline bool AParcel_nullableStdArrayExternalAllocator(void* arrayData, int32_t length) {
+    std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData);
+
+    if (length < 0) {
+        *arr = std::nullopt;
+        return true;
+    }
+
+    if (length != static_cast<int32_t>(N)) {
+        return false;
+    }
+
+    arr->emplace();
+    return true;
+}
+
+/**
  * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
  */
 template <typename T>
@@ -397,6 +476,118 @@
 }
 
 /**
+ * This retrieves the underlying value in a std::array which may not be contiguous at index from a
+ * corresponding arrData.
+ */
+template <typename T, size_t N>
+static inline T AParcel_stdArrayGetter(const void* arrData, size_t index) {
+    const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrData);
+    return (*arr)[index];
+}
+
+/**
+ * This sets the underlying value in a corresponding arrData which may not be contiguous at
+ * index.
+ */
+template <typename T, size_t N>
+static inline void AParcel_stdArraySetter(void* arrData, size_t index, T value) {
+    std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrData);
+    (*arr)[index] = value;
+}
+
+/**
+ * This retrieves the underlying value in a std::array which may not be contiguous at index from a
+ * corresponding arrData.
+ */
+template <typename T, size_t N>
+static inline T AParcel_nullableStdArrayGetter(const void* arrData, size_t index) {
+    const std::optional<std::array<T, N>>* arr =
+            static_cast<const std::optional<std::array<T, N>>*>(arrData);
+    return (*arr)[index];
+}
+
+/**
+ * This sets the underlying value in a corresponding arrData which may not be contiguous at
+ * index.
+ */
+template <typename T, size_t N>
+static inline void AParcel_nullableStdArraySetter(void* arrData, size_t index, T value) {
+    std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrData);
+    (*arr)->at(index) = value;
+}
+
+/**
+ * Allocates a std::string inside of std::array<std::string, N> at index 'index' to size 'length'.
+ */
+template <size_t N>
+static inline bool AParcel_stdArrayStringElementAllocator(void* arrData, size_t index,
+                                                          int32_t length, char** buffer) {
+    std::array<std::string, N>* arr = static_cast<std::array<std::string, N>*>(arrData);
+    std::string& element = arr->at(index);
+    return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::string inside of a std::array<std::string, N> at index
+ * 'index'.
+ */
+template <size_t N>
+static const char* AParcel_stdArrayStringElementGetter(const void* arrData, size_t index,
+                                                       int32_t* outLength) {
+    const std::array<std::string, N>* arr = static_cast<const std::array<std::string, N>*>(arrData);
+    const std::string& element = arr->at(index);
+
+    *outLength = static_cast<int32_t>(element.size());
+    return element.c_str();
+}
+
+/**
+ * Allocates a std::string inside of std::array<std::optional<std::string>, N> at index 'index' to
+ * size 'length'.
+ */
+template <size_t N>
+static inline bool AParcel_stdArrayNullableStringElementAllocator(void* arrData, size_t index,
+                                                                  int32_t length, char** buffer) {
+    std::array<std::optional<std::string>, N>* arr =
+            static_cast<std::array<std::optional<std::string>, N>*>(arrData);
+    std::optional<std::string>& element = arr->at(index);
+    return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
+ * This gets the length and buffer of a std::string inside of a
+ * std::array<std::optional<std::string>, N> at index 'index'.
+ */
+template <size_t N>
+static const char* AParcel_stdArrayNullableStringElementGetter(const void* arrData, size_t index,
+                                                               int32_t* outLength) {
+    const std::array<std::optional<std::string>, N>* arr =
+            static_cast<const std::array<std::optional<std::string>, N>*>(arrData);
+    const std::optional<std::string>& element = arr->at(index);
+
+    if (!element) {
+        *outLength = -1;
+        return nullptr;
+    }
+
+    *outLength = static_cast<int32_t>(element->size());
+    return element->c_str();
+}
+
+/**
+ * Allocates a std::string inside of std::optional<std::array<std::optional<std::string>, N>> at
+ * index 'index' to size 'length'.
+ */
+template <size_t N>
+static inline bool AParcel_nullableStdArrayStringElementAllocator(void* arrData, size_t index,
+                                                                  int32_t length, char** buffer) {
+    std::optional<std::array<std::optional<std::string>, N>>* arr =
+            static_cast<std::optional<std::array<std::optional<std::string>, N>>*>(arrData);
+    std::optional<std::string>& element = (*arr)->at(index);
+    return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
+}
+
+/**
  * Convenience API for writing a std::string.
  */
 static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
@@ -482,9 +673,7 @@
 template <typename P>
 static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) {
     if constexpr (is_interface_v<P>) {
-        if (!p) {
-            return STATUS_UNEXPECTED_NULL;
-        }
+        // Legacy behavior: allow null
         return first_template_type_t<P>::writeToParcel(parcel, p);
     } else {
         static_assert(is_parcelable_v<P>);
@@ -502,13 +691,8 @@
 template <typename P>
 static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) {
     if constexpr (is_interface_v<P>) {
-        binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p);
-        if (status == STATUS_OK) {
-            if (!*p) {
-                return STATUS_UNEXPECTED_NULL;
-            }
-        }
-        return status;
+        // Legacy behavior: allow null
+        return first_template_type_t<P>::readFromParcel(parcel, p);
     } else {
         static_assert(is_parcelable_v<P>);
         int32_t null;
@@ -560,7 +744,7 @@
             *p = std::nullopt;
             return STATUS_OK;
         }
-        *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{});
+        p->emplace(first_template_type_t<P>());
         return (*p)->readFromParcel(parcel);
     } else {
         static_assert(is_specialization_v<P, std::unique_ptr>);
@@ -578,6 +762,64 @@
     }
 }
 
+// Forward decls
+template <typename T>
+static inline binder_status_t AParcel_writeData(AParcel* parcel, const T& value);
+template <typename T>
+static inline binder_status_t AParcel_writeNullableData(AParcel* parcel, const T& value);
+template <typename T>
+static inline binder_status_t AParcel_readData(const AParcel* parcel, T* value);
+template <typename T>
+static inline binder_status_t AParcel_readNullableData(const AParcel* parcel, T* value);
+
+/**
+ * Reads an object of type T inside a std::array<T, N> at index 'index' from 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_readStdArrayData(const AParcel* parcel, void* arrayData, size_t index) {
+    std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData);
+    return AParcel_readData(parcel, &arr->at(index));
+}
+
+/**
+ * Reads a nullable object of type T inside a std::array<T, N> at index 'index' from 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_readStdArrayNullableData(const AParcel* parcel, void* arrayData,
+                                                 size_t index) {
+    std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData);
+    return AParcel_readNullableData(parcel, &arr->at(index));
+}
+
+/**
+ * Reads a nullable object of type T inside a std::array<T, N> at index 'index' from 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_readNullableStdArrayNullableData(const AParcel* parcel, void* arrayData,
+                                                         size_t index) {
+    std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData);
+    return AParcel_readNullableData(parcel, &(*arr)->at(index));
+}
+
+/**
+ * Writes an object of type T inside a std::array<T, N> at index 'index' to 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_writeStdArrayData(AParcel* parcel, const void* arrayData, size_t index) {
+    const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrayData);
+    return AParcel_writeData(parcel, arr->at(index));
+}
+
+/**
+ * Writes a nullable object of type T inside a std::array<T, N> at index 'index' to 'parcel'.
+ */
+template <typename T, size_t N>
+binder_status_t AParcel_writeStdArrayNullableData(AParcel* parcel, const void* arrayData,
+                                                  size_t index) {
+    const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrayData);
+    return AParcel_writeNullableData(parcel, arr->at(index));
+}
+
 /**
  * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
  */
@@ -721,9 +963,25 @@
  */
 template <typename P>
 static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) {
-    const void* vectorData = static_cast<const void*>(&vec);
-    return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
-                                        AParcel_writeStdVectorParcelableElement<P>);
+    if constexpr (std::is_enum_v<P>) {
+        if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+            return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()),
+                                          static_cast<int32_t>(vec.size()));
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+            return AParcel_writeInt32Array(parcel, reinterpret_cast<const int32_t*>(vec.data()),
+                                           static_cast<int32_t>(vec.size()));
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+            return AParcel_writeInt64Array(parcel, reinterpret_cast<const int64_t*>(vec.data()),
+                                           static_cast<int32_t>(vec.size()));
+        } else {
+            static_assert(dependent_false_v<P>, "unrecognized type");
+        }
+    } else {
+        static_assert(!std::is_same_v<P, std::string>, "specialization should be used");
+        const void* vectorData = static_cast<const void*>(&vec);
+        return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
+                                            AParcel_writeStdVectorParcelableElement<P>);
+    }
 }
 
 /**
@@ -731,9 +989,24 @@
  */
 template <typename P>
 static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>,
-                                       AParcel_readStdVectorParcelableElement<P>);
+    if constexpr (std::is_enum_v<P>) {
+        void* vectorData = static_cast<void*>(vec);
+        if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+            return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+            return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+            return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
+        } else {
+            static_assert(dependent_false_v<P>, "unrecognized type");
+        }
+    } else {
+        static_assert(!std::is_same_v<P, std::string>, "specialization should be used");
+        void* vectorData = static_cast<void*>(vec);
+        return AParcel_readParcelableArray(parcel, vectorData,
+                                           AParcel_stdVectorExternalAllocator<P>,
+                                           AParcel_readStdVectorParcelableElement<P>);
+    }
 }
 
 /**
@@ -742,10 +1015,30 @@
 template <typename P>
 static inline binder_status_t AParcel_writeVector(AParcel* parcel,
                                                   const std::optional<std::vector<P>>& vec) {
-    if (!vec) return AParcel_writeInt32(parcel, -1);
-    const void* vectorData = static_cast<const void*>(&vec);
-    return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()),
-                                        AParcel_writeNullableStdVectorParcelableElement<P>);
+    if constexpr (std::is_enum_v<P>) {
+        if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+            return AParcel_writeByteArray(
+                    parcel, vec ? reinterpret_cast<const int8_t*>(vec->data()) : nullptr,
+                    vec ? static_cast<int32_t>(vec->size()) : -1);
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+            return AParcel_writeInt32Array(
+                    parcel, vec ? reinterpret_cast<const int32_t*>(vec->data()) : nullptr,
+                    vec ? static_cast<int32_t>(vec->size()) : -1);
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+            return AParcel_writeInt64Array(
+                    parcel, vec ? reinterpret_cast<const int64_t*>(vec->data()) : nullptr,
+                    vec ? static_cast<int32_t>(vec->size()) : -1);
+        } else {
+            static_assert(dependent_false_v<P>, "unrecognized type");
+        }
+    } else {
+        static_assert(!std::is_same_v<P, std::optional<std::string>>,
+                      "specialization should be used");
+        if (!vec) return AParcel_writeInt32(parcel, -1);
+        const void* vectorData = static_cast<const void*>(&vec);
+        return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()),
+                                            AParcel_writeNullableStdVectorParcelableElement<P>);
+    }
 }
 
 /**
@@ -754,10 +1047,28 @@
 template <typename P>
 static inline binder_status_t AParcel_readVector(const AParcel* parcel,
                                                  std::optional<std::vector<P>>* vec) {
-    void* vectorData = static_cast<void*>(vec);
-    return AParcel_readParcelableArray(parcel, vectorData,
-                                       AParcel_nullableStdVectorExternalAllocator<P>,
-                                       AParcel_readNullableStdVectorParcelableElement<P>);
+    if constexpr (std::is_enum_v<P>) {
+        void* vectorData = static_cast<void*>(vec);
+        if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) {
+            return AParcel_readByteArray(parcel, vectorData,
+                                         AParcel_nullableStdVectorAllocator<int8_t>);
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) {
+            return AParcel_readInt32Array(parcel, vectorData,
+                                          AParcel_nullableStdVectorAllocator<int32_t>);
+        } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) {
+            return AParcel_readInt64Array(parcel, vectorData,
+                                          AParcel_nullableStdVectorAllocator<int64_t>);
+        } else {
+            static_assert(dependent_false_v<P>, "unrecognized type");
+        }
+    } else {
+        static_assert(!std::is_same_v<P, std::optional<std::string>>,
+                      "specialization should be used");
+        void* vectorData = static_cast<void*>(vec);
+        return AParcel_readParcelableArray(parcel, vectorData,
+                                           AParcel_nullableStdVectorExternalAllocator<P>,
+                                           AParcel_readNullableStdVectorParcelableElement<P>);
+    }
 }
 
 // @START
@@ -1139,6 +1450,294 @@
     return STATUS_OK;
 }
 
+/**
+ * Writes a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_writeFixedArray(AParcel* parcel,
+                                                      const std::array<T, N>& arr) {
+    if constexpr (std::is_same_v<T, bool>) {
+        const void* arrayData = static_cast<const void*>(&arr);
+        return AParcel_writeBoolArray(parcel, arrayData, static_cast<int32_t>(N),
+                                      &AParcel_stdArrayGetter<T, N>);
+    } else if constexpr (std::is_same_v<T, uint8_t>) {
+        return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(arr.data()),
+                                      static_cast<int32_t>(arr.size()));
+    } else if constexpr (std::is_same_v<T, char16_t>) {
+        return AParcel_writeCharArray(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+    } else if constexpr (std::is_same_v<T, int32_t>) {
+        return AParcel_writeInt32Array(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+    } else if constexpr (std::is_same_v<T, int64_t>) {
+        return AParcel_writeInt64Array(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+    } else if constexpr (std::is_same_v<T, float>) {
+        return AParcel_writeFloatArray(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+    } else if constexpr (std::is_same_v<T, double>) {
+        return AParcel_writeDoubleArray(parcel, arr.data(), static_cast<int32_t>(arr.size()));
+    } else if constexpr (std::is_same_v<T, std::string>) {
+        const void* arrayData = static_cast<const void*>(&arr);
+        return AParcel_writeStringArray(parcel, arrayData, static_cast<int32_t>(N),
+                                        &AParcel_stdArrayStringElementGetter<N>);
+    } else {
+        const void* arrayData = static_cast<const void*>(&arr);
+        return AParcel_writeParcelableArray(parcel, arrayData, static_cast<int32_t>(N),
+                                            &AParcel_writeStdArrayData<T, N>);
+    }
+}
+
+/**
+ * Writes a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_writeFixedArrayWithNullableData(AParcel* parcel,
+                                                                      const std::array<T, N>& arr) {
+    if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, uint8_t> ||
+                  std::is_same_v<T, char16_t> || std::is_same_v<T, int32_t> ||
+                  std::is_same_v<T, int64_t> || std::is_same_v<T, float> ||
+                  std::is_same_v<T, double> || std::is_same_v<T, std::string>) {
+        return AParcel_writeFixedArray(parcel, arr);
+    } else if constexpr (std::is_same_v<T, std::optional<std::string>>) {
+        const void* arrayData = static_cast<const void*>(&arr);
+        return AParcel_writeStringArray(parcel, arrayData, static_cast<int32_t>(N),
+                                        &AParcel_stdArrayNullableStringElementGetter<N>);
+    } else {
+        const void* arrayData = static_cast<const void*>(&arr);
+        return AParcel_writeParcelableArray(parcel, arrayData, static_cast<int32_t>(N),
+                                            &AParcel_writeStdArrayNullableData<T, N>);
+    }
+}
+
+/**
+ * Writes a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_writeNullableFixedArrayWithNullableData(
+        AParcel* parcel, const std::optional<std::array<T, N>>& arr) {
+    if (!arr) return AParcel_writeInt32(parcel, -1);
+    return AParcel_writeFixedArrayWithNullableData(parcel, arr.value());
+}
+
+/**
+ * Reads a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_readFixedArray(const AParcel* parcel, std::array<T, N>* arr) {
+    void* arrayData = static_cast<void*>(arr);
+    if constexpr (std::is_same_v<T, bool>) {
+        return AParcel_readBoolArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+                                     &AParcel_stdArraySetter<T, N>);
+    } else if constexpr (std::is_same_v<T, uint8_t>) {
+        return AParcel_readByteArray(parcel, arrayData, &AParcel_stdArrayAllocator<int8_t, N>);
+    } else if constexpr (std::is_same_v<T, char16_t>) {
+        return AParcel_readCharArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, int32_t>) {
+        return AParcel_readInt32Array(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, int64_t>) {
+        return AParcel_readInt64Array(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, float>) {
+        return AParcel_readFloatArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, double>) {
+        return AParcel_readDoubleArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, std::string>) {
+        return AParcel_readStringArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+                                       &AParcel_stdArrayStringElementAllocator<N>);
+    } else {
+        return AParcel_readParcelableArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+                                           &AParcel_readStdArrayData<T, N>);
+    }
+}
+
+/**
+ * Reads a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_readFixedArrayWithNullableData(const AParcel* parcel,
+                                                                     std::array<T, N>* arr) {
+    void* arrayData = static_cast<void*>(arr);
+    if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, uint8_t> ||
+                  std::is_same_v<T, char16_t> || std::is_same_v<T, int32_t> ||
+                  std::is_same_v<T, int64_t> || std::is_same_v<T, float> ||
+                  std::is_same_v<T, double> || std::is_same_v<T, std::string>) {
+        return AParcel_readFixedArray(parcel, arr);
+    } else if constexpr (std::is_same_v<T, std::optional<std::string>>) {
+        return AParcel_readStringArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+                                       &AParcel_stdArrayNullableStringElementAllocator<N>);
+    } else {
+        return AParcel_readParcelableArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>,
+                                           &AParcel_readStdArrayNullableData<T, N>);
+    }
+}
+
+/**
+ * Reads a fixed-size array of T.
+ */
+template <typename T, size_t N>
+static inline binder_status_t AParcel_readNullableFixedArrayWithNullableData(
+        const AParcel* parcel, std::optional<std::array<T, N>>* arr) {
+    void* arrayData = static_cast<void*>(arr);
+    if constexpr (std::is_same_v<T, bool>) {
+        return AParcel_readBoolArray(parcel, arrayData,
+                                     &AParcel_nullableStdArrayExternalAllocator<T, N>,
+                                     &AParcel_nullableStdArraySetter<T, N>);
+    } else if constexpr (std::is_same_v<T, uint8_t>) {
+        return AParcel_readByteArray(parcel, arrayData,
+                                     &AParcel_nullableStdArrayAllocator<int8_t, N>);
+    } else if constexpr (std::is_same_v<T, char16_t>) {
+        return AParcel_readCharArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, int32_t>) {
+        return AParcel_readInt32Array(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, int64_t>) {
+        return AParcel_readInt64Array(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, float>) {
+        return AParcel_readFloatArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, double>) {
+        return AParcel_readDoubleArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>);
+    } else if constexpr (std::is_same_v<T, std::string>) {
+        return AParcel_readStringArray(parcel, arrayData,
+                                       &AParcel_nullableStdArrayExternalAllocator<N>,
+                                       &AParcel_nullableStdArrayStringElementAllocator<N>);
+    } else {
+        return AParcel_readParcelableArray(parcel, arrayData,
+                                           &AParcel_nullableStdArrayExternalAllocator<T, N>,
+                                           &AParcel_readStdArrayNullableData<T, N>);
+    }
+}
+
+/**
+ * Convenience API for writing a value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeData(AParcel* parcel, const T& value) {
+    if constexpr (is_specialization_v<T, std::vector>) {
+        return AParcel_writeVector(parcel, value);
+    } else if constexpr (is_fixed_array_v<T>) {
+        return AParcel_writeFixedArray(parcel, value);
+    } else if constexpr (std::is_same_v<std::string, T>) {
+        return AParcel_writeString(parcel, value);
+    } else if constexpr (std::is_same_v<bool, T>) {
+        return AParcel_writeBool(parcel, value);
+    } else if constexpr (std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>) {
+        return AParcel_writeByte(parcel, value);
+    } else if constexpr (std::is_same_v<char16_t, T>) {
+        return AParcel_writeChar(parcel, value);
+    } else if constexpr (std::is_same_v<int32_t, T>) {
+        return AParcel_writeInt32(parcel, value);
+    } else if constexpr (std::is_same_v<int64_t, T>) {
+        return AParcel_writeInt64(parcel, value);
+    } else if constexpr (std::is_same_v<float, T>) {
+        return AParcel_writeFloat(parcel, value);
+    } else if constexpr (std::is_same_v<double, T>) {
+        return AParcel_writeDouble(parcel, value);
+    } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+        return AParcel_writeRequiredParcelFileDescriptor(parcel, value);
+    } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+        return AParcel_writeRequiredStrongBinder(parcel, value);
+    } else if constexpr (std::is_enum_v<T>) {
+        return AParcel_writeData(parcel, static_cast<std::underlying_type_t<T>>(value));
+    } else if constexpr (is_interface_v<T>) {
+        return AParcel_writeParcelable(parcel, value);
+    } else if constexpr (is_parcelable_v<T>) {
+        return AParcel_writeParcelable(parcel, value);
+    } else {
+        static_assert(dependent_false_v<T>, "unrecognized type");
+        return STATUS_OK;
+    }
+}
+
+/**
+ * Convenience API for writing a nullable value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_writeNullableData(AParcel* parcel, const T& value) {
+    if constexpr (is_specialization_v<T, std::optional> &&
+                  is_specialization_v<first_template_type_t<T>, std::vector>) {
+        return AParcel_writeVector(parcel, value);
+    } else if constexpr (is_specialization_v<T, std::optional> &&
+                         is_fixed_array_v<first_template_type_t<T>>) {
+        return AParcel_writeNullableFixedArrayWithNullableData(parcel, value);
+    } else if constexpr (is_fixed_array_v<T>) {  // happens with a nullable multi-dimensional array.
+        return AParcel_writeFixedArrayWithNullableData(parcel, value);
+    } else if constexpr (is_specialization_v<T, std::optional> &&
+                         std::is_same_v<first_template_type_t<T>, std::string>) {
+        return AParcel_writeString(parcel, value);
+    } else if constexpr (is_nullable_parcelable_v<T> || is_interface_v<T>) {
+        return AParcel_writeNullableParcelable(parcel, value);
+    } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+        return AParcel_writeNullableParcelFileDescriptor(parcel, value);
+    } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+        return AParcel_writeNullableStrongBinder(parcel, value);
+    } else {
+        return AParcel_writeData(parcel, value);
+    }
+}
+
+/**
+ * Convenience API for reading a value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_readData(const AParcel* parcel, T* value) {
+    if constexpr (is_specialization_v<T, std::vector>) {
+        return AParcel_readVector(parcel, value);
+    } else if constexpr (is_fixed_array_v<T>) {
+        return AParcel_readFixedArray(parcel, value);
+    } else if constexpr (std::is_same_v<std::string, T>) {
+        return AParcel_readString(parcel, value);
+    } else if constexpr (std::is_same_v<bool, T>) {
+        return AParcel_readBool(parcel, value);
+    } else if constexpr (std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>) {
+        return AParcel_readByte(parcel, value);
+    } else if constexpr (std::is_same_v<char16_t, T>) {
+        return AParcel_readChar(parcel, value);
+    } else if constexpr (std::is_same_v<int32_t, T>) {
+        return AParcel_readInt32(parcel, value);
+    } else if constexpr (std::is_same_v<int64_t, T>) {
+        return AParcel_readInt64(parcel, value);
+    } else if constexpr (std::is_same_v<float, T>) {
+        return AParcel_readFloat(parcel, value);
+    } else if constexpr (std::is_same_v<double, T>) {
+        return AParcel_readDouble(parcel, value);
+    } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+        return AParcel_readRequiredParcelFileDescriptor(parcel, value);
+    } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+        return AParcel_readRequiredStrongBinder(parcel, value);
+    } else if constexpr (std::is_enum_v<T>) {
+        return AParcel_readData(parcel, reinterpret_cast<std::underlying_type_t<T>*>(value));
+    } else if constexpr (is_interface_v<T>) {
+        return AParcel_readParcelable(parcel, value);
+    } else if constexpr (is_parcelable_v<T>) {
+        return AParcel_readParcelable(parcel, value);
+    } else {
+        static_assert(dependent_false_v<T>, "unrecognized type");
+        return STATUS_OK;
+    }
+}
+
+/**
+ * Convenience API for reading a nullable value of any type.
+ */
+template <typename T>
+static inline binder_status_t AParcel_readNullableData(const AParcel* parcel, T* value) {
+    if constexpr (is_specialization_v<T, std::optional> &&
+                  is_specialization_v<first_template_type_t<T>, std::vector>) {
+        return AParcel_readVector(parcel, value);
+    } else if constexpr (is_specialization_v<T, std::optional> &&
+                         is_fixed_array_v<first_template_type_t<T>>) {
+        return AParcel_readNullableFixedArrayWithNullableData(parcel, value);
+    } else if constexpr (is_fixed_array_v<T>) {  // happens with a nullable multi-dimensional array.
+        return AParcel_readFixedArrayWithNullableData(parcel, value);
+    } else if constexpr (is_specialization_v<T, std::optional> &&
+                         std::is_same_v<first_template_type_t<T>, std::string>) {
+        return AParcel_readString(parcel, value);
+    } else if constexpr (is_nullable_parcelable_v<T> || is_interface_v<T>) {
+        return AParcel_readNullableParcelable(parcel, value);
+    } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) {
+        return AParcel_readNullableParcelFileDescriptor(parcel, value);
+    } else if constexpr (std::is_same_v<SpAIBinder, T>) {
+        return AParcel_readNullableStrongBinder(parcel, value);
+    } else {
+        return AParcel_readData(parcel, value);
+    }
+}
+
 }  // namespace ndk
 
 /** @} */
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 aa3b978..972eca7 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -46,6 +46,18 @@
     AParcelableHolder() = delete;
     explicit AParcelableHolder(parcelable_stability_t stability)
         : mParcel(AParcel_create()), mStability(stability) {}
+
+#if __ANDROID_API__ >= 31
+    AParcelableHolder(const AParcelableHolder& other)
+        : mParcel(AParcel_create()), mStability(other.mStability) {
+        // AParcelableHolder has been introduced in 31.
+        if (__builtin_available(android 31, *)) {
+            AParcel_appendFrom(other.mParcel.get(), this->mParcel.get(), 0,
+                               AParcel_getDataSize(other.mParcel.get()));
+        }
+    }
+#endif
+
     AParcelableHolder(AParcelableHolder&& other) = default;
     virtual ~AParcelableHolder() = default;
 
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 3d2eddf..4d6b294 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -66,6 +66,35 @@
     }
 }
 
+/// Implemented by sync interfaces to specify what the associated async interface is.
+/// Generic to handle the fact that async interfaces are generic over a thread pool.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToAsyncInterface<P>
+where
+    Self: Interface,
+    Self::Target: FromIBinder,
+{
+    /// The async interface associated with this sync interface.
+    type Target: ?Sized;
+}
+
+/// Implemented by async interfaces to specify what the associated sync interface is.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToSyncInterface
+where
+    Self: Interface,
+    Self::Target: FromIBinder,
+{
+    /// The sync interface associated with this async interface.
+    type Target: ?Sized;
+}
+
 /// Interface stability promise
 ///
 /// An interface can promise to be a stable vendor interface ([`Vintf`]), or
@@ -337,6 +366,26 @@
     pub fn downgrade(this: &Strong<I>) -> Weak<I> {
         Weak::new(this)
     }
+
+    /// Convert this synchronous binder handle into an asynchronous one.
+    pub fn into_async<P>(self) -> Strong<<I as ToAsyncInterface<P>>::Target>
+    where
+        I: ToAsyncInterface<P>,
+    {
+        // By implementing the ToAsyncInterface trait, it is guaranteed that the binder
+        // object is also valid for the target type.
+        FromIBinder::try_from(self.0.as_binder()).unwrap()
+    }
+
+    /// Convert this asynchronous binder handle into a synchronous one.
+    pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
+    where
+        I: ToSyncInterface,
+    {
+        // By implementing the ToSyncInterface trait, it is guaranteed that the binder
+        // object is also valid for the target type.
+        FromIBinder::try_from(self.0.as_binder()).unwrap()
+    }
 }
 
 impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
@@ -1017,6 +1066,14 @@
                     .expect(concat!("Error cloning interface ", stringify!($async_interface)))
             }
         }
+
+        impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
+            type Target = dyn $async_interface<P>;
+        }
+
+        impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
+            type Target = dyn $interface;
+        }
         )?
     };
 }
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index b94dfa1..7c04a72 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -109,8 +109,8 @@
 
 pub use crate::binder::{
     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,
+    Stability, Strong, ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, Weak,
+    FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
 };
 pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
 pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index b0dea94..4d3d59a 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -60,6 +60,16 @@
     }
 }
 
+impl PartialEq for ParcelFileDescriptor {
+    // Since ParcelFileDescriptors own the FD, if this function ever returns true (and it is used to
+    // compare two different objects), then it would imply that an FD is double-owned.
+    fn eq(&self, other: &Self) -> bool {
+        self.as_raw_fd() == other.as_raw_fd()
+    }
+}
+
+impl Eq for ParcelFileDescriptor {}
+
 impl Serialize for ParcelFileDescriptor {
     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         let fd = self.0.as_raw_fd();
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 9007cba..61f88b6 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -652,6 +652,39 @@
     }
 }
 
+impl<T: SerializeArray, const N: usize> Serialize for [T; N] {
+    fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
+        // forwards to T::serialize_array.
+        SerializeArray::serialize_array(self, parcel)
+    }
+}
+
+impl<T: SerializeArray, const N: usize> SerializeOption for [T; N] {
+    fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
+        SerializeOption::serialize_option(this.map(|arr| &arr[..]), parcel)
+    }
+}
+
+impl<T: SerializeArray, const N: usize> SerializeArray for [T; N] {}
+
+impl<T: DeserializeArray, const N: usize> Deserialize for [T; N] {
+    fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
+        let vec = DeserializeArray::deserialize_array(parcel)
+            .transpose()
+            .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))?;
+        vec.try_into().or(Err(StatusCode::BAD_VALUE))
+    }
+}
+
+impl<T: DeserializeArray, const N: usize> DeserializeOption for [T; N] {
+    fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
+        let vec = DeserializeArray::deserialize_array(parcel)?;
+        vec.map(|v| v.try_into().or(Err(StatusCode::BAD_VALUE))).transpose()
+    }
+}
+
+impl<T: DeserializeArray, const N: usize> DeserializeArray for [T; N] {}
+
 impl Serialize for Stability {
     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
         i32::from(*self).serialize(parcel)
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 40359b4..80dc476 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -100,6 +100,7 @@
     Test = FIRST_CALL_TRANSACTION,
     GetDumpArgs,
     GetSelinuxContext,
+    GetIsHandlingTransaction,
 }
 
 impl TryFrom<u32> for TestTransactionCode {
@@ -112,6 +113,7 @@
             _ if c == TestTransactionCode::GetSelinuxContext as u32 => {
                 Ok(TestTransactionCode::GetSelinuxContext)
             }
+            _ if c == TestTransactionCode::GetIsHandlingTransaction as u32 => Ok(TestTransactionCode::GetIsHandlingTransaction),
             _ => Err(StatusCode::UNKNOWN_TRANSACTION),
         }
     }
@@ -140,6 +142,10 @@
             ThreadState::with_calling_sid(|sid| sid.map(|s| s.to_string_lossy().into_owned()));
         sid.ok_or(StatusCode::UNEXPECTED_NULL)
     }
+
+    fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+        Ok(binder::is_handling_transaction())
+    }
 }
 
 /// Trivial testing binder interface
@@ -152,6 +158,9 @@
 
     /// Returns the caller's SELinux context
     fn get_selinux_context(&self) -> binder::Result<String>;
+
+    /// Returns the value of calling `is_handling_transaction`.
+    fn get_is_handling_transaction(&self) -> binder::Result<bool>;
 }
 
 /// Async trivial testing binder interface
@@ -164,6 +173,9 @@
 
     /// Returns the caller's SELinux context
     fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
+
+    /// Returns the value of calling `is_handling_transaction`.
+    fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>>;
 }
 
 declare_binder_interface! {
@@ -186,6 +198,7 @@
         TestTransactionCode::Test => reply.write(&service.test()?),
         TestTransactionCode::GetDumpArgs => reply.write(&service.get_dump_args()?),
         TestTransactionCode::GetSelinuxContext => reply.write(&service.get_selinux_context()?),
+        TestTransactionCode::GetIsHandlingTransaction => reply.write(&service.get_is_handling_transaction()?),
     }
 }
 
@@ -212,6 +225,15 @@
         )?;
         reply.read()
     }
+
+    fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+        let reply = self.binder.transact(
+            TestTransactionCode::GetIsHandlingTransaction as TransactionCode,
+            0,
+            |_| Ok(()),
+        )?;
+        reply.read()
+    }
 }
 
 impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
@@ -238,6 +260,14 @@
             |reply| async move { reply?.read() }
         )
     }
+
+    fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
+        let binder = self.binder.clone();
+        P::spawn(
+            move || binder.transact(TestTransactionCode::GetIsHandlingTransaction as TransactionCode, 0, |_| Ok(())),
+            |reply| async move { reply?.read() }
+        )
+    }
 }
 
 impl ITest for Binder<BnTest> {
@@ -252,6 +282,10 @@
     fn get_selinux_context(&self) -> binder::Result<String> {
         self.0.get_selinux_context()
     }
+
+    fn get_is_handling_transaction(&self) -> binder::Result<bool> {
+        self.0.get_is_handling_transaction()
+    }
 }
 
 impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
@@ -269,6 +303,11 @@
         let res = self.0.get_selinux_context();
         Box::pin(async move { res })
     }
+
+    fn get_is_handling_transaction(&self) -> binder::BoxFuture<'static, binder::Result<bool>> {
+        let res = self.0.get_is_handling_transaction();
+        Box::pin(async move { res })
+    }
 }
 
 /// Trivial testing binder interface
@@ -500,7 +539,7 @@
 
     #[tokio::test]
     async fn get_selinux_context_async() {
-        let service_name = "get_selinux_context";
+        let service_name = "get_selinux_context_async";
         let _process = ScopedServiceProcess::new(service_name);
         let test_client: Strong<dyn IATest<Tokio>> =
             binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
@@ -510,6 +549,32 @@
         );
     }
 
+    #[tokio::test]
+    async fn get_selinux_context_sync_to_async() {
+        let service_name = "get_selinux_context";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn ITest> =
+            binder::get_interface(service_name).expect("Did not get manager binder service");
+        let test_client = test_client.into_async::<Tokio>();
+        assert_eq!(
+            test_client.get_selinux_context().await.unwrap(),
+            get_expected_selinux_context()
+        );
+    }
+
+    #[tokio::test]
+    async fn get_selinux_context_async_to_sync() {
+        let service_name = "get_selinux_context";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+        let test_client = test_client.into_sync();
+        assert_eq!(
+            test_client.get_selinux_context().unwrap(),
+            get_expected_selinux_context()
+        );
+    }
+
     struct Bools {
         binder_died: Arc<AtomicBool>,
         binder_dealloc: Arc<AtomicBool>,
@@ -867,4 +932,45 @@
             Err(err) => assert_eq!(err, binder::StatusCode::BAD_VALUE),
         }
     }
+
+    #[test]
+    fn get_is_handling_transaction() {
+        let service_name = "get_is_handling_transaction";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn ITest> =
+            binder::get_interface(service_name).expect("Did not get manager binder service");
+        // Should be true externally.
+        assert!(test_client.get_is_handling_transaction().unwrap());
+
+        // Should be false locally.
+        assert!(!binder::is_handling_transaction());
+
+        // Should also be false in spawned thread.
+        std::thread::spawn(|| {
+            assert!(!binder::is_handling_transaction());
+        }).join().unwrap();
+    }
+
+    #[tokio::test]
+    async fn get_is_handling_transaction_async() {
+        let service_name = "get_is_handling_transaction_async";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+        // Should be true externally.
+        assert!(test_client.get_is_handling_transaction().await.unwrap());
+
+        // Should be false locally.
+        assert!(!binder::is_handling_transaction());
+
+        // Should also be false in spawned task.
+        tokio::spawn(async {
+            assert!(!binder::is_handling_transaction());
+        }).await.unwrap();
+
+        // And in spawn_blocking task.
+        tokio::task::spawn_blocking(|| {
+            assert!(!binder::is_handling_transaction());
+        }).await.unwrap();
+    }
 }
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 32406e5..077d915 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -233,6 +233,32 @@
     PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<std::string>>>, readUtf8VectorFromUtf16Vector),
     PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
 
+#define COMMA ,
+    PARCEL_READ_WITH_STATUS(std::array<uint8_t COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<uint8_t COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<char16_t COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<char16_t COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<std::string COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<std::optional<std::string> COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<android::String16 COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<std::optional<android::String16> COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<android::sp<android::IBinder> COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<android::sp<android::IBinder> COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<ExampleParcelable COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<std::optional<ExampleParcelable> COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<ByteEnum COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<ByteEnum COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<IntEnum COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<IntEnum COMMA 3>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<LongEnum COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<LongEnum COMMA 3>>, readFixedArray),
+    // nested arrays
+    PARCEL_READ_WITH_STATUS(std::array<std::array<uint8_t COMMA 3> COMMA 4>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<uint8_t COMMA 3> COMMA 4>>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::array<ExampleParcelable COMMA 3>, readFixedArray),
+    PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<std::optional<ExampleParcelable> COMMA 3> COMMA 4>>, readFixedArray),
+#undef COMMA
+
     [] (const android::Parcel& p, uint8_t /*len*/) {
         FUZZ_LOG() << "about to read flattenable";
         ExampleFlattenable f;
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index 752fcbb..5aeb5cc 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -156,5 +156,21 @@
         PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector),
         PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector),
         PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector),
+
+        // methods for std::array<T,N>
+#define COMMA ,
+        PARCEL_READ(std::array<bool COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<uint8_t COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<char16_t COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<int32_t COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<int64_t COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<float COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<double COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<std::string COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<SomeParcelable COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<ndk::SpAIBinder COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<ndk::ScopedFileDescriptor COMMA 3>, ndk::AParcel_readData),
+        PARCEL_READ(std::array<std::shared_ptr<ISomeInterface> COMMA 3>, ndk::AParcel_readData),
+#undef COMMA
 };
 // clang-format on
diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp
index 9231a57..3800b88 100644
--- a/libs/gui/FrameTimelineInfo.cpp
+++ b/libs/gui/FrameTimelineInfo.cpp
@@ -33,12 +33,14 @@
 status_t FrameTimelineInfo::write(Parcel& output) const {
     SAFE_PARCEL(output.writeInt64, vsyncId);
     SAFE_PARCEL(output.writeInt32, inputEventId);
+    SAFE_PARCEL(output.writeInt64, startTimeNanos);
     return NO_ERROR;
 }
 
 status_t FrameTimelineInfo::read(const Parcel& input) {
     SAFE_PARCEL(input.readInt64, &vsyncId);
     SAFE_PARCEL(input.readInt32, &inputEventId);
+    SAFE_PARCEL(input.readInt64, &startTimeNanos);
     return NO_ERROR;
 }
 
@@ -48,16 +50,19 @@
         if (other.vsyncId > vsyncId) {
             vsyncId = other.vsyncId;
             inputEventId = other.inputEventId;
+            startTimeNanos = other.startTimeNanos;
         }
     } else if (vsyncId == INVALID_VSYNC_ID) {
         vsyncId = other.vsyncId;
         inputEventId = other.inputEventId;
+        startTimeNanos = other.startTimeNanos;
     }
 }
 
 void FrameTimelineInfo::clear() {
     vsyncId = INVALID_VSYNC_ID;
     inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID;
+    startTimeNanos = 0;
 }
 
 }; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 353a91d..20c4146 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1846,9 +1846,10 @@
     ATRACE_CALL();
     auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
     auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
+    auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t));
 
     ALOGV("Surface::%s", __func__);
-    return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
+    return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId, startTimeNanos});
 }
 
 bool Surface::transformToDisplayInverse() const {
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
index a23c202..255ce56 100644
--- a/libs/gui/include/gui/FrameTimelineInfo.h
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -36,6 +36,9 @@
     // not directly vendor available.
     int32_t inputEventId = 0;
 
+    // The current time in nanoseconds the application started to render the frame.
+    int64_t startTimeNanos = 0;
+
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
 
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 0bc2b5d..a319769 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1025,10 +1025,11 @@
 }
 
 static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
-                                                         int64_t frameTimelineVsyncId,
-                                                         int32_t inputEventId) {
-    return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO,
-                           frameTimelineVsyncId, inputEventId);
+                                                        int64_t frameTimelineVsyncId,
+                                                        int32_t inputEventId,
+                                                        int64_t startTimeNanos) {
+    return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, frameTimelineVsyncId,
+                           inputEventId, startTimeNanos);
 }
 
 // ------------------------------------------------------------------------------------------------
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index a7b5900..936e653 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -138,6 +138,7 @@
         "HdrCapabilities.cpp",
         "PixelFormat.cpp",
         "PublicFormat.cpp",
+        "StaticAsserts.cpp",
         "StaticDisplayInfo.cpp",
     ],
 
diff --git a/libs/ui/StaticAsserts.cpp b/libs/ui/StaticAsserts.cpp
new file mode 100644
index 0000000..85da64f
--- /dev/null
+++ b/libs/ui/StaticAsserts.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 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 <ui/PixelFormat.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+
+// Ideally, PIXEL_FORMAT_R_8 would simply be defined to match the aidl PixelFormat, but
+// PixelFormat.h (where PIXEL_FORMAT_R_8 is defined) is pulled in by builds for
+// which there is no aidl build (e.g. Windows).
+static_assert(android::PIXEL_FORMAT_R_8 ==static_cast<int32_t>(
+                                  aidl::android::hardware::graphics::common::PixelFormat::R_8));
diff --git a/services/gpuservice/gpuservice.rc b/services/gpuservice/gpuservice.rc
index 65a5c27..0da8bd3 100644
--- a/services/gpuservice/gpuservice.rc
+++ b/services/gpuservice/gpuservice.rc
@@ -1,4 +1,4 @@
 service gpu /system/bin/gpuservice
     class core
     user gpu_service
-    group graphics
+    group graphics readtracefs
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index d828aa9..6fbba3f 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -24,11 +24,11 @@
     ],
 
     aidl: {
-       local_include_dirs: ["include"],
-       include_dirs: [
-           "frameworks/base/core/java/android/os",
-       ],
-       export_aidl_headers: true
+        local_include_dirs: ["include"],
+        include_dirs: [
+            "frameworks/base/core/java/android/os",
+        ],
+        export_aidl_headers: true,
     },
 
     shared_libs: [
@@ -38,7 +38,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-V2-cpp",
+        "android.hardware.power-V3-cpp",
     ],
 
     cflags: [
@@ -50,6 +50,6 @@
 
     local_include_dirs: ["include"],
     export_include_dirs: [
-         "include",
+        "include",
     ],
 }
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
index 3997929..fcb012f 100644
--- a/services/powermanager/benchmarks/Android.bp
+++ b/services/powermanager/benchmarks/Android.bp
@@ -38,7 +38,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-V2-cpp",
+        "android.hardware.power-V3-cpp",
     ],
     static_libs: [
         "libtestUtil",
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
index 659b2d2..2d1558a 100644
--- a/services/powermanager/tests/Android.bp
+++ b/services/powermanager/tests/Android.bp
@@ -46,7 +46,7 @@
         "libutils",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
-        "android.hardware.power-V2-cpp",
+        "android.hardware.power-V3-cpp",
     ],
     static_libs: [
         "libgmock",
diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
index d890f5c..cb1a77a 100644
--- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
+++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
@@ -183,6 +183,10 @@
 
     auto result = mWrapper->setMode(Mode::LAUNCH, true);
     ASSERT_TRUE(result.isUnsupported());
+
+    EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::CAMERA_STREAMING_HIGH), _))
+            .Times(Exactly(1))
+            .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status())));
     result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
     ASSERT_TRUE(result.isUnsupported());
 }
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index b596708..dccbeb0 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -15,6 +15,7 @@
         "CorrectedGyroSensor.cpp",
         "Fusion.cpp",
         "GravitySensor.cpp",
+        "HidlSensorHalWrapper.cpp",
         "LinearAccelerationSensor.cpp",
         "OrientationSensor.cpp",
         "RecentEventLogger.cpp",
diff --git a/services/sensorservice/HidlSensorHalWrapper.cpp b/services/sensorservice/HidlSensorHalWrapper.cpp
new file mode 100644
index 0000000..dbb3da1
--- /dev/null
+++ b/services/sensorservice/HidlSensorHalWrapper.cpp
@@ -0,0 +1,562 @@
+/*
+ * 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 "HidlSensorHalWrapper.h"
+#include "android/hardware/sensors/2.0/types.h"
+#include "android/hardware/sensors/2.1/ISensorsCallback.h"
+#include "android/hardware/sensors/2.1/types.h"
+#include "convertV2_1.h"
+
+#include <android-base/logging.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::sensors::V1_0::RateLevel;
+using android::hardware::sensors::V1_0::Result;
+using android::hardware::sensors::V1_0::SharedMemFormat;
+using android::hardware::sensors::V1_0::SharedMemInfo;
+using android::hardware::sensors::V1_0::SharedMemType;
+using android::hardware::sensors::V2_0::EventQueueFlagBits;
+using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
+using android::hardware::sensors::V2_1::Event;
+using android::hardware::sensors::V2_1::ISensorsCallback;
+using android::hardware::sensors::V2_1::implementation::convertFromSensorEvent;
+using android::hardware::sensors::V2_1::implementation::convertToNewEvents;
+using android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
+using android::hardware::sensors::V2_1::implementation::convertToSensor;
+using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV1_0;
+using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_0;
+using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_1;
+
+namespace android {
+
+namespace {
+
+status_t statusFromResult(Result result) {
+    switch (result) {
+        case Result::OK:
+            return OK;
+        case Result::BAD_VALUE:
+            return BAD_VALUE;
+        case Result::PERMISSION_DENIED:
+            return PERMISSION_DENIED;
+        case Result::INVALID_OPERATION:
+            return INVALID_OPERATION;
+        case Result::NO_MEMORY:
+            return NO_MEMORY;
+    }
+}
+
+template <typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
+    return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+enum EventQueueFlagBitsInternal : uint32_t {
+    INTERNAL_WAKE = 1 << 16,
+};
+
+} // anonymous namespace
+
+void SensorsHalDeathReceiver::serviceDied(
+        uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
+    ALOGW("Sensors HAL died, attempting to reconnect.");
+    mHidlSensorHalWrapper->prepareForReconnect();
+}
+
+struct SensorsCallback : public ISensorsCallback {
+    using Result = ::android::hardware::sensors::V1_0::Result;
+    using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
+
+    SensorsCallback(ISensorHalWrapper::SensorDeviceCallback* sensorDeviceCallback) {
+        mSensorDeviceCallback = sensorDeviceCallback;
+    }
+
+    Return<void> onDynamicSensorsConnected_2_1(
+            const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
+        std::vector<sensor_t> sensors;
+        for (const android::hardware::sensors::V2_1::SensorInfo& info : dynamicSensorsAdded) {
+            sensor_t sensor;
+            convertToSensor(info, &sensor);
+            sensors.push_back(sensor);
+        }
+
+        mSensorDeviceCallback->onDynamicSensorsConnected(sensors);
+        return Return<void>();
+    }
+
+    Return<void> onDynamicSensorsConnected(
+            const hidl_vec<android::hardware::sensors::V1_0::SensorInfo>& dynamicSensorsAdded)
+            override {
+        return onDynamicSensorsConnected_2_1(convertToNewSensorInfos(dynamicSensorsAdded));
+    }
+
+    Return<void> onDynamicSensorsDisconnected(
+            const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
+        mSensorDeviceCallback->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved);
+        return Return<void>();
+    }
+
+private:
+    ISensorHalWrapper::SensorDeviceCallback* mSensorDeviceCallback;
+};
+
+bool HidlSensorHalWrapper::supportsPolling() {
+    return mSensors->supportsPolling();
+}
+
+bool HidlSensorHalWrapper::supportsMessageQueues() {
+    return mSensors->supportsMessageQueues();
+}
+
+bool HidlSensorHalWrapper::connect(SensorDeviceCallback* callback) {
+    mSensorDeviceCallback = callback;
+    bool ret = connectHidlService();
+    if (mEventQueueFlag != nullptr) {
+        mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+    }
+    return ret;
+}
+
+void HidlSensorHalWrapper::prepareForReconnect() {
+    mReconnecting = true;
+    if (mEventQueueFlag != nullptr) {
+        mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+    }
+}
+
+ssize_t HidlSensorHalWrapper::poll(sensors_event_t* buffer, size_t count) {
+    ssize_t err;
+    int numHidlTransportErrors = 0;
+    bool hidlTransportError = false;
+
+    do {
+        auto ret = mSensors->poll(
+                count, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+                    if (result == Result::OK) {
+                        convertToSensorEventsAndQuantize(convertToNewEvents(events),
+                                                         convertToNewSensorInfos(
+                                                                 dynamicSensorsAdded),
+                                                         buffer);
+                        err = (ssize_t)events.size();
+                    } else {
+                        err = statusFromResult(result);
+                    }
+                });
+
+        if (ret.isOk()) {
+            hidlTransportError = false;
+        } else {
+            hidlTransportError = true;
+            numHidlTransportErrors++;
+            if (numHidlTransportErrors > 50) {
+                // Log error and bail
+                ALOGE("Max Hidl transport errors this cycle : %d", numHidlTransportErrors);
+                handleHidlDeath(ret.description());
+            } else {
+                std::this_thread::sleep_for(std::chrono::milliseconds(10));
+            }
+        }
+    } while (hidlTransportError);
+
+    if (numHidlTransportErrors > 0) {
+        ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
+        HidlTransportErrorLog errLog(time(nullptr), numHidlTransportErrors);
+        mHidlTransportErrors.add(errLog);
+        mTotalHidlTransportErrors++;
+    }
+
+    return err;
+}
+
+ssize_t HidlSensorHalWrapper::pollFmq(sensors_event_t* buffer, size_t maxNumEventsToRead) {
+    ssize_t eventsRead = 0;
+    size_t availableEvents = mSensors->getEventQueue()->availableToRead();
+
+    if (availableEvents == 0) {
+        uint32_t eventFlagState = 0;
+
+        // Wait for events to become available. This is necessary so that the Event FMQ's read() is
+        // able to be called with the correct number of events to read. If the specified number of
+        // events is not available, then read() would return no events, possibly introducing
+        // additional latency in delivering events to applications.
+        if (mEventQueueFlag != nullptr) {
+            mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS) |
+                                          asBaseType(INTERNAL_WAKE),
+                                  &eventFlagState);
+        }
+        availableEvents = mSensors->getEventQueue()->availableToRead();
+
+        if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
+            ALOGD("Event FMQ internal wake, returning from poll with no events");
+            return DEAD_OBJECT;
+        }
+    }
+
+    size_t eventsToRead = std::min({availableEvents, maxNumEventsToRead, mEventBuffer.size()});
+    if (eventsToRead > 0) {
+        if (mSensors->getEventQueue()->read(mEventBuffer.data(), eventsToRead)) {
+            // Notify the Sensors HAL that sensor events have been read. This is required to support
+            // the use of writeBlocking by the Sensors HAL.
+            if (mEventQueueFlag != nullptr) {
+                mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
+            }
+
+            for (size_t i = 0; i < eventsToRead; i++) {
+                convertToSensorEvent(mEventBuffer[i], &buffer[i]);
+                android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
+                                                                      getResolutionForSensor(
+                                                                              buffer[i].sensor));
+            }
+            eventsRead = eventsToRead;
+        } else {
+            ALOGW("Failed to read %zu events, currently %zu events available", eventsToRead,
+                  availableEvents);
+        }
+    }
+
+    return eventsRead;
+}
+
+std::vector<sensor_t> HidlSensorHalWrapper::getSensorsList() {
+    std::vector<sensor_t> sensorsFound;
+    if (mSensors != nullptr) {
+        checkReturn(mSensors->getSensorsList([&](const auto& list) {
+            for (size_t i = 0; i < list.size(); i++) {
+                sensor_t sensor;
+                convertToSensor(list[i], &sensor);
+                sensorsFound.push_back(sensor);
+
+                // Only disable all sensors on HAL 1.0 since HAL 2.0
+                // handles this in its initialize method
+                if (!mSensors->supportsMessageQueues()) {
+                    checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
+                }
+            }
+        }));
+    }
+
+    return sensorsFound;
+}
+
+status_t HidlSensorHalWrapper::setOperationMode(SensorService::Mode mode) {
+    if (mSensors == nullptr) return NO_INIT;
+    return checkReturnAndGetStatus(
+            mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+}
+
+status_t HidlSensorHalWrapper::activate(int32_t sensorHandle, bool enabled) {
+    if (mSensors == nullptr) return NO_INIT;
+    return checkReturnAndGetStatus(mSensors->activate(sensorHandle, enabled));
+}
+
+status_t HidlSensorHalWrapper::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                                     int64_t maxReportLatencyNs) {
+    if (mSensors == nullptr) return NO_INIT;
+    return checkReturnAndGetStatus(
+            mSensors->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs));
+}
+
+status_t HidlSensorHalWrapper::flush(int32_t sensorHandle) {
+    if (mSensors == nullptr) return NO_INIT;
+    return checkReturnAndGetStatus(mSensors->flush(sensorHandle));
+}
+
+status_t HidlSensorHalWrapper::injectSensorData(const sensors_event_t* event) {
+    if (mSensors == nullptr) return NO_INIT;
+
+    Event ev;
+    convertFromSensorEvent(*event, &ev);
+    return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
+}
+
+status_t HidlSensorHalWrapper::registerDirectChannel(const sensors_direct_mem_t* memory,
+                                                     int32_t* /*channelHandle*/) {
+    if (mSensors == nullptr) return NO_INIT;
+
+    SharedMemType type;
+    switch (memory->type) {
+        case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
+            type = SharedMemType::ASHMEM;
+            break;
+        case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+            type = SharedMemType::GRALLOC;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    SharedMemFormat format;
+    if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
+        return BAD_VALUE;
+    }
+    format = SharedMemFormat::SENSORS_EVENT;
+
+    SharedMemInfo mem = {
+            .type = type,
+            .format = format,
+            .size = static_cast<uint32_t>(memory->size),
+            .memoryHandle = memory->handle,
+    };
+
+    status_t ret;
+    checkReturn(mSensors->registerDirectChannel(mem, [&ret](auto result, auto channelHandle) {
+        if (result == Result::OK) {
+            ret = channelHandle;
+        } else {
+            ret = statusFromResult(result);
+        }
+    }));
+    return ret;
+}
+
+status_t HidlSensorHalWrapper::unregisterDirectChannel(int32_t channelHandle) {
+    if (mSensors == nullptr) return NO_INIT;
+    return checkReturnAndGetStatus(mSensors->unregisterDirectChannel(channelHandle));
+}
+
+status_t HidlSensorHalWrapper::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+                                                      const struct sensors_direct_cfg_t* config) {
+    if (mSensors == nullptr) return NO_INIT;
+
+    RateLevel rate;
+    switch (config->rate_level) {
+        case SENSOR_DIRECT_RATE_STOP:
+            rate = RateLevel::STOP;
+            break;
+        case SENSOR_DIRECT_RATE_NORMAL:
+            rate = RateLevel::NORMAL;
+            break;
+        case SENSOR_DIRECT_RATE_FAST:
+            rate = RateLevel::FAST;
+            break;
+        case SENSOR_DIRECT_RATE_VERY_FAST:
+            rate = RateLevel::VERY_FAST;
+            break;
+        default:
+            return BAD_VALUE;
+    }
+
+    status_t ret;
+    checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
+                                             [&ret, rate](auto result, auto token) {
+                                                 if (rate == RateLevel::STOP) {
+                                                     ret = statusFromResult(result);
+                                                 } else {
+                                                     if (result == Result::OK) {
+                                                         ret = token;
+                                                     } else {
+                                                         ret = statusFromResult(result);
+                                                     }
+                                                 }
+                                             }));
+
+    return ret;
+}
+
+void HidlSensorHalWrapper::writeWakeLockHandled(uint32_t count) {
+    if (mWakeLockQueue->write(&count)) {
+        mWakeLockQueueFlag->wake(asBaseType(WakeLockQueueFlagBits::DATA_WRITTEN));
+    } else {
+        ALOGW("Failed to write wake lock handled");
+    }
+}
+
+status_t HidlSensorHalWrapper::checkReturnAndGetStatus(const hardware::Return<Result>& ret) {
+    checkReturn(ret);
+    return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
+}
+
+void HidlSensorHalWrapper::handleHidlDeath(const std::string& detail) {
+    if (!mSensors->supportsMessageQueues()) {
+        // restart is the only option at present.
+        LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
+    } else {
+        ALOGD("ISensors HAL died, death recipient will attempt reconnect");
+    }
+}
+
+bool HidlSensorHalWrapper::connectHidlService() {
+    HalConnectionStatus status = connectHidlServiceV2_1();
+    if (status == HalConnectionStatus::DOES_NOT_EXIST) {
+        status = connectHidlServiceV2_0();
+    }
+
+    if (status == HalConnectionStatus::DOES_NOT_EXIST) {
+        status = connectHidlServiceV1_0();
+    }
+    return (status == HalConnectionStatus::CONNECTED);
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::connectHidlServiceV1_0() {
+    // SensorDevice will wait for HAL service to start if HAL is declared in device manifest.
+    size_t retry = 10;
+    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+
+    while (retry-- > 0) {
+        sp<android::hardware::sensors::V1_0::ISensors> sensors =
+                android::hardware::sensors::V1_0::ISensors::getService();
+        if (sensors == nullptr) {
+            // no sensor hidl service found
+            connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
+            break;
+        }
+
+        mSensors = new ISensorsWrapperV1_0(sensors);
+        mRestartWaiter->reset();
+        // Poke ISensor service. If it has lingering connection from previous generation of
+        // system server, it will kill itself. There is no intention to handle the poll result,
+        // which will be done since the size is 0.
+        if (mSensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
+            // ok to continue
+            connectionStatus = HalConnectionStatus::CONNECTED;
+            break;
+        }
+
+        // hidl service is restarting, pointer is invalid.
+        mSensors = nullptr;
+        connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
+        ALOGI("%s unsuccessful, remaining retry %zu.", __FUNCTION__, retry);
+        mRestartWaiter->wait();
+    }
+
+    return connectionStatus;
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::connectHidlServiceV2_0() {
+    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+    sp<android::hardware::sensors::V2_0::ISensors> sensors =
+            android::hardware::sensors::V2_0::ISensors::getService();
+
+    if (sensors == nullptr) {
+        connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
+    } else {
+        mSensors = new ISensorsWrapperV2_0(sensors);
+        connectionStatus = initializeHidlServiceV2_X();
+    }
+
+    return connectionStatus;
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::connectHidlServiceV2_1() {
+    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+    sp<android::hardware::sensors::V2_1::ISensors> sensors =
+            android::hardware::sensors::V2_1::ISensors::getService();
+
+    if (sensors == nullptr) {
+        connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
+    } else {
+        mSensors = new ISensorsWrapperV2_1(sensors);
+        connectionStatus = initializeHidlServiceV2_X();
+    }
+
+    return connectionStatus;
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::initializeHidlServiceV2_X() {
+    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+
+    mWakeLockQueue =
+            std::make_unique<WakeLockQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
+                                            true /* configureEventFlagWord */);
+
+    hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
+    hardware::EventFlag::createEventFlag(mSensors->getEventQueue()->getEventFlagWord(),
+                                         &mEventQueueFlag);
+
+    hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+    hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakeLockQueueFlag);
+
+    CHECK(mSensors != nullptr && mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
+          mWakeLockQueueFlag != nullptr);
+
+    mCallback = new SensorsCallback(mSensorDeviceCallback);
+    status_t status =
+            checkReturnAndGetStatus(mSensors->initialize(*mWakeLockQueue->getDesc(), mCallback));
+
+    if (status != NO_ERROR) {
+        connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
+        ALOGE("Failed to initialize Sensors HAL (%s)", strerror(-status));
+    } else {
+        connectionStatus = HalConnectionStatus::CONNECTED;
+        mSensorsHalDeathReceiver = new SensorsHalDeathReceiver(this);
+        mSensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);
+    }
+
+    return connectionStatus;
+}
+
+void HidlSensorHalWrapper::convertToSensorEvent(const Event& src, sensors_event_t* dst) {
+    android::hardware::sensors::V2_1::implementation::convertToSensorEvent(src, dst);
+
+    if (src.sensorType == android::hardware::sensors::V2_1::SensorType::DYNAMIC_SENSOR_META) {
+        const hardware::sensors::V1_0::DynamicSensorInfo& dyn = src.u.dynamic;
+
+        dst->dynamic_sensor_meta.connected = dyn.connected;
+        dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
+        if (dyn.connected) {
+            std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
+            // Give MAX_DYN_SENSOR_WAIT_SEC for onDynamicSensorsConnected to be invoked since it
+            // can be received out of order from this event due to a bug in the HIDL spec that
+            // marks it as oneway.
+            auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+            if (it == mConnectedDynamicSensors.end()) {
+                mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT, [&, dyn] {
+                    return mConnectedDynamicSensors.find(dyn.sensorHandle) !=
+                            mConnectedDynamicSensors.end();
+                });
+                it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+                CHECK(it != mConnectedDynamicSensors.end());
+            }
+
+            dst->dynamic_sensor_meta.sensor = &it->second;
+
+            memcpy(dst->dynamic_sensor_meta.uuid, dyn.uuid.data(),
+                   sizeof(dst->dynamic_sensor_meta.uuid));
+        }
+    }
+}
+
+void HidlSensorHalWrapper::convertToSensorEventsAndQuantize(
+        const hidl_vec<Event>& src, const hidl_vec<SensorInfo>& dynamicSensorsAdded,
+        sensors_event_t* dst) {
+    if (dynamicSensorsAdded.size() > 0 && mCallback != nullptr) {
+        mCallback->onDynamicSensorsConnected_2_1(dynamicSensorsAdded);
+    }
+
+    for (size_t i = 0; i < src.size(); ++i) {
+        android::hardware::sensors::V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
+        android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
+                                                              getResolutionForSensor(
+                                                                      dst[i].sensor));
+    }
+}
+
+float HidlSensorHalWrapper::getResolutionForSensor(int sensorHandle) {
+    for (size_t i = 0; i < mSensorList.size(); i++) {
+        if (sensorHandle == mSensorList[i].handle) {
+            return mSensorList[i].resolution;
+        }
+    }
+
+    auto it = mConnectedDynamicSensors.find(sensorHandle);
+    if (it != mConnectedDynamicSensors.end()) {
+        return it->second.resolution;
+    }
+
+    return 0;
+}
+
+} // namespace android
diff --git a/services/sensorservice/HidlSensorHalWrapper.h b/services/sensorservice/HidlSensorHalWrapper.h
new file mode 100644
index 0000000..030247f
--- /dev/null
+++ b/services/sensorservice/HidlSensorHalWrapper.h
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HIDL_SENSOR_HAL_WRAPPER_H
+#define ANDROID_HIDL_SENSOR_HAL_WRAPPER_H
+
+#include <sensor/SensorEventQueue.h>
+#include <utils/Singleton.h>
+
+#include "ISensorHalWrapper.h"
+
+#include "ISensorsWrapper.h"
+#include "SensorDeviceUtils.h"
+
+namespace android {
+
+using android::hardware::sensors::V1_0::Result;
+using android::hardware::sensors::V2_1::Event;
+using android::hardware::sensors::V2_1::SensorInfo;
+
+class HidlTransportErrorLog {
+public:
+    HidlTransportErrorLog() {
+        mTs = 0;
+        mCount = 0;
+    }
+
+    HidlTransportErrorLog(time_t ts, int count) {
+        mTs = ts;
+        mCount = count;
+    }
+
+    String8 toString() const {
+        String8 result;
+        struct tm* timeInfo = localtime(&mTs);
+        result.appendFormat("%02d:%02d:%02d :: %d", timeInfo->tm_hour, timeInfo->tm_min,
+                            timeInfo->tm_sec, mCount);
+        return result;
+    }
+
+private:
+    time_t mTs; // timestamp of the error
+    int mCount; // number of transport errors observed
+};
+
+class SensorsHalDeathReceiver : public android::hardware::hidl_death_recipient {
+public:
+    SensorsHalDeathReceiver(ISensorHalWrapper* wrapper) : mHidlSensorHalWrapper(wrapper) {}
+
+    virtual void serviceDied(uint64_t cookie,
+                             const wp<::android::hidl::base::V1_0::IBase>& service) override;
+
+private:
+    ISensorHalWrapper* mHidlSensorHalWrapper;
+};
+
+class HidlSensorHalWrapper : public ISensorHalWrapper {
+public:
+    HidlSensorHalWrapper()
+          : mHidlTransportErrors(20),
+            mTotalHidlTransportErrors(0),
+            mRestartWaiter(new SensorDeviceUtils::HidlServiceRegistrationWaiter()),
+            mEventQueueFlag(nullptr),
+            mWakeLockQueueFlag(nullptr) {}
+
+    ~HidlSensorHalWrapper() override {
+        if (mEventQueueFlag != nullptr) {
+            hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
+            mEventQueueFlag = nullptr;
+        }
+        if (mWakeLockQueueFlag != nullptr) {
+            hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+            mWakeLockQueueFlag = nullptr;
+        }
+    }
+    virtual bool connect(SensorDeviceCallback* callback) override;
+
+    virtual void prepareForReconnect() override;
+
+    virtual bool supportsPolling() override;
+
+    virtual bool supportsMessageQueues() override;
+
+    virtual ssize_t poll(sensors_event_t* buffer, size_t count) override;
+
+    virtual ssize_t pollFmq(sensors_event_t* buffer, size_t count) override;
+
+    virtual std::vector<sensor_t> getSensorsList() override;
+
+    virtual status_t setOperationMode(SensorService::Mode mode) override;
+
+    virtual status_t activate(int32_t sensorHandle, bool enabled) override;
+
+    virtual status_t batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                           int64_t maxReportLatencyNs) override;
+
+    virtual status_t flush(int32_t sensorHandle) override;
+
+    virtual status_t injectSensorData(const sensors_event_t* event) override;
+
+    virtual status_t registerDirectChannel(const sensors_direct_mem_t* memory,
+                                           int32_t* channelHandle) override;
+
+    virtual status_t unregisterDirectChannel(int32_t channelHandle) override;
+
+    virtual status_t configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+                                            const struct sensors_direct_cfg_t* config) override;
+
+    virtual void writeWakeLockHandled(uint32_t count) override;
+
+private:
+    sp<::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase> mSensors;
+    sp<::android::hardware::sensors::V2_1::ISensorsCallback> mCallback;
+    std::vector<sensor_t> mSensorList;
+    std::unordered_map<int32_t, sensor_t> mConnectedDynamicSensors;
+
+    std::mutex mDynamicSensorsMutex;
+    std::condition_variable mDynamicSensorsCv;
+    static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
+
+    // Keep track of any hidl transport failures
+    SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
+    int mTotalHidlTransportErrors;
+
+    SensorDeviceCallback* mSensorDeviceCallback = nullptr;
+
+    // TODO(b/67425500): remove waiter after bug is resolved.
+    sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
+
+    template <typename T>
+    void checkReturn(const hardware::Return<T>& ret) {
+        if (!ret.isOk()) {
+            handleHidlDeath(ret.description());
+        }
+    }
+
+    status_t checkReturnAndGetStatus(const hardware::Return<Result>& ret);
+
+    void handleHidlDeath(const std::string& detail);
+
+    void convertToSensorEvent(const Event& src, sensors_event_t* dst);
+
+    void convertToSensorEventsAndQuantize(const hardware::hidl_vec<Event>& src,
+                                          const hardware::hidl_vec<SensorInfo>& dynamicSensorsAdded,
+                                          sensors_event_t* dst);
+
+    bool connectHidlService();
+
+    HalConnectionStatus connectHidlServiceV1_0();
+    HalConnectionStatus connectHidlServiceV2_0();
+    HalConnectionStatus connectHidlServiceV2_1();
+    HalConnectionStatus initializeHidlServiceV2_X();
+
+    typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue;
+    std::unique_ptr<WakeLockQueue> mWakeLockQueue;
+
+    float getResolutionForSensor(int sensorHandle);
+
+    hardware::EventFlag* mEventQueueFlag;
+    hardware::EventFlag* mWakeLockQueueFlag;
+
+    std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
+
+    sp<SensorsHalDeathReceiver> mSensorsHalDeathReceiver;
+};
+
+} // namespace android
+
+#endif // ANDROID_HIDL_SENSOR_HAL_WRAPPER_H
diff --git a/services/sensorservice/ISensorHalWrapper.h b/services/sensorservice/ISensorHalWrapper.h
index c9e089e..3d33540 100644
--- a/services/sensorservice/ISensorHalWrapper.h
+++ b/services/sensorservice/ISensorHalWrapper.h
@@ -30,26 +30,45 @@
  */
 class ISensorHalWrapper {
 public:
-    class ICallback : public ISensorsCallback {
-
-        void onDynamicSensorsConnected(
+    class SensorDeviceCallback {
+    public:
+        virtual void onDynamicSensorsConnected(
                 const std::vector<sensor_t> &dynamicSensorsAdded) = 0;
 
-        void onDynamicSensorsDisconnected(
+        virtual void onDynamicSensorsDisconnected(
                 const std::vector<int32_t> &dynamicSensorHandlesRemoved) = 0;
+
+        virtual ~SensorDeviceCallback(){};
     };
 
+    enum HalConnectionStatus {
+        CONNECTED,         // Successfully connected to the HAL
+        DOES_NOT_EXIST,    // Could not find the HAL
+        FAILED_TO_CONNECT, // Found the HAL but failed to connect/initialize
+        UNKNOWN,
+    };
+
+    virtual ~ISensorHalWrapper(){};
+
     /**
      * Connects to the underlying sensors HAL. This should also be used for any reconnections
      * due to HAL resets.
      */
-    virtual bool connect(ICallback *callback) = 0;
+    virtual bool connect(SensorDeviceCallback *callback) = 0;
+
+    virtual void prepareForReconnect() = 0;
+
+    virtual bool supportsPolling() = 0;
+
+    virtual bool supportsMessageQueues() = 0;
 
     /**
      * Polls for available sensor events. This could be using the traditional sensors
      * polling or from a FMQ.
      */
-    virtual ssize_t poll(sensors_event_t* buffer, size_t count) = 0;
+    virtual ssize_t poll(sensors_event_t *buffer, size_t count) = 0;
+
+    virtual ssize_t pollFmq(sensors_event_t *buffer, size_t maxNumEventsToRead) = 0;
 
     /**
      * The below functions directly mirrors the sensors HAL definitions.
@@ -70,11 +89,15 @@
     virtual status_t registerDirectChannel(const sensors_direct_mem_t *memory,
                                            int32_t *channelHandle) = 0;
 
-    virtual void unregisterDirectChannel(int32_t channelHandle) = 0;
+    virtual status_t unregisterDirectChannel(int32_t channelHandle) = 0;
 
     virtual status_t configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
                                             const struct sensors_direct_cfg_t *config) = 0;
-}
+
+    virtual void writeWakeLockHandled(uint32_t count) = 0;
+
+    std::atomic_bool mReconnecting = false;
+};
 
 } // namespace android
 
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c67acbf..84a1076 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -17,7 +17,6 @@
 #include "SensorDevice.h"
 
 #include "android/hardware/sensors/2.0/types.h"
-#include "android/hardware/sensors/2.1/ISensorsCallback.h"
 #include "android/hardware/sensors/2.1/types.h"
 #include "convertV2_1.h"
 
@@ -35,21 +34,7 @@
 #include <thread>
 
 using namespace android::hardware::sensors;
-using namespace android::hardware::sensors::V1_0;
-using namespace android::hardware::sensors::V1_0::implementation;
-using android::hardware::hidl_vec;
 using android::hardware::Return;
-using android::hardware::sensors::V2_0::EventQueueFlagBits;
-using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
-using android::hardware::sensors::V2_1::ISensorsCallback;
-using android::hardware::sensors::V2_1::implementation::convertToNewEvents;
-using android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
-using android::hardware::sensors::V2_1::implementation::convertToOldSensorInfo;
-using android::hardware::sensors::V2_1::implementation::convertToSensor;
-using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV1_0;
-using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_0;
-using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_1;
-using android::SensorDeviceUtils::HidlServiceRegistrationWaiter;
 using android::util::ProtoOutputStream;
 
 namespace android {
@@ -59,21 +44,6 @@
 
 namespace {
 
-status_t statusFromResult(Result result) {
-    switch (result) {
-        case Result::OK:
-            return OK;
-        case Result::BAD_VALUE:
-            return BAD_VALUE;
-        case Result::PERMISSION_DENIED:
-            return PERMISSION_DENIED;
-        case Result::INVALID_OPERATION:
-            return INVALID_OPERATION;
-        case Result::NO_MEMORY:
-            return NO_MEMORY;
-    }
-}
-
 template <typename EnumType>
 constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
     return static_cast<typename std::underlying_type<EnumType>::type>(value);
@@ -85,245 +55,98 @@
     INTERNAL_WAKE = 1 << 16,
 };
 
-} // anonymous namespace
-
-void SensorsHalDeathReceivier::serviceDied(
-        uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
-    ALOGW("Sensors HAL died, attempting to reconnect.");
-    SensorDevice::getInstance().prepareForReconnect();
-}
-
-struct SensorsCallback : public ISensorsCallback {
-    using Result = ::android::hardware::sensors::V1_0::Result;
-    using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
-
-    Return<void> onDynamicSensorsConnected_2_1(
-            const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
-        std::vector<sensor_t> sensors;
-        for (const V2_1::SensorInfo& info : dynamicSensorsAdded) {
-            sensor_t sensor;
-            convertToSensor(info, &sensor);
-            sensors.push_back(sensor);
-        }
-
-        SensorDevice::getInstance().onDynamicSensorsConnected(sensors);
-        return Return<void>();
-    }
-
-    Return<void> onDynamicSensorsConnected(
-            const hidl_vec<V1_0::SensorInfo>& dynamicSensorsAdded) override {
-        return onDynamicSensorsConnected_2_1(convertToNewSensorInfos(dynamicSensorsAdded));
-    }
-
-    Return<void> onDynamicSensorsDisconnected(
-            const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
-        SensorDevice::getInstance().onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved);
-        return Return<void>();
-    }
+enum DevicePrivateBase : int32_t {
+    DEVICE_PRIVATE_BASE = 65536,
 };
 
-SensorDevice::SensorDevice()
-      : mHidlTransportErrors(20),
-        mRestartWaiter(new HidlServiceRegistrationWaiter()),
-        mEventQueueFlag(nullptr),
-        mWakeLockQueueFlag(nullptr),
-        mReconnecting(false) {
-    if (!connectHidlService()) {
+} // anonymous namespace
+
+SensorDevice::SensorDevice() {
+    if (!connectHalService()) {
         return;
     }
 
     initializeSensorList();
 
-    mIsDirectReportSupported =
-            (checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
+    mIsDirectReportSupported = (mHalWrapper->unregisterDirectChannel(-1) != INVALID_OPERATION);
 }
 
 void SensorDevice::initializeSensorList() {
-    checkReturn(mSensors->getSensorsList([&](const auto& list) {
-        const size_t count = list.size();
+    if (mHalWrapper == nullptr) {
+        return;
+    }
 
-        mActivationCount.setCapacity(count);
-        Info model;
-        for (size_t i = 0; i < count; i++) {
-            sensor_t sensor;
-            convertToSensor(list[i], &sensor);
+    auto list = mHalWrapper->getSensorsList();
+    const size_t count = list.size();
 
-            if (sensor.type < static_cast<int>(SensorType::DEVICE_PRIVATE_BASE)) {
-                sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
+    mActivationCount.setCapacity(count);
+    Info model;
+    for (size_t i = 0; i < count; i++) {
+        sensor_t sensor = list[i];
 
-                // Some sensors don't have a default resolution and will be left at 0.
-                // Don't crash in this case since CTS will verify that devices don't go to
-                // production with a resolution of 0.
-                if (sensor.resolution != 0) {
-                    float quantizedRange = sensor.maxRange;
-                    SensorDeviceUtils::quantizeValue(&quantizedRange, sensor.resolution,
-                                                     /*factor=*/1);
-                    // Only rewrite maxRange if the requantization produced a "significant"
-                    // change, which is fairly arbitrarily defined as resolution / 8.
-                    // Smaller deltas are permitted, as they may simply be due to floating
-                    // point representation error, etc.
-                    if (fabsf(sensor.maxRange - quantizedRange) > sensor.resolution / 8) {
-                        ALOGW("%s's max range %.12f is not a multiple of the resolution "
-                              "%.12f - updated to %.12f",
-                              sensor.name, sensor.maxRange, sensor.resolution, quantizedRange);
-                        sensor.maxRange = quantizedRange;
-                    }
-                } else {
-                    // Don't crash here or the device will go into a crashloop.
-                    ALOGW("%s should have a non-zero resolution", sensor.name);
+        if (sensor.type < DEVICE_PRIVATE_BASE) {
+            sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
+
+            // Some sensors don't have a default resolution and will be left at 0.
+            // Don't crash in this case since CTS will verify that devices don't go to
+            // production with a resolution of 0.
+            if (sensor.resolution != 0) {
+                float quantizedRange = sensor.maxRange;
+                SensorDeviceUtils::quantizeValue(&quantizedRange, sensor.resolution,
+                                                 /*factor=*/1);
+                // Only rewrite maxRange if the requantization produced a "significant"
+                // change, which is fairly arbitrarily defined as resolution / 8.
+                // Smaller deltas are permitted, as they may simply be due to floating
+                // point representation error, etc.
+                if (fabsf(sensor.maxRange - quantizedRange) > sensor.resolution / 8) {
+                    ALOGW("%s's max range %.12f is not a multiple of the resolution "
+                          "%.12f - updated to %.12f",
+                          sensor.name, sensor.maxRange, sensor.resolution, quantizedRange);
+                    sensor.maxRange = quantizedRange;
                 }
-            }
-
-            // Check and clamp power if it is 0 (or close)
-            constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
-            if (sensor.power < MIN_POWER_MA) {
-                ALOGI("%s's reported power %f invalid, clamped to %f", sensor.name, sensor.power,
-                      MIN_POWER_MA);
-                sensor.power = MIN_POWER_MA;
-            }
-            mSensorList.push_back(sensor);
-
-            mActivationCount.add(list[i].sensorHandle, model);
-
-            // Only disable all sensors on HAL 1.0 since HAL 2.0
-            // handles this in its initialize method
-            if (!mSensors->supportsMessageQueues()) {
-                checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
+            } else {
+                // Don't crash here or the device will go into a crashloop.
+                ALOGW("%s should have a non-zero resolution", sensor.name);
             }
         }
-    }));
-}
 
-SensorDevice::~SensorDevice() {
-    if (mEventQueueFlag != nullptr) {
-        hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
-        mEventQueueFlag = nullptr;
-    }
-
-    if (mWakeLockQueueFlag != nullptr) {
-        hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
-        mWakeLockQueueFlag = nullptr;
-    }
-}
-
-bool SensorDevice::connectHidlService() {
-    HalConnectionStatus status = connectHidlServiceV2_1();
-    if (status == HalConnectionStatus::DOES_NOT_EXIST) {
-        status = connectHidlServiceV2_0();
-    }
-
-    if (status == HalConnectionStatus::DOES_NOT_EXIST) {
-        status = connectHidlServiceV1_0();
-    }
-    return (status == HalConnectionStatus::CONNECTED);
-}
-
-SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV1_0() {
-    // SensorDevice will wait for HAL service to start if HAL is declared in device manifest.
-    size_t retry = 10;
-    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
-
-    while (retry-- > 0) {
-        sp<V1_0::ISensors> sensors = V1_0::ISensors::getService();
-        if (sensors == nullptr) {
-            // no sensor hidl service found
-            connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
-            break;
+        // Check and clamp power if it is 0 (or close)
+        constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
+        if (sensor.power < MIN_POWER_MA) {
+            ALOGI("%s's reported power %f invalid, clamped to %f", sensor.name, sensor.power,
+                  MIN_POWER_MA);
+            sensor.power = MIN_POWER_MA;
         }
+        mSensorList.push_back(sensor);
 
-        mSensors = new ISensorsWrapperV1_0(sensors);
-        mRestartWaiter->reset();
-        // Poke ISensor service. If it has lingering connection from previous generation of
-        // system server, it will kill itself. There is no intention to handle the poll result,
-        // which will be done since the size is 0.
-        if (mSensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
-            // ok to continue
-            connectionStatus = HalConnectionStatus::CONNECTED;
-            break;
+        mActivationCount.add(list[i].handle, model);
+
+        // Only disable all sensors on HAL 1.0 since HAL 2.0
+        // handles this in its initialize method
+        if (!mHalWrapper->supportsMessageQueues()) {
+            mHalWrapper->activate(list[i].handle, 0 /* enabled */);
         }
-
-        // hidl service is restarting, pointer is invalid.
-        mSensors = nullptr;
-        connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
-        ALOGI("%s unsuccessful, remaining retry %zu.", __FUNCTION__, retry);
-        mRestartWaiter->wait();
     }
-
-    return connectionStatus;
 }
 
-SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV2_0() {
-    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
-    sp<V2_0::ISensors> sensors = V2_0::ISensors::getService();
+SensorDevice::~SensorDevice() {}
 
-    if (sensors == nullptr) {
-        connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
-    } else {
-        mSensors = new ISensorsWrapperV2_0(sensors);
-        connectionStatus = initializeHidlServiceV2_X();
+bool SensorDevice::connectHalService() {
+    std::unique_ptr<ISensorHalWrapper> hidl_wrapper = std::make_unique<HidlSensorHalWrapper>();
+    if (hidl_wrapper->connect(this)) {
+        mHalWrapper = std::move(hidl_wrapper);
+        return true;
     }
-
-    return connectionStatus;
-}
-
-SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV2_1() {
-    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
-    sp<V2_1::ISensors> sensors = V2_1::ISensors::getService();
-
-    if (sensors == nullptr) {
-        connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
-    } else {
-        mSensors = new ISensorsWrapperV2_1(sensors);
-        connectionStatus = initializeHidlServiceV2_X();
-    }
-
-    return connectionStatus;
-}
-
-SensorDevice::HalConnectionStatus SensorDevice::initializeHidlServiceV2_X() {
-    HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
-
-    mWakeLockQueue =
-            std::make_unique<WakeLockQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
-                                            true /* configureEventFlagWord */);
-
-    hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
-    hardware::EventFlag::createEventFlag(mSensors->getEventQueue()->getEventFlagWord(),
-                                         &mEventQueueFlag);
-
-    hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
-    hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakeLockQueueFlag);
-
-    CHECK(mSensors != nullptr && mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
-          mWakeLockQueueFlag != nullptr);
-
-    mCallback = new SensorsCallback();
-    status_t status =
-            checkReturnAndGetStatus(mSensors->initialize(*mWakeLockQueue->getDesc(), mCallback));
-
-    if (status != NO_ERROR) {
-        connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
-        ALOGE("Failed to initialize Sensors HAL (%s)", strerror(-status));
-    } else {
-        connectionStatus = HalConnectionStatus::CONNECTED;
-        mSensorsHalDeathReceiver = new SensorsHalDeathReceivier();
-        mSensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);
-    }
-
-    return connectionStatus;
+    // TODO: check aidl connection;
+    return false;
 }
 
 void SensorDevice::prepareForReconnect() {
-    mReconnecting = true;
-
-    // Wake up the polling thread so it returns and allows the SensorService to initiate
-    // a reconnect.
-    mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+    mHalWrapper->prepareForReconnect();
 }
 
 void SensorDevice::reconnect() {
     Mutex::Autolock _l(mLock);
-    mSensors = nullptr;
 
     auto previousActivations = mActivationCount;
     auto previousSensorList = mSensorList;
@@ -331,7 +154,7 @@
     mActivationCount.clear();
     mSensorList.clear();
 
-    if (connectHidlService()) {
+    if (mHalWrapper->connect(this)) {
         initializeSensorList();
 
         if (sensorHandlesChanged(previousSensorList, mSensorList)) {
@@ -340,7 +163,7 @@
             reactivateSensors(previousActivations);
         }
     }
-    mReconnecting = false;
+    mHalWrapper->mReconnecting = false;
 }
 
 bool SensorDevice::sensorHandlesChanged(const std::vector<sensor_t>& oldSensorList,
@@ -422,14 +245,14 @@
     if (connected) {
         Info model;
         mActivationCount.add(handle, model);
-        checkReturn(mSensors->activate(handle, 0 /* enabled */));
+        mHalWrapper->activate(handle, 0 /* enabled */);
     } else {
         mActivationCount.removeItem(handle);
     }
 }
 
 std::string SensorDevice::dump() const {
-    if (mSensors == nullptr) return "HAL not initialized\n";
+    if (mHalWrapper == nullptr) return "HAL not initialized\n";
 
     String8 result;
     result.appendFormat("Total %zu h/w sensors, %zu running %zu disabled clients:\n",
@@ -476,7 +299,7 @@
  */
 void SensorDevice::dump(ProtoOutputStream* proto) const {
     using namespace service::SensorDeviceProto;
-    if (mSensors == nullptr) {
+    if (mHalWrapper == nullptr) {
         proto->write(INITIALIZED, false);
         return;
     }
@@ -511,17 +334,17 @@
 }
 
 status_t SensorDevice::initCheck() const {
-    return mSensors != nullptr ? NO_ERROR : NO_INIT;
+    return mHalWrapper != nullptr ? NO_ERROR : NO_INIT;
 }
 
 ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
-    if (mSensors == nullptr) return NO_INIT;
+    if (mHalWrapper == nullptr) return NO_INIT;
 
     ssize_t eventsRead = 0;
-    if (mSensors->supportsMessageQueues()) {
-        eventsRead = pollFmq(buffer, count);
-    } else if (mSensors->supportsPolling()) {
-        eventsRead = pollHal(buffer, count);
+    if (mHalWrapper->supportsMessageQueues()) {
+        eventsRead = mHalWrapper->pollFmq(buffer, count);
+    } else if (mHalWrapper->supportsPolling()) {
+        eventsRead = mHalWrapper->poll(buffer, count);
     } else {
         ALOGE("Must support polling or FMQ");
         eventsRead = -1;
@@ -529,95 +352,6 @@
     return eventsRead;
 }
 
-ssize_t SensorDevice::pollHal(sensors_event_t* buffer, size_t count) {
-    ssize_t err;
-    int numHidlTransportErrors = 0;
-    bool hidlTransportError = false;
-
-    do {
-        auto ret = mSensors->poll(
-                count, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
-                    if (result == Result::OK) {
-                        convertToSensorEventsAndQuantize(convertToNewEvents(events),
-                                                         convertToNewSensorInfos(
-                                                                 dynamicSensorsAdded),
-                                                         buffer);
-                        err = (ssize_t)events.size();
-                    } else {
-                        err = statusFromResult(result);
-                    }
-                });
-
-        if (ret.isOk()) {
-            hidlTransportError = false;
-        } else {
-            hidlTransportError = true;
-            numHidlTransportErrors++;
-            if (numHidlTransportErrors > 50) {
-                // Log error and bail
-                ALOGE("Max Hidl transport errors this cycle : %d", numHidlTransportErrors);
-                handleHidlDeath(ret.description());
-            } else {
-                std::this_thread::sleep_for(std::chrono::milliseconds(10));
-            }
-        }
-    } while (hidlTransportError);
-
-    if (numHidlTransportErrors > 0) {
-        ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
-        HidlTransportErrorLog errLog(time(nullptr), numHidlTransportErrors);
-        mHidlTransportErrors.add(errLog);
-        mTotalHidlTransportErrors++;
-    }
-
-    return err;
-}
-
-ssize_t SensorDevice::pollFmq(sensors_event_t* buffer, size_t maxNumEventsToRead) {
-    ssize_t eventsRead = 0;
-    size_t availableEvents = mSensors->getEventQueue()->availableToRead();
-
-    if (availableEvents == 0) {
-        uint32_t eventFlagState = 0;
-
-        // Wait for events to become available. This is necessary so that the Event FMQ's read() is
-        // able to be called with the correct number of events to read. If the specified number of
-        // events is not available, then read() would return no events, possibly introducing
-        // additional latency in delivering events to applications.
-        mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS) |
-                                      asBaseType(INTERNAL_WAKE),
-                              &eventFlagState);
-        availableEvents = mSensors->getEventQueue()->availableToRead();
-
-        if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
-            ALOGD("Event FMQ internal wake, returning from poll with no events");
-            return DEAD_OBJECT;
-        }
-    }
-
-    size_t eventsToRead = std::min({availableEvents, maxNumEventsToRead, mEventBuffer.size()});
-    if (eventsToRead > 0) {
-        if (mSensors->getEventQueue()->read(mEventBuffer.data(), eventsToRead)) {
-            // Notify the Sensors HAL that sensor events have been read. This is required to support
-            // the use of writeBlocking by the Sensors HAL.
-            mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
-
-            for (size_t i = 0; i < eventsToRead; i++) {
-                convertToSensorEvent(mEventBuffer[i], &buffer[i]);
-                android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
-                                                                      getResolutionForSensor(
-                                                                              buffer[i].sensor));
-            }
-            eventsRead = eventsToRead;
-        } else {
-            ALOGW("Failed to read %zu events, currently %zu events available", eventsToRead,
-                  availableEvents);
-        }
-    }
-
-    return eventsRead;
-}
-
 void SensorDevice::onDynamicSensorsConnected(const std::vector<sensor_t>& dynamicSensorsAdded) {
     std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
 
@@ -641,12 +375,8 @@
 }
 
 void SensorDevice::writeWakeLockHandled(uint32_t count) {
-    if (mSensors != nullptr && mSensors->supportsMessageQueues()) {
-        if (mWakeLockQueue->write(&count)) {
-            mWakeLockQueueFlag->wake(asBaseType(WakeLockQueueFlagBits::DATA_WRITTEN));
-        } else {
-            ALOGW("Failed to write wake lock handled");
-        }
+    if (mHalWrapper != nullptr && mHalWrapper->supportsMessageQueues()) {
+        mHalWrapper->writeWakeLockHandled(count);
     }
 }
 
@@ -665,7 +395,7 @@
 }
 
 status_t SensorDevice::activate(void* ident, int handle, int enabled) {
-    if (mSensors == nullptr) return NO_INIT;
+    if (mHalWrapper == nullptr) return NO_INIT;
 
     Mutex::Autolock _l(mLock);
     return activateLocked(ident, handle, enabled);
@@ -724,8 +454,8 @@
                 // events, and the best effort batch parameters might have changed.
                 ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w batch 0x%08x %" PRId64 " %" PRId64,
                          handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
-                checkReturn(mSensors->batch(handle, info.bestBatchParams.mTSample,
-                                            info.bestBatchParams.mTBatch));
+                mHalWrapper->batch(handle, info.bestBatchParams.mTSample,
+                                   info.bestBatchParams.mTBatch);
             }
         } else {
             // sensor wasn't enabled for this ident
@@ -756,7 +486,7 @@
 status_t SensorDevice::doActivateHardwareLocked(int handle, bool enabled) {
     ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
              enabled);
-    status_t err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
+    status_t err = mHalWrapper->activate(handle, enabled);
     ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
              strerror(-err));
     return err;
@@ -764,7 +494,7 @@
 
 status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                              int64_t maxBatchReportLatencyNs) {
-    if (mSensors == nullptr) return NO_INIT;
+    if (mHalWrapper == nullptr) return NO_INIT;
 
     if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
         samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
@@ -801,8 +531,8 @@
 
     status_t err = updateBatchParamsLocked(handle, info);
     if (err != NO_ERROR) {
-        ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s", mSensors.get(),
-              handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch, strerror(-err));
+        ALOGE("sensor batch failed 0x%08x %" PRId64 " %" PRId64 " err=%s", handle,
+              info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch, strerror(-err));
         info.removeBatchParamsForIdent(ident);
     }
 
@@ -825,8 +555,8 @@
     if (prevBestBatchParams != info.bestBatchParams && info.numActiveClients() > 0) {
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
                  info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
-        err = checkReturnAndGetStatus(mSensors->batch(handle, info.bestBatchParams.mTSample,
-                                                      info.bestBatchParams.mTBatch));
+        err = mHalWrapper->batch(handle, info.bestBatchParams.mTSample,
+                                 info.bestBatchParams.mTBatch);
     }
 
     return err;
@@ -837,15 +567,12 @@
 }
 
 int SensorDevice::getHalDeviceVersion() const {
-    if (mSensors == nullptr) return -1;
+    if (mHalWrapper == nullptr) return -1;
     return SENSORS_DEVICE_API_VERSION_1_4;
 }
 
-status_t SensorDevice::flush(void* ident, int handle) {
-    if (mSensors == nullptr) return NO_INIT;
-    if (isClientDisabled(ident)) return INVALID_OPERATION;
-    ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
-    return checkReturnAndGetStatus(mSensors->flush(handle));
+status_t SensorDevice::flush(void* /*ident*/, int handle) {
+    return mHalWrapper->flush(handle);
 }
 
 bool SensorDevice::isClientDisabled(void* ident) const {
@@ -928,7 +655,7 @@
 }
 
 void SensorDevice::enableAllSensors() {
-    if (mSensors == nullptr) return;
+    if (mHalWrapper == nullptr) return;
     Mutex::Autolock _l(mLock);
 
     for (void* client : getDisabledClientsLocked()) {
@@ -943,13 +670,12 @@
         const int sensor_handle = mActivationCount.keyAt(i);
         ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
                  sensor_handle);
-        status_t err = checkReturnAndGetStatus(mSensors->batch(sensor_handle,
-                                                               info.bestBatchParams.mTSample,
-                                                               info.bestBatchParams.mTBatch));
+        status_t err = mHalWrapper->batch(sensor_handle, info.bestBatchParams.mTSample,
+                                          info.bestBatchParams.mTBatch);
         ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
 
         if (err == NO_ERROR) {
-            err = checkReturnAndGetStatus(mSensors->activate(sensor_handle, 1 /* enabled */));
+            err = mHalWrapper->activate(sensor_handle, 1 /* enabled */);
             ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
         }
 
@@ -960,7 +686,7 @@
 }
 
 void SensorDevice::disableAllSensors() {
-    if (mSensors == nullptr) return;
+    if (mHalWrapper == nullptr) return;
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mActivationCount.size(); ++i) {
         Info& info = mActivationCount.editValueAt(i);
@@ -969,7 +695,7 @@
             const int sensor_handle = mActivationCount.keyAt(i);
             ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
                      sensor_handle);
-            checkReturn(mSensors->activate(sensor_handle, 0 /* enabled */));
+            mHalWrapper->activate(sensor_handle, 0 /* enabled */);
 
             // Add all the connections that were registered for this sensor to the disabled
             // clients list.
@@ -985,110 +711,29 @@
 }
 
 status_t SensorDevice::injectSensorData(const sensors_event_t* injected_sensor_event) {
-    if (mSensors == nullptr) return NO_INIT;
-    ALOGD_IF(DEBUG_CONNECTIONS,
-             "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
-             injected_sensor_event->sensor, injected_sensor_event->timestamp,
-             injected_sensor_event->data[0], injected_sensor_event->data[1],
-             injected_sensor_event->data[2], injected_sensor_event->data[3],
-             injected_sensor_event->data[4], injected_sensor_event->data[5]);
-
-    Event ev;
-    V2_1::implementation::convertFromSensorEvent(*injected_sensor_event, &ev);
-
-    return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
+    return mHalWrapper->injectSensorData(injected_sensor_event);
 }
 
 status_t SensorDevice::setMode(uint32_t mode) {
-    if (mSensors == nullptr) return NO_INIT;
-    return checkReturnAndGetStatus(
-            mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+    if (mHalWrapper == nullptr) return NO_INIT;
+    return mHalWrapper->setOperationMode(static_cast<SensorService::Mode>(mode));
 }
 
 int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
-    if (mSensors == nullptr) return NO_INIT;
     Mutex::Autolock _l(mLock);
 
-    SharedMemType type;
-    switch (memory->type) {
-        case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
-            type = SharedMemType::ASHMEM;
-            break;
-        case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
-            type = SharedMemType::GRALLOC;
-            break;
-        default:
-            return BAD_VALUE;
-    }
-
-    SharedMemFormat format;
-    if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
-        return BAD_VALUE;
-    }
-    format = SharedMemFormat::SENSORS_EVENT;
-
-    SharedMemInfo mem = {
-            .type = type,
-            .format = format,
-            .size = static_cast<uint32_t>(memory->size),
-            .memoryHandle = memory->handle,
-    };
-
-    int32_t ret;
-    checkReturn(mSensors->registerDirectChannel(mem, [&ret](auto result, auto channelHandle) {
-        if (result == Result::OK) {
-            ret = channelHandle;
-        } else {
-            ret = statusFromResult(result);
-        }
-    }));
-    return ret;
+    return mHalWrapper->registerDirectChannel(memory, nullptr);
 }
 
 void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
-    if (mSensors == nullptr) return;
-    Mutex::Autolock _l(mLock);
-    checkReturn(mSensors->unregisterDirectChannel(channelHandle));
+    mHalWrapper->unregisterDirectChannel(channelHandle);
 }
 
 int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
                                              const struct sensors_direct_cfg_t* config) {
-    if (mSensors == nullptr) return NO_INIT;
     Mutex::Autolock _l(mLock);
 
-    RateLevel rate;
-    switch (config->rate_level) {
-        case SENSOR_DIRECT_RATE_STOP:
-            rate = RateLevel::STOP;
-            break;
-        case SENSOR_DIRECT_RATE_NORMAL:
-            rate = RateLevel::NORMAL;
-            break;
-        case SENSOR_DIRECT_RATE_FAST:
-            rate = RateLevel::FAST;
-            break;
-        case SENSOR_DIRECT_RATE_VERY_FAST:
-            rate = RateLevel::VERY_FAST;
-            break;
-        default:
-            return BAD_VALUE;
-    }
-
-    int32_t ret;
-    checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
-                                             [&ret, rate](auto result, auto token) {
-                                                 if (rate == RateLevel::STOP) {
-                                                     ret = statusFromResult(result);
-                                                 } else {
-                                                     if (result == Result::OK) {
-                                                         ret = token;
-                                                     } else {
-                                                         ret = statusFromResult(result);
-                                                     }
-                                                 }
-                                             }));
-
-    return ret;
+    return mHalWrapper->configureDirectChannel(sensorHandle, channelHandle, config);
 }
 
 // ---------------------------------------------------------------------------
@@ -1153,52 +798,6 @@
     return mIsDirectReportSupported;
 }
 
-void SensorDevice::convertToSensorEvent(const Event& src, sensors_event_t* dst) {
-    V2_1::implementation::convertToSensorEvent(src, dst);
-
-    if (src.sensorType == V2_1::SensorType::DYNAMIC_SENSOR_META) {
-        const DynamicSensorInfo& dyn = src.u.dynamic;
-
-        dst->dynamic_sensor_meta.connected = dyn.connected;
-        dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
-        if (dyn.connected) {
-            std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
-            // Give MAX_DYN_SENSOR_WAIT_SEC for onDynamicSensorsConnected to be invoked since it
-            // can be received out of order from this event due to a bug in the HIDL spec that
-            // marks it as oneway.
-            auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
-            if (it == mConnectedDynamicSensors.end()) {
-                mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT, [&, dyn] {
-                    return mConnectedDynamicSensors.find(dyn.sensorHandle) !=
-                            mConnectedDynamicSensors.end();
-                });
-                it = mConnectedDynamicSensors.find(dyn.sensorHandle);
-                CHECK(it != mConnectedDynamicSensors.end());
-            }
-
-            dst->dynamic_sensor_meta.sensor = &it->second;
-
-            memcpy(dst->dynamic_sensor_meta.uuid, dyn.uuid.data(),
-                   sizeof(dst->dynamic_sensor_meta.uuid));
-        }
-    }
-}
-
-void SensorDevice::convertToSensorEventsAndQuantize(const hidl_vec<Event>& src,
-                                                    const hidl_vec<SensorInfo>& dynamicSensorsAdded,
-                                                    sensors_event_t* dst) {
-    if (dynamicSensorsAdded.size() > 0 && mCallback != nullptr) {
-        mCallback->onDynamicSensorsConnected_2_1(dynamicSensorsAdded);
-    }
-
-    for (size_t i = 0; i < src.size(); ++i) {
-        V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
-        android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
-                                                              getResolutionForSensor(
-                                                                      dst[i].sensor));
-    }
-}
-
 float SensorDevice::getResolutionForSensor(int sensorHandle) {
     for (size_t i = 0; i < mSensorList.size(); i++) {
         if (sensorHandle == mSensorList[i].handle) {
@@ -1214,19 +813,5 @@
     return 0;
 }
 
-void SensorDevice::handleHidlDeath(const std::string& detail) {
-    if (!mSensors->supportsMessageQueues()) {
-        // restart is the only option at present.
-        LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
-    } else {
-        ALOGD("ISensors HAL died, death recipient will attempt reconnect");
-    }
-}
-
-status_t SensorDevice::checkReturnAndGetStatus(const Return<Result>& ret) {
-    checkReturn(ret);
-    return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 314ddb8..80e77d9 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -17,12 +17,14 @@
 #ifndef ANDROID_SENSOR_DEVICE_H
 #define ANDROID_SENSOR_DEVICE_H
 
+#include "HidlSensorHalWrapper.h"
+#include "ISensorHalWrapper.h"
+
 #include "ISensorsWrapper.h"
 #include "SensorDeviceUtils.h"
 #include "SensorService.h"
 #include "SensorServiceUtils.h"
 
-#include <fmq/MessageQueue.h>
 #include <sensor/Sensor.h>
 #include <sensor/SensorEventQueue.h>
 #include <stdint.h>
@@ -43,41 +45,12 @@
 
 namespace android {
 
-using Result = ::android::hardware::sensors::V1_0::Result;
-
 // ---------------------------------------------------------------------------
-class SensorsHalDeathReceivier : public android::hardware::hidl_death_recipient {
-    virtual void serviceDied(uint64_t cookie,
-                             const wp<::android::hidl::base::V1_0::IBase>& service) override;
-};
 
-class SensorDevice : public Singleton<SensorDevice>, public SensorServiceUtil::Dumpable {
+class SensorDevice : public Singleton<SensorDevice>,
+                     public SensorServiceUtil::Dumpable,
+                     public ISensorHalWrapper::SensorDeviceCallback {
 public:
-    class HidlTransportErrorLog {
-    public:
-        HidlTransportErrorLog() {
-            mTs = 0;
-            mCount = 0;
-        }
-
-        HidlTransportErrorLog(time_t ts, int count) {
-            mTs = ts;
-            mCount = count;
-        }
-
-        String8 toString() const {
-            String8 result;
-            struct tm* timeInfo = localtime(&mTs);
-            result.appendFormat("%02d:%02d:%02d :: %d", timeInfo->tm_hour, timeInfo->tm_min,
-                                timeInfo->tm_sec, mCount);
-            return result;
-        }
-
-    private:
-        time_t mTs; // timestamp of the error
-        int mCount; // number of transport errors observed
-    };
-
     ~SensorDevice();
     void prepareForReconnect();
     void reconnect();
@@ -112,12 +85,15 @@
     status_t injectSensorData(const sensors_event_t* event);
     void notifyConnectionDestroyed(void* ident);
 
-    void onDynamicSensorsConnected(const std::vector<sensor_t>& dynamicSensorsAdded);
-    void onDynamicSensorsDisconnected(const std::vector<int32_t>& dynamicSensorHandlesRemoved);
+    // SensorDeviceCallback
+    virtual void onDynamicSensorsConnected(
+            const std::vector<sensor_t>& dynamicSensorsAdded) override;
+    virtual void onDynamicSensorsDisconnected(
+            const std::vector<int32_t>& dynamicSensorHandlesRemoved) override;
 
     void setUidStateForConnection(void* ident, SensorService::UidState state);
 
-    bool isReconnecting() const { return mReconnecting; }
+    bool isReconnecting() const { return mHalWrapper->mReconnecting; }
 
     bool isSensorActive(int handle) const;
 
@@ -132,8 +108,8 @@
 private:
     friend class Singleton<SensorDevice>;
 
-    sp<::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase> mSensors;
-    sp<::android::hardware::sensors::V2_1::ISensorsCallback> mCallback;
+    std::unique_ptr<ISensorHalWrapper> mHalWrapper;
+
     std::vector<sensor_t> mSensorList;
     std::unordered_map<int32_t, sensor_t> mConnectedDynamicSensors;
 
@@ -143,7 +119,6 @@
     // HAL implementations.
     std::mutex mDynamicSensorsMutex;
     std::condition_variable mDynamicSensorsCv;
-    static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
 
     static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
     mutable Mutex mLock;                                  // protect mActivationCount[].batchParams
@@ -203,8 +178,6 @@
     };
     DefaultKeyedVector<int, Info> mActivationCount;
 
-    // Keep track of any hidl transport failures
-    SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
     int mTotalHidlTransportErrors;
 
     /**
@@ -228,26 +201,13 @@
     void removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
 
     SensorDevice();
-    bool connectHidlService();
+    bool connectHalService();
     void initializeSensorList();
     void reactivateSensors(const DefaultKeyedVector<int, Info>& previousActivations);
     static bool sensorHandlesChanged(const std::vector<sensor_t>& oldSensorList,
                                      const std::vector<sensor_t>& newSensorList);
     static bool sensorIsEquivalent(const sensor_t& prevSensor, const sensor_t& newSensor);
 
-    enum HalConnectionStatus {
-        CONNECTED,         // Successfully connected to the HAL
-        DOES_NOT_EXIST,    // Could not find the HAL
-        FAILED_TO_CONNECT, // Found the HAL but failed to connect/initialize
-        UNKNOWN,
-    };
-    HalConnectionStatus connectHidlServiceV1_0();
-    HalConnectionStatus connectHidlServiceV2_0();
-    HalConnectionStatus connectHidlServiceV2_1();
-    HalConnectionStatus initializeHidlServiceV2_X();
-
-    ssize_t pollHal(sensors_event_t* buffer, size_t count);
-    ssize_t pollFmq(sensors_event_t* buffer, size_t count);
     status_t activateLocked(void* ident, int handle, int enabled);
     status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
                          int64_t maxBatchReportLatencyNs);
@@ -255,47 +215,15 @@
     status_t updateBatchParamsLocked(int handle, Info& info);
     status_t doActivateHardwareLocked(int handle, bool enable);
 
-    void handleHidlDeath(const std::string& detail);
-    template <typename T>
-    void checkReturn(const Return<T>& ret) {
-        if (!ret.isOk()) {
-            handleHidlDeath(ret.description());
-        }
-    }
-
-    status_t checkReturnAndGetStatus(const Return<Result>& ret);
-    // TODO(b/67425500): remove waiter after bug is resolved.
-    sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
-
     bool isClientDisabled(void* ident) const;
     bool isClientDisabledLocked(void* ident) const;
     std::vector<void*> getDisabledClientsLocked() const;
 
     bool clientHasNoAccessLocked(void* ident) const;
 
-    using Event = hardware::sensors::V2_1::Event;
-    using SensorInfo = hardware::sensors::V2_1::SensorInfo;
-
-    void convertToSensorEvent(const Event& src, sensors_event_t* dst);
-
-    void convertToSensorEventsAndQuantize(const hardware::hidl_vec<Event>& src,
-                                          const hardware::hidl_vec<SensorInfo>& dynamicSensorsAdded,
-                                          sensors_event_t* dst);
-
     float getResolutionForSensor(int sensorHandle);
 
     bool mIsDirectReportSupported;
-
-    typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue;
-    std::unique_ptr<WakeLockQueue> mWakeLockQueue;
-
-    hardware::EventFlag* mEventQueueFlag;
-    hardware::EventFlag* mWakeLockQueueFlag;
-
-    std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
-
-    sp<SensorsHalDeathReceivier> mSensorsHalDeathReceiver;
-    std::atomic_bool mReconnecting;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 64ddd68..e26c763 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -292,14 +292,15 @@
     // Sideband layers
     auto* compositionState = editCompositionState();
     if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) {
-        compositionState->compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+        compositionState->compositionType =
+                aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;
         return;
     } else {
         // Normal buffer layers
         compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
         compositionState->compositionType = mPotentialCursor
-                ? Hwc2::IComposerClient::Composition::CURSOR
-                : Hwc2::IComposerClient::Composition::DEVICE;
+                ? aidl::android::hardware::graphics::composer3::Composition::CURSOR
+                : aidl::android::hardware::graphics::composer3::Composition::DEVICE;
     }
 
     compositionState->buffer = mBufferInfo.mBuffer->getBuffer();
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 7e605f9..8bf7f8f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -39,6 +39,8 @@
 
 #include "DisplayHardware/Hal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -156,7 +158,8 @@
      */
 
     // The type of composition for this layer
-    hal::Composition compositionType{hal::Composition::INVALID};
+    aidl::android::hardware::graphics::composer3::Composition compositionType{
+            aidl::android::hardware::graphics::composer3::Composition::INVALID};
 
     // The buffer and related state
     sp<GraphicBuffer> buffer;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index ead941d..a2824f5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -33,6 +33,8 @@
 
 #include "LayerFE.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -112,7 +114,8 @@
     virtual bool isHardwareCursor() const = 0;
 
     // Applies a HWC device requested composition type change
-    virtual void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) = 0;
+    virtual void applyDeviceCompositionTypeChange(
+            aidl::android::hardware::graphics::composer3::Composition) = 0;
 
     // Prepares to apply any HWC device layer requests
     virtual void prepareForDeviceLayerRequests() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index c15249d..0082dac 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -27,6 +27,8 @@
 
 #include "DisplayHardware/DisplayIdentification.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace android::compositionengine {
 
 struct LayerFECompositionState;
@@ -50,7 +52,8 @@
     HWC2::Layer* getHwcLayer() const override;
     bool requiresClientComposition() const override;
     bool isHardwareCursor() const override;
-    void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override;
+    void applyDeviceCompositionTypeChange(
+            aidl::android::hardware::graphics::composer3::Composition) override;
     void prepareForDeviceLayerRequests() override;
     void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override;
     bool needsFiltering() const override;
@@ -68,21 +71,24 @@
 
 private:
     Rect calculateInitialCrop() const;
-    void writeOutputDependentGeometryStateToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
-                                                uint32_t z);
+    void writeOutputDependentGeometryStateToHWC(
+            HWC2::Layer*, aidl::android::hardware::graphics::composer3::Composition, uint32_t z);
     void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&,
                                                   bool skipLayer);
     void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*);
     void writeOutputIndependentPerFrameStateToHWC(
             HWC2::Layer*, const LayerFECompositionState&,
-            Hwc2::IComposerClient::Composition compositionType, bool skipLayer);
+            aidl::android::hardware::graphics::composer3::Composition compositionType,
+            bool skipLayer);
     void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
     void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
     void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&, bool skipLayer);
-    void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
+    void writeCompositionTypeToHWC(HWC2::Layer*,
+                                   aidl::android::hardware::graphics::composer3::Composition,
                                    bool isPeekingThrough, bool skipLayer);
-    void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
-                                               Hwc2::IComposerClient::Composition to) const;
+    void detectDisallowedCompositionTypeChange(
+            aidl::android::hardware::graphics::composer3::Composition from,
+            aidl::android::hardware::graphics::composer3::Composition to) const;
     bool isClientCompositionForced(bool isPeekingThrough) const;
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 627b80b..49cb912 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -35,6 +35,8 @@
 
 #include "DisplayHardware/ComposerHal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -123,8 +125,8 @@
         std::shared_ptr<HWC2::Layer> hwcLayer;
 
         // The most recently set HWC composition type for this layer
-        Hwc2::IComposerClient::Composition hwcCompositionType{
-                Hwc2::IComposerClient::Composition::INVALID};
+        aidl::android::hardware::graphics::composer3::Composition hwcCompositionType{
+                aidl::android::hardware::graphics::composer3::Composition::INVALID};
 
         // The buffer cache for this layer. This is used to lower the
         // cost of sending reused buffers to the HWC.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index 7397c19..14324de 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -28,6 +28,8 @@
 #include "DisplayHardware/Hal.h"
 #include "math/HashCombine.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace std {
 template <typename T>
 struct hash<android::sp<T>> {
@@ -232,7 +234,7 @@
         return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty();
     }
     int32_t getBackgroundBlurRadius() const { return mBackgroundBlurRadius.get(); }
-    hardware::graphics::composer::hal::Composition getCompositionType() const {
+    aidl::android::hardware::graphics::composer3::Composition getCompositionType() const {
         return mCompositionType.get();
     }
 
@@ -370,17 +372,18 @@
 
     OutputLayerState<mat4, LayerStateField::ColorTransform> mColorTransform;
 
-    using CompositionTypeState = OutputLayerState<hardware::graphics::composer::hal::Composition,
-                                                  LayerStateField::CompositionType>;
-    CompositionTypeState
-            mCompositionType{[](auto layer) {
-                                 return layer->getState().forceClientComposition
-                                         ? hardware::graphics::composer::hal::Composition::CLIENT
-                                         : layer->getLayerFE()
-                                                   .getCompositionState()
-                                                   ->compositionType;
-                             },
-                             CompositionTypeState::getHalToStrings()};
+    using CompositionTypeState =
+            OutputLayerState<aidl::android::hardware::graphics::composer3::Composition,
+                             LayerStateField::CompositionType>;
+    CompositionTypeState mCompositionType{[](auto layer) {
+                                              return layer->getState().forceClientComposition
+                                                      ? aidl::android::hardware::graphics::
+                                                                composer3::Composition::CLIENT
+                                                      : layer->getLayerFE()
+                                                                .getCompositionState()
+                                                                ->compositionType;
+                                          },
+                                          CompositionTypeState::getHalToStrings()};
 
     OutputLayerState<void*, LayerStateField::SidebandStream>
             mSidebandStream{[](auto layer) {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
index fe486d3..ef1560e 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
@@ -109,7 +109,7 @@
     static std::optional<Plan> fromString(const std::string&);
 
     void reset() { mLayerTypes.clear(); }
-    void addLayerType(hardware::graphics::composer::hal::Composition type) {
+    void addLayerType(aidl::android::hardware::graphics::composer3::Composition type) {
         mLayerTypes.emplace_back(type);
     }
 
@@ -125,7 +125,7 @@
     }
 
 private:
-    std::vector<hardware::graphics::composer::hal::Composition> mLayerTypes;
+    std::vector<aidl::android::hardware::graphics::composer3::Composition> mLayerTypes;
 };
 
 } // namespace android::compositionengine::impl::planner
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index 358ed5a..a6cb811 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -46,7 +46,8 @@
     MOCK_CONST_METHOD0(getHwcLayer, HWC2::Layer*());
     MOCK_CONST_METHOD0(requiresClientComposition, bool());
     MOCK_CONST_METHOD0(isHardwareCursor, bool());
-    MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition));
+    MOCK_METHOD1(applyDeviceCompositionTypeChange,
+                 void(aidl::android::hardware::graphics::composer3::Composition));
     MOCK_METHOD0(prepareForDeviceLayerRequests, void());
     MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request));
     MOCK_CONST_METHOD0(needsFiltering, bool());
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 4603e6b..3571319 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -282,7 +282,8 @@
 
         if (auto it = changedTypes.find(hwcLayer); it != changedTypes.end()) {
             layer->applyDeviceCompositionTypeChange(
-                    static_cast<Hwc2::IComposerClient::Composition>(it->second));
+                    static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                            it->second));
         }
     }
 }
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index b010d9f..94ad6c3 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -37,6 +37,8 @@
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion"
 
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 
 OutputLayer::~OutputLayer() = default;
@@ -358,8 +360,8 @@
 
     auto requestedCompositionType = outputIndependentState->compositionType;
 
-    if (requestedCompositionType == hal::Composition::SOLID_COLOR && state.overrideInfo.buffer) {
-        requestedCompositionType = hal::Composition::DEVICE;
+    if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) {
+        requestedCompositionType = Composition::DEVICE;
     }
 
     // TODO(b/181172795): We now update geometry for all flattened layers. We should update it
@@ -380,7 +382,7 @@
     writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
                               skipLayer);
 
-    if (requestedCompositionType == hal::Composition::SOLID_COLOR) {
+    if (requestedCompositionType == Composition::SOLID_COLOR) {
         writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
     }
 
@@ -389,7 +391,7 @@
 }
 
 void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
-                                                         hal::Composition requestedCompositionType,
+                                                         Composition requestedCompositionType,
                                                          uint32_t z) {
     const auto& outputDependentState = getState();
 
@@ -423,7 +425,7 @@
     }
 
     // Solid-color layers and overridden buffers should always use an identity transform.
-    const auto bufferTransform = (requestedCompositionType != hal::Composition::SOLID_COLOR &&
+    const auto bufferTransform = (requestedCompositionType != Composition::SOLID_COLOR &&
                                   getState().overrideInfo.buffer == nullptr)
             ? outputDependentState.bufferTransform
             : static_cast<hal::Transform>(0);
@@ -504,7 +506,7 @@
 
 void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
         HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
-        hal::Composition compositionType, bool skipLayer) {
+        Composition compositionType, bool skipLayer) {
     switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
         case hal::Error::NONE:
             break;
@@ -529,18 +531,19 @@
 
     // Content-specific per-frame state
     switch (compositionType) {
-        case hal::Composition::SOLID_COLOR:
+        case Composition::SOLID_COLOR:
             // For compatibility, should be written AFTER the composition type.
             break;
-        case hal::Composition::SIDEBAND:
+        case Composition::SIDEBAND:
             writeSidebandStateToHWC(hwcLayer, outputIndependentState);
             break;
-        case hal::Composition::CURSOR:
-        case hal::Composition::DEVICE:
+        case Composition::CURSOR:
+        case Composition::DEVICE:
+        case Composition::DISPLAY_DECORATION:
             writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer);
             break;
-        case hal::Composition::INVALID:
-        case hal::Composition::CLIENT:
+        case Composition::INVALID:
+        case Composition::CLIENT:
             // Ignored
             break;
     }
@@ -606,13 +609,13 @@
 }
 
 void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
-                                            hal::Composition requestedCompositionType,
+                                            Composition requestedCompositionType,
                                             bool isPeekingThrough, bool skipLayer) {
     auto& outputDependentState = editState();
 
     if (isClientCompositionForced(isPeekingThrough)) {
         // If we are forcing client composition, we need to tell the HWC
-        requestedCompositionType = hal::Composition::CLIENT;
+        requestedCompositionType = Composition::CLIENT;
     }
 
     // Set the requested composition type with the HWC whenever it changes
@@ -625,7 +628,7 @@
         if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
             error != hal::Error::NONE) {
             ALOGE("[%s] Failed to set composition type %s: %s (%d)", getLayerFE().getDebugName(),
-                  toString(requestedCompositionType).c_str(), to_string(error).c_str(),
+                  to_string(requestedCompositionType).c_str(), to_string(error).c_str(),
                   static_cast<int32_t>(error));
         }
     }
@@ -664,38 +667,38 @@
 
 bool OutputLayer::requiresClientComposition() const {
     const auto& state = getState();
-    return !state.hwc || state.hwc->hwcCompositionType == hal::Composition::CLIENT;
+    return !state.hwc || state.hwc->hwcCompositionType == Composition::CLIENT;
 }
 
 bool OutputLayer::isHardwareCursor() const {
     const auto& state = getState();
-    return state.hwc && state.hwc->hwcCompositionType == hal::Composition::CURSOR;
+    return state.hwc && state.hwc->hwcCompositionType == Composition::CURSOR;
 }
 
-void OutputLayer::detectDisallowedCompositionTypeChange(hal::Composition from,
-                                                        hal::Composition to) const {
+void OutputLayer::detectDisallowedCompositionTypeChange(Composition from, Composition to) const {
     bool result = false;
     switch (from) {
-        case hal::Composition::INVALID:
-        case hal::Composition::CLIENT:
+        case Composition::INVALID:
+        case Composition::CLIENT:
             result = false;
             break;
 
-        case hal::Composition::DEVICE:
-        case hal::Composition::SOLID_COLOR:
-            result = (to == hal::Composition::CLIENT);
+        case Composition::DEVICE:
+        case Composition::SOLID_COLOR:
+        case Composition::DISPLAY_DECORATION:
+            result = (to == Composition::CLIENT);
             break;
 
-        case hal::Composition::CURSOR:
-        case hal::Composition::SIDEBAND:
-            result = (to == hal::Composition::CLIENT || to == hal::Composition::DEVICE);
+        case Composition::CURSOR:
+        case Composition::SIDEBAND:
+            result = (to == Composition::CLIENT || to == Composition::DEVICE);
             break;
     }
 
     if (!result) {
         ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
-              getLayerFE().getDebugName(), toString(from).c_str(), static_cast<int>(from),
-              toString(to).c_str(), static_cast<int>(to));
+              getLayerFE().getDebugName(), to_string(from).c_str(), static_cast<int>(from),
+              to_string(to).c_str(), static_cast<int>(to));
     }
 }
 
@@ -704,7 +707,7 @@
             (!isPeekingThrough && getLayerFE().hasRoundedCorners());
 }
 
-void OutputLayer::applyDeviceCompositionTypeChange(hal::Composition compositionType) {
+void OutputLayer::applyDeviceCompositionTypeChange(Composition compositionType) {
     auto& state = editState();
     LOG_FATAL_IF(!state.hwc);
     auto& hwcState = *state.hwc;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index c14effc..0918510 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -211,7 +211,8 @@
         displayCost += static_cast<size_t>(layer->getDisplayFrame().width() *
                                            layer->getDisplayFrame().height());
 
-        hasClientComposition |= layer->getCompositionType() == hal::Composition::CLIENT;
+        hasClientComposition |= layer->getCompositionType() ==
+                aidl::android::hardware::graphics::composer3::Composition::CLIENT;
     }
 
     if (hasClientComposition) {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
index 2532e3d..c79ca0d 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
@@ -160,7 +160,8 @@
             lhs.mColorTransform == rhs.mColorTransform &&
             lhs.mCompositionType == rhs.mCompositionType &&
             lhs.mSidebandStream == rhs.mSidebandStream && lhs.mBuffer == rhs.mBuffer &&
-            (lhs.mCompositionType.get() != hal::Composition::SOLID_COLOR ||
+            (lhs.mCompositionType.get() !=
+                     aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR ||
              lhs.mSolidColor == rhs.mSolidColor);
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
index f5b1cee..74d2701 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
@@ -193,7 +193,7 @@
 
         finalPlan.addLayerType(
                 forcedOrRequestedClient
-                        ? hardware::graphics::composer::hal::Composition::CLIENT
+                        ? aidl::android::hardware::graphics::composer3::Composition::CLIENT
                         : layer->getLayerFE().getCompositionState()->compositionType);
     }
 
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
index 8226ef7..2d53583 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
@@ -39,8 +39,10 @@
 
         // Skip layers where both are client-composited, since that doesn't change the
         // composition plan
-        if (mLayers[i].getCompositionType() == hal::Composition::CLIENT &&
-            other[i]->getCompositionType() == hal::Composition::CLIENT) {
+        if (mLayers[i].getCompositionType() ==
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT &&
+            other[i]->getCompositionType() ==
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT) {
             continue;
         }
 
@@ -89,22 +91,32 @@
     for (char c : string) {
         switch (c) {
             case 'C':
-                plan.addLayerType(hal::Composition::CLIENT);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::CLIENT);
                 continue;
             case 'U':
-                plan.addLayerType(hal::Composition::CURSOR);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::CURSOR);
                 continue;
             case 'D':
-                plan.addLayerType(hal::Composition::DEVICE);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::DEVICE);
                 continue;
             case 'I':
-                plan.addLayerType(hal::Composition::INVALID);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::INVALID);
                 continue;
             case 'B':
-                plan.addLayerType(hal::Composition::SIDEBAND);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::SIDEBAND);
                 continue;
             case 'S':
-                plan.addLayerType(hal::Composition::SOLID_COLOR);
+                plan.addLayerType(
+                        aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR);
+                continue;
+            case 'A':
+                plan.addLayerType(aidl::android::hardware::graphics::composer3::Composition::
+                                          DISPLAY_DECORATION);
                 continue;
             default:
                 return std::nullopt;
@@ -117,24 +129,28 @@
     std::string result;
     for (auto type : plan.mLayerTypes) {
         switch (type) {
-            case hal::Composition::CLIENT:
+            case aidl::android::hardware::graphics::composer3::Composition::CLIENT:
                 result.append("C");
                 break;
-            case hal::Composition::CURSOR:
+            case aidl::android::hardware::graphics::composer3::Composition::CURSOR:
                 result.append("U");
                 break;
-            case hal::Composition::DEVICE:
+            case aidl::android::hardware::graphics::composer3::Composition::DEVICE:
                 result.append("D");
                 break;
-            case hal::Composition::INVALID:
+            case aidl::android::hardware::graphics::composer3::Composition::INVALID:
                 result.append("I");
                 break;
-            case hal::Composition::SIDEBAND:
+            case aidl::android::hardware::graphics::composer3::Composition::SIDEBAND:
                 result.append("B");
                 break;
-            case hal::Composition::SOLID_COLOR:
+            case aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR:
                 result.append("S");
                 break;
+            case aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION:
+                // A for "Alpha", since the decoration is an alpha layer.
+                result.append("A");
+                break;
         }
     }
     return result;
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 568efce..3bdb2c0 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -38,6 +38,10 @@
 #include "MockHWComposer.h"
 #include "MockPowerAdvisor.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 namespace {
 
@@ -592,7 +596,7 @@
 
 TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) {
     android::HWComposer::DeviceRequestedChanges changes{
-            {{nullptr, hal::Composition::CLIENT}},
+            {{nullptr, Composition::CLIENT}},
             hal::DisplayRequest::FLIP_CLIENT_TARGET,
             {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
             {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
@@ -700,17 +704,15 @@
 }
 
 TEST_F(DisplayApplyChangedTypesToLayersTest, appliesChanges) {
-    EXPECT_CALL(*mLayer1.outputLayer,
-                applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT))
+    EXPECT_CALL(*mLayer1.outputLayer, applyDeviceCompositionTypeChange(Composition::CLIENT))
             .Times(1);
-    EXPECT_CALL(*mLayer2.outputLayer,
-                applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::DEVICE))
+    EXPECT_CALL(*mLayer2.outputLayer, applyDeviceCompositionTypeChange(Composition::DEVICE))
             .Times(1);
 
     mDisplay->applyChangedTypesToLayers(impl::Display::ChangedTypes{
-            {&mLayer1.hwc2Layer, hal::Composition::CLIENT},
-            {&mLayer2.hwc2Layer, hal::Composition::DEVICE},
-            {&hwc2LayerUnknown, hal::Composition::SOLID_COLOR},
+            {&mLayer1.hwc2Layer, Composition::CLIENT},
+            {&mLayer2.hwc2Layer, Composition::DEVICE},
+            {&hwc2LayerUnknown, Composition::SOLID_COLOR},
     });
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index 9e08f9e..ff68053 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -32,6 +32,8 @@
 #include <ui/GraphicTypes.h>
 #include "DisplayHardware/HWC2.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -57,7 +59,8 @@
     MOCK_METHOD1(setSurfaceDamage, Error(const android::Region&));
     MOCK_METHOD1(setBlendMode, Error(hal::BlendMode));
     MOCK_METHOD1(setColor, Error(hal::Color));
-    MOCK_METHOD1(setCompositionType, Error(hal::Composition));
+    MOCK_METHOD1(setCompositionType,
+                 Error(aidl::android::hardware::graphics::composer3::Composition));
     MOCK_METHOD1(setDataspace, Error(android::ui::Dataspace));
     MOCK_METHOD2(setPerFrameMetadata, Error(const int32_t, const android::HdrMetadata&));
     MOCK_METHOD1(setDisplayFrame, Error(const android::Rect&));
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 207c31e..ad7976f 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -30,6 +30,10 @@
 #include "MockHWComposer.h"
 #include "RegionMatcher.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine {
 namespace {
 
@@ -851,7 +855,7 @@
         EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(surfaceDamage))).WillOnce(Return(kError));
     }
 
-    void expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition compositionType) {
+    void expectSetCompositionTypeCall(Composition compositionType) {
         EXPECT_CALL(*mHwcLayer, setCompositionType(compositionType)).WillOnce(Return(kError));
     }
 
@@ -975,7 +979,7 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls();
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
@@ -984,7 +988,7 @@
     // check this in this test only by setting up an testing::InSeqeuence
     // instance before setting up the two expectations.
     InSequence s;
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SOLID_COLOR);
+    expectSetCompositionTypeCall(Composition::SOLID_COLOR);
     expectSetColorCall();
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
@@ -992,11 +996,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
+    mLayerFEState.compositionType = Composition::SIDEBAND;
 
     expectPerFrameCommonCalls();
     expectSetSidebandHandleCall();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SIDEBAND);
+    expectSetCompositionTypeCall(Composition::SIDEBAND);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1005,11 +1009,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::CURSOR;
+    mLayerFEState.compositionType = Composition::CURSOR;
 
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CURSOR);
+    expectSetCompositionTypeCall(Composition::CURSOR);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1018,11 +1022,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
 
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1031,10 +1035,9 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) {
-    (*mOutputLayer.editState().hwc).hwcCompositionType =
-            Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    (*mOutputLayer.editState().hwc).hwcCompositionType = Composition::SOLID_COLOR;
 
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls();
     expectSetColorCall();
@@ -1047,11 +1050,11 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform);
     expectSetColorCall();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
@@ -1060,25 +1063,25 @@
 TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) {
     mOutputLayer.editState().forceClientComposition = true;
 
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
 
     expectPerFrameCommonCalls();
     expectSetColorCall();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ false, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, allStateIncludesMetadataIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeGenericLayerMetadataInState();
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
     expectGenericLayerMetadataCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1087,12 +1090,12 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, perFrameStateDoesNotIncludeMetadataIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeGenericLayerMetadataInState();
 
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
@@ -1101,7 +1104,7 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerDoesNotSendBuffer) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
@@ -1109,7 +1112,7 @@
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
                               kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
@@ -1117,7 +1120,7 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, overriddenSkipLayerForSolidColorDoesNotSendBuffer) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
@@ -1125,7 +1128,7 @@
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
                               kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ true, 0,
@@ -1133,7 +1136,7 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
@@ -1141,7 +1144,7 @@
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
                               kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1149,7 +1152,7 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoForSolidColorIfPresent) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    mLayerFEState.compositionType = Composition::SOLID_COLOR;
     includeOverrideInfo();
 
     expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
@@ -1157,7 +1160,7 @@
     expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
                               kOverrideSurfaceDamage, kDisplayBrightnessNits);
     expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1165,14 +1168,14 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.editState().hwc->stateOverridden = true;
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                               Region::INVALID_REGION);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1180,16 +1183,16 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedDeviceCompositionInfo) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.editState().hwc->stateOverridden = true;
     mOutputLayer.editState().hwc->layerSkipped = true;
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                               Region::INVALID_REGION);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1197,17 +1200,17 @@
 }
 
 TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedClientCompositionInfo) {
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.editState().forceClientComposition = true;
     mOutputLayer.editState().hwc->stateOverridden = true;
     mOutputLayer.editState().hwc->layerSkipped = true;
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::CLIENT;
 
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                               Region::INVALID_REGION);
     expectSetHdrMetadataAndBufferCalls();
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
@@ -1253,7 +1256,7 @@
     expectGeometryCommonCalls();
     expectPerFrameCommonCalls();
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(true));
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
+    expectSetCompositionTypeCall(Composition::CLIENT);
 
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/
@@ -1265,14 +1268,13 @@
     expectPerFrameCommonCalls();
     expectSetHdrMetadataAndBufferCalls();
     EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
-    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+    expectSetCompositionTypeCall(Composition::DEVICE);
 
-    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mLayerFEState.compositionType = Composition::DEVICE;
     mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                  /*zIsOverridden*/ false, /*isPeekingThrough*/
                                  true);
-    EXPECT_EQ(Hwc2::IComposerClient::Composition::DEVICE,
-              mOutputLayer.getState().hwc->hwcCompositionType);
+    EXPECT_EQ(Composition::DEVICE, mOutputLayer.getState().hwc->hwcCompositionType);
 }
 
 /*
@@ -1371,14 +1373,14 @@
 
 TEST_F(OutputLayerTest, requiresClientCompositionReturnsTrueIfSetToClientComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::CLIENT;
 
     EXPECT_TRUE(mOutputLayer.requiresClientComposition());
 }
 
 TEST_F(OutputLayerTest, requiresClientCompositionReturnsFalseIfSetToDeviceComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
     EXPECT_FALSE(mOutputLayer.requiresClientComposition());
 }
@@ -1395,14 +1397,14 @@
 
 TEST_F(OutputLayerTest, isHardwareCursorReturnsTrueIfSetToCursorComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CURSOR;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::CURSOR;
 
     EXPECT_TRUE(mOutputLayer.isHardwareCursor());
 }
 
 TEST_F(OutputLayerTest, isHardwareCursorReturnsFalseIfSetToDeviceComposition) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
     EXPECT_FALSE(mOutputLayer.isHardwareCursor());
 }
@@ -1413,13 +1415,12 @@
 
 TEST_F(OutputLayerTest, applyDeviceCompositionTypeChangeSetsNewType) {
     mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr};
-    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;
+    mOutputLayer.editState().hwc->hwcCompositionType = Composition::DEVICE;
 
-    mOutputLayer.applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition::CLIENT);
+    mOutputLayer.applyDeviceCompositionTypeChange(Composition::CLIENT);
 
     ASSERT_TRUE(mOutputLayer.getState().hwc);
-    EXPECT_EQ(Hwc2::IComposerClient::Composition::CLIENT,
-              mOutputLayer.getState().hwc->hwcCompositionType);
+    EXPECT_EQ(Composition::CLIENT, mOutputLayer.getState().hwc->hwcCompositionType);
 }
 
 /*
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
index 9ad3ab4..84b3fc5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
@@ -27,6 +27,10 @@
 #include "android/hardware_buffer.h"
 #include "compositionengine/LayerFECompositionState.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine::impl::planner {
 namespace {
 
@@ -277,33 +281,28 @@
 TEST_F(LayerStateTest, getCompositionType) {
     OutputLayerCompositionState outputLayerCompositionState;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
-    EXPECT_EQ(hardware::graphics::composer::hal::Composition::DEVICE,
-              mLayerState->getCompositionType());
+    EXPECT_EQ(Composition::DEVICE, mLayerState->getCompositionType());
 }
 
 TEST_F(LayerStateTest, getCompositionType_forcedClient) {
     OutputLayerCompositionState outputLayerCompositionState;
     outputLayerCompositionState.forceClientComposition = true;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
-    EXPECT_EQ(hardware::graphics::composer::hal::Composition::CLIENT,
-              mLayerState->getCompositionType());
+    EXPECT_EQ(Composition::CLIENT, mLayerState->getCompositionType());
 }
 
 TEST_F(LayerStateTest, updateCompositionType) {
     OutputLayerCompositionState outputLayerCompositionState;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
@@ -311,29 +310,25 @@
     mock::OutputLayer newOutputLayer;
     mock::LayerFE newLayerFE;
     LayerFECompositionState layerFECompositionStateTwo;
-    layerFECompositionStateTwo.compositionType =
-            hardware::graphics::composer::hal::Composition::SOLID_COLOR;
+    layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
     setupMocksForLayer(newOutputLayer, newLayerFE, outputLayerCompositionState,
                        layerFECompositionStateTwo);
     Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
-    EXPECT_EQ(hardware::graphics::composer::hal::Composition::SOLID_COLOR,
-              mLayerState->getCompositionType());
+    EXPECT_EQ(Composition::SOLID_COLOR, mLayerState->getCompositionType());
     EXPECT_EQ(Flags<LayerStateField>(LayerStateField::CompositionType), updates);
 }
 
 TEST_F(LayerStateTest, compareCompositionType) {
     OutputLayerCompositionState outputLayerCompositionState;
     LayerFECompositionState layerFECompositionState;
-    layerFECompositionState.compositionType =
-            hardware::graphics::composer::hal::Composition::DEVICE;
+    layerFECompositionState.compositionType = Composition::DEVICE;
     setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
                        layerFECompositionState);
     mLayerState = std::make_unique<LayerState>(&mOutputLayer);
     mock::OutputLayer newOutputLayer;
     mock::LayerFE newLayerFE;
     LayerFECompositionState layerFECompositionStateTwo;
-    layerFECompositionStateTwo.compositionType =
-            hardware::graphics::composer::hal::Composition::SOLID_COLOR;
+    layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
     setupMocksForLayer(newOutputLayer, newLayerFE, outputLayerCompositionState,
                        layerFECompositionStateTwo);
     auto otherLayerState = std::make_unique<LayerState>(&newOutputLayer);
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp
index 1492707..6038268 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp
@@ -24,6 +24,10 @@
 #include <gtest/gtest.h>
 #include <log/log.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android::compositionengine::impl::planner {
 namespace {
 
@@ -103,7 +107,7 @@
     mock::LayerFE layerFEOne;
     OutputLayerCompositionState outputLayerCompositionStateOne;
     LayerFECompositionState layerFECompositionStateOne;
-    layerFECompositionStateOne.compositionType = hal::Composition::DEVICE;
+    layerFECompositionStateOne.compositionType = Composition::DEVICE;
     setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne,
                        layerFECompositionStateOne);
     LayerState layerStateOne(&outputLayerOne);
@@ -112,7 +116,7 @@
     mock::LayerFE layerFETwo;
     OutputLayerCompositionState outputLayerCompositionStateTwo;
     LayerFECompositionState layerFECompositionStateTwo;
-    layerFECompositionStateTwo.compositionType = hal::Composition::SOLID_COLOR;
+    layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
     setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo,
                        layerFECompositionStateTwo);
     LayerState layerStateTwo(&outputLayerTwo);
@@ -370,7 +374,7 @@
 
 TEST_F(PredictionTest, constructPrediction) {
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Prediction prediction({}, plan);
 
@@ -442,13 +446,13 @@
     mock::LayerFE layerFEOne;
     OutputLayerCompositionState outputLayerCompositionStateOne;
     LayerFECompositionState layerFECompositionStateOne;
-    layerFECompositionStateOne.compositionType = hal::Composition::DEVICE;
+    layerFECompositionStateOne.compositionType = Composition::DEVICE;
     setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne,
                        layerFECompositionStateOne);
     LayerState layerStateOne(&outputLayerOne);
 
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Predictor predictor;
 
@@ -484,7 +488,7 @@
     LayerState layerStateTwo(&outputLayerTwo);
 
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Predictor predictor;
 
@@ -521,7 +525,7 @@
     LayerState layerStateTwo(&outputLayerTwo);
 
     Plan plan;
-    plan.addLayerType(hal::Composition::DEVICE);
+    plan.addLayerType(Composition::DEVICE);
 
     Predictor predictor;
 
@@ -535,7 +539,7 @@
     EXPECT_EQ(Prediction::Type::Approximate, predictedPlan->type);
 
     Plan planTwo;
-    planTwo.addLayerType(hal::Composition::CLIENT);
+    planTwo.addLayerType(Composition::CLIENT);
     predictor.recordResult(predictedPlan, hashTwo, {&layerStateTwo}, false, planTwo);
     // Now trying to retrieve the predicted plan again returns a nullopt instead.
     // TODO(b/158790260): Even though this is enforced in this test, we might want to reassess this.
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 29e5a74..3bed796 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -41,7 +41,7 @@
 using aidl::android::hardware::graphics::composer3::PowerMode;
 using aidl::android::hardware::graphics::composer3::VirtualDisplay;
 
-using aidl::android::hardware::graphics::composer3::command::CommandResultPayload;
+using aidl::android::hardware::graphics::composer3::CommandResultPayload;
 
 using AidlColorMode = aidl::android::hardware::graphics::composer3::ColorMode;
 using AidlContentType = aidl::android::hardware::graphics::composer3::ContentType;
@@ -253,6 +253,13 @@
 
 AidlComposer::~AidlComposer() = default;
 
+bool AidlComposer::isSupported(OptionalFeature feature) const {
+    switch (feature) {
+        case OptionalFeature::RefreshRateSwitching:
+            return true;
+    }
+}
+
 std::vector<IComposer::Capability> AidlComposer::getCapabilities() {
     std::vector<Capability> capabilities;
     const auto status = mAidlComposer->getCapabilities(&capabilities);
@@ -375,13 +382,11 @@
 
 Error AidlComposer::getChangedCompositionTypes(
         Display display, std::vector<Layer>* outLayers,
-        std::vector<IComposerClient::Composition>* outTypes) {
+        std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) {
     std::vector<int64_t> layers;
-    std::vector<Composition> types;
-    mReader.takeChangedCompositionTypes(translate<int64_t>(display), &layers, &types);
+    mReader.takeChangedCompositionTypes(translate<int64_t>(display), &layers, outTypes);
 
     *outLayers = translate<Layer>(layers);
-    *outTypes = translate<IComposerClient::Composition>(types);
     return Error::NONE;
 }
 
@@ -442,12 +447,15 @@
 }
 
 Error AidlComposer::getDozeSupport(Display display, bool* outSupport) {
+    std::vector<AidlDisplayCapability> capabilities;
     const auto status =
-            mAidlComposerClient->getDozeSupport(translate<int64_t>(display), outSupport);
+            mAidlComposerClient->getDisplayCapabilities(translate<int64_t>(display), &capabilities);
     if (!status.isOk()) {
-        ALOGE("getDozeSupport failed %s", status.getDescription().c_str());
+        ALOGE("getDisplayCapabilities failed %s", status.getDescription().c_str());
         return static_cast<Error>(status.getServiceSpecificError());
     }
+    *outSupport = std::find(capabilities.begin(), capabilities.end(),
+                            AidlDisplayCapability::DOZE) != capabilities.end();
     return Error::NONE;
 }
 
@@ -649,10 +657,10 @@
     return Error::NONE;
 }
 
-Error AidlComposer::setLayerCompositionType(Display display, Layer layer,
-                                            IComposerClient::Composition type) {
-    mWriter.setLayerCompositionType(translate<int64_t>(display), translate<int64_t>(layer),
-                                    translate<Composition>(type));
+Error AidlComposer::setLayerCompositionType(
+        Display display, Layer layer,
+        aidl::android::hardware::graphics::composer3::Composition type) {
+    mWriter.setLayerCompositionType(translate<int64_t>(display), translate<int64_t>(layer), type);
     return Error::NONE;
 }
 
@@ -730,16 +738,11 @@
         }
 
         const auto& command = commands[index];
-        if (command.getTag() == command::CommandPayload::Tag::displayCommand) {
-            const auto& displayCommand =
-                    command.get<command::CommandPayload::Tag::displayCommand>();
-            if (displayCommand.validateDisplay || displayCommand.presentDisplay ||
-                displayCommand.presentOrValidateDisplay) {
-                error = translate<Error>(cmdErr.errorCode);
-            } else {
-                ALOGW("command '%s' generated error %" PRId32, command.toString().c_str(),
-                      cmdErr.errorCode);
-            }
+        if (command.validateDisplay || command.presentDisplay || command.presentOrValidateDisplay) {
+            error = translate<Error>(cmdErr.errorCode);
+        } else {
+            ALOGW("command '%s' generated error %" PRId32, command.toString().c_str(),
+                  cmdErr.errorCode);
         }
     }
 
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 8cae25f..076b898 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -36,6 +36,8 @@
 #include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
 #include <android/hardware/graphics/composer3/command-buffer.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -43,7 +45,6 @@
 
 using AidlCommandWriterBase = aidl::android::hardware::graphics::composer3::CommandWriterBase;
 using AidlCommandReaderBase = aidl::android::hardware::graphics::composer3::CommandReaderBase;
-using aidl::android::hardware::graphics::composer3::command::CommandResultPayload;
 
 class AidlIComposerCallbackWrapper;
 
@@ -55,6 +56,8 @@
     explicit AidlComposer(const std::string& serviceName);
     ~AidlComposer() override;
 
+    bool isSupported(OptionalFeature) const;
+
     std::vector<IComposer::Capability> getCapabilities() override;
     std::string dumpDebugInfo() override;
 
@@ -78,8 +81,10 @@
     Error destroyLayer(Display display, Layer layer) override;
 
     Error getActiveConfig(Display display, Config* outConfig) override;
-    Error getChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
-                                     std::vector<IComposerClient::Composition>* outTypes) override;
+    Error getChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes)
+            override;
     Error getColorModes(Display display, std::vector<ColorMode>* outModes) override;
     Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
                               int32_t* outValue) override;
@@ -132,8 +137,9 @@
                                 const std::vector<IComposerClient::Rect>& damage) override;
     Error setLayerBlendMode(Display display, Layer layer, IComposerClient::BlendMode mode) override;
     Error setLayerColor(Display display, Layer layer, const IComposerClient::Color& color) override;
-    Error setLayerCompositionType(Display display, Layer layer,
-                                  IComposerClient::Composition type) override;
+    Error setLayerCompositionType(
+            Display display, Layer layer,
+            aidl::android::hardware::graphics::composer3::Composition type) override;
     Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override;
     Error setLayerDisplayFrame(Display display, Layer layer,
                                const IComposerClient::Rect& frame) override;
@@ -174,7 +180,6 @@
     Error setDisplayBrightness(Display display, float brightness) override;
 
     // Composer HAL 2.4
-    bool isVsyncPeriodSwitchSupported() override { return true; }
     Error getDisplayCapabilities(Display display,
                                  std::vector<DisplayCapability>* outCapabilities) override;
     V2_4::Error getDisplayConnectionType(Display display,
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 3cc5e5e..6f2aa78 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -31,6 +31,8 @@
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -73,6 +75,12 @@
 
     virtual ~Composer() = 0;
 
+    enum class OptionalFeature {
+        RefreshRateSwitching,
+    };
+
+    virtual bool isSupported(OptionalFeature) const = 0;
+
     virtual std::vector<IComposer::Capability> getCapabilities() = 0;
     virtual std::string dumpDebugInfo() = 0;
 
@@ -98,7 +106,7 @@
     virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
     virtual Error getChangedCompositionTypes(
             Display display, std::vector<Layer>* outLayers,
-            std::vector<IComposerClient::Composition>* outTypes) = 0;
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) = 0;
     virtual Error getColorModes(Display display, std::vector<ColorMode>* outModes) = 0;
     virtual Error getDisplayAttribute(Display display, Config config,
                                       IComposerClient::Attribute attribute, int32_t* outValue) = 0;
@@ -155,8 +163,9 @@
                                     IComposerClient::BlendMode mode) = 0;
     virtual Error setLayerColor(Display display, Layer layer,
                                 const IComposerClient::Color& color) = 0;
-    virtual Error setLayerCompositionType(Display display, Layer layer,
-                                          IComposerClient::Composition type) = 0;
+    virtual Error setLayerCompositionType(
+            Display display, Layer layer,
+            aidl::android::hardware::graphics::composer3::Composition type) = 0;
     virtual Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) = 0;
     virtual Error setLayerDisplayFrame(Display display, Layer layer,
                                        const IComposerClient::Rect& frame) = 0;
@@ -197,7 +206,6 @@
     virtual Error setDisplayBrightness(Display display, float brightness) = 0;
 
     // Composer HAL 2.4
-    virtual bool isVsyncPeriodSwitchSupported() = 0;
     virtual Error getDisplayCapabilities(Display display,
                                          std::vector<DisplayCapability>* outCapabilities) = 0;
     virtual V2_4::Error getDisplayConnectionType(
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 596666c..5dbec05 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -39,6 +39,8 @@
 
 #include "ComposerHal.h"
 
+using aidl::android::hardware::graphics::composer3::Composition;
+
 namespace android {
 
 using android::Fence;
@@ -142,12 +144,12 @@
 bool Display::isVsyncPeriodSwitchSupported() const {
     ALOGV("[%" PRIu64 "] isVsyncPeriodSwitchSupported()", mId);
 
-    return mComposer.isVsyncPeriodSwitchSupported();
+    return mComposer.isSupported(android::Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
 }
 
 Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
     std::vector<Hwc2::Layer> layerIds;
-    std::vector<Hwc2::IComposerClient::Composition> types;
+    std::vector<Composition> types;
     auto intError = mComposer.getChangedCompositionTypes(
             mId, &layerIds, &types);
     uint32_t numElements = layerIds.size();
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 5e0ba06..1425c61 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -36,6 +36,8 @@
 
 #include "Hal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace android {
 
 class Fence;
@@ -88,7 +90,8 @@
     [[clang::warn_unused_result]] virtual base::expected<std::shared_ptr<HWC2::Layer>, hal::Error>
     createLayer() = 0;
     [[clang::warn_unused_result]] virtual hal::Error getChangedCompositionTypes(
-            std::unordered_map<Layer*, hal::Composition>* outTypes) = 0;
+            std::unordered_map<Layer*, aidl::android::hardware::graphics::composer3::Composition>*
+                    outTypes) = 0;
     [[clang::warn_unused_result]] virtual hal::Error getColorModes(
             std::vector<hal::ColorMode>* outModes) const = 0;
     // Returns a bitmask which contains HdrMetadata::Type::*.
@@ -163,7 +166,9 @@
     hal::Error acceptChanges() override;
     base::expected<std::shared_ptr<HWC2::Layer>, hal::Error> createLayer() override;
     hal::Error getChangedCompositionTypes(
-            std::unordered_map<HWC2::Layer*, hal::Composition>* outTypes) override;
+            std::unordered_map<HWC2::Layer*,
+                               aidl::android::hardware::graphics::composer3::Composition>* outTypes)
+            override;
     hal::Error getColorModes(std::vector<hal::ColorMode>* outModes) const override;
     // Returns a bitmask which contains HdrMetadata::Type::*.
     int32_t getSupportedPerFrameMetadata() const override;
@@ -266,7 +271,8 @@
 
     [[clang::warn_unused_result]] virtual hal::Error setBlendMode(hal::BlendMode mode) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setColor(hal::Color color) = 0;
-    [[clang::warn_unused_result]] virtual hal::Error setCompositionType(hal::Composition type) = 0;
+    [[clang::warn_unused_result]] virtual hal::Error setCompositionType(
+            aidl::android::hardware::graphics::composer3::Composition type) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setDataspace(hal::Dataspace dataspace) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setPerFrameMetadata(
             const int32_t supportedPerFrameMetadata, const android::HdrMetadata& metadata) = 0;
@@ -316,7 +322,8 @@
 
     hal::Error setBlendMode(hal::BlendMode mode) override;
     hal::Error setColor(hal::Color color) override;
-    hal::Error setCompositionType(hal::Composition type) override;
+    hal::Error setCompositionType(
+            aidl::android::hardware::graphics::composer3::Composition type) override;
     hal::Error setDataspace(hal::Dataspace dataspace) override;
     hal::Error setPerFrameMetadata(const int32_t supportedPerFrameMetadata,
                                    const android::HdrMetadata& metadata) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index d851e22..514c879 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -159,8 +159,10 @@
     }
     mRegisteredCallback = true;
 
+    const bool vsyncSwitchingSupported =
+            mComposer->isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
     mComposer->registerCallback(
-            sp<ComposerCallbackBridge>::make(callback, mComposer->isVsyncPeriodSwitchSupported()));
+            sp<ComposerCallbackBridge>::make(callback, vsyncSwitchingSupported));
 }
 
 bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index bd79977..aa4abdf 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -43,6 +43,8 @@
 #include "HWC2.h"
 #include "Hal.h"
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 namespace android {
 
 namespace hal = hardware::graphics::composer::hal;
@@ -70,7 +72,9 @@
 class HWComposer {
 public:
     struct DeviceRequestedChanges {
-        using ChangedTypes = std::unordered_map<HWC2::Layer*, hal::Composition>;
+        using ChangedTypes =
+                std::unordered_map<HWC2::Layer*,
+                                   aidl::android::hardware::graphics::composer3::Composition>;
         using ClientTargetProperty = hal::ClientTargetProperty;
         using DisplayRequests = hal::DisplayRequest;
         using LayerRequests = std::unordered_map<HWC2::Layer*, hal::LayerRequest>;
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 02d0658..7236868 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -20,6 +20,8 @@
 #include <android/hardware/graphics/composer/2.4/IComposer.h>
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 #define ERROR_HAS_CHANGES 5
 
 namespace android {
@@ -49,7 +51,6 @@
 using Attribute = IComposerClient::Attribute;
 using BlendMode = IComposerClient::BlendMode;
 using Color = IComposerClient::Color;
-using Composition = IComposerClient::Composition;
 using Connection = IComposerCallback::Connection;
 using ContentType = IComposerClient::ContentType;
 using Capability = IComposer::Capability;
@@ -95,20 +96,23 @@
     }
 }
 
-inline std::string to_string(hardware::graphics::composer::hal::Composition composition) {
+inline std::string to_string(
+        aidl::android::hardware::graphics::composer3::Composition composition) {
     switch (composition) {
-        case hardware::graphics::composer::hal::Composition::INVALID:
+        case aidl::android::hardware::graphics::composer3::Composition::INVALID:
             return "Invalid";
-        case hardware::graphics::composer::hal::Composition::CLIENT:
+        case aidl::android::hardware::graphics::composer3::Composition::CLIENT:
             return "Client";
-        case hardware::graphics::composer::hal::Composition::DEVICE:
+        case aidl::android::hardware::graphics::composer3::Composition::DEVICE:
             return "Device";
-        case hardware::graphics::composer::hal::Composition::SOLID_COLOR:
+        case aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR:
             return "SolidColor";
-        case hardware::graphics::composer::hal::Composition::CURSOR:
+        case aidl::android::hardware::graphics::composer3::Composition::CURSOR:
             return "Cursor";
-        case hardware::graphics::composer::hal::Composition::SIDEBAND:
+        case aidl::android::hardware::graphics::composer3::Composition::SIDEBAND:
             return "Sideband";
+        case aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION:
+            return "DisplayDecoration";
         default:
             return "Unknown";
     }
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 11d41c0..ab16027 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -30,6 +30,7 @@
 #include <hidl/HidlTransportUtils.h>
 #include <log/log.h>
 #include <utils/Trace.h>
+#include "Hal.h"
 
 #include <algorithm>
 #include <cinttypes>
@@ -153,6 +154,13 @@
     }
 }
 
+bool HidlComposer::isSupported(OptionalFeature feature) const {
+    switch (feature) {
+        case OptionalFeature::RefreshRateSwitching:
+            return mClient_2_4 != nullptr;
+    }
+}
+
 std::vector<IComposer::Capability> HidlComposer::getCapabilities() {
     std::vector<IComposer::Capability> capabilities;
     mComposer->getCapabilities(
@@ -278,7 +286,7 @@
 
 Error HidlComposer::getChangedCompositionTypes(
         Display display, std::vector<Layer>* outLayers,
-        std::vector<IComposerClient::Composition>* outTypes) {
+        std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) {
     mReader.takeChangedCompositionTypes(display, outLayers, outTypes);
     return Error::NONE;
 }
@@ -618,11 +626,22 @@
     return Error::NONE;
 }
 
-Error HidlComposer::setLayerCompositionType(Display display, Layer layer,
-                                            IComposerClient::Composition type) {
+static IComposerClient::Composition to_hidl_type(
+        aidl::android::hardware::graphics::composer3::Composition type) {
+    LOG_ALWAYS_FATAL_IF(static_cast<int32_t>(type) >
+                                static_cast<int32_t>(IComposerClient::Composition::SIDEBAND),
+                        "Trying to use %s, which is not supported by HidlComposer!",
+                        android::to_string(type).c_str());
+
+    return static_cast<IComposerClient::Composition>(type);
+}
+
+Error HidlComposer::setLayerCompositionType(
+        Display display, Layer layer,
+        aidl::android::hardware::graphics::composer3::Composition type) {
     mWriter.selectDisplay(display);
     mWriter.selectLayer(layer);
-    mWriter.setLayerCompositionType(type);
+    mWriter.setLayerCompositionType(to_hidl_type(type));
     return Error::NONE;
 }
 
@@ -1266,7 +1285,8 @@
     mCurrentReturnData->compositionTypes.reserve(count);
     while (count > 0) {
         auto layer = read64();
-        auto type = static_cast<IComposerClient::Composition>(readSigned());
+        auto type = static_cast<aidl::android::hardware::graphics::composer3::Composition>(
+                readSigned());
 
         mCurrentReturnData->changedLayers.push_back(layer);
         mCurrentReturnData->compositionTypes.push_back(type);
@@ -1394,7 +1414,7 @@
 
 void CommandReader::takeChangedCompositionTypes(
         Display display, std::vector<Layer>* outLayers,
-        std::vector<IComposerClient::Composition>* outTypes) {
+        std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes) {
     auto found = mReturnData.find(display);
     if (found == mReturnData.end()) {
         outLayers->clear();
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 18c0635..d60d12c 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -37,6 +37,8 @@
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
@@ -92,8 +94,9 @@
                     uint32_t* outNumLayerRequestMasks) const;
 
     // Get and clear saved changed composition types.
-    void takeChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
-                                     std::vector<IComposerClient::Composition>* outTypes);
+    void takeChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes);
 
     // Get and clear saved display requests.
     void takeDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
@@ -130,7 +133,7 @@
         uint32_t displayRequests = 0;
 
         std::vector<Layer> changedLayers;
-        std::vector<IComposerClient::Composition> compositionTypes;
+        std::vector<aidl::android::hardware::graphics::composer3::Composition> compositionTypes;
 
         std::vector<Layer> requestedLayers;
         std::vector<uint32_t> requestMasks;
@@ -165,6 +168,8 @@
     explicit HidlComposer(const std::string& serviceName);
     ~HidlComposer() override;
 
+    bool isSupported(OptionalFeature) const;
+
     std::vector<IComposer::Capability> getCapabilities() override;
     std::string dumpDebugInfo() override;
 
@@ -188,8 +193,10 @@
     Error destroyLayer(Display display, Layer layer) override;
 
     Error getActiveConfig(Display display, Config* outConfig) override;
-    Error getChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
-                                     std::vector<IComposerClient::Composition>* outTypes) override;
+    Error getChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<aidl::android::hardware::graphics::composer3::Composition>* outTypes)
+            override;
     Error getColorModes(Display display, std::vector<ColorMode>* outModes) override;
     Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
                               int32_t* outValue) override;
@@ -242,8 +249,9 @@
                                 const std::vector<IComposerClient::Rect>& damage) override;
     Error setLayerBlendMode(Display display, Layer layer, IComposerClient::BlendMode mode) override;
     Error setLayerColor(Display display, Layer layer, const IComposerClient::Color& color) override;
-    Error setLayerCompositionType(Display display, Layer layer,
-                                  IComposerClient::Composition type) override;
+    Error setLayerCompositionType(
+            Display display, Layer layer,
+            aidl::android::hardware::graphics::composer3::Composition type) override;
     Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override;
     Error setLayerDisplayFrame(Display display, Layer layer,
                                const IComposerClient::Rect& frame) override;
@@ -284,7 +292,6 @@
     Error setDisplayBrightness(Display display, float brightness) override;
 
     // Composer HAL 2.4
-    bool isVsyncPeriodSwitchSupported() override { return mClient_2_4 != nullptr; }
     Error getDisplayCapabilities(Display display,
                                  std::vector<DisplayCapability>* outCapabilities) override;
     V2_4::Error getDisplayConnectionType(Display display,
diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp
index 845176c..cc85352 100644
--- a/services/surfaceflinger/EffectLayer.cpp
+++ b/services/surfaceflinger/EffectLayer.cpp
@@ -109,7 +109,8 @@
 
     auto* compositionState = editCompositionState();
     compositionState->color = getColor();
-    compositionState->compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+    compositionState->compositionType =
+            aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR;
 }
 
 sp<compositionengine::LayerFE> EffectLayer::getCompositionEngineLayerFE() const {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 0c4e112..86e96d7 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -667,7 +667,8 @@
             packet->set_timestamp(
                     static_cast<uint64_t>(endTime - kPredictionExpiredStartTimeDelta));
         } else {
-            packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
+            packet->set_timestamp(static_cast<uint64_t>(
+                    mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime));
         }
 
         auto* event = packet->set_frame_timeline_event();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index b395159..5948a78 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -650,15 +650,16 @@
     return {*layerSettings};
 }
 
-Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice& display) const {
+aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType(
+        const DisplayDevice& display) const {
     const auto outputLayer = findOutputLayerForDisplay(&display);
     if (outputLayer == nullptr) {
-        return Hwc2::IComposerClient::Composition::INVALID;
+        return aidl::android::hardware::graphics::composer3::Composition::INVALID;
     }
     if (outputLayer->getState().hwc) {
         return (*outputLayer->getState().hwc).hwcCompositionType;
     } else {
-        return Hwc2::IComposerClient::Composition::CLIENT;
+        return aidl::android::hardware::graphics::composer3::Composition::CLIENT;
     }
 }
 
@@ -1262,6 +1263,7 @@
                                                                  getSequence(), mName,
                                                                  mTransactionName,
                                                                  /*isBuffer*/ false, getGameMode());
+    surfaceFrame->setActualStartTime(info.startTimeNanos);
     // For Transactions, the post time is considered to be both queue and acquire fence time.
     surfaceFrame->setActualQueueTime(postTime);
     surfaceFrame->setAcquireFenceTime(postTime);
@@ -1279,6 +1281,7 @@
             mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
                                                                  getSequence(), mName, debugName,
                                                                  /*isBuffer*/ true, getGameMode());
+    surfaceFrame->setActualStartTime(info.startTimeNanos);
     // For buffers, acquire fence time will set during latch.
     surfaceFrame->setActualQueueTime(queueTime);
     const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
@@ -2004,7 +2007,7 @@
     if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
         // Only populate for the primary display.
         if (display) {
-            const Hwc2::IComposerClient::Composition compositionType = getCompositionType(*display);
+            const auto compositionType = getCompositionType(*display);
             layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
         }
     }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3f4d48b..31cdf0b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1037,7 +1037,8 @@
     // Returns true if the layer can draw shadows on its border.
     virtual bool canDrawShadows() const { return true; }
 
-    Hwc2::IComposerClient::Composition getCompositionType(const DisplayDevice&) const;
+    aidl::android::hardware::graphics::composer3::Composition getCompositionType(
+            const DisplayDevice&) const;
 
     /**
      * Returns an unsorted vector of all layers that are part of this tree.
diff --git a/services/surfaceflinger/Tracing/RingBuffer.h b/services/surfaceflinger/Tracing/RingBuffer.h
index 281cd19..3b2626d 100644
--- a/services/surfaceflinger/Tracing/RingBuffer.h
+++ b/services/surfaceflinger/Tracing/RingBuffer.h
@@ -37,22 +37,21 @@
     size_t used() const { return mUsedInBytes; }
     size_t frameCount() const { return mStorage.size(); }
     void setSize(size_t newSize) { mSizeInBytes = newSize; }
-    EntryProto& front() { return mStorage.front(); }
-    const EntryProto& front() const { return mStorage.front(); }
-    const EntryProto& back() const { return mStorage.back(); }
+    const std::string& front() const { return mStorage.front(); }
+    const std::string& back() const { return mStorage.back(); }
 
     void reset() {
         // use the swap trick to make sure memory is released
-        std::deque<EntryProto>().swap(mStorage);
+        std::deque<std::string>().swap(mStorage);
         mUsedInBytes = 0U;
     }
 
     void writeToProto(FileProto& fileProto) {
         fileProto.mutable_entry()->Reserve(static_cast<int>(mStorage.size()) +
                                            fileProto.entry().size());
-        for (const EntryProto& entry : mStorage) {
+        for (const std::string& entry : mStorage) {
             EntryProto* entryProto = fileProto.add_entry();
-            *entryProto = entry;
+            entryProto->ParseFromString(entry);
         }
     }
 
@@ -74,28 +73,35 @@
         return NO_ERROR;
     }
 
-    std::vector<EntryProto> emplace(EntryProto&& proto) {
-        std::vector<EntryProto> replacedEntries;
-        size_t protoSize = static_cast<size_t>(proto.ByteSize());
+    std::vector<std::string> emplace(std::string&& serializedProto) {
+        std::vector<std::string> replacedEntries;
+        size_t protoSize = static_cast<size_t>(serializedProto.size());
         while (mUsedInBytes + protoSize > mSizeInBytes) {
             if (mStorage.empty()) {
                 return {};
             }
-            mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
+            mUsedInBytes -= static_cast<size_t>(mStorage.front().size());
             replacedEntries.emplace_back(mStorage.front());
             mStorage.pop_front();
         }
         mUsedInBytes += protoSize;
-        mStorage.emplace_back();
-        mStorage.back().Swap(&proto);
+        mStorage.emplace_back(serializedProto);
         return replacedEntries;
     }
 
+    std::vector<std::string> emplace(EntryProto&& proto) {
+        std::string serializedProto;
+        proto.SerializeToString(&serializedProto);
+        return emplace(std::move(serializedProto));
+    }
+
     void dump(std::string& result) const {
         std::chrono::milliseconds duration(0);
         if (frameCount() > 0) {
+            EntryProto entry;
+            entry.ParseFromString(mStorage.front());
             duration = std::chrono::duration_cast<std::chrono::milliseconds>(
-                    std::chrono::nanoseconds(systemTime() - front().elapsed_realtime_nanos()));
+                    std::chrono::nanoseconds(systemTime() - entry.elapsed_realtime_nanos()));
         }
         const int64_t durationCount = duration.count();
         base::StringAppendF(&result,
@@ -107,7 +113,7 @@
 private:
     size_t mUsedInBytes = 0U;
     size_t mSizeInBytes = 0U;
-    std::deque<EntryProto> mStorage;
+    std::deque<std::string> mStorage;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index c1b3d2e..b5966d5 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -177,9 +177,9 @@
                                   const std::vector<int32_t>& removedLayers) {
     ATRACE_CALL();
     std::scoped_lock lock(mTraceLock);
-    std::vector<proto::TransactionTraceEntry> removedEntries;
+    std::vector<std::string> removedEntries;
+    proto::TransactionTraceEntry entryProto;
     for (const CommittedTransactions& entry : committedTransactions) {
-        proto::TransactionTraceEntry entryProto;
         entryProto.set_elapsed_realtime_nanos(entry.timestamp);
         entryProto.set_vsync_id(entry.vsyncId);
         entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mCreatedLayers.size()));
@@ -202,13 +202,21 @@
                 ALOGW("Could not find transaction id %" PRIu64, id);
             }
         }
-        std::vector<proto::TransactionTraceEntry> entries = mBuffer->emplace(std::move(entryProto));
+
+        std::string serializedProto;
+        entryProto.SerializeToString(&serializedProto);
+        entryProto.Clear();
+        std::vector<std::string> entries = mBuffer->emplace(std::move(serializedProto));
+        removedEntries.reserve(removedEntries.size() + entries.size());
         removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
                               std::make_move_iterator(entries.end()));
     }
 
-    for (const proto::TransactionTraceEntry& removedEntry : removedEntries) {
-        updateStartingStateLocked(removedEntry);
+    proto::TransactionTraceEntry removedEntryProto;
+    for (const std::string& removedEntry : removedEntries) {
+        removedEntryProto.ParseFromString(removedEntry);
+        updateStartingStateLocked(removedEntryProto);
+        removedEntryProto.Clear();
     }
     mTransactionsAddedToBufferCv.notify_one();
 }
@@ -220,7 +228,11 @@
     std::unique_lock<std::mutex> lock(mTraceLock);
     base::ScopedLockAssertion assumeLocked(mTraceLock);
     mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) {
-        return mBuffer->used() > 0 && mBuffer->back().vsync_id() >= vsyncId;
+        proto::TransactionTraceEntry entry;
+        if (mBuffer->used() > 0) {
+            entry.ParseFromString(mBuffer->back());
+        }
+        return mBuffer->used() > 0 && entry.vsync_id() >= vsyncId;
     });
 }
 
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f1e6e48..554e454 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -1029,9 +1029,10 @@
     }
 };
 
-template <IComposerClient::Composition CompositionType>
+template <aidl::android::hardware::graphics::composer3::Composition CompositionType>
 struct KeepCompositionTypeVariant {
-    static constexpr hal::Composition TYPE = CompositionType;
+    static constexpr aidl::android::hardware::graphics::composer3::Composition TYPE =
+            CompositionType;
 
     static void setupHwcSetCallExpectations(CompositionTest* test) {
         if (!test->mDisplayOff) {
@@ -1046,10 +1047,11 @@
     }
 };
 
-template <IComposerClient::Composition InitialCompositionType,
-          IComposerClient::Composition FinalCompositionType>
+template <aidl::android::hardware::graphics::composer3::Composition InitialCompositionType,
+          aidl::android::hardware::graphics::composer3::Composition FinalCompositionType>
 struct ChangeCompositionTypeVariant {
-    static constexpr hal::Composition TYPE = FinalCompositionType;
+    static constexpr aidl::android::hardware::graphics::composer3::Composition TYPE =
+            FinalCompositionType;
 
     static void setupHwcSetCallExpectations(CompositionTest* test) {
         if (!test->mDisplayOff) {
@@ -1063,8 +1065,9 @@
         EXPECT_CALL(*test->mComposer, getChangedCompositionTypes(HWC_DISPLAY, _, _))
                 .WillOnce(DoAll(SetArgPointee<1>(std::vector<Hwc2::Layer>{
                                         static_cast<Hwc2::Layer>(HWC_LAYER)}),
-                                SetArgPointee<2>(std::vector<IComposerClient::Composition>{
-                                        FinalCompositionType}),
+                                SetArgPointee<2>(
+                                        std::vector<aidl::android::hardware::graphics::composer3::
+                                                            Composition>{FinalCompositionType}),
                                 Return(Error::NONE)));
     }
 };
@@ -1258,25 +1261,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedNormalBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedNormalBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedNormalBufferLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::DEVICE,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenNormalBufferLayer) {
@@ -1290,25 +1296,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedEffectLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SOLID_COLOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedEffectLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SOLID_COLOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedEffectLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::SOLID_COLOR,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, EffectLayerVariant<EffectLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenEffectLayer) {
@@ -1322,25 +1331,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedSidebandBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SIDEBAND>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SIDEBAND>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedSidebandBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::SIDEBAND>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SIDEBAND>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedSidebandBufferLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::SIDEBAND,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SidebandLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::SIDEBAND,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenSidebandBufferLayer) {
@@ -1354,25 +1366,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedSecureBufferLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::DEVICE,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenSecureBufferLayerOnSecureDisplay) {
@@ -1386,17 +1401,19 @@
  */
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerOnInsecureDisplayWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedSecureBufferLayerOnInsecureDisplayWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            InsecureDisplaySetupVariant, BufferLayerVariant<SecureLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenSecureBufferLayerOnInsecureDisplay) {
@@ -1411,22 +1428,24 @@
 
 TEST_F(CompositionTest,
        HWCComposedBufferLayerWithSecureParentLayerOnInsecureDisplayWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<InsecureDisplaySetupVariant,
-                            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
-                                              ContainerLayerVariant<SecureLayerProperties>>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            InsecureDisplaySetupVariant,
+            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
+                              ContainerLayerVariant<SecureLayerProperties>>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest,
        HWCComposedBufferLayerWithSecureParentLayerOnInsecureDisplayWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<InsecureDisplaySetupVariant,
-                            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
-                                              ContainerLayerVariant<SecureLayerProperties>>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            InsecureDisplaySetupVariant,
+            ChildLayerVariant<BufferLayerVariant<ParentSecureLayerProperties>,
+                              ContainerLayerVariant<SecureLayerProperties>>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenBufferLayerWithSecureParentLayerOnInsecureDisplay) {
@@ -1442,25 +1461,28 @@
  */
 
 TEST_F(CompositionTest, HWCComposedCursorLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CURSOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CURSOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, HWCComposedCursorLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CURSOR>,
-                            HwcCompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CURSOR>,
+            HwcCompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, REComposedCursorLayer) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
-                            ChangeCompositionTypeVariant<IComposerClient::Composition::CURSOR,
-                                                         IComposerClient::Composition::CLIENT>,
-                            RECompositionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<CursorLayerProperties>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CURSOR,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            RECompositionResultVariant>>();
 }
 
 TEST_F(CompositionTest, captureScreenCursorLayer) {
@@ -1477,7 +1499,8 @@
     mDisplayOff = true;
     displayRefreshCompositionDirtyGeometry<CompositionCase<
             PoweredOffDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
             HwcCompositionResultVariant>>();
 }
 
@@ -1485,7 +1508,8 @@
     mDisplayOff = true;
     displayRefreshCompositionDirtyFrame<CompositionCase<
             PoweredOffDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-            KeepCompositionTypeVariant<IComposerClient::Composition::DEVICE>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE>,
             HwcCompositionResultVariant>>();
 }
 
@@ -1493,8 +1517,9 @@
     mDisplayOff = true;
     displayRefreshCompositionDirtyFrame<CompositionCase<
             PoweredOffDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-            ChangeCompositionTypeVariant<IComposerClient::Composition::DEVICE,
-                                         IComposerClient::Composition::CLIENT>,
+            ChangeCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::DEVICE,
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
             RECompositionResultVariant>>();
 }
 
@@ -1509,17 +1534,19 @@
  */
 
 TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirtyGeometry) {
-    displayRefreshCompositionDirtyGeometry<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionViaDebugOptionResultVariant>>();
+    displayRefreshCompositionDirtyGeometry<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionViaDebugOptionResultVariant>>();
 }
 
 TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirtyFrame) {
-    displayRefreshCompositionDirtyFrame<
-            CompositionCase<DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
-                            KeepCompositionTypeVariant<IComposerClient::Composition::CLIENT>,
-                            ForcedClientCompositionViaDebugOptionResultVariant>>();
+    displayRefreshCompositionDirtyFrame<CompositionCase<
+            DefaultDisplaySetupVariant, BufferLayerVariant<DefaultLayerProperties>,
+            KeepCompositionTypeVariant<
+                    aidl::android::hardware::graphics::composer3::Composition::CLIENT>,
+            ForcedClientCompositionViaDebugOptionResultVariant>>();
 }
 
 } // namespace
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 655baf8..01724dc 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -86,7 +86,8 @@
                             }),
                             Return(hardware::graphics::composer::V2_4::Error::NONE)));
     EXPECT_CALL(*mHal, registerCallback(_));
-    EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported()).WillOnce(Return(false));
+    EXPECT_CALL(*mHal, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
+            .WillOnce(Return(false));
 
     impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
     hwc.setCallback(&mCallback);
@@ -104,7 +105,8 @@
     EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_))
             .WillOnce(Return(hardware::graphics::composer::V2_4::Error::UNSUPPORTED));
     EXPECT_CALL(*mHal, registerCallback(_));
-    EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported()).WillOnce(Return(false));
+    EXPECT_CALL(*mHal, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
+            .WillOnce(Return(false));
 
     impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
     hwc.setCallback(&mCallback);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 9796a70..56a0506 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -52,7 +52,8 @@
 
         // isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy
         // will call setActiveConfig instead of setActiveConfigWithConstraints.
-        ON_CALL(*mComposer, isVsyncPeriodSwitchSupported()).WillByDefault(Return(true));
+        ON_CALL(*mComposer, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
+                .WillByDefault(Return(true));
     }
 
 protected:
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 100a78d..0067997 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -270,7 +270,8 @@
         layer->editCompositionState()->sidebandStream = sidebandStream;
     }
 
-    void setLayerCompositionType(const sp<Layer>& layer, hal::Composition type) {
+    void setLayerCompositionType(const sp<Layer>& layer,
+                                 aidl::android::hardware::graphics::composer3::Composition type) {
         auto outputLayer = findOutputLayerForDisplay(layer, mFlinger->getDefaultDisplayDevice());
         LOG_ALWAYS_FATAL_IF(!outputLayer);
         auto& state = outputLayer->editState();
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index 71c7bd9..43b09fd 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -56,7 +56,9 @@
 
     auto bufferFront() {
         std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
-        return mTracing->mBuffer->front();
+        proto::TransactionTraceEntry entry;
+        entry.ParseFromString(mTracing->mBuffer->front());
+        return entry;
     }
 
     bool threadIsJoinable() {
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 1debd65..5cf8278 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -48,6 +48,7 @@
     Composer();
     ~Composer() override;
 
+    MOCK_METHOD(bool, isSupported, (OptionalFeature), (const, override));
     MOCK_METHOD0(getCapabilities, std::vector<IComposer::Capability>());
     MOCK_METHOD0(dumpDebugInfo, std::string());
     MOCK_METHOD1(registerCallback, void(const sp<IComposerCallback>&));
@@ -61,7 +62,8 @@
     MOCK_METHOD2(destroyLayer, Error(Display, Layer));
     MOCK_METHOD2(getActiveConfig, Error(Display, Config*));
     MOCK_METHOD3(getChangedCompositionTypes,
-                 Error(Display, std::vector<Layer>*, std::vector<IComposerClient::Composition>*));
+                 Error(Display, std::vector<Layer>*,
+                       std::vector<aidl::android::hardware::graphics::composer3::Composition>*));
     MOCK_METHOD2(getColorModes, Error(Display, std::vector<ColorMode>*));
     MOCK_METHOD4(getDisplayAttribute,
                  Error(Display, Config config, IComposerClient::Attribute, int32_t*));
@@ -95,7 +97,8 @@
                  Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
     MOCK_METHOD3(setLayerBlendMode, Error(Display, Layer, IComposerClient::BlendMode));
     MOCK_METHOD3(setLayerColor, Error(Display, Layer, const IComposerClient::Color&));
-    MOCK_METHOD3(setLayerCompositionType, Error(Display, Layer, IComposerClient::Composition));
+    MOCK_METHOD3(setLayerCompositionType,
+                 Error(Display, Layer, aidl::android::hardware::graphics::composer3::Composition));
     MOCK_METHOD3(setLayerDataspace, Error(Display, Layer, Dataspace));
     MOCK_METHOD3(setLayerPerFrameMetadata,
                  Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadata>&));
@@ -117,7 +120,6 @@
     MOCK_METHOD3(setLayerPerFrameMetadataBlobs,
                  Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadataBlob>&));
     MOCK_METHOD2(setDisplayBrightness, Error(Display, float));
-    MOCK_METHOD0(isVsyncPeriodSwitchSupported, bool());
     MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*));
     MOCK_METHOD2(getDisplayConnectionType,
                  V2_4::Error(Display, IComposerClient::DisplayConnectionType*));
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 83a0996..d4fefee 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -38,7 +38,9 @@
     MOCK_METHOD((base::expected<std::shared_ptr<HWC2::Layer>, hal::Error>), createLayer, (),
                 (override));
     MOCK_METHOD(hal::Error, getChangedCompositionTypes,
-                ((std::unordered_map<Layer *, hal::Composition> *)), (override));
+                ((std::unordered_map<Layer *,
+                                     aidl::android::hardware::graphics::composer3::Composition> *)),
+                (override));
     MOCK_METHOD(hal::Error, getColorModes, (std::vector<hal::ColorMode> *), (const, override));
     MOCK_METHOD(int32_t, getSupportedPerFrameMetadata, (), (const, override));
     MOCK_METHOD(hal::Error, getRenderIntents, (hal::ColorMode, std::vector<hal::RenderIntent> *),
@@ -103,7 +105,8 @@
     MOCK_METHOD(hal::Error, setSurfaceDamage, (const android::Region &), (override));
     MOCK_METHOD(hal::Error, setBlendMode, (hal::BlendMode), (override));
     MOCK_METHOD(hal::Error, setColor, (hal::Color), (override));
-    MOCK_METHOD(hal::Error, setCompositionType, (hal::Composition), (override));
+    MOCK_METHOD(hal::Error, setCompositionType,
+                (aidl::android::hardware::graphics::composer3::Composition), (override));
     MOCK_METHOD(hal::Error, setDataspace, (android::ui::Dataspace), (override));
     MOCK_METHOD(hal::Error, setPerFrameMetadata, (const int32_t, const android::HdrMetadata &),
                 (override));
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index eb4befd..e6717d7 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1222,12 +1222,14 @@
         swap_interval ? create_info->minImageCount : mailbox_num_images;
     uint32_t num_images = requested_images - 1 + min_undequeued_buffers;
 
-    // Lower layer insists that we have at least two buffers. This is wasteful
-    // and we'd like to relax it in the shared case, but not all the pieces are
-    // in place for that to work yet. Note we only lie to the lower layer-- we
-    // don't want to give the app back a swapchain with extra images (which they
-    // can't actually use!).
-    err = native_window_set_buffer_count(window, std::max(2u, num_images));
+    // Lower layer insists that we have at least min_undequeued_buffers + 1
+    // buffers.  This is wasteful and we'd like to relax it in the shared case,
+    // but not all the pieces are in place for that to work yet.  Note we only
+    // lie to the lower layer--we don't want to give the app back a swapchain
+    // with extra images (which they can't actually use!).
+    uint32_t min_buffer_count = min_undequeued_buffers + 1;
+    err = native_window_set_buffer_count(
+        window, std::max(min_buffer_count, num_images));
     if (err != android::OK) {
         ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
               strerror(-err), err);