Merge "Implement AIDL sensors conversion for additional info"
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 34ccb21..8da1352 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -11,6 +11,286 @@
 
 # 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/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 289c2ae..2207405 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1131,16 +1131,15 @@
 }
 
 static int32_t copy_directory_recursive(const char* from, const char* to) {
-    char *argv[] = {
-        (char*) kCpPath,
-        (char*) "-F", /* delete any existing destination file first (--remove-destination) */
-        (char*) "-p", /* preserve timestamps, ownership, and permissions */
-        (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */
-        (char*) "-P", /* Do not follow symlinks [default] */
-        (char*) "-d", /* don't dereference symlinks */
-        (char*) from,
-        (char*) to
-    };
+    char* argv[] =
+            {(char*)kCpPath,
+             (char*)"-F", /* delete any existing destination file first (--remove-destination) */
+             (char*)"--preserve=mode,ownership,timestamps,xattr", /* preserve properties */
+             (char*)"-R", /* recurse into subdirectories (DEST must be a directory) */
+             (char*)"-P", /* Do not follow symlinks [default] */
+             (char*)"-d", /* don't dereference symlinks */
+             (char*)from,
+             (char*)to};
 
     LOG(DEBUG) << "Copying " << from << " to " << to;
     return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
diff --git a/data/etc/android.hardware.type.automotive.xml b/data/etc/android.hardware.type.automotive.xml
index a9b4b05..113945b 100644
--- a/data/etc/android.hardware.type.automotive.xml
+++ b/data/etc/android.hardware.type.automotive.xml
@@ -17,4 +17,6 @@
 <!-- These features determine that the device running android is a car. -->
 <permissions>
     <feature name="android.hardware.type.automotive" />
+    <!-- TODO: Revert this after enabling work profiles refer b/170332519 -->
+    <unavailable-feature name="android.software.managed_users"/>
 </permissions>
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 451ca3c..f6f8939 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -84,7 +84,7 @@
 
     const std::string getLoadFileName() const;
 
-    /* Combines this key character map with an overlay. */
+    /* Combines this key character map with the provided overlay. */
     void combine(const KeyCharacterMap& overlay);
 
     /* Gets the keyboard type. */
@@ -144,6 +144,8 @@
 
     bool operator==(const KeyCharacterMap& other) const;
 
+    bool operator!=(const KeyCharacterMap& other) const;
+
     KeyCharacterMap(const KeyCharacterMap& other);
 
     virtual ~KeyCharacterMap();
@@ -230,11 +232,12 @@
     KeyedVector<int32_t, Key*> mKeys;
     KeyboardType mType;
     std::string mLoadFileName;
+    bool mLayoutOverlayApplied;
 
     KeyedVector<int32_t, int32_t> mKeysByScanCode;
     KeyedVector<int32_t, int32_t> mKeysByUsageCode;
 
-    KeyCharacterMap();
+    KeyCharacterMap(const std::string& filename);
 
     bool getKey(int32_t keyCode, const Key** outKey) const;
     bool getKeyBehavior(int32_t keyCode, int32_t metaState,
@@ -243,8 +246,6 @@
 
     bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
 
-    static base::Result<std::shared_ptr<KeyCharacterMap>> load(Tokenizer* tokenizer, Format format);
-
     static void addKey(Vector<KeyEvent>& outEvents,
             int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time);
     static void addMetaKeys(Vector<KeyEvent>& outEvents,
@@ -264,6 +265,15 @@
             int32_t deviceId, int32_t metaState, nsecs_t time,
             int32_t keyCode, int32_t keyMetaState,
             int32_t* currentMetaState);
+
+    /* Clears all data stored in this key character map */
+    void clear();
+
+    /* Loads the KeyCharacterMap provided by the tokenizer into this instance. */
+    status_t load(Tokenizer* tokenizer, Format format);
+
+    /* Reloads the data from mLoadFileName and unapplies any overlay. */
+    status_t reloadBaseFromFile();
 };
 
 } // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index b2ea441..7448308 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -329,7 +329,6 @@
 cc_library {
     name: "libbinder_rpc_unstable",
     srcs: ["libbinder_rpc_unstable.cpp"],
-    defaults: ["libbinder_ndk_host_user"],
     shared_libs: [
         "libbase",
         "libbinder",
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
index bffab5e..949835b 100644
--- a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -27,7 +27,5 @@
   @utf8InCpp String diskImagePath;
   long versionCode;
   @utf8InCpp String versionName;
-  boolean hasBootClassPathJars;
-  boolean hasDex2OatBootClassPathJars;
-  boolean hasSystemServerClassPathJars;
+  boolean hasClassPathJars;
 }
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 4289574..77493b3 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -32,17 +32,10 @@
     ],
 }
 
+// TODO(b/211908498): remove this
 cc_defaults {
     name: "libbinder_ndk_host_user",
     target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(n)=",
-                "-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",
-            ],
-        },
         darwin: {
             enabled: false,
         },
@@ -52,7 +45,6 @@
 cc_library {
     name: "libbinder_ndk",
 
-    defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
     recovery_available: true,
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 6f1fdfc..76c7aac 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -32,11 +32,26 @@
 
 __BEGIN_DECLS
 
-#ifndef __ANDROID_API__
-#error Android builds must be compiled against a specific API. If this is an \
- android platform host build, you must use libbinder_ndk_host_user.
+#ifndef __BIONIC__
+
+#ifndef __INTRODUCED_IN
+#define __INTRODUCED_IN(n)
 #endif
 
+#ifndef __assert
+#define __assert(a, b, c)          \
+    do {                           \
+        syslog(LOG_ERR, a ": " c); \
+        abort();                   \
+    } while (false)
+#endif
+
+#ifndef __ANDROID_API__
+#define __ANDROID_API__ 10000
+#endif
+
+#endif  // __BIONIC__
+
 /**
  * Low-level status types for use in binder. This is the least preferable way to
  * return an error for binder services (where binder_exception_t should be used,
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index e2fc18d..e4df98a 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -127,14 +127,6 @@
     // Currently necessary for host builds
     // TODO(b/31559095): bionic on host should define this
     target: {
-        host: {
-            cflags: [
-                "-D__INTRODUCED_IN(n)=",
-                "-D__assert(a,b,c)=",
-                // We want all the APIs to be available on the host.
-                "-D__ANDROID_API__=10000",
-            ],
-        },
         darwin: {
             enabled: false,
         },
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index acf3f8f..1446802 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -9,7 +9,6 @@
 
 cc_fuzz {
     name: "binder_parcel_fuzzer",
-    defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
 
     fuzz_config: {
@@ -50,6 +49,9 @@
                 "libbinder",
             ],
         },
+        darwin: {
+            enabled: false,
+        },
     },
     // This flag enables verbose output in the fuzz target, and is very useful
     // for debugging a failure. If you are trying to diagnose how a crash was
@@ -63,7 +65,7 @@
     target: {
         darwin: {
             enabled: false,
-        }
+        },
     },
     srcs: [
         "random_fd.cpp",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 34faf87..bdc6127 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -119,16 +119,11 @@
     if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
 }
 
-void BLASTBufferItemConsumer::setBlastBufferQueue(BLASTBufferQueue* blastbufferqueue) {
-    std::scoped_lock lock(mBufferQueueMutex);
-    mBLASTBufferQueue = blastbufferqueue;
-}
-
 void BLASTBufferItemConsumer::onSidebandStreamChanged() {
-    std::scoped_lock lock(mBufferQueueMutex);
-    if (mBLASTBufferQueue != nullptr) {
+    sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+    if (bbq != nullptr) {
         sp<NativeHandle> stream = getSidebandStream();
-        mBLASTBufferQueue->setSidebandStream(stream);
+        bbq->setSidebandStream(stream);
     }
 }
 
@@ -148,7 +143,7 @@
     mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
                                                       GraphicBuffer::USAGE_HW_COMPOSER |
                                                               GraphicBuffer::USAGE_HW_TEXTURE,
-                                                      1, false);
+                                                      1, false, this);
     static int32_t id = 0;
     mName = name + "#" + std::to_string(id);
     auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
@@ -157,7 +152,6 @@
     mBufferItemConsumer->setName(String8(consumerName.c_str()));
     mBufferItemConsumer->setFrameAvailableListener(this);
     mBufferItemConsumer->setBufferFreedListener(this);
-    mBufferItemConsumer->setBlastBufferQueue(this);
 
     ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
     mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
@@ -174,7 +168,6 @@
 }
 
 BLASTBufferQueue::~BLASTBufferQueue() {
-    mBufferItemConsumer->setBlastBufferQueue(nullptr);
     if (mPendingTransactions.empty()) {
         return;
     }
@@ -507,8 +500,7 @@
             std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
                       std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
     sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
-    t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseCallbackId,
-                 releaseBufferCallback);
+    t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseBufferCallback);
     t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
     t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
     t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
@@ -622,7 +614,7 @@
             if (bufferData) {
                 BQA_LOGD("Releasing previous buffer when syncing: framenumber=%" PRIu64,
                          bufferData->frameNumber);
-                releaseBuffer(bufferData->releaseCallbackId, bufferData->acquireFence);
+                releaseBuffer(bufferData->generateReleaseCallbackId(), bufferData->acquireFence);
                 // Because we just released a buffer, we know there's no need to wait for a free
                 // buffer.
                 mayNeedToWaitForBuffer = false;
@@ -1025,7 +1017,6 @@
         mBufferItemConsumer->abandon();
         mBufferItemConsumer->setFrameAvailableListener(nullptr);
         mBufferItemConsumer->setBufferFreedListener(nullptr);
-        mBufferItemConsumer->setBlastBufferQueue(nullptr);
     }
     mBufferItemConsumer = nullptr;
     mConsumer = nullptr;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index ec0573a..acd9ac5 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -677,6 +677,10 @@
     return NO_ERROR;
 }
 
+ReleaseCallbackId BufferData::generateReleaseCallbackId() const {
+    return {buffer->getId(), frameNumber};
+}
+
 status_t BufferData::write(Parcel& output) const {
     SAFE_PARCEL(output.writeInt32, flags.get());
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index cf04ec8..3ec347f 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -736,10 +736,10 @@
         // if the callback is in process, run on a different thread to avoid any lock contigency
         // issues in the client.
         SurfaceComposerClient::getDefault()
-                ->mReleaseCallbackThread.addReleaseCallback(state.bufferData.releaseCallbackId,
-                                                            fence);
+                ->mReleaseCallbackThread
+                .addReleaseCallback(state.bufferData.generateReleaseCallbackId(), fence);
     } else {
-        listener->onReleaseBuffer(state.bufferData.releaseCallbackId, fence, UINT_MAX);
+        listener->onReleaseBuffer(state.bufferData.generateReleaseCallbackId(), fence, UINT_MAX);
     }
 }
 
@@ -1335,7 +1335,7 @@
     BufferData bufferData = s->bufferData;
 
     TransactionCompletedListener::getInstance()->removeReleaseBufferCallback(
-            bufferData.releaseCallbackId);
+            bufferData.generateReleaseCallbackId());
     BufferData emptyBufferData;
     s->what &= ~layer_state_t::eBufferChanged;
     s->bufferData = emptyBufferData;
@@ -1347,7 +1347,7 @@
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
         const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
         const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber,
-        const ReleaseCallbackId& id, ReleaseBufferCallback callback) {
+        ReleaseBufferCallback callback) {
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
@@ -1371,7 +1371,7 @@
     if (mIsAutoTimestamp) {
         mDesiredPresentTime = systemTime();
     }
-    setReleaseBufferCallback(&bufferData, id, callback);
+    setReleaseBufferCallback(&bufferData, callback);
     s->what |= layer_state_t::eBufferChanged;
     s->bufferData = bufferData;
     registerSurfaceControlForCallback(sc);
@@ -1381,7 +1381,6 @@
 }
 
 void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData,
-                                                                  const ReleaseCallbackId& id,
                                                                   ReleaseBufferCallback callback) {
     if (!callback) {
         return;
@@ -1394,9 +1393,8 @@
     }
 
     bufferData->releaseBufferListener = TransactionCompletedListener::getIInstance();
-    bufferData->releaseCallbackId = id;
     auto listener = TransactionCompletedListener::getInstance();
-    listener->setReleaseBufferCallback(id, callback);
+    listener->setReleaseBufferCallback(bufferData->generateReleaseCallbackId(), callback);
 }
 
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace(
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 8b2310d..f77cfe6 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -38,11 +38,11 @@
 class BLASTBufferItemConsumer : public BufferItemConsumer {
 public:
     BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage,
-                            int bufferCount, bool controlledByApp)
+                            int bufferCount, bool controlledByApp, wp<BLASTBufferQueue> bbq)
           : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
+            mBLASTBufferQueue(std::move(bbq)),
             mCurrentlyConnected(false),
-            mPreviouslyConnected(false),
-            mBLASTBufferQueue(nullptr) {}
+            mPreviouslyConnected(false) {}
 
     void onDisconnect() override;
     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
@@ -53,21 +53,20 @@
                                CompositorTiming compositorTiming, nsecs_t latchTime,
                                nsecs_t dequeueReadyTime) REQUIRES(mMutex);
     void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect);
-    void setBlastBufferQueue(BLASTBufferQueue* blastbufferqueue) REQUIRES(mMutex);
 
 protected:
     void onSidebandStreamChanged() override REQUIRES(mMutex);
 
 private:
+    const wp<BLASTBufferQueue> mBLASTBufferQueue;
+
     uint64_t mCurrentFrameNumber = 0;
 
     Mutex mMutex;
-    std::mutex mBufferQueueMutex;
     ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mMutex);
     std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mMutex);
     bool mCurrentlyConnected GUARDED_BY(mMutex);
     bool mPreviouslyConnected GUARDED_BY(mMutex);
-    BLASTBufferQueue* mBLASTBufferQueue GUARDED_BY(mBufferQueueMutex);
 };
 
 class BLASTBufferQueue
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index a0d3162..e48f52d 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -77,12 +77,6 @@
     // buffer id to identify the buffer.
     sp<ITransactionCompletedListener> releaseBufferListener = nullptr;
 
-    // Keeps track of the release callback id associated with the listener. This
-    // is not sent to the server since the id can be reconstructed there. This
-    // is used to remove the old callback from the client process map if it is
-    // overwritten by another setBuffer call.
-    ReleaseCallbackId releaseCallbackId = ReleaseCallbackId::INVALID_ID;
-
     // Stores which endpoint the release information should be sent to. We don't want to send the
     // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
     // was called with.
@@ -92,6 +86,9 @@
 
     client_cache_t cachedBuffer;
 
+    // Generates the release callback id based on the buffer id and frame number.
+    // This is used as an identifier when release callbacks are invoked.
+    ReleaseCallbackId generateReleaseCallbackId() const;
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
 };
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 17b4846..4798678 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -416,7 +416,7 @@
 
         void cacheBuffers();
         void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc);
-        void setReleaseBufferCallback(BufferData*, const ReleaseCallbackId&, ReleaseBufferCallback);
+        void setReleaseBufferCallback(BufferData*, ReleaseBufferCallback);
 
     public:
         Transaction();
@@ -490,7 +490,6 @@
         Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
                                const std::optional<sp<Fence>>& fence = std::nullopt,
                                const std::optional<uint64_t>& frameNumber = std::nullopt,
-                               const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID,
                                ReleaseBufferCallback callback = nullptr);
         std::optional<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc);
         Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 3baeb55..2039fa6 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -86,10 +86,13 @@
 
 // --- KeyCharacterMap ---
 
-KeyCharacterMap::KeyCharacterMap() : mType(KeyboardType::UNKNOWN) {}
+KeyCharacterMap::KeyCharacterMap(const std::string& filename)
+      : mType(KeyboardType::UNKNOWN), mLoadFileName(filename) {}
 
 KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other)
       : mType(other.mType),
+        mLoadFileName(other.mLoadFileName),
+        mLayoutOverlayApplied(other.mLayoutOverlayApplied),
         mKeysByScanCode(other.mKeysByScanCode),
         mKeysByUsageCode(other.mKeysByUsageCode) {
     for (size_t i = 0; i < other.mKeys.size(); i++) {
@@ -98,16 +101,19 @@
 }
 
 KeyCharacterMap::~KeyCharacterMap() {
-    for (size_t i = 0; i < mKeys.size(); i++) {
-        Key* key = mKeys.editValueAt(i);
-        delete key;
-    }
+    clear();
 }
 
 bool KeyCharacterMap::operator==(const KeyCharacterMap& other) const {
     if (mType != other.mType) {
         return false;
     }
+    if (mLoadFileName != other.mLoadFileName) {
+        return false;
+    }
+    if (mLayoutOverlayApplied != other.mLayoutOverlayApplied) {
+        return false;
+    }
     if (mKeys.size() != other.mKeys.size() ||
         mKeysByScanCode.size() != other.mKeysByScanCode.size() ||
         mKeysByUsageCode.size() != other.mKeysByUsageCode.size()) {
@@ -146,6 +152,10 @@
     return true;
 }
 
+bool KeyCharacterMap::operator!=(const KeyCharacterMap& other) const {
+    return !(*this == other);
+}
+
 base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(const std::string& filename,
                                                                      Format format) {
     Tokenizer* tokenizer;
@@ -153,12 +163,18 @@
     if (status) {
         return Errorf("Error {} opening key character map file {}.", status, filename.c_str());
     }
-    std::unique_ptr<Tokenizer> t(tokenizer);
-    auto ret = load(t.get(), format);
-    if (ret.ok()) {
-        (*ret)->mLoadFileName = filename;
+    std::shared_ptr<KeyCharacterMap> map =
+            std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(filename));
+    if (!map.get()) {
+        ALOGE("Error allocating key character map.");
+        return Errorf("Error allocating key character map.");
     }
-    return ret;
+    std::unique_ptr<Tokenizer> t(tokenizer);
+    status = map->load(t.get(), format);
+    if (status == OK) {
+        return map;
+    }
+    return Errorf("Load KeyCharacterMap failed {}.", status);
 }
 
 base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::loadContents(
@@ -169,40 +185,67 @@
         ALOGE("Error %d opening key character map.", status);
         return Errorf("Error {} opening key character map.", status);
     }
-    std::unique_ptr<Tokenizer> t(tokenizer);
-    auto ret = load(t.get(), format);
-    if (ret.ok()) {
-        (*ret)->mLoadFileName = filename;
-    }
-    return ret;
-}
-
-base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(Tokenizer* tokenizer,
-                                                                     Format format) {
-    status_t status = OK;
-    std::shared_ptr<KeyCharacterMap> map = std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap());
+    std::shared_ptr<KeyCharacterMap> map =
+            std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(filename));
     if (!map.get()) {
         ALOGE("Error allocating key character map.");
         return Errorf("Error allocating key character map.");
     }
+    std::unique_ptr<Tokenizer> t(tokenizer);
+    status = map->load(t.get(), format);
+    if (status == OK) {
+        return map;
+    }
+    return Errorf("Load KeyCharacterMap failed {}.", status);
+}
+
+status_t KeyCharacterMap::load(Tokenizer* tokenizer, Format format) {
+    status_t status = OK;
 #if DEBUG_PARSER_PERFORMANCE
     nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
 #endif
-    Parser parser(map.get(), tokenizer, format);
+    Parser parser(this, tokenizer, format);
     status = parser.parse();
 #if DEBUG_PARSER_PERFORMANCE
     nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
     ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
           tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0);
 #endif
-    if (status == OK) {
-        return map;
+    if (status != OK) {
+        ALOGE("Loading KeyCharacterMap failed with status %s", statusToString(status).c_str());
     }
+    return status;
+}
 
-    return Errorf("Load KeyCharacterMap failed {}.", status);
+void KeyCharacterMap::clear() {
+    mKeysByScanCode.clear();
+    mKeysByUsageCode.clear();
+    for (size_t i = 0; i < mKeys.size(); i++) {
+        Key* key = mKeys.editValueAt(i);
+        delete key;
+    }
+    mKeys.clear();
+    mLayoutOverlayApplied = false;
+    mType = KeyboardType::UNKNOWN;
+}
+
+status_t KeyCharacterMap::reloadBaseFromFile() {
+    clear();
+    Tokenizer* tokenizer;
+    status_t status = Tokenizer::open(String8(mLoadFileName.c_str()), &tokenizer);
+    if (status) {
+        ALOGE("Error %s opening key character map file %s.", statusToString(status).c_str(),
+              mLoadFileName.c_str());
+        return status;
+    }
+    std::unique_ptr<Tokenizer> t(tokenizer);
+    return load(t.get(), KeyCharacterMap::Format::BASE);
 }
 
 void KeyCharacterMap::combine(const KeyCharacterMap& overlay) {
+    if (mLayoutOverlayApplied) {
+        reloadBaseFromFile();
+    }
     for (size_t i = 0; i < overlay.mKeys.size(); i++) {
         int32_t keyCode = overlay.mKeys.keyAt(i);
         Key* key = overlay.mKeys.valueAt(i);
@@ -224,7 +267,7 @@
         mKeysByUsageCode.replaceValueFor(overlay.mKeysByUsageCode.keyAt(i),
                                          overlay.mKeysByUsageCode.valueAt(i));
     }
-    mLoadFileName = overlay.mLoadFileName;
+    mLayoutOverlayApplied = true;
 }
 
 KeyCharacterMap::KeyboardType KeyCharacterMap::getKeyboardType() const {
@@ -636,8 +679,11 @@
         ALOGE("%s: Null parcel", __func__);
         return nullptr;
     }
-    std::shared_ptr<KeyCharacterMap> map = std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap());
+    std::string loadFileName = parcel->readCString();
+    std::shared_ptr<KeyCharacterMap> map =
+            std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap(loadFileName));
     map->mType = static_cast<KeyCharacterMap::KeyboardType>(parcel->readInt32());
+    map->mLayoutOverlayApplied = parcel->readBool();
     size_t numKeys = parcel->readInt32();
     if (parcel->errorCheck()) {
         return nullptr;
@@ -687,6 +733,30 @@
             return nullptr;
         }
     }
+    size_t numKeysByScanCode = parcel->readInt32();
+    if (parcel->errorCheck()) {
+        return nullptr;
+    }
+    for (size_t i = 0; i < numKeysByScanCode; i++) {
+        int32_t key = parcel->readInt32();
+        int32_t value = parcel->readInt32();
+        map->mKeysByScanCode.add(key, value);
+        if (parcel->errorCheck()) {
+            return nullptr;
+        }
+    }
+    size_t numKeysByUsageCode = parcel->readInt32();
+    if (parcel->errorCheck()) {
+        return nullptr;
+    }
+    for (size_t i = 0; i < numKeysByUsageCode; i++) {
+        int32_t key = parcel->readInt32();
+        int32_t value = parcel->readInt32();
+        map->mKeysByUsageCode.add(key, value);
+        if (parcel->errorCheck()) {
+            return nullptr;
+        }
+    }
     return map;
 }
 
@@ -695,7 +765,9 @@
         ALOGE("%s: Null parcel", __func__);
         return;
     }
+    parcel->writeCString(mLoadFileName.c_str());
     parcel->writeInt32(static_cast<int32_t>(mType));
+    parcel->writeBool(mLayoutOverlayApplied);
 
     size_t numKeys = mKeys.size();
     parcel->writeInt32(numKeys);
@@ -715,6 +787,18 @@
         }
         parcel->writeInt32(0);
     }
+    size_t numKeysByScanCode = mKeysByScanCode.size();
+    parcel->writeInt32(numKeysByScanCode);
+    for (size_t i = 0; i < numKeysByScanCode; i++) {
+        parcel->writeInt32(mKeysByScanCode.keyAt(i));
+        parcel->writeInt32(mKeysByScanCode.valueAt(i));
+    }
+    size_t numKeysByUsageCode = mKeysByUsageCode.size();
+    parcel->writeInt32(numKeysByUsageCode);
+    for (size_t i = 0; i < numKeysByUsageCode; i++) {
+        parcel->writeInt32(mKeysByUsageCode.keyAt(i));
+        parcel->writeInt32(mKeysByUsageCode.valueAt(i));
+    }
 }
 #endif // __linux__
 
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 18ab1cb..6ffe851 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -37,6 +37,7 @@
         "libui",
         "libutils",
     ],
+    data: ["data/*.kcm"],
     test_suites: ["device-tests"],
 }
 
@@ -59,5 +60,5 @@
         "libbinder",
         "libui",
         "libbase",
-    ]
+    ],
 }
diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp
index f8f2f4e..61e88df 100644
--- a/libs/input/tests/InputDevice_test.cpp
+++ b/libs/input/tests/InputDevice_test.cpp
@@ -20,6 +20,7 @@
 #include <input/InputDevice.h>
 #include <input/KeyLayoutMap.h>
 #include <input/Keyboard.h>
+#include "android-base/file.h"
 
 namespace android {
 
@@ -82,4 +83,53 @@
     ASSERT_EQ(*map, *mKeyMap.keyCharacterMap);
 }
 
+TEST_F(InputDeviceKeyMapTest, keyCharacterMapWithOverlayParcelingTest) {
+    Parcel parcel;
+    std::string overlayPath = base::GetExecutableDirectory() + "/data/german.kcm";
+    base::Result<std::shared_ptr<KeyCharacterMap>> overlay =
+            KeyCharacterMap::load(overlayPath, KeyCharacterMap::Format::OVERLAY);
+    ASSERT_TRUE(overlay.ok()) << "Cannot load KeyCharacterMap at " << overlayPath;
+    mKeyMap.keyCharacterMap->combine(*overlay->get());
+    mKeyMap.keyCharacterMap->writeToParcel(&parcel);
+    parcel.setDataPosition(0);
+    std::shared_ptr<KeyCharacterMap> map = KeyCharacterMap::readFromParcel(&parcel);
+    ASSERT_EQ(*map, *mKeyMap.keyCharacterMap);
+}
+
+TEST_F(InputDeviceKeyMapTest, keyCharacteMapApplyMultipleOverlaysTest) {
+    std::string frenchOverlayPath = base::GetExecutableDirectory() + "/data/french.kcm";
+    std::string englishOverlayPath = base::GetExecutableDirectory() + "/data/english_us.kcm";
+    std::string germanOverlayPath = base::GetExecutableDirectory() + "/data/german.kcm";
+    base::Result<std::shared_ptr<KeyCharacterMap>> frenchOverlay =
+            KeyCharacterMap::load(frenchOverlayPath, KeyCharacterMap::Format::OVERLAY);
+    ASSERT_TRUE(frenchOverlay.ok()) << "Cannot load KeyCharacterMap at " << frenchOverlayPath;
+    base::Result<std::shared_ptr<KeyCharacterMap>> englishOverlay =
+            KeyCharacterMap::load(englishOverlayPath, KeyCharacterMap::Format::OVERLAY);
+    ASSERT_TRUE(englishOverlay.ok()) << "Cannot load KeyCharacterMap at " << englishOverlayPath;
+    base::Result<std::shared_ptr<KeyCharacterMap>> germanOverlay =
+            KeyCharacterMap::load(germanOverlayPath, KeyCharacterMap::Format::OVERLAY);
+    ASSERT_TRUE(germanOverlay.ok()) << "Cannot load KeyCharacterMap at " << germanOverlayPath;
+
+    // Apply the French overlay
+    mKeyMap.keyCharacterMap->combine(*frenchOverlay->get());
+    // Copy the result for later
+    std::shared_ptr<KeyCharacterMap> frenchOverlaidKeyCharacterMap =
+            std::make_shared<KeyCharacterMap>(*mKeyMap.keyCharacterMap);
+
+    // Apply the English overlay
+    mKeyMap.keyCharacterMap->combine(*englishOverlay->get());
+    // Verify that the result is different from the French overlay result
+    ASSERT_NE(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
+
+    // Apply the German overlay
+    mKeyMap.keyCharacterMap->combine(*germanOverlay->get());
+    // Verify that the result is different from the French overlay result
+    ASSERT_NE(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
+
+    // Apply the French overlay
+    mKeyMap.keyCharacterMap->combine(*frenchOverlay->get());
+    // Verify that the result is the same like after applying it initially
+    ASSERT_EQ(*mKeyMap.keyCharacterMap, *frenchOverlaidKeyCharacterMap);
+}
+
 } // namespace android
diff --git a/libs/input/tests/data/english_us.kcm b/libs/input/tests/data/english_us.kcm
new file mode 100644
index 0000000..d0ef027
--- /dev/null
+++ b/libs/input/tests/data/english_us.kcm
@@ -0,0 +1,311 @@
+# 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.
+
+#
+# English (US) keyboard layout.
+# Unlike the default (generic) keyboard layout, English (US) does not contain any
+# special ALT characters.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+    label:                              '`'
+    base:                               '`'
+    shift:                              '~'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '^'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '&'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '*'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              '('
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              ')'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '='
+    shift:                              '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '['
+    base:                               '['
+    shift:                              '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              ']'
+    base:                               ']'
+    shift:                              '}'
+}
+
+key BACKSLASH {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base:                               ';'
+    shift:                              ':'
+}
+
+key APOSTROPHE {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '"'
+}
+
+### ROW 4
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              '>'
+}
+
+key SLASH {
+    label:                              '/'
+    base:                               '/'
+    shift:                              '?'
+}
\ No newline at end of file
diff --git a/libs/input/tests/data/french.kcm b/libs/input/tests/data/french.kcm
new file mode 100644
index 0000000..db69ea0
--- /dev/null
+++ b/libs/input/tests/data/french.kcm
@@ -0,0 +1,336 @@
+# 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.
+
+#
+# French keyboard layout, AZERTY style.
+#
+
+type OVERLAY
+
+map key 16 A
+map key 17 Z
+map key 30 Q
+map key 39 M
+map key 44 W
+map key 50 COMMA
+map key 51 SEMICOLON
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u00b2'
+    base:                               '\u00b2'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '&'
+    shift:                              '1'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u00e9'
+    shift:                              '2'
+    ralt:                               '~'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '"'
+    shift:                              '3'
+    ralt:                               '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\''
+    shift:                              '4'
+    ralt:                               '{'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '('
+    shift:                              '5'
+    ralt:                               '['
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '-'
+    shift:                              '6'
+    ralt:                               '|'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u00e8'
+    shift:                              '7'
+    ralt:                               '`'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '_'
+    shift:                              '8'
+    ralt:                               '\\'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '\u00e7'
+    shift:                              '9'
+    ralt:                               '^'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '\u00e0'
+    shift:                              '0'
+    ralt:                               '@'
+}
+
+key MINUS {
+    label:                              ')'
+    base:                               ')'
+    shift:                              '\u00b0'
+    ralt:                               ']'
+}
+
+key EQUALS {
+    label:                              '='
+    base:                               '='
+    shift:                              '+'
+    ralt:                               '}'
+}
+
+### ROW 2
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u02c6'
+    base:                               '\u0302'
+    shift:                              '\u0308'
+}
+
+key RIGHT_BRACKET {
+    label:                              '$'
+    base:                               '$'
+    shift:                              '\u00a3'
+    ralt:                               '\u00a4'
+}
+
+### ROW 3
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key APOSTROPHE {
+    label:                              '\u00f9'
+    base:                               '\u00f9'
+    shift:                              '%'
+}
+
+key BACKSLASH {
+    label:                              '*'
+    base:                               '*'
+    shift:                              '\u00b5'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '?'
+}
+
+key SEMICOLON {
+    label:                              ';'
+    base:                               ';'
+    shift:                              '.'
+}
+
+key PERIOD {
+    label:                              ':'
+    base:                               ':'
+    shift:                              '/'
+}
+
+key SLASH {
+    label:                              '!'
+    base:                               '!'
+    shift:                              '\u00a7'
+}
\ No newline at end of file
diff --git a/libs/input/tests/data/german.kcm b/libs/input/tests/data/german.kcm
new file mode 100644
index 0000000..2fbc5e5
--- /dev/null
+++ b/libs/input/tests/data/german.kcm
@@ -0,0 +1,336 @@
+# 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.
+
+#
+# German keyboard layout, QWERTZ style.
+#
+
+type OVERLAY
+
+map key 12 SLASH            # � ? \
+map key 21 Z
+map key 44 Y
+map key 53 MINUS            # - _
+map key 86 PLUS             # < > |
+
+map key usage 32 A              # for testing purposes only
+map key usage 67 B              # for testing purposes only
+
+### ROW 1
+
+key GRAVE {
+    label:                              '^'
+    base:                               '^'
+    shift:                              '\u00b0'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '\u00b2'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '\u00a7'
+    ralt:                               '\u00b3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '\u00df'
+    base:                               '\u00df'
+    shift:                              '?'
+    ralt:                               '\\'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0300'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '@'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00dc'
+    base:                               '\u00fc'
+    shift, capslock:                    '\u00dc'
+}
+
+key RIGHT_BRACKET {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               '~'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+}
+
+key APOSTROPHE {
+    label:                              '\u00c4'
+    base:                               '\u00e4'
+    shift, capslock:                    '\u00c4'
+}
+
+key BACKSLASH {
+    label:                              '#'
+    base:                               '#'
+    shift:                              '\''
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '|'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index b9cc648..d646756 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -189,6 +189,10 @@
     static void validateInputBufferUsage(const sp<GraphicBuffer>&);
     static void validateOutputBufferUsage(const sp<GraphicBuffer>&);
 
+    // Allows flinger to get the render engine thread id for power management with ADPF
+    // Returns the tid of the renderengine thread if it's threaded, and std::nullopt otherwise
+    virtual std::optional<pid_t> getRenderEngineTid() const { return std::nullopt; }
+
 protected:
     RenderEngine() : RenderEngine(RenderEngineType::GLES) {}
 
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 08fc814..a7176d3 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -389,6 +389,20 @@
     mCondition.notify_one();
 }
 
+std::optional<pid_t> RenderEngineThreaded::getRenderEngineTid() const {
+    std::promise<pid_t> tidPromise;
+    std::future<pid_t> tidFuture = tidPromise.get_future();
+    {
+        std::lock_guard lock(mThreadMutex);
+        mFunctionCalls.push([&tidPromise](renderengine::RenderEngine& instance) {
+            tidPromise.set_value(gettid());
+        });
+    }
+
+    mCondition.notify_one();
+    return std::make_optional(tidFuture.get());
+}
+
 } // namespace threaded
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 0159cfa..1ba72dd 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -66,6 +66,7 @@
     int getContextPriority() override;
     bool supportsBackgroundBlur() override;
     void onActiveDisplaySizeChanged(ui::Size size) override;
+    std::optional<pid_t> getRenderEngineTid() const override;
 
 protected:
     void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override;
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 269bdab..09a62f3 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -1262,12 +1262,11 @@
 bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr<KeyCharacterMap> map) {
     std::scoped_lock _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device != nullptr && map != nullptr && device->keyMap.keyCharacterMap != nullptr) {
-        device->keyMap.keyCharacterMap->combine(*map);
-        device->keyMap.keyCharacterMapFile = device->keyMap.keyCharacterMap->getLoadFileName();
-        return true;
+    if (device == nullptr || map == nullptr || device->keyMap.keyCharacterMap == nullptr) {
+        return false;
     }
-    return false;
+    device->keyMap.keyCharacterMap->combine(*map);
+    return true;
 }
 
 static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index db4151b..50adcfb 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -39,11 +39,10 @@
     MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
     MOCK_METHOD(bool, isPowerHintSessionRunning, (), (override));
     MOCK_METHOD(void, setTargetWorkDuration, (int64_t targetDurationNanos), (override));
-    MOCK_METHOD(void, setPowerHintSessionThreadIds, (const std::vector<int32_t>& threadIds),
-                (override));
     MOCK_METHOD(void, sendActualWorkDuration, (int64_t actualDurationNanos, nsecs_t timestamp),
                 (override));
     MOCK_METHOD(void, enablePowerHint, (bool enabled), (override));
+    MOCK_METHOD(bool, startPowerHintSession, (const std::vector<int32_t>& threadIds), (override));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 5c2390e..930ddea 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -93,13 +93,6 @@
 
 void PowerAdvisor::onBootFinished() {
     mBootFinished.store(true);
-    {
-        std::lock_guard lock(mPowerHalMutex);
-        HalWrapper* halWrapper = getPowerHal();
-        if (halWrapper != nullptr && usePowerHintSession()) {
-            mPowerHintSessionRunning = halWrapper->startPowerHintSession();
-        }
-    }
 }
 
 void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
@@ -156,7 +149,6 @@
 // checks both if it supports and if it's enabled
 bool PowerAdvisor::usePowerHintSession() {
     // uses cached value since the underlying support and flag are unlikely to change at runtime
-    ALOGE_IF(!mPowerHintEnabled.has_value(), "Power hint session cannot be used before boot!");
     return mPowerHintEnabled.value_or(false) && supportsPowerHintSession();
 }
 
@@ -175,10 +167,7 @@
 }
 
 void PowerAdvisor::setTargetWorkDuration(int64_t targetDurationNanos) {
-    // we check "supports" here not "usePowerHintSession" because this needs to work
-    // before the session is actually running, and "use" will always fail before boot
-    // we store the values passed in before boot to start the session with during onBootFinished
-    if (!supportsPowerHintSession()) {
+    if (!usePowerHintSession()) {
         ALOGV("Power hint session target duration cannot be set, skipping");
         return;
     }
@@ -186,24 +175,7 @@
         std::lock_guard lock(mPowerHalMutex);
         HalWrapper* const halWrapper = getPowerHal();
         if (halWrapper != nullptr) {
-            halWrapper->setTargetWorkDuration(targetDurationNanos);
-        }
-    }
-}
-
-void PowerAdvisor::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
-    // we check "supports" here not "usePowerHintSession" because this needs to wsork
-    // before the session is actually running, and "use" will always fail before boot.
-    // we store the values passed in before boot to start the session with during onBootFinished
-    if (!supportsPowerHintSession()) {
-        ALOGV("Power hint session thread ids cannot be set, skipping");
-        return;
-    }
-    {
-        std::lock_guard lock(mPowerHalMutex);
-        HalWrapper* const halWrapper = getPowerHal();
-        if (halWrapper != nullptr) {
-            halWrapper->setPowerHintSessionThreadIds(const_cast<std::vector<int32_t>&>(threadIds));
+            halWrapper->setTargetWorkDuration(targetDurationNanos - kTargetSafetyMargin.count());
         }
     }
 }
@@ -227,6 +199,21 @@
     mPowerHintEnabled = enabled;
 }
 
+bool PowerAdvisor::startPowerHintSession(const std::vector<int32_t>& threadIds) {
+    if (!usePowerHintSession()) {
+        ALOGI("Power hint session cannot be started, skipping");
+    }
+    {
+        std::lock_guard lock(mPowerHalMutex);
+        HalWrapper* halWrapper = getPowerHal();
+        if (halWrapper != nullptr && usePowerHintSession()) {
+            halWrapper->setPowerHintSessionThreadIds(threadIds);
+            mPowerHintSessionRunning = halWrapper->startPowerHintSession();
+        }
+    }
+    return mPowerHintSessionRunning;
+}
+
 class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
 public:
     HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
@@ -307,11 +294,10 @@
             mHasDisplayUpdateImminent = false;
         }
 
-        // This just gives a number not a binder status, so no .isOk()
-        mSupportsPowerHints = mPowerHal->getInterfaceVersion() >= 2;
+        mSupportsPowerHint = checkPowerHintSessionSupported();
 
-        if (mSupportsPowerHints) {
-            mPowerHintQueue.reserve(MAX_QUEUE_SIZE);
+        if (mSupportsPowerHint) {
+            mPowerHintQueue.reserve(kMaxQueueSize);
         }
     }
 
@@ -356,7 +342,14 @@
     }
 
     // only version 2+ of the aidl supports power hint sessions, hidl has no support
-    bool supportsPowerHintSession() override { return mSupportsPowerHints; }
+    bool supportsPowerHintSession() override { return mSupportsPowerHint; }
+
+    bool checkPowerHintSessionSupported() {
+        int64_t unused;
+        // Try to get preferred rate to determine if hint sessions are supported
+        // We check for isOk not EX_UNSUPPORTED_OPERATION to lump other errors
+        return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
+    }
 
     bool isPowerHintSessionRunning() override { return mPowerHintSession != nullptr; }
 
@@ -382,38 +375,43 @@
     }
 
     bool startPowerHintSession() override {
-        if (mPowerHintSession != nullptr || !mPowerHintTargetDuration.has_value() ||
-            mPowerHintThreadIds.empty()) {
+        if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
             ALOGV("Cannot start power hint session, skipping");
             return false;
         }
         auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
-                                                mPowerHintThreadIds, *mPowerHintTargetDuration,
+                                                mPowerHintThreadIds, mTargetDuration,
                                                 &mPowerHintSession);
         if (!ret.isOk()) {
             ALOGW("Failed to start power hint session with error: %s",
                   ret.exceptionToString(ret.exceptionCode()).c_str());
-            // Indicate to the poweradvisor that this wrapper likely needs to be remade
-            mShouldReconnectHal = true;
+        } else {
+            mLastTargetDurationSent = mTargetDuration;
         }
         return isPowerHintSessionRunning();
     }
 
     bool shouldSetTargetDuration(int64_t targetDurationNanos) {
-        if (!mLastTargetDurationSent.has_value()) {
-            return true;
-        }
-
         // report if the change in target from our last submission to now exceeds the threshold
         return abs(1.0 -
-                   static_cast<double>(*mLastTargetDurationSent) /
+                   static_cast<double>(mLastTargetDurationSent) /
                            static_cast<double>(targetDurationNanos)) >=
-                ALLOWED_TARGET_DEVIATION_PERCENT;
+                kAllowedTargetDeviationPercent;
     }
 
     void setTargetWorkDuration(int64_t targetDurationNanos) override {
-        mPowerHintTargetDuration = targetDurationNanos;
-        if (shouldSetTargetDuration(targetDurationNanos) && isPowerHintSessionRunning()) {
+        ATRACE_CALL();
+        mTargetDuration = targetDurationNanos;
+        if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDurationNanos);
+        if (!sNormalizeTarget && shouldSetTargetDuration(targetDurationNanos) &&
+            isPowerHintSessionRunning()) {
+            if (mLastActualDurationSent.has_value()) {
+                // update the error term here since we are actually sending an update to powerhal
+                if (sTraceHintSessionData)
+                    ATRACE_INT64("Target error term",
+                                 targetDurationNanos - *mLastActualDurationSent);
+            }
+            ALOGV("Sending target time: %lld ns", static_cast<long long>(targetDurationNanos));
             mLastTargetDurationSent = targetDurationNanos;
             auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
             if (!ret.isOk()) {
@@ -426,23 +424,27 @@
 
     bool shouldReportActualDurationsNow() {
         // report if we have never reported before or have exceeded the max queue size
-        if (!mLastMessageReported.has_value() || mPowerHintQueue.size() >= MAX_QUEUE_SIZE) {
+        if (!mLastActualDurationSent.has_value() || mPowerHintQueue.size() >= kMaxQueueSize) {
             return true;
         }
 
+        if (!mActualDuration.has_value()) {
+            return false;
+        }
+
         // duration of most recent timing
-        const double mostRecentActualDuration =
-                static_cast<double>(mPowerHintQueue.back().durationNanos);
+        const double mostRecentActualDuration = static_cast<double>(*mActualDuration);
         // duration of the last timing actually reported to the powerhal
-        const double lastReportedActualDuration =
-                static_cast<double>(mLastMessageReported->durationNanos);
+        const double lastReportedActualDuration = static_cast<double>(*mLastActualDurationSent);
 
         // report if the change in duration from then to now exceeds the threshold
         return abs(1.0 - mostRecentActualDuration / lastReportedActualDuration) >=
-                ALLOWED_ACTUAL_DEVIATION_PERCENT;
+                kAllowedActualDeviationPercent;
     }
 
     void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override {
+        ATRACE_CALL();
+
         if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
             ALOGV("Failed to send actual work duration, skipping");
             return;
@@ -450,13 +452,31 @@
 
         WorkDuration duration;
         duration.durationNanos = actualDurationNanos;
+        mActualDuration = actualDurationNanos;
+
+        // normalize the sent values to a pre-set target
+        if (sNormalizeTarget) {
+            duration.durationNanos += mLastTargetDurationSent - mTargetDuration;
+        }
         duration.timeStampNanos = timeStampNanos;
         mPowerHintQueue.push_back(duration);
 
+        long long targetNsec = mTargetDuration;
+        long long durationNsec = actualDurationNanos;
+
+        if (sTraceHintSessionData) {
+            ATRACE_INT64("Measured duration", durationNsec);
+            ATRACE_INT64("Target error term", targetNsec - durationNsec);
+        }
+
+        ALOGV("Sending actual work duration of: %lld on target: %lld with error: %lld",
+              durationNsec, targetNsec, targetNsec - durationNsec);
+
         // This rate limiter queues similar duration reports to the powerhal into
         // batches to avoid excessive binder calls. The criteria to send a given batch
         // are outlined in shouldReportActualDurationsNow()
         if (shouldReportActualDurationsNow()) {
+            ALOGV("Sending hint update batch");
             auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
             if (!ret.isOk()) {
                 ALOGW("Failed to report actual work durations with error: %s",
@@ -464,7 +484,8 @@
                 mShouldReconnectHal = true;
             }
             mPowerHintQueue.clear();
-            mLastMessageReported = duration;
+            // we save the non-normalized value here to detect % changes
+            mLastActualDurationSent = actualDurationNanos;
         }
     }
 
@@ -472,32 +493,48 @@
 
     std::vector<int32_t> getPowerHintSessionThreadIds() override { return mPowerHintThreadIds; }
 
-    std::optional<int64_t> getTargetWorkDuration() override { return mPowerHintTargetDuration; }
+    std::optional<int64_t> getTargetWorkDuration() override { return mTargetDuration; }
 
 private:
-    // max number of messages allowed in mPowerHintQueue before reporting is forced
-    static constexpr int32_t MAX_QUEUE_SIZE = 15;
-    // max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
-    static constexpr double ALLOWED_ACTUAL_DEVIATION_PERCENT = 0.1;
-    // max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
-    static constexpr double ALLOWED_TARGET_DEVIATION_PERCENT = 0.05;
-
     const sp<IPower> mPowerHal = nullptr;
     bool mHasExpensiveRendering = false;
     bool mHasDisplayUpdateImminent = false;
-    bool mShouldReconnectHal = false; // used to indicate an error state and need for reconstruction
+    // Used to indicate an error state and need for reconstruction
+    bool mShouldReconnectHal = false;
     // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
     sp<IPowerHintSession> mPowerHintSession = nullptr;
+    // Queue of actual durations saved to report
     std::vector<WorkDuration> mPowerHintQueue;
-    // halwrapper owns these values so we can init when we want and reconnect if broken
-    std::optional<int64_t> mPowerHintTargetDuration;
+    // The latest un-normalized values we have received for target and actual
+    int64_t mTargetDuration = kDefaultTarget;
+    std::optional<int64_t> mActualDuration;
+    // The list of thread ids, stored so we can restart the session from this class if needed
     std::vector<int32_t> mPowerHintThreadIds;
-    // keep track of the last messages sent for rate limiter change detection
-    std::optional<WorkDuration> mLastMessageReported;
-    std::optional<int64_t> mLastTargetDurationSent;
-    bool mSupportsPowerHints;
+    bool mSupportsPowerHint;
+    // Keep track of the last messages sent for rate limiter change detection
+    std::optional<int64_t> mLastActualDurationSent;
+    int64_t mLastTargetDurationSent = kDefaultTarget;
+    // Whether to normalize all the actual values as error terms relative to a constant target
+    // This saves a binder call by not setting the target, and should not affect the pid values
+    static const bool sNormalizeTarget;
+    // Whether we should emit ATRACE_INT data for hint sessions
+    static const bool sTraceHintSessionData;
+    // Max number of messages allowed in mPowerHintQueue before reporting is forced
+    static constexpr int32_t kMaxQueueSize = 15;
+    // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
+    static constexpr double kAllowedActualDeviationPercent = 0.1;
+    // Max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
+    static constexpr double kAllowedTargetDeviationPercent = 0.05;
+    // Target used for init and normalization, the actual value does not really matter
+    static constexpr int64_t kDefaultTarget = 50000000;
 };
 
+const bool AidlPowerHalWrapper::sTraceHintSessionData =
+        base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
+
+const bool AidlPowerHalWrapper::sNormalizeTarget =
+        base::GetBoolProperty(std::string("debug.sf.normalize_hint_session_durations"), true);
+
 PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
     static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
     static bool sHasHal = true;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index b8fd17d..28d28f4 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <atomic>
+#include <chrono>
 #include <unordered_set>
 
 #include <utils/Mutex.h>
@@ -24,6 +25,8 @@
 #include "../Scheduler/OneShotTimer.h"
 #include "DisplayIdentification.h"
 
+using namespace std::chrono_literals;
+
 namespace android {
 
 class SurfaceFlinger;
@@ -44,9 +47,9 @@
     virtual bool supportsPowerHintSession() = 0;
     virtual bool isPowerHintSessionRunning() = 0;
     virtual void setTargetWorkDuration(int64_t targetDurationNanos) = 0;
-    virtual void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) = 0;
     virtual void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timestamp) = 0;
     virtual void enablePowerHint(bool enabled) = 0;
+    virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0;
 };
 
 namespace impl {
@@ -86,9 +89,9 @@
     bool supportsPowerHintSession() override;
     bool isPowerHintSessionRunning() override;
     void setTargetWorkDuration(int64_t targetDurationNanos) override;
-    void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override;
     void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timestamp) override;
     void enablePowerHint(bool enabled) override;
+    bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
 
 private:
     HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex);
@@ -100,6 +103,12 @@
     std::optional<bool> mSupportsPowerHint;
     bool mPowerHintSessionRunning = false;
 
+    // An adjustable safety margin which moves the "target" earlier to allow flinger to
+    // go a bit over without dropping a frame, especially since we can't measure
+    // the exact time HWC finishes composition so "actual" durations are measured
+    // from the end of present() instead, which is a bit later.
+    static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 2ms;
+
     std::unordered_set<DisplayId> mExpensiveDisplays;
     bool mNotifiedExpensiveRendering = false;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a6eeda2..ecfa3a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -721,7 +721,6 @@
     ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
 
     mFlagManager = std::make_unique<android::FlagManager>();
-    mPowerAdvisor.enablePowerHint(mFlagManager->use_adpf_cpu_hint());
     mFrameTracer->initialize();
     mFrameTimeline->onBootFinished();
 
@@ -751,7 +750,18 @@
         }
 
         readPersistentProperties();
+        std::optional<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid();
+        std::vector<int32_t> tidList;
+        tidList.emplace_back(gettid());
+        if (renderEngineTid.has_value()) {
+            tidList.emplace_back(*renderEngineTid);
+        }
         mPowerAdvisor.onBootFinished();
+        mPowerAdvisor.enablePowerHint(mFlagManager->use_adpf_cpu_hint());
+        if (mPowerAdvisor.usePowerHintSession()) {
+            mPowerAdvisor.startPowerHintSession(tidList);
+        }
+
         mBootStage = BootStage::FINISHED;
 
         if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
@@ -1922,6 +1932,13 @@
 }
 
 bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) {
+    MainThreadScopedGuard mainThreadGuard(SF_MAIN_THREAD);
+    // we set this once at the beginning of commit to ensure consistency throughout the whole frame
+    mPowerHintSessionData.sessionEnabled = mPowerAdvisor.usePowerHintSession();
+    if (mPowerHintSessionData.sessionEnabled) {
+        mPowerHintSessionData.commitStart = systemTime();
+    }
+
     // calculate the expected present time once and use the cached
     // value throughout this frame to make sure all layers are
     // seeing this same value.
@@ -1935,6 +1952,10 @@
     const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
     mScheduledPresentTime = expectedVsyncTime;
 
+    if (mPowerHintSessionData.sessionEnabled) {
+        mPowerAdvisor.setTargetWorkDuration(mExpectedPresentTime -
+                                            mPowerHintSessionData.commitStart);
+    }
     const auto vsyncIn = [&] {
         if (!ATRACE_ENABLED()) return 0.f;
         return (mExpectedPresentTime - systemTime()) / 1e6f;
@@ -2074,6 +2095,10 @@
 
 void SurfaceFlinger::composite(nsecs_t frameTime) {
     ATRACE_CALL();
+    MainThreadScopedGuard mainThreadGuard(SF_MAIN_THREAD);
+    if (mPowerHintSessionData.sessionEnabled) {
+        mPowerHintSessionData.compositeStart = systemTime();
+    }
 
     compositionengine::CompositionRefreshArgs refreshArgs;
     const auto& displays = ON_MAIN_THREAD(mDisplays);
@@ -2127,6 +2152,11 @@
     const auto presentTime = systemTime();
 
     mCompositionEngine->present(refreshArgs);
+
+    if (mPowerHintSessionData.sessionEnabled) {
+        mPowerHintSessionData.presentEnd = systemTime();
+    }
+
     mTimeStats->recordFrameDuration(frameTime, systemTime());
 
     mScheduler->onPostComposition(presentTime);
@@ -2174,6 +2204,13 @@
     if (mCompositionEngine->needsAnotherUpdate()) {
         scheduleCommit(FrameHint::kNone);
     }
+
+    // calculate total render time for performance hinting if adpf cpu hint is enabled,
+    if (mPowerHintSessionData.sessionEnabled) {
+        const nsecs_t flingerDuration =
+                (mPowerHintSessionData.presentEnd - mPowerHintSessionData.commitStart);
+        mPowerAdvisor.sendActualWorkDuration(flingerDuration, mPowerHintSessionData.presentEnd);
+    }
 }
 
 void SurfaceFlinger::updateLayerGeometry() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e1b52c5..d6d31cb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1357,6 +1357,13 @@
     float getLayerFramerate(nsecs_t now, int32_t id) const {
         return mScheduler->getLayerFramerate(now, id);
     }
+
+    struct {
+        bool sessionEnabled = false;
+        nsecs_t commitStart;
+        nsecs_t compositeStart;
+        nsecs_t presentEnd;
+    } mPowerHintSessionData GUARDED_BY(SF_MAIN_THREAD);
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index f6b0def..027a15e 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -85,7 +85,7 @@
                              sp<Fence> fence, CallbackHelper& callback, const ReleaseCallbackId& id,
                              ReleaseBufferCallbackHelper& releaseCallback) {
         Transaction t;
-        t.setBuffer(layer, buffer, fence, id.framenumber, id, releaseCallback.getCallback());
+        t.setBuffer(layer, buffer, fence, id.framenumber, releaseCallback.getCallback());
         t.addTransactionCompletedCallback(callback.function, callback.getContext());
         t.apply();
     }
@@ -300,7 +300,7 @@
     nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
 
     Transaction t;
-    t.setBuffer(layer, firstBuffer, std::nullopt, std::nullopt, firstBufferCallbackId,
+    t.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber,
                 releaseCallback->getCallback());
     t.addTransactionCompletedCallback(transactionCallback.function,
                                       transactionCallback.getContext());
@@ -316,7 +316,7 @@
     // Dropping frames in transaction queue emits a callback
     sp<GraphicBuffer> secondBuffer = getBuffer();
     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
-    t.setBuffer(layer, secondBuffer, std::nullopt, std::nullopt, secondBufferCallbackId,
+    t.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
                 releaseCallback->getCallback());
     t.addTransactionCompletedCallback(transactionCallback.function,
                                       transactionCallback.getContext());
@@ -360,7 +360,7 @@
 
     Transaction transaction1;
     transaction1.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
-                           secondBufferCallbackId, releaseCallback->getCallback());
+                           releaseCallback->getCallback());
     transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext());
 
     // Set a different TransactionCompletedListener to mimic a second process
@@ -395,14 +395,14 @@
     // Create transaction with a buffer.
     Transaction transaction;
     transaction.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber,
-                          firstBufferCallbackId, releaseCallback->getCallback());
+                          releaseCallback->getCallback());
 
     sp<GraphicBuffer> secondBuffer = getBuffer();
     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
 
     // Call setBuffer on the same transaction with a different buffer.
     transaction.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
-                          secondBufferCallbackId, releaseCallback->getCallback());
+                          releaseCallback->getCallback());
 
     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
 }
@@ -417,7 +417,7 @@
     // Create transaction with a buffer.
     Transaction transaction1;
     transaction1.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber,
-                           firstBufferCallbackId, releaseCallback->getCallback());
+                           releaseCallback->getCallback());
 
     sp<GraphicBuffer> secondBuffer = getBuffer();
     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
@@ -425,7 +425,7 @@
     // Create a second transaction with a new buffer for the same layer.
     Transaction transaction2;
     transaction2.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
-                           secondBufferCallbackId, releaseCallback->getCallback());
+                           releaseCallback->getCallback());
 
     // merge transaction1 into transaction2 so ensure we get a proper buffer release callback.
     transaction1.merge(std::move(transaction2));
@@ -446,7 +446,7 @@
 
     Transaction transaction1;
     transaction1.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber,
-                           firstBufferCallbackId, releaseCallback->getCallback());
+                           releaseCallback->getCallback());
 
     // Sent a second buffer to allow the first buffer to get released.
     sp<GraphicBuffer> secondBuffer = getBuffer();
@@ -454,7 +454,7 @@
 
     Transaction transaction2;
     transaction2.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
-                           secondBufferCallbackId, releaseCallback->getCallback());
+                           releaseCallback->getCallback());
 
     // Set a different TransactionCompletedListener to mimic a second process
     TransactionCompletedListener::setInstance(secondCompletedListener);
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index 23b849a..c598cbc 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -37,11 +37,10 @@
     MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
     MOCK_METHOD(bool, isPowerHintSessionRunning, (), (override));
     MOCK_METHOD(void, setTargetWorkDuration, (int64_t targetDurationNanos), (override));
-    MOCK_METHOD(void, setPowerHintSessionThreadIds, (const std::vector<int32_t>& threadIds),
-                (override));
     MOCK_METHOD(void, sendActualWorkDuration, (int64_t actualDurationNanos, nsecs_t timestamp),
                 (override));
     MOCK_METHOD(void, enablePowerHint, (bool enabled), (override));
+    MOCK_METHOD(bool, startPowerHintSession, (const std::vector<int32_t>& threadIds), (override));
 };
 
 } // namespace android::Hwc2::mock