Merge "BBQ: Capture initial destframe change from BBQ"
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 7ae98a0..2935c6a 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1980,7 +1980,18 @@
}
fts_close(fts);
}
-
+static bool ownsExternalStorage(int32_t appId) {
+ // Fetch external storage owner appid and check if it is the same as the
+ // current appId whose size is calculated
+ struct stat s;
+ auto _picDir = StringPrintf("%s/Pictures", create_data_media_path(nullptr, 0).c_str());
+ // check if the stat are present
+ if (stat(_picDir.c_str(), &s) == 0) {
+ // fetch the appId from the uid of the media app
+ return ((int32_t)multiuser_get_app_id(s.st_uid) == appId);
+ }
+ return false;
+}
binder::Status InstalldNativeService::getAppSize(const std::optional<std::string>& uuid,
const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
int32_t appId, const std::vector<int64_t>& ceDataInodes,
@@ -2035,8 +2046,10 @@
calculate_tree_size(obbCodePath, &extStats.codeSize);
}
ATRACE_END();
-
- if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) {
+ // Calculating the app size of the external storage owning app in a manual way, since
+ // calculating it through quota apis also includes external media storage in the app storage
+ // numbers
+ if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START && !ownsExternalStorage(appId)) {
ATRACE_BEGIN("code");
for (const auto& codePath : codePaths) {
calculate_tree_size(codePath, &stats.codeSize, -1,
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 13e15ca..4cde7e3 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -13,7 +13,10 @@
test_suites: ["device-tests"],
clang: true,
srcs: ["installd_utils_test.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libbase",
"libutils",
@@ -33,7 +36,10 @@
test_suites: ["device-tests"],
clang: true,
srcs: ["installd_cache_test.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libbase",
"libbinder",
@@ -75,7 +81,10 @@
test_suites: ["device-tests"],
clang: true,
srcs: ["installd_service_test.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libbase",
"libbinder",
@@ -84,6 +93,7 @@
"libprocessgroup",
"libselinux",
"libutils",
+ "packagemanager_aidl-cpp",
"server_configurable_flags",
],
static_libs: [
@@ -117,7 +127,10 @@
test_suites: ["device-tests"],
clang: true,
srcs: ["installd_dexopt_test.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libbase",
"libbinder",
@@ -160,7 +173,10 @@
test_suites: ["device-tests"],
clang: true,
srcs: ["installd_otapreopt_test.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libbase",
"libcutils",
@@ -169,6 +185,6 @@
],
static_libs: [
"liblog",
- "libotapreoptparameters"
+ "libotapreoptparameters",
],
}
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 8edb3bf..b831515 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -18,10 +18,11 @@
#include <string>
#include <fcntl.h>
+#include <pwd.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/statvfs.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/xattr.h>
#include <android-base/file.h>
@@ -32,8 +33,10 @@
#include <cutils/properties.h>
#include <gtest/gtest.h>
-#include "binder_test_utils.h"
+#include <android/content/pm/IPackageManagerNative.h>
+#include <binder/IServiceManager.h>
#include "InstalldNativeService.h"
+#include "binder_test_utils.h"
#include "dexopt.h"
#include "globals.h"
#include "utils.h"
@@ -41,6 +44,34 @@
using android::base::StringPrintf;
namespace android {
+std::string get_package_name(uid_t uid) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<content::pm::IPackageManagerNative> package_mgr;
+ if (sm.get() == nullptr) {
+ LOG(INFO) << "Cannot find service manager";
+ } else {
+ sp<IBinder> binder = sm->getService(String16("package_native"));
+ if (binder.get() == nullptr) {
+ LOG(INFO) << "Cannot find package_native";
+ } else {
+ package_mgr = interface_cast<content::pm::IPackageManagerNative>(binder);
+ }
+ }
+ // find package name
+ std::string pkg;
+ if (package_mgr != nullptr) {
+ std::vector<std::string> names;
+ binder::Status status = package_mgr->getNamesForUids({(int)uid}, &names);
+ if (!status.isOk()) {
+ LOG(INFO) << "getNamesForUids failed: %s", status.exceptionMessage().c_str();
+ } else {
+ if (!names[0].empty()) {
+ pkg = names[0].c_str();
+ }
+ }
+ }
+ return pkg;
+}
namespace installd {
constexpr const char* kTestUuid = "TEST";
@@ -248,7 +279,50 @@
EXPECT_TRUE(create_cache_path(buf, "/path/to/file.apk", "isa"));
EXPECT_EQ("/data/dalvik-cache/isa/path@to@file.apk@classes.dex", std::string(buf));
}
+TEST_F(ServiceTest, GetAppSize) {
+ struct stat s;
+ std::string externalPicDir =
+ StringPrintf("%s/Pictures", create_data_media_path(nullptr, 0).c_str());
+ if (stat(externalPicDir.c_str(), &s) == 0) {
+ // fetch the appId from the uid of the external storage owning app
+ int32_t externalStorageAppId = multiuser_get_app_id(s.st_uid);
+ // Fetch Package Name for the external storage owning app uid
+ std::string pkg = get_package_name(s.st_uid);
+
+ std::vector<int64_t> externalStorageSize, externalStorageSizeAfterAddingExternalFile;
+ std::vector<int64_t> ceDataInodes;
+
+ std::vector<std::string> codePaths;
+ std::vector<std::string> packageNames;
+ // set up parameters
+ packageNames.push_back(pkg);
+ ceDataInodes.push_back(0);
+ // initialise the mounts
+ service->invalidateMounts();
+ // call the getAppSize to get the current size of the external storage owning app
+ service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
+ externalStorageAppId, ceDataInodes, codePaths, &externalStorageSize);
+ // add a file with 20MB size to the external storage
+ std::string externalFileLocation =
+ StringPrintf("%s/Pictures/%s", getenv("EXTERNAL_STORAGE"), "External.jpg");
+ std::string externalFileContentCommand =
+ StringPrintf("dd if=/dev/zero of=%s bs=1M count=20", externalFileLocation.c_str());
+ system(externalFileContentCommand.c_str());
+ // call the getAppSize again to get the new size of the external storage owning app
+ service->getAppSize(std::nullopt, packageNames, 0, InstalldNativeService::FLAG_USE_QUOTA,
+ externalStorageAppId, ceDataInodes, codePaths,
+ &externalStorageSizeAfterAddingExternalFile);
+ // check that the size before adding the file and after should be the same, as the app size
+ // is not changed.
+ for (size_t i = 0; i < externalStorageSize.size(); i++) {
+ ASSERT_TRUE(externalStorageSize[i] == externalStorageSizeAfterAddingExternalFile[i]);
+ }
+ // remove the external file
+ std::string removeCommand = StringPrintf("rm -f %s", externalFileLocation.c_str());
+ system(removeCommand.c_str());
+ }
+}
static bool mkdirs(const std::string& path, mode_t mode) {
struct stat sb;
if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 4e44ac7..4374abe 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -28,6 +28,9 @@
#ifndef VENDORSERVICEMANAGER
#include <vintf/VintfObject.h>
+#ifdef __ANDROID_RECOVERY__
+#include <vintf/VintfObjectRecovery.h>
+#endif // __ANDROID_RECOVERY__
#include <vintf/constants.h>
#endif // !VENDORSERVICEMANAGER
@@ -37,16 +40,33 @@
namespace android {
#ifndef VENDORSERVICEMANAGER
+
struct ManifestWithDescription {
std::shared_ptr<const vintf::HalManifest> manifest;
const char* description;
};
+static std::vector<ManifestWithDescription> GetManifestsWithDescription() {
+#ifdef __ANDROID_RECOVERY__
+ auto vintfObject = vintf::VintfObjectRecovery::GetInstance();
+ if (vintfObject == nullptr) {
+ LOG(ERROR) << "NULL VintfObjectRecovery!";
+ return {};
+ }
+ return {ManifestWithDescription{vintfObject->getRecoveryHalManifest(), "recovery"}};
+#else
+ auto vintfObject = vintf::VintfObject::GetInstance();
+ if (vintfObject == nullptr) {
+ LOG(ERROR) << "NULL VintfObject!";
+ return {};
+ }
+ return {ManifestWithDescription{vintfObject->getDeviceHalManifest(), "device"},
+ ManifestWithDescription{vintfObject->getFrameworkHalManifest(), "framework"}};
+#endif
+}
+
// func true -> stop search and forEachManifest will return true
static bool forEachManifest(const std::function<bool(const ManifestWithDescription&)>& func) {
- for (const ManifestWithDescription& mwd : {
- ManifestWithDescription{ vintf::VintfObject::GetDeviceHalManifest(), "device" },
- ManifestWithDescription{ vintf::VintfObject::GetFrameworkHalManifest(), "framework" },
- }) {
+ for (const ManifestWithDescription& mwd : GetManifestsWithDescription()) {
if (mwd.manifest == nullptr) {
LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description;
// note, we explicitly do not retry here, so that we can detect VINTF
diff --git a/include/input/Input.h b/include/input/Input.h
index 70c7909..29503af 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -382,6 +382,7 @@
// window scale. The global scale will be applied to TOUCH/TOOL_MAJOR/MINOR
// axes, however the window scaling will not.
void scale(float globalScale, float windowXScale, float windowYScale);
+ void applyOffset(float xOffset, float yOffset);
void transform(const ui::Transform& transform);
@@ -571,7 +572,7 @@
inline float getYOffset() const { return mTransform.ty(); }
- inline const ui::Transform& getTransform() const { return mTransform; }
+ inline ui::Transform getTransform() const { return mTransform; }
int getSurfaceRotation() const;
@@ -589,7 +590,7 @@
void setCursorPosition(float x, float y);
- inline const ui::Transform& getRawTransform() const { return mRawTransform; }
+ ui::Transform getRawTransform() const { return mRawTransform; }
static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); }
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 4561d6e..e2fc18d 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -24,13 +24,15 @@
target: {
darwin: {
enabled: false,
- }
+ },
},
apex_available: [
"//apex_available:platform",
"com.android.compos",
+ "com.android.uwb",
"com.android.virt",
],
+ min_sdk_version: "current",
}
rust_library {
@@ -45,7 +47,7 @@
target: {
darwin: {
enabled: false,
- }
+ },
},
apex_available: [
"//apex_available:platform",
@@ -69,13 +71,15 @@
target: {
darwin: {
enabled: false,
- }
+ },
},
apex_available: [
"//apex_available:platform",
"com.android.compos",
+ "com.android.uwb",
"com.android.virt",
],
+ min_sdk_version: "current",
lints: "none",
clippy_lints: "none",
}
@@ -88,20 +92,31 @@
bindgen_flags: [
// Unfortunately the only way to specify the rust_non_exhaustive enum
// style for a type is to make it the default
- "--default-enum-style", "rust_non_exhaustive",
+ "--default-enum-style",
+ "rust_non_exhaustive",
// and then specify constified enums for the enums we don't want
// rustified
- "--constified-enum", "android::c_interface::consts::.*",
+ "--constified-enum",
+ "android::c_interface::consts::.*",
- "--allowlist-type", "android::c_interface::.*",
- "--allowlist-type", "AStatus",
- "--allowlist-type", "AIBinder_Class",
- "--allowlist-type", "AIBinder",
- "--allowlist-type", "AIBinder_Weak",
- "--allowlist-type", "AIBinder_DeathRecipient",
- "--allowlist-type", "AParcel",
- "--allowlist-type", "binder_status_t",
- "--allowlist-function", ".*",
+ "--allowlist-type",
+ "android::c_interface::.*",
+ "--allowlist-type",
+ "AStatus",
+ "--allowlist-type",
+ "AIBinder_Class",
+ "--allowlist-type",
+ "AIBinder",
+ "--allowlist-type",
+ "AIBinder_Weak",
+ "--allowlist-type",
+ "AIBinder_DeathRecipient",
+ "--allowlist-type",
+ "AParcel",
+ "--allowlist-type",
+ "binder_status_t",
+ "--allowlist-function",
+ ".*",
],
shared_libs: [
"libbinder_ndk",
@@ -127,8 +142,10 @@
apex_available: [
"//apex_available:platform",
"com.android.compos",
+ "com.android.uwb",
"com.android.virt",
],
+ min_sdk_version: "current",
}
// TODO(b/184872979): remove once the Rust API is created.
@@ -142,8 +159,10 @@
],
apex_available: [
"com.android.compos",
+ "com.android.uwb",
"com.android.virt",
],
+ min_sdk_version: "current",
}
rust_test {
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index cd1c810..ec0573a 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -550,9 +550,7 @@
}
bool InputWindowCommands::empty() const {
- bool empty = true;
- empty = focusRequests.empty() && !syncInputWindows;
- return empty;
+ return focusRequests.empty() && !syncInputWindows;
}
void InputWindowCommands::clear() {
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 349880c..44487c3 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -344,6 +344,11 @@
scaleAxisValue(*this, AMOTION_EVENT_AXIS_RELATIVE_Y, windowYScale);
}
+void PointerCoords::applyOffset(float xOffset, float yOffset) {
+ setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
+ setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
+}
+
#ifdef __linux__
status_t PointerCoords::readFromParcel(Parcel* parcel) {
bits = parcel->readInt64();
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index d429551..cb3361b 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -30,7 +30,7 @@
#include <private/android/AHardwareBufferHelpers.h>
#include <android/hardware/graphics/common/1.1/types.h>
-
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
static constexpr int kFdBufferSize = 128 * sizeof(int); // 128 ints
@@ -588,8 +588,12 @@
"HAL and AHardwareBuffer pixel format don't match");
static_assert(HAL_PIXEL_FORMAT_YCBCR_422_I == AHARDWAREBUFFER_FORMAT_YCbCr_422_I,
"HAL and AHardwareBuffer pixel format don't match");
+ static_assert(static_cast<int>(aidl::android::hardware::graphics::common::PixelFormat::R_8) ==
+ AHARDWAREBUFFER_FORMAT_R8_UNORM,
+ "HAL and AHardwareBuffer pixel format don't match");
switch (format) {
+ case AHARDWAREBUFFER_FORMAT_R8_UNORM:
case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
@@ -641,6 +645,8 @@
uint32_t AHardwareBuffer_bytesPerPixel(uint32_t format) {
switch (format) {
+ case AHARDWAREBUFFER_FORMAT_R8_UNORM:
+ return 1;
case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
case AHARDWAREBUFFER_FORMAT_D16_UNORM:
return 2;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index d5e7cb2..6f1f04d 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -158,6 +158,13 @@
* cube-maps or multi-layered textures.
*/
AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23,
+
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R8_UNORM
+ * OpenGL ES: GR_GL_R8
+ */
+ AHARDWAREBUFFER_FORMAT_R8_UNORM = 0x38,
};
/**
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 36d001f..a7b5900 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -225,6 +225,11 @@
"libui_headers",
],
min_sdk_version: "29",
+
+ pgo: {
+ sampling: true,
+ profile_file: "libui/libui.profdata",
+ },
}
cc_library_headers {
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 1f006ce..073da89 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -302,6 +302,8 @@
return std::string("RGB_565");
case android::PIXEL_FORMAT_BGRA_8888:
return std::string("BGRA_8888");
+ case android::PIXEL_FORMAT_R_8:
+ return std::string("R_8");
default:
return StringPrintf("Unknown %#08x", format);
}
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index d1925cb..799fbc9 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -35,6 +35,8 @@
case PIXEL_FORMAT_RGBA_5551:
case PIXEL_FORMAT_RGBA_4444:
return 2;
+ case PIXEL_FORMAT_R_8:
+ return 1;
}
return 0;
}
diff --git a/libs/ui/include/ui/PixelFormat.h b/libs/ui/include/ui/PixelFormat.h
index 91ff39e..f422ce4 100644
--- a/libs/ui/include/ui/PixelFormat.h
+++ b/libs/ui/include/ui/PixelFormat.h
@@ -62,6 +62,7 @@
PIXEL_FORMAT_RGBA_4444 = 7, // 16-bit ARGB
PIXEL_FORMAT_RGBA_FP16 = HAL_PIXEL_FORMAT_RGBA_FP16, // 64-bit RGBA
PIXEL_FORMAT_RGBA_1010102 = HAL_PIXEL_FORMAT_RGBA_1010102, // 32-bit RGBA
+ PIXEL_FORMAT_R_8 = 0x38,
};
typedef int32_t PixelFormat;
diff --git a/opengl/libs/EGL/GLES_layers.md b/opengl/libs/EGL/GLES_layers.md
index bfc44db..f6a8f14 100644
--- a/opengl/libs/EGL/GLES_layers.md
+++ b/opengl/libs/EGL/GLES_layers.md
@@ -251,7 +251,7 @@
- Secondly, if you want to determine from an application that can't call out to ADB for this, you can check for the [EGL_ANDROID_GLES_layers](../../specs/EGL_ANDROID_GLES_layers.txt). It simply indicates support of this layering system:
```cpp
std::string display_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- if (display_extension.find("EGL_ANDROID_GLES_layers") != std::string::npos)
+ if (display_extensions.find("EGL_ANDROID_GLES_layers") != std::string::npos)
{
// Layers are supported!
}
diff --git a/services/gpuservice/gpumem/GpuMem.cpp b/services/gpuservice/gpumem/GpuMem.cpp
index 3aa862f..dd3cc3b 100644
--- a/services/gpuservice/gpumem/GpuMem.cpp
+++ b/services/gpuservice/gpumem/GpuMem.cpp
@@ -22,7 +22,7 @@
#include <android-base/stringprintf.h>
#include <libbpf.h>
-#include <libbpf_android.h>
+#include <bpf/WaitForProgsLoaded.h>
#include <log/log.h>
#include <unistd.h>
#include <utils/Timers.h>
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index d8636dd..f6bb6a6 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -214,7 +214,7 @@
int32_t edgeFlags, float xPrecision, float yPrecision,
float xCursorPosition, float yCursorPosition, nsecs_t downTime,
uint32_t pointerCount, const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords)
+ const PointerCoords* pointerCoords, float xOffset, float yOffset)
: EventEntry(id, Type::MOTION, eventTime, policyFlags),
deviceId(deviceId),
source(source),
@@ -235,6 +235,9 @@
for (uint32_t i = 0; i < pointerCount; i++) {
this->pointerProperties[i].copyFrom(pointerProperties[i]);
this->pointerCoords[i].copyFrom(pointerCoords[i]);
+ if (xOffset || yOffset) {
+ this->pointerCoords[i].applyOffset(xOffset, yOffset);
+ }
}
}
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 0f79296..477781a 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -184,7 +184,8 @@
int32_t metaState, int32_t buttonState, MotionClassification classification,
int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+ float xOffset, float yOffset);
std::string getDescription() const override;
~MotionEntry() override;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index de4090c..c9397c3 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -378,7 +378,7 @@
motionEntry.yPrecision, motionEntry.xCursorPosition,
motionEntry.yCursorPosition, motionEntry.downTime,
motionEntry.pointerCount, motionEntry.pointerProperties,
- pointerCoords.data());
+ pointerCoords.data(), 0 /* xOffset */, 0 /* yOffset */);
if (motionEntry.injectionState) {
combinedMotionEntry->injectionState = motionEntry.injectionState;
@@ -506,6 +506,12 @@
return true;
}
+vec2 transformWithoutTranslation(const ui::Transform& transform, float x, float y) {
+ const vec2 transformedXy = transform.transform(x, y);
+ const vec2 transformedOrigin = transform.transform(0, 0);
+ return transformedXy - transformedOrigin;
+}
+
// Returns true if the event type passed as argument represents a user activity.
bool isUserActivityEvent(const EventEntry& eventEntry) {
switch (eventEntry.type) {
@@ -3757,7 +3763,7 @@
originalMotionEntry.xCursorPosition,
originalMotionEntry.yCursorPosition,
originalMotionEntry.downTime, splitPointerCount,
- splitPointerProperties, splitPointerCoords);
+ splitPointerProperties, splitPointerCoords, 0, 0);
if (originalMotionEntry.injectionState) {
splitMotionEntry->injectionState = originalMotionEntry.injectionState;
@@ -3983,7 +3989,7 @@
args->xPrecision, args->yPrecision,
args->xCursorPosition, args->yCursorPosition,
args->downTime, args->pointerCount,
- args->pointerProperties, args->pointerCoords);
+ args->pointerProperties, args->pointerCoords, 0, 0);
if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER &&
@@ -4213,8 +4219,10 @@
motionEvent.getRawXCursorPosition(),
motionEvent.getRawYCursorPosition(),
motionEvent.getDownTime(), uint32_t(pointerCount),
- pointerProperties, samplePointerCoords);
- transformMotionEntryForInjectionLocked(*injectedEntry, motionEvent.getTransform());
+ pointerProperties, samplePointerCoords,
+ motionEvent.getXOffset(),
+ motionEvent.getYOffset());
+ transformMotionEntryForInjectionLocked(*injectedEntry);
injectedEntries.push(std::move(injectedEntry));
for (size_t i = motionEvent.getHistorySize(); i > 0; i--) {
sampleEventTimes += 1;
@@ -4233,9 +4241,9 @@
motionEvent.getRawYCursorPosition(),
motionEvent.getDownTime(),
uint32_t(pointerCount), pointerProperties,
- samplePointerCoords);
- transformMotionEntryForInjectionLocked(*nextInjectedEntry,
- motionEvent.getTransform());
+ samplePointerCoords, motionEvent.getXOffset(),
+ motionEvent.getYOffset());
+ transformMotionEntryForInjectionLocked(*nextInjectedEntry);
injectedEntries.push(std::move(nextInjectedEntry));
}
break;
@@ -4399,28 +4407,35 @@
}
}
-void InputDispatcher::transformMotionEntryForInjectionLocked(
- MotionEntry& entry, const ui::Transform& injectedTransform) const {
+void InputDispatcher::transformMotionEntryForInjectionLocked(MotionEntry& entry) const {
+ const bool isRelativeMouseEvent = isFromSource(entry.source, AINPUT_SOURCE_MOUSE_RELATIVE);
+ if (!isRelativeMouseEvent && !isFromSource(entry.source, AINPUT_SOURCE_CLASS_POINTER)) {
+ return;
+ }
+
// Input injection works in the logical display coordinate space, but the input pipeline works
// display space, so we need to transform the injected events accordingly.
const auto it = mDisplayInfos.find(entry.displayId);
if (it == mDisplayInfos.end()) return;
- const auto& transformToDisplay = it->second.transform.inverse() * injectedTransform;
+ const auto& transformToDisplay = it->second.transform.inverse();
for (uint32_t i = 0; i < entry.pointerCount; i++) {
PointerCoords& pc = entry.pointerCoords[i];
- // Make a copy of the injected coords. We cannot change them in place because some of them
- // are interdependent (for example, X coordinate might depend on the Y coordinate).
- PointerCoords injectedCoords = entry.pointerCoords[i];
+ const auto xy = isRelativeMouseEvent
+ ? transformWithoutTranslation(transformToDisplay, pc.getX(), pc.getY())
+ : transformToDisplay.transform(pc.getXYValue());
+ pc.setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
+ pc.setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
- BitSet64 bits(injectedCoords.bits);
- while (!bits.isEmpty()) {
- const auto axis = static_cast<int32_t>(bits.clearFirstMarkedBit());
- const float value =
- MotionEvent::calculateTransformedAxisValue(axis, entry.source,
- transformToDisplay, injectedCoords);
- pc.setAxisValue(axis, value);
- }
+ // Axes with relative values never represent points on a screen, so they should never have
+ // translation applied. If a device does not report relative values, these values are always
+ // 0, and will remain unaffected by the following operation.
+ const auto rel =
+ transformWithoutTranslation(transformToDisplay,
+ pc.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ pc.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
+ pc.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, rel.x);
+ pc.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, rel.y);
}
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 6f05670..8a551cf 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -280,9 +280,7 @@
bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
void setInjectionResult(EventEntry& entry,
android::os::InputEventInjectionResult injectionResult);
- void transformMotionEntryForInjectionLocked(MotionEntry&,
- const ui::Transform& injectedTransform) const
- REQUIRES(mLock);
+ void transformMotionEntryForInjectionLocked(MotionEntry&) const REQUIRES(mLock);
std::condition_variable mInjectionSyncFinished;
void incrementPendingForegroundDispatches(EventEntry& entry);
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index ad3c615..3bb0bc9 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -296,7 +296,8 @@
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
memento.pointerCount, memento.pointerProperties,
- memento.pointerCoords));
+ memento.pointerCoords, 0 /*xOffset*/,
+ 0 /*yOffset*/));
}
}
return events;
@@ -348,7 +349,8 @@
AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
- pointerCount, pointerProperties, pointerCoords));
+ pointerCount, pointerProperties, pointerCoords,
+ 0 /*xOffset*/, 0 /*yOffset*/));
}
memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 8122b4a..39c5262 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -2176,33 +2176,6 @@
secondWindow->assertNoEvents();
}
-// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
-// event should be treated as being in the logical display space.
-TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
- auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
-
- const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
- ui::Transform injectedEventTransform;
- injectedEventTransform.set(matrix);
- const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
- const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
-
- MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .displayId(ADISPLAY_ID_DEFAULT)
- .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
- .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
- .x(untransformedPoint.x)
- .y(untransformedPoint.y))
- .build();
- event.transform(matrix);
-
- injectMotionEvent(mDispatcher, event, INJECT_EVENT_TIMEOUT,
- InputEventInjectionSync::WAIT_FOR_RESULT);
-
- firstWindow->consumeMotionDown();
- secondWindow->assertNoEvents();
-}
-
TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 1be5a96..b596708 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -78,6 +78,11 @@
"libsensorprivacy",
"libpermission",
],
+
+ pgo: {
+ sampling: true,
+ profile_file: "sensorservice/libsensorservice.profdata",
+ },
}
cc_binary {
diff --git a/services/surfaceflinger/BackgroundExecutor.cpp b/services/surfaceflinger/BackgroundExecutor.cpp
index 3663cdb..de8e6b3 100644
--- a/services/surfaceflinger/BackgroundExecutor.cpp
+++ b/services/surfaceflinger/BackgroundExecutor.cpp
@@ -32,7 +32,9 @@
std::vector<std::function<void()>> tasks;
{
std::unique_lock lock(mMutex);
- mWorkAvailableCv.wait(lock, [&]() { return mDone || !mTasks.empty(); });
+ android::base::ScopedLockAssertion assumeLock(mMutex);
+ mWorkAvailableCv.wait(lock,
+ [&]() REQUIRES(mMutex) { return mDone || !mTasks.empty(); });
tasks = std::move(mTasks);
mTasks.clear();
done = mDone;
@@ -47,7 +49,7 @@
BackgroundExecutor::~BackgroundExecutor() {
{
- std::unique_lock lock(mMutex);
+ std::scoped_lock lock(mMutex);
mDone = true;
mWorkAvailableCv.notify_all();
}
@@ -57,7 +59,7 @@
}
void BackgroundExecutor::execute(std::function<void()> task) {
- std::unique_lock lock(mMutex);
+ std::scoped_lock lock(mMutex);
mTasks.emplace_back(std::move(task));
mWorkAvailableCv.notify_all();
}
diff --git a/services/surfaceflinger/BackgroundExecutor.h b/services/surfaceflinger/BackgroundExecutor.h
index 6f6d305..6db7dda 100644
--- a/services/surfaceflinger/BackgroundExecutor.h
+++ b/services/surfaceflinger/BackgroundExecutor.h
@@ -16,6 +16,7 @@
#pragma once
+#include <android-base/thread_annotations.h>
#include <utils/Singleton.h>
#include <condition_variable>
#include <mutex>
@@ -33,10 +34,10 @@
private:
std::mutex mMutex;
- std::condition_variable mWorkAvailableCv;
+ std::condition_variable mWorkAvailableCv GUARDED_BY(mMutex);
+ bool mDone GUARDED_BY(mMutex) = false;
+ std::vector<std::function<void()>> mTasks GUARDED_BY(mMutex);
std::thread mThread;
- bool mDone = false;
- std::vector<std::function<void()>> mTasks;
};
} // namespace android
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 494b61c..64ddd68 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -564,15 +564,16 @@
// hardware.h, instead of using hard-coded values here.
#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-bool BufferLayer::getOpacityForFormat(uint32_t format) {
+bool BufferLayer::getOpacityForFormat(PixelFormat format) {
if (HARDWARE_IS_DEVICE_FORMAT(format)) {
return true;
}
switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case PIXEL_FORMAT_RGBA_8888:
+ case PIXEL_FORMAT_BGRA_8888:
+ case PIXEL_FORMAT_RGBA_FP16:
+ case PIXEL_FORMAT_RGBA_1010102:
+ case PIXEL_FORMAT_R_8:
return false;
}
// in all other case, we have no blending (also for unknown formats)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index a4c21f4..34d11ac 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -153,7 +153,7 @@
bool onPreComposition(nsecs_t) override;
void preparePerFrameCompositionState() override;
- static bool getOpacityForFormat(uint32_t format);
+ static bool getOpacityForFormat(PixelFormat format);
// from graphics API
const uint32_t mTextureName;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index a000661..36594ea 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -200,6 +200,9 @@
// The output-independent frame for the cursor
Rect cursorFrame;
+ // framerate of the layer as measured by LayerHistory
+ float fps;
+
virtual ~LayerFECompositionState();
// Debugging
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index 244f8ab..c15249d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -73,8 +73,9 @@
void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&,
bool skipLayer);
void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*);
- void writeOutputIndependentPerFrameStateToHWC(HWC2::Layer*, const LayerFECompositionState&,
- bool skipLayer);
+ void writeOutputIndependentPerFrameStateToHWC(
+ HWC2::Layer*, const LayerFECompositionState&,
+ Hwc2::IComposerClient::Composition compositionType, bool skipLayer);
void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&, bool skipLayer);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
index cff6527..92cc484 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
@@ -87,6 +87,13 @@
const bool mEnableHolePunch;
};
+ // Constants not yet backed by a sysprop
+ // CachedSets that contain no more than this many layers may be considered inactive on the basis
+ // of FPS.
+ static constexpr int kNumLayersFpsConsideration = 1;
+ // Frames/Second threshold below which these CachedSets may be considered inactive.
+ static constexpr float kFpsActiveThreshold = 1.f;
+
Flattener(renderengine::RenderEngine& renderEngine, const Tunables& tunables);
void setDisplaySize(ui::Size size) {
@@ -127,21 +134,22 @@
class Builder {
private:
std::vector<CachedSet>::const_iterator mStart;
- std::vector<size_t> mLengths;
+ int32_t mNumSets = 0;
const CachedSet* mHolePunchCandidate = nullptr;
const CachedSet* mBlurringLayer = nullptr;
+ bool mBuilt = false;
public:
// Initializes a Builder a CachedSet to start from.
// This start iterator must be an iterator for mLayers
void init(const std::vector<CachedSet>::const_iterator& start) {
mStart = start;
- mLengths.push_back(start->getLayerCount());
+ mNumSets = 1;
}
// Appends a new CachedSet to the end of the run
// The provided length must be the size of the next sequential CachedSet in layers
- void append(size_t length) { mLengths.push_back(length); }
+ void increment() { mNumSets++; }
// Sets the hole punch candidate for the Run.
void setHolePunchCandidate(const CachedSet* holePunchCandidate) {
@@ -154,19 +162,36 @@
// Builds a Run instance, if a valid Run may be built.
std::optional<Run> validateAndBuild() {
- if (mLengths.size() == 0) {
- return std::nullopt;
- }
- // Runs of length 1 which are hole punch candidates are allowed if the candidate is
- // going to be used.
- if (mLengths.size() == 1 &&
- (!mHolePunchCandidate || !(mHolePunchCandidate->requiresHolePunch()))) {
+ const bool built = mBuilt;
+ mBuilt = true;
+ if (mNumSets <= 0 || built) {
return std::nullopt;
}
+ const bool requiresHolePunch =
+ mHolePunchCandidate && mHolePunchCandidate->requiresHolePunch();
+
+ if (!requiresHolePunch) {
+ // If we don't require a hole punch, then treat solid color layers at the front
+ // to be "cheap", so remove them from the candidate cached set.
+ while (mNumSets > 1 && mStart->getLayerCount() == 1 &&
+ mStart->getFirstLayer().getBuffer() == nullptr) {
+ mStart++;
+ mNumSets--;
+ }
+
+ // Only allow for single cached sets if a hole punch is required. If we're here,
+ // then we don't require a hole punch, so don't build a run.
+ if (mNumSets <= 1) {
+ return std::nullopt;
+ }
+ }
+
return Run(mStart,
- std::reduce(mLengths.cbegin(), mLengths.cend(), 0u,
- [](size_t left, size_t right) { return left + right; }),
+ std::reduce(mStart, mStart + mNumSets, 0u,
+ [](size_t length, const CachedSet& set) {
+ return length + set.getLayerCount();
+ }),
mHolePunchCandidate, mBlurringLayer);
}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index 5237527..7397c19 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -245,6 +245,7 @@
bool isProtected() const {
return getOutputLayer()->getLayerFE().getCompositionState()->hasProtectedContent;
}
+ float getFps() const { return getOutputLayer()->getLayerFE().getCompositionState()->fps; }
void dump(std::string& result) const;
std::optional<std::string> compare(const LayerState& other) const;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index e958549..cf76183 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -347,6 +347,10 @@
auto requestedCompositionType = outputIndependentState->compositionType;
+ if (requestedCompositionType == hal::Composition::SOLID_COLOR && state.overrideInfo.buffer) {
+ requestedCompositionType = hal::Composition::DEVICE;
+ }
+
// TODO(b/181172795): We now update geometry for all flattened layers. We should update it
// only when the geometry actually changes
const bool isOverridden =
@@ -359,13 +363,15 @@
}
writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
- writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState, skipLayer);
+ writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState,
+ requestedCompositionType, skipLayer);
writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
skipLayer);
- // Always set the layer color after setting the composition type.
- writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
+ if (requestedCompositionType == hal::Composition::SOLID_COLOR) {
+ writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
+ }
editState().hwc->stateOverridden = isOverridden;
editState().hwc->layerSkipped = skipLayer;
@@ -477,7 +483,7 @@
void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
- bool skipLayer) {
+ hal::Composition compositionType, bool skipLayer) {
switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
case hal::Error::NONE:
break;
@@ -501,7 +507,7 @@
}
// Content-specific per-frame state
- switch (outputIndependentState.compositionType) {
+ switch (compositionType) {
case hal::Composition::SOLID_COLOR:
// For compatibility, should be written AFTER the composition type.
break;
@@ -521,10 +527,6 @@
void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
const LayerFECompositionState& outputIndependentState) {
- if (outputIndependentState.compositionType != hal::Composition::SOLID_COLOR) {
- return;
- }
-
hal::Color color = {static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.r)),
static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.g)),
static_cast<uint8_t>(std::round(255.0f * outputIndependentState.color.b)),
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index ec52e59..ff96d94 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -25,6 +25,7 @@
#include <math/HashCombine.h>
#include <renderengine/DisplaySettings.h>
#include <renderengine/RenderEngine.h>
+#include <ui/DebugUtils.h>
#include <utils/Trace.h>
#include <utils/Trace.h>
@@ -391,20 +392,29 @@
if (mLayers.size() == 1) {
base::StringAppendF(&result, " Layer [%s]\n", mLayers[0].getName().c_str());
- base::StringAppendF(&result, " Buffer %p", mLayers[0].getBuffer().get());
- base::StringAppendF(&result, " Protected [%s]",
+ if (auto* buffer = mLayers[0].getBuffer().get()) {
+ base::StringAppendF(&result, " Buffer %p", buffer);
+ base::StringAppendF(&result, " Format %s",
+ decodePixelFormat(buffer->getPixelFormat()).c_str());
+ }
+ base::StringAppendF(&result, " Protected [%s]\n",
mLayers[0].getState()->isProtected() ? "true" : "false");
} else {
- result.append(" Cached set of:");
+ result.append(" Cached set of:\n");
for (const Layer& layer : mLayers) {
- base::StringAppendF(&result, "\n Layer [%s]", layer.getName().c_str());
- base::StringAppendF(&result, "\n Protected [%s]",
+ base::StringAppendF(&result, " Layer [%s]\n", layer.getName().c_str());
+ if (auto* buffer = layer.getBuffer().get()) {
+ base::StringAppendF(&result, " Buffer %p", buffer);
+ base::StringAppendF(&result, " Format[%s]",
+ decodePixelFormat(buffer->getPixelFormat()).c_str());
+ }
+ base::StringAppendF(&result, " Protected [%s]\n",
layer.getState()->isProtected() ? "true" : "false");
}
}
- base::StringAppendF(&result, "\n Creation cost: %zd", getCreationCost());
- base::StringAppendF(&result, "\n Display cost: %zd\n", getDisplayCost());
+ base::StringAppendF(&result, " Creation cost: %zd\n", getCreationCost());
+ base::StringAppendF(&result, " Display cost: %zd\n", getDisplayCost());
}
} // namespace android::compositionengine::impl::planner
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 2272099..c14effc 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -409,25 +409,29 @@
bool runHasFirstLayer = false;
for (auto currentSet = mLayers.cbegin(); currentSet != mLayers.cend(); ++currentSet) {
- const bool layerIsInactive =
- now - currentSet->getLastUpdate() > mTunables.mActiveLayerTimeout;
+ bool layerIsInactive = now - currentSet->getLastUpdate() > mTunables.mActiveLayerTimeout;
const bool layerHasBlur = currentSet->hasBlurBehind();
+ // Layers should also be considered inactive whenever their framerate is lower than 1fps.
+ if (!layerIsInactive && currentSet->getLayerCount() == kNumLayersFpsConsideration) {
+ auto layerFps = currentSet->getFirstLayer().getState()->getFps();
+ if (layerFps > 0 && layerFps <= kFpsActiveThreshold) {
+ ATRACE_FORMAT("layer is considered inactive due to low FPS [%s] %f",
+ currentSet->getFirstLayer().getName().c_str(), layerFps);
+ layerIsInactive = true;
+ }
+ }
+
if (layerIsInactive && (firstLayer || runHasFirstLayer || !layerHasBlur) &&
!currentSet->hasUnsupportedDataspace()) {
if (isPartOfRun) {
- builder.append(currentSet->getLayerCount());
+ builder.increment();
} else {
- // Runs can't start with a non-buffer layer
- if (currentSet->getFirstLayer().getBuffer() == nullptr) {
- ALOGV("[%s] Skipping initial non-buffer layer", __func__);
- } else {
- builder.init(currentSet);
- if (firstLayer) {
- runHasFirstLayer = true;
- }
- isPartOfRun = true;
+ builder.init(currentSet);
+ if (firstLayer) {
+ runHasFirstLayer = true;
}
+ isPartOfRun = true;
}
} else if (isPartOfRun) {
builder.setHolePunchCandidate(&(*currentSet));
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index fbc2089..31b131a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -1109,6 +1109,22 @@
/*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}
+TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoForSolidColorIfPresent) {
+ mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
+ includeOverrideInfo();
+
+ expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform,
+ kOverrideBlendMode, kOverrideAlpha);
+ expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion,
+ kOverrideSurfaceDamage);
+ expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
+ expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
+ EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));
+
+ mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
+ /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
+}
+
TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) {
mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
mOutputLayer.editState().hwc->stateOverridden = true;
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 9b0a75f..35d051e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -224,6 +224,22 @@
mFlattener->renderCachedSets(mOutputState, std::nullopt);
}
+TEST_F(FlattenerTest, flattenLayers_ActiveLayersWithLowFpsAreFlattened) {
+ mTestLayers[0]->layerFECompositionState.fps = Flattener::kFpsActiveThreshold / 2;
+ mTestLayers[1]->layerFECompositionState.fps = Flattener::kFpsActiveThreshold;
+
+ auto& layerState1 = mTestLayers[0]->layerState;
+ auto& layerState2 = mTestLayers[1]->layerState;
+
+ const std::vector<const LayerState*> layers = {
+ layerState1.get(),
+ layerState2.get(),
+ };
+
+ initializeFlattener(layers);
+ expectAllLayersFlattened(layers);
+}
+
TEST_F(FlattenerTest, flattenLayers_basicFlatten) {
auto& layerState1 = mTestLayers[0]->layerState;
auto& layerState2 = mTestLayers[1]->layerState;
@@ -746,6 +762,76 @@
EXPECT_EQ(nullptr, peekThroughLayer1);
}
+TEST_F(FlattenerTest, flattenLayers_holePunchSingleColorLayer) {
+ mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
+ mTestLayers[0]->layerFECompositionState.color = half4(255.f, 0.f, 0.f, 255.f);
+ mTestLayers[0]->layerFECompositionState.buffer = nullptr;
+
+ // An opaque static background
+ auto& layerState0 = mTestLayers[0]->layerState;
+ const auto& overrideBuffer0 = layerState0->getOutputLayer()->getState().overrideInfo.buffer;
+
+ // a rounded updating layer
+ auto& layerState1 = mTestLayers[1]->layerState;
+ const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+
+ EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
+
+ std::vector<LayerFE::LayerSettings> clientCompositionList = {
+ LayerFE::LayerSettings{},
+ };
+ clientCompositionList[0].source.buffer.buffer = std::make_shared<
+ renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
+ mRenderEngine,
+ renderengine::ExternalTexture::Usage::READABLE);
+ EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_))
+ .WillOnce(Return(clientCompositionList));
+
+ const std::vector<const LayerState*> layers = {
+ layerState0.get(),
+ layerState1.get(),
+ };
+
+ initializeFlattener(layers);
+
+ // layer 1 satisfies every condition in CachedSet::requiresHolePunch()
+ mTime += 200ms;
+ layerState1->resetFramesSinceBufferUpdate(); // it is updating
+
+ initializeOverrideBuffer(layers);
+ // Expect no cache invalidation the first time (there's no cache yet)
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+
+ // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the
+ // exception that there would be a hole punch above it.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
+ .WillOnce(Return(ByMove(
+ futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ // We've rendered a CachedSet, but we haven't merged it in.
+ EXPECT_EQ(nullptr, overrideBuffer0);
+
+ // This time we merge the CachedSet in and we should still have only two sets.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
+ initializeOverrideBuffer(layers);
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ EXPECT_NE(nullptr, overrideBuffer0); // got overridden
+ EXPECT_EQ(nullptr, overrideBuffer1); // did not
+
+ // expect 0's peek though layer to be 1's output layer
+ const auto* peekThroughLayer0 =
+ layerState0->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
+ const auto* peekThroughLayer1 =
+ layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
+ EXPECT_EQ(&mTestLayers[1]->outputLayer, peekThroughLayer0);
+ EXPECT_EQ(nullptr, peekThroughLayer1);
+}
+
TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) {
auto& layerState1 = mTestLayers[0]->layerState;
@@ -1191,5 +1277,61 @@
EXPECT_EQ(nullptr, overrideBuffer3);
}
+TEST_F(FlattenerTest, flattenLayers_skipsColorLayers) {
+ auto& layerState1 = mTestLayers[0]->layerState;
+ const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+ auto& layerState2 = mTestLayers[1]->layerState;
+ const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
+ auto& layerState3 = mTestLayers[2]->layerState;
+ const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
+ auto& layerState4 = mTestLayers[3]->layerState;
+ const auto& overrideBuffer4 = layerState4->getOutputLayer()->getState().overrideInfo.buffer;
+
+ // Rewrite the first two layers to just be a solid color.
+ mTestLayers[0]->layerFECompositionState.color = half4(255.f, 0.f, 0.f, 255.f);
+ mTestLayers[0]->layerFECompositionState.buffer = nullptr;
+ mTestLayers[1]->layerFECompositionState.color = half4(0.f, 255.f, 0.f, 255.f);
+ mTestLayers[1]->layerFECompositionState.buffer = nullptr;
+
+ const std::vector<const LayerState*> layers = {
+ layerState1.get(),
+ layerState2.get(),
+ layerState3.get(),
+ layerState4.get(),
+ };
+
+ initializeFlattener(layers);
+
+ mTime += 200ms;
+ initializeOverrideBuffer(layers);
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+
+ // This will render a CachedSet.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
+ .WillOnce(Return(ByMove(
+ futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ // We've rendered a CachedSet, but we haven't merged it in.
+ EXPECT_EQ(nullptr, overrideBuffer1);
+ EXPECT_EQ(nullptr, overrideBuffer2);
+ EXPECT_EQ(nullptr, overrideBuffer3);
+ EXPECT_EQ(nullptr, overrideBuffer4);
+
+ // This time we merge the CachedSet in, so we have a new hash, and we should
+ // only have two sets.
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
+ initializeOverrideBuffer(layers);
+ EXPECT_NE(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mOutputState, std::nullopt);
+
+ EXPECT_EQ(nullptr, overrideBuffer1);
+ EXPECT_EQ(nullptr, overrideBuffer2);
+ EXPECT_EQ(overrideBuffer3, overrideBuffer4);
+ EXPECT_NE(nullptr, overrideBuffer4);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index ba57be5..200bb65 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -41,6 +41,8 @@
using aidl::android::hardware::graphics::composer3::PowerMode;
using aidl::android::hardware::graphics::composer3::VirtualDisplay;
+using aidl::android::hardware::graphics::composer3::command::CommandResultPayload;
+
using AidlColorMode = aidl::android::hardware::graphics::composer3::ColorMode;
using AidlContentType = aidl::android::hardware::graphics::composer3::ContentType;
using AidlDisplayIdentification =
@@ -48,8 +50,6 @@
using AidlDisplayContentSample = aidl::android::hardware::graphics::composer3::DisplayContentSample;
using AidlDisplayAttribute = aidl::android::hardware::graphics::composer3::DisplayAttribute;
using AidlDisplayCapability = aidl::android::hardware::graphics::composer3::DisplayCapability;
-using AidlExecuteCommandsStatus =
- aidl::android::hardware::graphics::composer3::ExecuteCommandsStatus;
using AidlHdrCapabilities = aidl::android::hardware::graphics::composer3::HdrCapabilities;
using AidlPerFrameMetadata = aidl::android::hardware::graphics::composer3::PerFrameMetadata;
using AidlPerFrameMetadataKey = aidl::android::hardware::graphics::composer3::PerFrameMetadataKey;
@@ -174,6 +174,14 @@
};
}
+template <>
+IComposerClient::ClientTargetProperty translate(ClientTargetProperty x) {
+ return IComposerClient::ClientTargetProperty{
+ .pixelFormat = translate<PixelFormat>(x.pixelFormat),
+ .dataspace = translate<Dataspace>(x.dataspace),
+ };
+}
+
mat4 makeMat4(std::vector<float> in) {
return mat4(static_cast<const float*>(in.data()));
}
@@ -226,7 +234,7 @@
return AServiceManager_isDeclared(instance(serviceName).c_str());
}
-AidlComposer::AidlComposer(const std::string& serviceName) : mWriter(kWriterInitialSize) {
+AidlComposer::AidlComposer(const std::string& serviceName) {
// This only waits if the service is actually declared
mAidlComposer = AidlIComposer::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService(instance(serviceName).c_str())));
@@ -327,8 +335,7 @@
}
Error AidlComposer::acceptDisplayChanges(Display display) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.acceptDisplayChanges();
+ mWriter.acceptDisplayChanges(translate<int64_t>(display));
return Error::NONE;
}
@@ -369,7 +376,12 @@
Error AidlComposer::getChangedCompositionTypes(
Display display, std::vector<Layer>* outLayers,
std::vector<IComposerClient::Composition>* outTypes) {
- mReader.takeChangedCompositionTypes(display, outLayers, outTypes);
+ std::vector<int64_t> layers;
+ std::vector<Composition> types;
+ mReader.takeChangedCompositionTypes(translate<int64_t>(display), &layers, &types);
+
+ *outLayers = translate<Layer>(layers);
+ *outTypes = translate<IComposerClient::Composition>(types);
return Error::NONE;
}
@@ -422,7 +434,10 @@
Error AidlComposer::getDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
std::vector<Layer>* outLayers,
std::vector<uint32_t>* outLayerRequestMasks) {
- mReader.takeDisplayRequests(display, outDisplayRequestMask, outLayers, outLayerRequestMasks);
+ std::vector<int64_t> layers;
+ mReader.takeDisplayRequests(translate<int64_t>(display), outDisplayRequestMask, &layers,
+ outLayerRequestMasks);
+ *outLayers = translate<Layer>(layers);
return Error::NONE;
}
@@ -456,21 +471,22 @@
Error AidlComposer::getReleaseFences(Display display, std::vector<Layer>* outLayers,
std::vector<int>* outReleaseFences) {
- mReader.takeReleaseFences(display, outLayers, outReleaseFences);
+ std::vector<int64_t> layers;
+ mReader.takeReleaseFences(translate<int64_t>(display), &layers, outReleaseFences);
+ *outLayers = translate<Layer>(layers);
return Error::NONE;
}
Error AidlComposer::presentDisplay(Display display, int* outPresentFence) {
ATRACE_NAME("HwcPresentDisplay");
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.presentDisplay();
+ mWriter.presentDisplay(translate<int64_t>(display));
Error error = execute();
if (error != Error::NONE) {
return error;
}
- mReader.takePresentFence(display, outPresentFence);
+ mReader.takePresentFence(translate<int64_t>(display), outPresentFence);
return Error::NONE;
}
@@ -488,14 +504,12 @@
Error AidlComposer::setClientTarget(Display display, uint32_t slot, const sp<GraphicBuffer>& target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage) {
- mWriter.selectDisplay(translate<int64_t>(display));
-
const native_handle_t* handle = nullptr;
if (target.get()) {
handle = target->getNativeBuffer()->handle;
}
- mWriter.setClientTarget(slot, handle, acquireFence,
+ mWriter.setClientTarget(translate<int64_t>(display), slot, handle, acquireFence,
translate<aidl::android::hardware::graphics::common::Dataspace>(
dataspace),
translate<AidlRect>(damage));
@@ -515,15 +529,14 @@
}
Error AidlComposer::setColorTransform(Display display, const float* matrix, ColorTransform hint) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.setColorTransform(matrix, translate<AidlColorTransform>(hint));
+ mWriter.setColorTransform(translate<int64_t>(display), matrix,
+ translate<AidlColorTransform>(hint));
return Error::NONE;
}
Error AidlComposer::setOutputBuffer(Display display, const native_handle_t* buffer,
int releaseFence) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.setOutputBuffer(0, buffer, dup(releaseFence));
+ mWriter.setOutputBuffer(translate<int64_t>(display), 0, buffer, dup(releaseFence));
return Error::NONE;
}
@@ -562,15 +575,14 @@
Error AidlComposer::validateDisplay(Display display, uint32_t* outNumTypes,
uint32_t* outNumRequests) {
ATRACE_NAME("HwcValidateDisplay");
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.validateDisplay();
+ mWriter.validateDisplay(translate<int64_t>(display));
Error error = execute();
if (error != Error::NONE) {
return error;
}
- mReader.hasChanges(display, outNumTypes, outNumRequests);
+ mReader.hasChanges(translate<int64_t>(display), outNumTypes, outNumRequests);
return Error::NONE;
}
@@ -579,207 +591,154 @@
uint32_t* outNumRequests, int* outPresentFence,
uint32_t* state) {
ATRACE_NAME("HwcPresentOrValidateDisplay");
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.presentOrvalidateDisplay();
+ mWriter.presentOrvalidateDisplay(translate<int64_t>(display));
Error error = execute();
if (error != Error::NONE) {
return error;
}
- mReader.takePresentOrValidateStage(display, state);
+ mReader.takePresentOrValidateStage(translate<int64_t>(display), state);
if (*state == 1) { // Present succeeded
- mReader.takePresentFence(display, outPresentFence);
+ mReader.takePresentFence(translate<int64_t>(display), outPresentFence);
}
if (*state == 0) { // Validate succeeded.
- mReader.hasChanges(display, outNumTypes, outNumRequests);
+ mReader.hasChanges(translate<int64_t>(display), outNumTypes, outNumRequests);
}
return Error::NONE;
}
Error AidlComposer::setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerCursorPosition(x, y);
+ mWriter.setLayerCursorPosition(translate<int64_t>(display), translate<int64_t>(layer), x, y);
return Error::NONE;
}
Error AidlComposer::setLayerBuffer(Display display, Layer layer, uint32_t slot,
const sp<GraphicBuffer>& buffer, int acquireFence) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
-
const native_handle_t* handle = nullptr;
if (buffer.get()) {
handle = buffer->getNativeBuffer()->handle;
}
- mWriter.setLayerBuffer(slot, handle, acquireFence);
+ mWriter.setLayerBuffer(translate<int64_t>(display), translate<int64_t>(layer), slot, handle,
+ acquireFence);
return Error::NONE;
}
Error AidlComposer::setLayerSurfaceDamage(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& damage) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerSurfaceDamage(translate<AidlRect>(damage));
+ mWriter.setLayerSurfaceDamage(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlRect>(damage));
return Error::NONE;
}
Error AidlComposer::setLayerBlendMode(Display display, Layer layer,
IComposerClient::BlendMode mode) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerBlendMode(translate<BlendMode>(mode));
+ mWriter.setLayerBlendMode(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<BlendMode>(mode));
return Error::NONE;
}
Error AidlComposer::setLayerColor(Display display, Layer layer,
const IComposerClient::Color& color) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerColor(translate<Color>(color));
+ mWriter.setLayerColor(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<Color>(color));
return Error::NONE;
}
Error AidlComposer::setLayerCompositionType(Display display, Layer layer,
IComposerClient::Composition type) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerCompositionType(translate<Composition>(type));
+ mWriter.setLayerCompositionType(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<Composition>(type));
return Error::NONE;
}
Error AidlComposer::setLayerDataspace(Display display, Layer layer, Dataspace dataspace) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerDataspace(translate<AidlDataspace>(dataspace));
+ mWriter.setLayerDataspace(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlDataspace>(dataspace));
return Error::NONE;
}
Error AidlComposer::setLayerDisplayFrame(Display display, Layer layer,
const IComposerClient::Rect& frame) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerDisplayFrame(translate<AidlRect>(frame));
+ mWriter.setLayerDisplayFrame(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlRect>(frame));
return Error::NONE;
}
Error AidlComposer::setLayerPlaneAlpha(Display display, Layer layer, float alpha) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerPlaneAlpha(alpha);
+ mWriter.setLayerPlaneAlpha(translate<int64_t>(display), translate<int64_t>(layer), alpha);
return Error::NONE;
}
Error AidlComposer::setLayerSidebandStream(Display display, Layer layer,
const native_handle_t* stream) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerSidebandStream(stream);
+ mWriter.setLayerSidebandStream(translate<int64_t>(display), translate<int64_t>(layer), stream);
return Error::NONE;
}
Error AidlComposer::setLayerSourceCrop(Display display, Layer layer,
const IComposerClient::FRect& crop) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerSourceCrop(translate<AidlFRect>(crop));
+ mWriter.setLayerSourceCrop(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlFRect>(crop));
return Error::NONE;
}
Error AidlComposer::setLayerTransform(Display display, Layer layer, Transform transform) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerTransform(translate<AidlTransform>(transform));
+ mWriter.setLayerTransform(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlTransform>(transform));
return Error::NONE;
}
Error AidlComposer::setLayerVisibleRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& visible) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerVisibleRegion(translate<AidlRect>(visible));
+ mWriter.setLayerVisibleRegion(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlRect>(visible));
return Error::NONE;
}
Error AidlComposer::setLayerZOrder(Display display, Layer layer, uint32_t z) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerZOrder(z);
+ mWriter.setLayerZOrder(translate<int64_t>(display), translate<int64_t>(layer), z);
return Error::NONE;
}
Error AidlComposer::execute() {
- // prepare input command queue
- bool queueChanged = false;
- int32_t commandLength = 0;
- std::vector<aidl::android::hardware::common::NativeHandle> commandHandles;
- if (!mWriter.writeQueue(&queueChanged, &commandLength, &commandHandles)) {
- mWriter.reset();
- return Error::NO_RESOURCES;
- }
-
- // set up new input command queue if necessary
- if (queueChanged) {
- const auto status = mAidlComposerClient->setInputCommandQueue(mWriter.getMQDescriptor());
- if (!status.isOk()) {
- ALOGE("setInputCommandQueue failed %s", status.getDescription().c_str());
- mWriter.reset();
- return static_cast<Error>(status.getServiceSpecificError());
- }
- }
-
- if (commandLength == 0) {
+ const auto& commands = mWriter.getPendingCommands();
+ if (commands.empty()) {
mWriter.reset();
return Error::NONE;
}
- AidlExecuteCommandsStatus commandStatus;
- auto status =
- mAidlComposerClient->executeCommands(commandLength, commandHandles, &commandStatus);
- // executeCommands can fail because of out-of-fd and we do not want to
- // abort() in that case
+ std::vector<CommandResultPayload> results;
+ auto status = mAidlComposerClient->executeCommands(commands, &results);
if (!status.isOk()) {
ALOGE("executeCommands failed %s", status.getDescription().c_str());
return static_cast<Error>(status.getServiceSpecificError());
}
- // set up new output command queue if necessary
- if (commandStatus.queueChanged) {
- ::aidl::android::hardware::common::fmq::MQDescriptor<
- int32_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
- outputCommandQueue;
- status = mAidlComposerClient->getOutputCommandQueue(&outputCommandQueue);
- if (!status.isOk()) {
- ALOGE("getOutputCommandQueue failed %s", status.getDescription().c_str());
- return static_cast<Error>(status.getServiceSpecificError());
+ mReader.parse(results);
+ const auto commandErrors = mReader.takeErrors();
+ Error error = Error::NONE;
+ for (const auto& cmdErr : commandErrors) {
+ const auto index = static_cast<size_t>(cmdErr.commandIndex);
+ if (index < 0 || index >= commands.size()) {
+ ALOGE("invalid command index %zu", index);
+ return Error::BAD_PARAMETER;
}
- mReader.setMQDescriptor(outputCommandQueue);
- }
-
- Error error;
- if (mReader.readQueue(commandStatus.length, std::move(commandStatus.handles))) {
- error = static_cast<Error>(mReader.parse());
- mReader.reset();
- } else {
- error = Error::NO_RESOURCES;
- }
-
- if (error == Error::NONE) {
- std::vector<AidlCommandReader::CommandError> commandErrors = mReader.takeErrors();
-
- for (const auto& cmdErr : commandErrors) {
- auto command = mWriter.getCommand(cmdErr.location);
- if (command == Command::VALIDATE_DISPLAY || command == Command::PRESENT_DISPLAY ||
- command == Command::PRESENT_OR_VALIDATE_DISPLAY) {
- error = cmdErr.error;
+ const auto& command = commands[index];
+ if (command.getTag() == command::CommandPayload::Tag::displayCommand) {
+ const auto& displayCommand =
+ command.get<command::CommandPayload::Tag::displayCommand>();
+ if (displayCommand.validateDisplay || displayCommand.presentDisplay ||
+ displayCommand.presentOrValidateDisplay) {
+ error = translate<Error>(cmdErr.errorCode);
} else {
- ALOGW("command 0x%x generated error %d", command, cmdErr.error);
+ ALOGW("command '%s' generated error %" PRId32, command.toString().c_str(),
+ cmdErr.errorCode);
}
}
}
@@ -792,9 +751,8 @@
Error AidlComposer::setLayerPerFrameMetadata(
Display display, Layer layer,
const std::vector<IComposerClient::PerFrameMetadata>& perFrameMetadatas) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerPerFrameMetadata(translate<AidlPerFrameMetadata>(perFrameMetadatas));
+ mWriter.setLayerPerFrameMetadata(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlPerFrameMetadata>(perFrameMetadatas));
return Error::NONE;
}
@@ -855,9 +813,7 @@
}
Error AidlComposer::setLayerColorTransform(Display display, Layer layer, const float* matrix) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerColorTransform(matrix);
+ mWriter.setLayerColorTransform(translate<int64_t>(display), translate<int64_t>(layer), matrix);
return Error::NONE;
}
@@ -921,9 +877,8 @@
Error AidlComposer::setLayerPerFrameMetadataBlobs(
Display display, Layer layer,
const std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerPerFrameMetadataBlobs(translate<AidlPerFrameMetadataBlob>(metadata));
+ mWriter.setLayerPerFrameMetadataBlobs(translate<int64_t>(display), translate<int64_t>(layer),
+ translate<AidlPerFrameMetadataBlob>(metadata));
return Error::NONE;
}
@@ -1032,9 +987,8 @@
V2_4::Error AidlComposer::setLayerGenericMetadata(Display display, Layer layer,
const std::string& key, bool mandatory,
const std::vector<uint8_t>& value) {
- mWriter.selectDisplay(translate<int64_t>(display));
- mWriter.selectLayer(translate<int64_t>(layer));
- mWriter.setLayerGenericMetadata(key, mandatory, value);
+ mWriter.setLayerGenericMetadata(translate<int64_t>(display), translate<int64_t>(layer), key,
+ mandatory, value);
return V2_4::Error::NONE;
}
@@ -1052,320 +1006,11 @@
Error AidlComposer::getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) {
- mReader.takeClientTargetProperty(display, outClientTargetProperty);
+ ClientTargetProperty property;
+ mReader.takeClientTargetProperty(translate<int64_t>(display), &property);
+ *outClientTargetProperty = translate<IComposerClient::ClientTargetProperty>(property);
return Error::NONE;
}
-AidlCommandReader::~AidlCommandReader() {
- resetData();
-}
-
-int AidlCommandReader::parse() {
- resetData();
-
- Command command;
- uint16_t length = 0;
-
- while (!isEmpty()) {
- if (!beginCommand(&command, &length)) {
- break;
- }
-
- bool parsed = false;
- switch (command) {
- case Command::SELECT_DISPLAY:
- parsed = parseSelectDisplay(length);
- break;
- case Command::SET_ERROR:
- parsed = parseSetError(length);
- break;
- case Command::SET_CHANGED_COMPOSITION_TYPES:
- parsed = parseSetChangedCompositionTypes(length);
- break;
- case Command::SET_DISPLAY_REQUESTS:
- parsed = parseSetDisplayRequests(length);
- break;
- case Command::SET_PRESENT_FENCE:
- parsed = parseSetPresentFence(length);
- break;
- case Command::SET_RELEASE_FENCES:
- parsed = parseSetReleaseFences(length);
- break;
- case Command ::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT:
- parsed = parseSetPresentOrValidateDisplayResult(length);
- break;
- case Command::SET_CLIENT_TARGET_PROPERTY:
- parsed = parseSetClientTargetProperty(length);
- break;
- default:
- parsed = false;
- break;
- }
-
- endCommand();
-
- if (!parsed) {
- ALOGE("failed to parse command 0x%x length %" PRIu16, command, length);
- break;
- }
- }
-
- return isEmpty() ? 0 : AidlIComposerClient::EX_NO_RESOURCES;
-}
-
-bool AidlCommandReader::parseSelectDisplay(uint16_t length) {
- if (length != CommandWriterBase::kSelectDisplayLength) {
- return false;
- }
-
- mCurrentReturnData = &mReturnData[read64()];
-
- return true;
-}
-
-bool AidlCommandReader::parseSetError(uint16_t length) {
- if (length != CommandWriterBase::kSetErrorLength) {
- return false;
- }
-
- auto location = read();
- auto error = static_cast<Error>(readSigned());
-
- mErrors.emplace_back(CommandError{location, error});
-
- return true;
-}
-
-bool AidlCommandReader::parseSetChangedCompositionTypes(uint16_t length) {
- // (layer id [64bit], composition type [32bit]) pairs
- static constexpr int kCommandWords = 3;
-
- if (length % kCommandWords != 0 || !mCurrentReturnData) {
- return false;
- }
-
- uint32_t count = length / kCommandWords;
- mCurrentReturnData->changedLayers.reserve(count);
- mCurrentReturnData->compositionTypes.reserve(count);
- while (count > 0) {
- auto layer = read64();
- auto type = static_cast<IComposerClient::Composition>(readSigned());
-
- mCurrentReturnData->changedLayers.push_back(layer);
- mCurrentReturnData->compositionTypes.push_back(type);
-
- count--;
- }
-
- return true;
-}
-
-bool AidlCommandReader::parseSetDisplayRequests(uint16_t length) {
- // display requests [32 bit] followed by
- // (layer id [64bit], layer requests [32bit]) pairs
- static constexpr int kDisplayRequestsWords = 1;
- static constexpr int kCommandWords = 3;
- if (length % kCommandWords != kDisplayRequestsWords || !mCurrentReturnData) {
- return false;
- }
-
- mCurrentReturnData->displayRequests = read();
-
- uint32_t count = (length - kDisplayRequestsWords) / kCommandWords;
- mCurrentReturnData->requestedLayers.reserve(count);
- mCurrentReturnData->requestMasks.reserve(count);
- while (count > 0) {
- auto layer = read64();
- auto layerRequestMask = read();
-
- mCurrentReturnData->requestedLayers.push_back(layer);
- mCurrentReturnData->requestMasks.push_back(layerRequestMask);
-
- count--;
- }
-
- return true;
-}
-
-bool AidlCommandReader::parseSetPresentFence(uint16_t length) {
- if (length != CommandWriterBase::kSetPresentFenceLength || !mCurrentReturnData) {
- return false;
- }
-
- if (mCurrentReturnData->presentFence >= 0) {
- close(mCurrentReturnData->presentFence);
- }
- mCurrentReturnData->presentFence = readFence();
-
- return true;
-}
-
-bool AidlCommandReader::parseSetReleaseFences(uint16_t length) {
- // (layer id [64bit], release fence index [32bit]) pairs
- static constexpr int kCommandWords = 3;
-
- if (length % kCommandWords != 0 || !mCurrentReturnData) {
- return false;
- }
-
- uint32_t count = length / kCommandWords;
- mCurrentReturnData->releasedLayers.reserve(count);
- mCurrentReturnData->releaseFences.reserve(count);
- while (count > 0) {
- auto layer = read64();
- auto fence = readFence();
-
- mCurrentReturnData->releasedLayers.push_back(layer);
- mCurrentReturnData->releaseFences.push_back(fence);
-
- count--;
- }
-
- return true;
-}
-
-bool AidlCommandReader::parseSetPresentOrValidateDisplayResult(uint16_t length) {
- if (length != CommandWriterBase::kPresentOrValidateDisplayResultLength || !mCurrentReturnData) {
- return false;
- }
- mCurrentReturnData->presentOrValidateState = read();
- return true;
-}
-
-bool AidlCommandReader::parseSetClientTargetProperty(uint16_t length) {
- if (length != CommandWriterBase::kSetClientTargetPropertyLength || !mCurrentReturnData) {
- return false;
- }
- mCurrentReturnData->clientTargetProperty.pixelFormat = static_cast<PixelFormat>(readSigned());
- mCurrentReturnData->clientTargetProperty.dataspace = static_cast<Dataspace>(readSigned());
- return true;
-}
-
-void AidlCommandReader::resetData() {
- mErrors.clear();
-
- for (auto& data : mReturnData) {
- if (data.second.presentFence >= 0) {
- close(data.second.presentFence);
- }
- for (auto fence : data.second.releaseFences) {
- if (fence >= 0) {
- close(fence);
- }
- }
- }
-
- mReturnData.clear();
- mCurrentReturnData = nullptr;
-}
-
-std::vector<AidlCommandReader::CommandError> AidlCommandReader::takeErrors() {
- return std::move(mErrors);
-}
-
-bool AidlCommandReader::hasChanges(Display display, uint32_t* outNumChangedCompositionTypes,
- uint32_t* outNumLayerRequestMasks) const {
- auto found = mReturnData.find(display);
- if (found == mReturnData.end()) {
- *outNumChangedCompositionTypes = 0;
- *outNumLayerRequestMasks = 0;
- return false;
- }
-
- const ReturnData& data = found->second;
-
- *outNumChangedCompositionTypes = static_cast<uint32_t>(data.compositionTypes.size());
- *outNumLayerRequestMasks = static_cast<uint32_t>(data.requestMasks.size());
-
- return !(data.compositionTypes.empty() && data.requestMasks.empty());
-}
-
-void AidlCommandReader::takeChangedCompositionTypes(
- Display display, std::vector<Layer>* outLayers,
- std::vector<IComposerClient::Composition>* outTypes) {
- auto found = mReturnData.find(display);
- if (found == mReturnData.end()) {
- outLayers->clear();
- outTypes->clear();
- return;
- }
-
- ReturnData& data = found->second;
-
- *outLayers = std::move(data.changedLayers);
- *outTypes = std::move(data.compositionTypes);
-}
-
-void AidlCommandReader::takeDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
- std::vector<Layer>* outLayers,
- std::vector<uint32_t>* outLayerRequestMasks) {
- auto found = mReturnData.find(display);
- if (found == mReturnData.end()) {
- *outDisplayRequestMask = 0;
- outLayers->clear();
- outLayerRequestMasks->clear();
- return;
- }
-
- ReturnData& data = found->second;
-
- *outDisplayRequestMask = data.displayRequests;
- *outLayers = std::move(data.requestedLayers);
- *outLayerRequestMasks = std::move(data.requestMasks);
-}
-
-void AidlCommandReader::takeReleaseFences(Display display, std::vector<Layer>* outLayers,
- std::vector<int>* outReleaseFences) {
- auto found = mReturnData.find(display);
- if (found == mReturnData.end()) {
- outLayers->clear();
- outReleaseFences->clear();
- return;
- }
-
- ReturnData& data = found->second;
-
- *outLayers = std::move(data.releasedLayers);
- *outReleaseFences = std::move(data.releaseFences);
-}
-
-void AidlCommandReader::takePresentFence(Display display, int* outPresentFence) {
- auto found = mReturnData.find(display);
- if (found == mReturnData.end()) {
- *outPresentFence = -1;
- return;
- }
-
- ReturnData& data = found->second;
-
- *outPresentFence = data.presentFence;
- data.presentFence = -1;
-}
-
-void AidlCommandReader::takePresentOrValidateStage(Display display, uint32_t* state) {
- auto found = mReturnData.find(display);
- if (found == mReturnData.end()) {
- *state = static_cast<uint32_t>(-1);
- return;
- }
- ReturnData& data = found->second;
- *state = data.presentOrValidateState;
-}
-
-void AidlCommandReader::takeClientTargetProperty(
- Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) {
- auto found = mReturnData.find(display);
-
- // If not found, return the default values.
- if (found == mReturnData.end()) {
- outClientTargetProperty->pixelFormat = PixelFormat::RGBA_8888;
- outClientTargetProperty->dataspace = Dataspace::UNKNOWN;
- return;
- }
-
- ReturnData& data = found->second;
- *outClientTargetProperty = data.clientTargetProperty;
-}
-
} // namespace Hwc2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index a6d9500..418a8cc 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -43,95 +43,10 @@
using AidlCommandWriterBase = aidl::android::hardware::graphics::composer3::CommandWriterBase;
using AidlCommandReaderBase = aidl::android::hardware::graphics::composer3::CommandReaderBase;
+using aidl::android::hardware::graphics::composer3::command::CommandResultPayload;
class AidlIComposerCallbackWrapper;
-class AidlCommandReader : public AidlCommandReaderBase {
-public:
- ~AidlCommandReader();
-
- // Parse and execute commands from the command queue. The commands are
- // actually return values from the server and will be saved in ReturnData.
- int parse();
-
- // Get and clear saved errors.
- struct CommandError {
- uint32_t location;
- Error error;
- };
- std::vector<CommandError> takeErrors();
-
- bool hasChanges(Display display, uint32_t* outNumChangedCompositionTypes,
- uint32_t* outNumLayerRequestMasks) const;
-
- // Get and clear saved changed composition types.
- void takeChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
- std::vector<IComposerClient::Composition>* outTypes);
-
- // Get and clear saved display requests.
- void takeDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
- std::vector<Layer>* outLayers,
- std::vector<uint32_t>* outLayerRequestMasks);
-
- // Get and clear saved release fences.
- void takeReleaseFences(Display display, std::vector<Layer>* outLayers,
- std::vector<int>* outReleaseFences);
-
- // Get and clear saved present fence.
- void takePresentFence(Display display, int* outPresentFence);
-
- // Get what stage succeeded during PresentOrValidate: Present or Validate
- void takePresentOrValidateStage(Display display, uint32_t* state);
-
- // Get the client target properties requested by hardware composer.
- void takeClientTargetProperty(Display display,
- IComposerClient::ClientTargetProperty* outClientTargetProperty);
-
-private:
- void resetData();
-
- bool parseSelectDisplay(uint16_t length);
- bool parseSetError(uint16_t length);
- bool parseSetChangedCompositionTypes(uint16_t length);
- bool parseSetDisplayRequests(uint16_t length);
- bool parseSetPresentFence(uint16_t length);
- bool parseSetReleaseFences(uint16_t length);
- bool parseSetPresentOrValidateDisplayResult(uint16_t length);
- bool parseSetClientTargetProperty(uint16_t length);
-
- struct ReturnData {
- uint32_t displayRequests = 0;
-
- std::vector<Layer> changedLayers;
- std::vector<IComposerClient::Composition> compositionTypes;
-
- std::vector<Layer> requestedLayers;
- std::vector<uint32_t> requestMasks;
-
- int presentFence = -1;
-
- std::vector<Layer> releasedLayers;
- std::vector<int> releaseFences;
-
- uint32_t presentOrValidateState;
-
- // Composer 2.4 implementation can return a client target property
- // structure to indicate the client target properties that hardware
- // composer requests. The composer client must change the client target
- // properties to match this request.
- IComposerClient::ClientTargetProperty clientTargetProperty{PixelFormat::RGBA_8888,
- Dataspace::UNKNOWN};
- };
-
- std::vector<CommandError> mErrors;
- std::unordered_map<Display, ReturnData> mReturnData;
-
- // When SELECT_DISPLAY is parsed, this is updated to point to the
- // display's return data in mReturnData. We use it to avoid repeated
- // map lookups.
- ReturnData* mCurrentReturnData;
-};
-
// Composer is a wrapper to IComposer, a proxy to server-side composer.
class AidlComposer final : public Hwc2::Composer {
public:
@@ -284,13 +199,6 @@
IComposerClient::ClientTargetProperty* outClientTargetProperty) override;
private:
- class AidlCommandWriter : public AidlCommandWriterBase {
- public:
- explicit AidlCommandWriter(uint32_t initialMaxSize)
- : AidlCommandWriterBase(initialMaxSize) {}
- ~AidlCommandWriter() override {}
- };
-
// Many public functions above simply write a command into the command
// queue to batch the calls. validateDisplay and presentDisplay will call
// this function to execute the command queue.
@@ -306,8 +214,8 @@
// 1. Tightly coupling this cache to the max size of BufferQueue
// 2. Adding an additional slot for the layer caching feature in SurfaceFlinger (see: Planner.h)
static const constexpr uint32_t kMaxLayerBufferCount = BufferQueue::NUM_BUFFER_SLOTS + 1;
- AidlCommandWriter mWriter;
- AidlCommandReader mReader;
+ AidlCommandWriterBase mWriter;
+ AidlCommandReaderBase mReader;
// Aidl interface
using AidlIComposer = aidl::android::hardware::graphics::composer3::IComposer;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index dfb99cc..4606746 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -418,6 +418,8 @@
compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
compositionState->alpha = alpha;
+ compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
+ compositionState->blurRegions = drawingState.blurRegions;
compositionState->stretchEffect = getStretchEffect();
}
@@ -482,6 +484,11 @@
// If there are no visible region changes, we still need to update blur parameters.
compositionState->blurRegions = drawingState.blurRegions;
compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
+
+ // Layer framerate is used in caching decisions.
+ // Retrieve it from the scheduler which maintains an instance of LayerHistory, and store it in
+ // LayerFECompositionState where it would be visible to Flattener.
+ compositionState->fps = mFlinger->getLayerFramerate(systemTime(), getSequence());
}
void Layer::prepareCursorCompositionState() {
@@ -932,7 +939,6 @@
setTransactionFlags(eTransactionNeeded);
return true;
}
-
bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix,
bool allowNonRectPreservingTransforms) {
ui::Transform t;
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 712ab16..81c1566 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -203,12 +203,13 @@
return false;
}
- SurfaceComposerClient::Transaction t;
- t.setFrameRate(mSurfaceControl, 0.0f,
- static_cast<int8_t>(Layer::FrameRateCompatibility::NoVote),
- static_cast<int8_t>(scheduler::Seamlessness::OnlySeamless));
- t.setLayer(mSurfaceControl, INT32_MAX - 2);
- t.apply();
+ SurfaceComposerClient::Transaction()
+ .setFrameRate(mSurfaceControl, 0.0f,
+ static_cast<int8_t>(Layer::FrameRateCompatibility::NoVote),
+ static_cast<int8_t>(scheduler::Seamlessness::OnlySeamless))
+ .setLayer(mSurfaceControl, INT32_MAX - 2)
+ .setTrustedOverlay(mSurfaceControl, true)
+ .apply();
return true;
}
diff --git a/services/surfaceflinger/Scheduler/Android.bp b/services/surfaceflinger/Scheduler/Android.bp
index 2318a57..409d098 100644
--- a/services/surfaceflinger/Scheduler/Android.bp
+++ b/services/surfaceflinger/Scheduler/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "libscheduler_defaults",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 84e3548..74a2ca7 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -84,42 +84,38 @@
void LayerHistory::registerLayer(Layer* layer, LayerVoteType type) {
std::lock_guard lock(mLock);
- for (const auto& info : mLayerInfos) {
- LOG_ALWAYS_FATAL_IF(info.first == layer, "%s already registered", layer->getName().c_str());
- }
+ LOG_ALWAYS_FATAL_IF(findLayer(layer->getSequence()).first !=
+ LayerHistory::layerStatus::NotFound,
+ "%s already registered", layer->getName().c_str());
auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type);
- mLayerInfos.emplace_back(layer, std::move(info));
+
+ // The layer can be placed on either map, it is assumed that partitionLayers() will be called
+ // to correct them.
+ mInactiveLayerInfos.insert({layer->getSequence(), std::make_pair(layer, std::move(info))});
}
void LayerHistory::deregisterLayer(Layer* layer) {
std::lock_guard lock(mLock);
-
- const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
- [layer](const auto& pair) { return pair.first == layer; });
- LOG_ALWAYS_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
-
- const size_t i = static_cast<size_t>(it - mLayerInfos.begin());
- if (i < mActiveLayersEnd) {
- mActiveLayersEnd--;
+ if (!mActiveLayerInfos.erase(layer->getSequence())) {
+ if (!mInactiveLayerInfos.erase(layer->getSequence())) {
+ LOG_ALWAYS_FATAL("%s: unknown layer %p", __FUNCTION__, layer);
+ }
}
- const size_t last = mLayerInfos.size() - 1;
- std::swap(mLayerInfos[i], mLayerInfos[last]);
- mLayerInfos.erase(mLayerInfos.begin() + static_cast<long>(last));
}
void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now,
LayerUpdateType updateType) {
std::lock_guard lock(mLock);
+ auto id = layer->getSequence();
- const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
- [layer](const auto& pair) { return pair.first == layer; });
- if (it == mLayerInfos.end()) {
+ auto [found, layerPair] = findLayer(id);
+ if (found == LayerHistory::layerStatus::NotFound) {
// Offscreen layer
ALOGV("LayerHistory::record: %s not registered", layer->getName().c_str());
return;
}
- const auto& info = it->second;
+ const auto& info = layerPair->second;
const auto layerProps = LayerInfo::LayerProps{
.visible = layer->isVisible(),
.bounds = layer->getBounds(),
@@ -131,9 +127,10 @@
info->setLastPresentTime(presentTime, now, updateType, mModeChangePending, layerProps);
// Activate layer if inactive.
- if (const auto end = activeLayers().end(); it >= end) {
- std::iter_swap(it, end);
- mActiveLayersEnd++;
+ if (found == LayerHistory::layerStatus::LayerInInactiveMap) {
+ mActiveLayerInfos.insert(
+ {id, std::make_pair(layerPair->first, std::move(layerPair->second))});
+ mInactiveLayerInfos.erase(id);
}
}
@@ -145,7 +142,8 @@
partitionLayers(now);
- for (const auto& [layer, info] : activeLayers()) {
+ for (const auto& [key, value] : mActiveLayerInfos) {
+ auto& info = value.second;
const auto frameRateSelectionPriority = info->getFrameRateSelectionPriority();
const auto layerFocused = Layer::isLayerFocusedBasedOnPriority(frameRateSelectionPriority);
ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority,
@@ -179,12 +177,29 @@
void LayerHistory::partitionLayers(nsecs_t now) {
const nsecs_t threshold = getActiveLayerThreshold(now);
- // Collect expired and inactive layers after active layers.
- size_t i = 0;
- while (i < mActiveLayersEnd) {
- auto& [layerUnsafe, info] = mLayerInfos[i];
+ // iterate over inactive map
+ LayerInfos::iterator it = mInactiveLayerInfos.begin();
+ while (it != mInactiveLayerInfos.end()) {
+ auto& [layerUnsafe, info] = it->second;
if (isLayerActive(*info, threshold)) {
- i++;
+ // move this to the active map
+
+ mActiveLayerInfos.insert({it->first, std::move(it->second)});
+ it = mInactiveLayerInfos.erase(it);
+ } else {
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
+ }
+ info->onLayerInactive(now);
+ it++;
+ }
+ }
+
+ // iterate over active map
+ it = mActiveLayerInfos.begin();
+ while (it != mActiveLayerInfos.end()) {
+ auto& [layerUnsafe, info] = it->second;
+ if (isLayerActive(*info, threshold)) {
// Set layer vote if set
const auto frameRate = info->getSetFrameRateVote();
const auto voteType = [&]() {
@@ -206,30 +221,68 @@
} else {
info->resetLayerVote();
}
- continue;
- }
- if (CC_UNLIKELY(mTraceEnabled)) {
- trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
+ it++;
+ } else {
+ if (CC_UNLIKELY(mTraceEnabled)) {
+ trace(*info, LayerHistory::LayerVoteType::NoVote, 0);
+ }
+ info->onLayerInactive(now);
+ // move this to the inactive map
+ mInactiveLayerInfos.insert({it->first, std::move(it->second)});
+ it = mActiveLayerInfos.erase(it);
}
-
- info->onLayerInactive(now);
- std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]);
}
}
void LayerHistory::clear() {
std::lock_guard lock(mLock);
-
- for (const auto& [layer, info] : activeLayers()) {
- info->clearHistory(systemTime());
+ for (const auto& [key, value] : mActiveLayerInfos) {
+ value.second->clearHistory(systemTime());
}
}
std::string LayerHistory::dump() const {
std::lock_guard lock(mLock);
- return base::StringPrintf("LayerHistory{size=%zu, active=%zu}", mLayerInfos.size(),
- mActiveLayersEnd);
+ return base::StringPrintf("LayerHistory{size=%zu, active=%zu}",
+ mActiveLayerInfos.size() + mInactiveLayerInfos.size(),
+ mActiveLayerInfos.size());
+}
+
+float LayerHistory::getLayerFramerate(nsecs_t now, int32_t id) const {
+ std::lock_guard lock(mLock);
+ auto [found, layerPair] = findLayer(id);
+ if (found != LayerHistory::layerStatus::NotFound) {
+ return layerPair->second->getFps(now).getValue();
+ }
+ return 0.f;
+}
+
+std::pair<LayerHistory::layerStatus, LayerHistory::LayerPair*> LayerHistory::findLayer(int32_t id) {
+ // the layer could be in either the active or inactive map, try both
+ auto it = mActiveLayerInfos.find(id);
+ if (it != mActiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInActiveMap, &(it->second));
+ }
+ it = mInactiveLayerInfos.find(id);
+ if (it != mInactiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInInactiveMap, &(it->second));
+ }
+ return std::make_pair(LayerHistory::layerStatus::NotFound, nullptr);
+}
+
+std::pair<LayerHistory::layerStatus, const LayerHistory::LayerPair*> LayerHistory::findLayer(
+ int32_t id) const {
+ // the layer could be in either the active or inactive map, try both
+ auto it = mActiveLayerInfos.find(id);
+ if (it != mActiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInActiveMap, &(it->second));
+ }
+ it = mInactiveLayerInfos.find(id);
+ if (it != mInactiveLayerInfos.end()) {
+ return std::make_pair(LayerHistory::layerStatus::LayerInInactiveMap, &(it->second));
+ }
+ return std::make_pair(LayerHistory::layerStatus::NotFound, nullptr);
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 8d56951..cc55700 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -20,6 +20,7 @@
#include <utils/RefBase.h>
#include <utils/Timers.h>
+#include <map>
#include <memory>
#include <mutex>
#include <string>
@@ -72,34 +73,43 @@
void deregisterLayer(Layer*);
std::string dump() const;
+ // return the frames per second of the layer with the given sequence id.
+ float getLayerFramerate(nsecs_t now, int32_t id) const;
+
private:
friend class LayerHistoryTest;
friend class TestableScheduler;
using LayerPair = std::pair<Layer*, std::unique_ptr<LayerInfo>>;
- using LayerInfos = std::vector<LayerPair>;
+ // keyed by id as returned from Layer::getSequence()
+ using LayerInfos = std::unordered_map<int32_t, LayerPair>;
- struct ActiveLayers {
- LayerInfos& infos;
- const size_t index;
+ // Iterates over layers maps moving all active layers to mActiveLayerInfos and all inactive
+ // layers to mInactiveLayerInfos.
+ // worst case time complexity is O(2 * inactive + active)
+ void partitionLayers(nsecs_t now) REQUIRES(mLock);
- auto begin() { return infos.begin(); }
- auto end() { return begin() + static_cast<long>(index); }
+ enum class layerStatus {
+ NotFound,
+ LayerInActiveMap,
+ LayerInInactiveMap,
};
- ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; }
-
- // Iterates over layers in a single pass, swapping pairs such that active layers precede
- // inactive layers, and inactive layers precede expired layers. Removes expired layers by
- // truncating after inactive layers.
- void partitionLayers(nsecs_t now) REQUIRES(mLock);
+ // looks up a layer by sequence id in both layerInfo maps.
+ // The first element indicates if and where the item was found
+ std::pair<layerStatus, LayerHistory::LayerPair*> findLayer(int32_t id) REQUIRES(mLock);
+ std::pair<layerStatus, const LayerHistory::LayerPair*> findLayer(int32_t id) const
+ REQUIRES(mLock);
mutable std::mutex mLock;
- // Partitioned such that active layers precede inactive layers. For fast lookup, the few active
- // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache.
- LayerInfos mLayerInfos GUARDED_BY(mLock);
- size_t mActiveLayersEnd GUARDED_BY(mLock) = 0;
+ // Partitioned into two maps to facility two kinds of retrieval:
+ // 1. retrieval of a layer by id (attempt lookup in both maps)
+ // 2. retrieval of all active layers (iterate that map)
+ // The partitioning is allowed to become out of date but calling partitionLayers refreshes the
+ // validity of each map.
+ LayerInfos mActiveLayerInfos GUARDED_BY(mLock);
+ LayerInfos mInactiveLayerInfos GUARDED_BY(mLock);
uint32_t mDisplayArea = 0;
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index ae61eeb..943615c 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -75,12 +75,16 @@
}
bool LayerInfo::isFrequent(nsecs_t now) const {
+ using fps_approx_ops::operator>=;
// If we know nothing about this layer we consider it as frequent as it might be the start
// of an animation.
if (mFrameTimes.size() < kFrequentLayerWindowSize) {
return true;
}
+ return getFps(now) >= kMinFpsForFrequentLayer;
+}
+Fps LayerInfo::getFps(nsecs_t now) const {
// Find the first active frame
auto it = mFrameTimes.begin();
for (; it != mFrameTimes.end(); ++it) {
@@ -91,14 +95,12 @@
const auto numFrames = std::distance(it, mFrameTimes.end());
if (numFrames < kFrequentLayerWindowSize) {
- return false;
+ return Fps();
}
- using fps_approx_ops::operator>=;
-
// Layer is considered frequent if the average frame rate is higher than the threshold
const auto totalTime = mFrameTimes.back().queueTime - it->queueTime;
- return Fps::fromPeriodNsecs(totalTime / (numFrames - 1)) >= kMinFpsForFrequentLayer;
+ return Fps::fromPeriodNsecs(totalTime / (numFrames - 1));
}
bool LayerInfo::isAnimating(nsecs_t now) const {
@@ -236,7 +238,7 @@
if (!isFrequent(now)) {
ALOGV("%s is infrequent", mName.c_str());
mLastRefreshRate.animatingOrInfrequent = true;
- // Infrequent layers vote for minimal refresh rate for
+ // Infrequent layers vote for mininal refresh rate for
// battery saving purposes and also to prevent b/135718869.
return {LayerHistory::LayerVoteType::Min, Fps()};
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 690abda..2d88a4f 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -178,6 +178,9 @@
// Returns a C string for tracing a vote
const char* getTraceTag(LayerHistory::LayerVoteType type) const;
+ // Return the framerate of this layer.
+ Fps getFps(nsecs_t now) const;
+
void onLayerInactive(nsecs_t now) {
// Mark mFrameTimeValidSince to now to ignore all previous frame times.
// We are not deleting the old frame to keep track of whether we should treat the first
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index e127ff7..818f1ed 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -233,6 +233,11 @@
return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
}
+ // Returns the framerate of the layer with the given sequence ID
+ float getLayerFramerate(nsecs_t now, int32_t id) const {
+ return mLayerHistory.getLayerFramerate(now, id);
+ }
+
private:
friend class TestableScheduler;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 21f3872..b7327b2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -93,6 +93,7 @@
#include <type_traits>
#include <unordered_map>
+#include "BackgroundExecutor.h"
#include "BufferLayer.h"
#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
@@ -3054,28 +3055,45 @@
return;
}
+ std::vector<WindowInfo> windowInfos;
+ std::vector<DisplayInfo> displayInfos;
+ bool updateWindowInfo = false;
if (mVisibleRegionsDirty || mInputInfoChanged) {
mInputInfoChanged = false;
- notifyWindowInfos();
- } else if (mInputWindowCommands.syncInputWindows) {
- // If the caller requested to sync input windows, but there are no
- // changes to input windows, notify immediately.
- windowInfosReported();
+ updateWindowInfo = true;
+ buildWindowInfos(windowInfos, displayInfos);
}
+ if (!updateWindowInfo && mInputWindowCommands.empty()) {
+ return;
+ }
+ BackgroundExecutor::getInstance().execute([updateWindowInfo,
+ windowInfos = std::move(windowInfos),
+ displayInfos = std::move(displayInfos),
+ inputWindowCommands =
+ std::move(mInputWindowCommands),
+ inputFlinger = mInputFlinger, this]() {
+ ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
+ if (updateWindowInfo) {
+ mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
+ inputWindowCommands.syncInputWindows);
+ } else if (inputWindowCommands.syncInputWindows) {
+ // If the caller requested to sync input windows, but there are no
+ // changes to input windows, notify immediately.
+ windowInfosReported();
+ }
+ for (const auto& focusRequest : inputWindowCommands.focusRequests) {
+ inputFlinger->setFocusedWindow(focusRequest);
+ }
+ });
- for (const auto& focusRequest : mInputWindowCommands.focusRequests) {
- mInputFlinger->setFocusedWindow(focusRequest);
- }
mInputWindowCommands.clear();
}
-void SurfaceFlinger::notifyWindowInfos() {
- std::vector<WindowInfo> windowInfos;
- std::vector<DisplayInfo> displayInfos;
+void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
+ std::vector<DisplayInfo>& outDisplayInfos) {
std::unordered_map<uint32_t /*layerStackId*/,
std::pair<bool /* isSecure */, const ui::Transform>>
inputDisplayDetails;
-
for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
if (!display->receivesInput()) {
continue;
@@ -3089,7 +3107,7 @@
layerStackId);
continue;
}
- displayInfos.emplace_back(info);
+ outDisplayInfos.emplace_back(info);
}
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
@@ -3109,10 +3127,8 @@
layer->getDebugName(), layerStackId);
}
- windowInfos.push_back(layer->fillInputInfo(displayTransform, isSecure));
+ outWindowInfos.push_back(layer->fillInputInfo(displayTransform, isSecure));
});
- mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
- mInputWindowCommands.syncInputWindows);
}
void SurfaceFlinger::updateCursorAsync() {
@@ -4952,6 +4968,7 @@
});
LayerProtoHelper::writeTransformToProto(display->getTransform(),
displayProto->mutable_transform());
+ displayProto->set_is_virtual(display->isVirtual());
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9794639..17dfef9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -690,7 +690,8 @@
void updateLayerGeometry();
void updateInputFlinger();
- void notifyWindowInfos();
+ void buildWindowInfos(std::vector<gui::WindowInfo>& outWindowInfos,
+ std::vector<gui::DisplayInfo>& outDisplayInfos);
void commitInputWindowCommands() REQUIRES(mStateLock);
void updateCursorAsync();
@@ -1294,8 +1295,8 @@
const float mInternalDisplayDensity;
const float mEmulatedDisplayDensity;
- sp<os::IInputFlinger> mInputFlinger;
// Should only be accessed by the main thread.
+ sp<os::IInputFlinger> mInputFlinger;
InputWindowCommands mInputWindowCommands;
Hwc2::impl::PowerAdvisor mPowerAdvisor;
@@ -1351,6 +1352,11 @@
const sp<WindowInfosListenerInvoker> mWindowInfosListenerInvoker;
std::unique_ptr<FlagManager> mFlagManager;
+
+ // returns the framerate of the layer with the given sequence ID
+ float getLayerFramerate(nsecs_t now, int32_t id) const {
+ return mScheduler->getLayerFramerate(now, id);
+ }
};
} // namespace android
diff --git a/services/surfaceflinger/layerproto/display.proto b/services/surfaceflinger/layerproto/display.proto
index ee8830e..c8cd926 100644
--- a/services/surfaceflinger/layerproto/display.proto
+++ b/services/surfaceflinger/layerproto/display.proto
@@ -33,4 +33,6 @@
RectProto layer_stack_space_rect = 5;
TransformProto transform = 6;
+
+ bool is_virtual = 7;
}
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 561d9e2..5568418 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -119,6 +119,7 @@
static_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
+ "android.hardware.graphics.common-V3-ndk",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 00687ad..cdb2240 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -63,33 +63,42 @@
const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); }
LayerHistory::Summary summarizeLayerHistory(nsecs_t now) {
- return history().summarize(*mScheduler->refreshRateConfigs(), now);
+ // LayerHistory::summarize makes no guarantee of the order of the elements in the summary
+ // however, for testing only, a stable order is required, therefore we sort the list here.
+ // Any tests requiring ordered results must create layers with names.
+ auto summary = history().summarize(*mScheduler->refreshRateConfigs(), now);
+ std::sort(summary.begin(), summary.end(),
+ [](const RefreshRateConfigs::LayerRequirement& a,
+ const RefreshRateConfigs::LayerRequirement& b) -> bool {
+ return a.name < b.name;
+ });
+ return summary;
}
size_t layerCount() const { return mScheduler->layerHistorySize(); }
- size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; }
+ size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS {
+ return history().mActiveLayerInfos.size();
+ }
auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS {
- const auto& infos = history().mLayerInfos;
- return std::count_if(infos.begin(),
- infos.begin() + static_cast<long>(history().mActiveLayersEnd),
- [now](const auto& pair) { return pair.second->isFrequent(now); });
+ const auto& infos = history().mActiveLayerInfos;
+ return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) {
+ return pair.second.second->isFrequent(now);
+ });
}
auto animatingLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS {
- const auto& infos = history().mLayerInfos;
- return std::count_if(infos.begin(),
- infos.begin() + static_cast<long>(history().mActiveLayersEnd),
- [now](const auto& pair) { return pair.second->isAnimating(now); });
+ const auto& infos = history().mActiveLayerInfos;
+ return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) {
+ return pair.second.second->isAnimating(now);
+ });
}
void setDefaultLayerVote(Layer* layer,
LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS {
- for (auto& [layerUnsafe, info] : history().mLayerInfos) {
- if (layerUnsafe == layer) {
- info->setDefaultLayerVote(vote);
- return;
- }
+ auto [found, layerPair] = history().findLayer(layer->getSequence());
+ if (found != LayerHistory::layerStatus::NotFound) {
+ layerPair->second->setDefaultLayerVote(vote);
}
}
@@ -144,6 +153,8 @@
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+ // history().registerLayer(layer, LayerHistory::LayerVoteType::Max);
+
EXPECT_EQ(1, layerCount());
EXPECT_EQ(0, activeLayerCount());
@@ -368,9 +379,9 @@
}
TEST_F(LayerHistoryTest, multipleLayers) {
- auto layer1 = createLayer();
- auto layer2 = createLayer();
- auto layer3 = createLayer();
+ auto layer1 = createLayer("A");
+ auto layer2 = createLayer("B");
+ auto layer3 = createLayer("C");
EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true));
EXPECT_CALL(*layer1, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
@@ -654,6 +665,29 @@
EXPECT_EQ(1, animatingLayerCount(time));
}
+TEST_F(LayerHistoryTest, getFramerate) {
+ auto layer = createLayer();
+
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+
+ nsecs_t time = systemTime();
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+ EXPECT_EQ(0, frequentLayerCount(time));
+ EXPECT_EQ(0, animatingLayerCount(time));
+
+ // layer is active but infrequent.
+ for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
+ history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
+ time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
+ }
+
+ float expectedFramerate = 1e9f / MAX_FREQUENT_LAYER_PERIOD_NS.count();
+ EXPECT_FLOAT_EQ(expectedFramerate, history().getLayerFramerate(time, layer->getSequence()));
+}
+
TEST_F(LayerHistoryTest, heuristicLayer60Hz) {
const auto layer = createLayer();
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index dabd2d2..364d8f1 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -67,11 +67,16 @@
auto& mutableLayerHistory() { return mLayerHistory; }
- size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS { return mLayerHistory.mLayerInfos.size(); }
- size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS { return mLayerHistory.mActiveLayersEnd; }
+ size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
+ return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size();
+ }
auto refreshRateConfigs() { return holdRefreshRateConfigs(); }
+ size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {
+ return mLayerHistory.mActiveLayerInfos.size();
+ }
+
void replaceTouchTimer(int64_t millis) {
if (mTouchTimer) {
mTouchTimer.reset();