Merge changes I53c7d59d,Ie45d9381
* changes:
InputDispatcher: Don't split mouse events
InputDispatcher: Refactoring to prepare for spy windows
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 8da1352..34ccb21 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -11,286 +11,6 @@
# Grant unix world read/write permissions to kernel tracepoints.
# Access control to these files is now entirely in selinux policy.
- chmod 0755 /sys/kernel/debug/tracing/events
- chmod 0755 /sys/kernel/debug/tracing/events/binder
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_lock
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_locked
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_set_priority
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction_alloc_buf
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_transaction_received
- chmod 0755 /sys/kernel/debug/tracing/events/binder/binder_unlock
- chmod 0755 /sys/kernel/debug/tracing/events/block
- chmod 0755 /sys/kernel/debug/tracing/events/block/block_rq_complete
- chmod 0755 /sys/kernel/debug/tracing/events/block/block_rq_issue
- chmod 0755 /sys/kernel/debug/tracing/events/cgroup
- chmod 0755 /sys/kernel/debug/tracing/events/clk
- chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_disable
- chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_enable
- chmod 0755 /sys/kernel/debug/tracing/events/clk/clk_set_rate
- chmod 0755 /sys/kernel/debug/tracing/events/cpufreq_interactive
- chmod 0755 /sys/kernel/debug/tracing/events/cpuhp
- chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_enter
- chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_exit
- chmod 0755 /sys/kernel/debug/tracing/events/cpuhp/cpuhp_pause
- chmod 0755 /sys/kernel/debug/tracing/events/dma_fence
- chmod 0755 /sys/kernel/debug/tracing/events/ext4
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_enter
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_es_lookup_extent_exit
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_load_inode
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter
- chmod 0755 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_get_data_block
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_iget
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin
- chmod 0755 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end
- chmod 0755 /sys/kernel/debug/tracing/events/fence
- chmod 0755 /sys/kernel/debug/tracing/events/filemap
- chmod 0755 /sys/kernel/debug/tracing/events/filemap/mm_filemap_add_to_page_cache
- chmod 0755 /sys/kernel/debug/tracing/events/filemap/mm_filemap_delete_from_page_cache
- chmod 0755 /sys/kernel/debug/tracing/events/gpu_mem
- chmod 0755 /sys/kernel/debug/tracing/events/gpu_mem/gpu_mem_total
- chmod 0755 /sys/kernel/debug/tracing/events/i2c
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_read
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_reply
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_result
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/i2c_write
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_read
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_reply
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_result
- chmod 0755 /sys/kernel/debug/tracing/events/i2c/smbus_write
- chmod 0755 /sys/kernel/debug/tracing/events/ion
- chmod 0755 /sys/kernel/debug/tracing/events/ion/ion_stat
- chmod 0755 /sys/kernel/debug/tracing/events/ipi
- chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_entry
- chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_exit
- chmod 0755 /sys/kernel/debug/tracing/events/ipi/ipi_raise
- chmod 0755 /sys/kernel/debug/tracing/events/irq
- chmod 0755 /sys/kernel/debug/tracing/events/irq/irq_handler_entry
- chmod 0755 /sys/kernel/debug/tracing/events/irq/irq_handler_exit
- chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_entry
- chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_exit
- chmod 0755 /sys/kernel/debug/tracing/events/irq/softirq_raise
- chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_entry
- chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_exit
- chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_hi_entry
- chmod 0755 /sys/kernel/debug/tracing/events/irq/tasklet_hi_exit
- chmod 0755 /sys/kernel/debug/tracing/events/kmem
- chmod 0755 /sys/kernel/debug/tracing/events/kmem/ion_heap_grow
- chmod 0755 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink
- chmod 0755 /sys/kernel/debug/tracing/events/kmem/rss_stat
- chmod 0755 /sys/kernel/debug/tracing/events/lowmemorykiller
- chmod 0755 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill
- chmod 0755 /sys/kernel/debug/tracing/events/mm_event
- chmod 0755 /sys/kernel/debug/tracing/events/mm_event/mm_event_record
- chmod 0755 /sys/kernel/debug/tracing/events/oom
- chmod 0755 /sys/kernel/debug/tracing/events/oom/mark_victim
- chmod 0755 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update
- chmod 0755 /sys/kernel/debug/tracing/events/power
- chmod 0755 /sys/kernel/debug/tracing/events/power/clock_disable
- chmod 0755 /sys/kernel/debug/tracing/events/power/clock_enable
- chmod 0755 /sys/kernel/debug/tracing/events/power/clock_set_rate
- chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_frequency
- chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits
- chmod 0755 /sys/kernel/debug/tracing/events/power/cpu_idle
- chmod 0755 /sys/kernel/debug/tracing/events/power/gpu_frequency
- chmod 0755 /sys/kernel/debug/tracing/events/power/suspend_resume
- chmod 0755 /sys/kernel/debug/tracing/events/sched
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_pi_setprio
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_process_exit
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_process_free
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_switch
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_wakeup
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new
- chmod 0755 /sys/kernel/debug/tracing/events/sched/sched_waking
- chmod 0755 /sys/kernel/debug/tracing/events/signal
- chmod 0755 /sys/kernel/debug/tracing/events/signal/signal_deliver
- chmod 0755 /sys/kernel/debug/tracing/events/signal/signal_generate
- chmod 0755 /sys/kernel/debug/tracing/events/sync
- chmod 0755 /sys/kernel/debug/tracing/events/task
- chmod 0755 /sys/kernel/debug/tracing/events/task/task_newtask
- chmod 0755 /sys/kernel/debug/tracing/events/task/task_rename
- chmod 0755 /sys/kernel/debug/tracing/events/thermal
- chmod 0755 /sys/kernel/debug/tracing/events/thermal/cdev_update
- chmod 0755 /sys/kernel/debug/tracing/events/thermal/thermal_temperature
- chmod 0755 /sys/kernel/debug/tracing/events/vmscan
- chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin
- chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end
- chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep
- chmod 0755 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake
- chmod 0755 /sys/kernel/debug/tracing/options
- chmod 0755 /sys/kernel/debug/tracing/per_cpu
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu0
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu1
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu2
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu3
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu4
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu5
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu6
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu7
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu8
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu9
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu10
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu11
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu12
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu13
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu14
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu15
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu16
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu17
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu18
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu19
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu20
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu21
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu22
- chmod 0755 /sys/kernel/debug/tracing/per_cpu/cpu23
- chmod 0755 /sys/kernel/tracing/events
- chmod 0755 /sys/kernel/tracing/events/binder
- chmod 0755 /sys/kernel/tracing/events/binder/binder_lock
- chmod 0755 /sys/kernel/tracing/events/binder/binder_locked
- chmod 0755 /sys/kernel/tracing/events/binder/binder_set_priority
- chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction
- chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction_alloc_buf
- chmod 0755 /sys/kernel/tracing/events/binder/binder_transaction_received
- chmod 0755 /sys/kernel/tracing/events/binder/binder_unlock
- chmod 0755 /sys/kernel/tracing/events/block
- chmod 0755 /sys/kernel/tracing/events/block/block_rq_complete
- chmod 0755 /sys/kernel/tracing/events/block/block_rq_issue
- chmod 0755 /sys/kernel/tracing/events/cgroup
- chmod 0755 /sys/kernel/tracing/events/clk
- chmod 0755 /sys/kernel/tracing/events/clk/clk_disable
- chmod 0755 /sys/kernel/tracing/events/clk/clk_enable
- chmod 0755 /sys/kernel/tracing/events/clk/clk_set_rate
- chmod 0755 /sys/kernel/tracing/events/cpufreq_interactive
- chmod 0755 /sys/kernel/tracing/events/cpuhp
- chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_enter
- chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_exit
- chmod 0755 /sys/kernel/tracing/events/cpuhp/cpuhp_pause
- chmod 0755 /sys/kernel/tracing/events/dma_fence
- chmod 0755 /sys/kernel/tracing/events/ext4
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_da_write_begin
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_da_write_end
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_enter
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_es_lookup_extent_exit
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_load_inode
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter
- chmod 0755 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit
- chmod 0755 /sys/kernel/tracing/events/f2fs
- chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block
- chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_iget
- chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter
- chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit
- chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_write_begin
- chmod 0755 /sys/kernel/tracing/events/f2fs/f2fs_write_end
- chmod 0755 /sys/kernel/tracing/events/fence
- chmod 0755 /sys/kernel/tracing/events/filemap
- chmod 0755 /sys/kernel/tracing/events/filemap/mm_filemap_add_to_page_cache
- chmod 0755 /sys/kernel/tracing/events/filemap/mm_filemap_delete_from_page_cache
- chmod 0755 /sys/kernel/tracing/events/gpu_mem
- chmod 0755 /sys/kernel/tracing/events/gpu_mem/gpu_mem_total
- chmod 0755 /sys/kernel/tracing/events/i2c
- chmod 0755 /sys/kernel/tracing/events/i2c/i2c_read
- chmod 0755 /sys/kernel/tracing/events/i2c/i2c_reply
- chmod 0755 /sys/kernel/tracing/events/i2c/i2c_result
- chmod 0755 /sys/kernel/tracing/events/i2c/i2c_write
- chmod 0755 /sys/kernel/tracing/events/i2c/smbus_read
- chmod 0755 /sys/kernel/tracing/events/i2c/smbus_reply
- chmod 0755 /sys/kernel/tracing/events/i2c/smbus_result
- chmod 0755 /sys/kernel/tracing/events/i2c/smbus_write
- chmod 0755 /sys/kernel/tracing/events/ion
- chmod 0755 /sys/kernel/tracing/events/ion/ion_stat
- chmod 0755 /sys/kernel/tracing/events/ipi
- chmod 0755 /sys/kernel/tracing/events/ipi/ipi_entry
- chmod 0755 /sys/kernel/tracing/events/ipi/ipi_exit
- chmod 0755 /sys/kernel/tracing/events/ipi/ipi_raise
- chmod 0755 /sys/kernel/tracing/events/irq
- chmod 0755 /sys/kernel/tracing/events/irq/irq_handler_entry
- chmod 0755 /sys/kernel/tracing/events/irq/irq_handler_exit
- chmod 0755 /sys/kernel/tracing/events/irq/softirq_entry
- chmod 0755 /sys/kernel/tracing/events/irq/softirq_exit
- chmod 0755 /sys/kernel/tracing/events/irq/softirq_raise
- chmod 0755 /sys/kernel/tracing/events/irq/tasklet_entry
- chmod 0755 /sys/kernel/tracing/events/irq/tasklet_exit
- chmod 0755 /sys/kernel/tracing/events/irq/tasklet_hi_entry
- chmod 0755 /sys/kernel/tracing/events/irq/tasklet_hi_exit
- chmod 0755 /sys/kernel/tracing/events/kmem
- chmod 0755 /sys/kernel/tracing/events/kmem/ion_heap_grow
- chmod 0755 /sys/kernel/tracing/events/kmem/ion_heap_shrink
- chmod 0755 /sys/kernel/tracing/events/kmem/rss_stat
- chmod 0755 /sys/kernel/tracing/events/lowmemorykiller
- chmod 0755 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill
- chmod 0755 /sys/kernel/tracing/events/mm_event
- chmod 0755 /sys/kernel/tracing/events/mm_event/mm_event_record
- chmod 0755 /sys/kernel/tracing/events/oom
- chmod 0755 /sys/kernel/tracing/events/oom/mark_victim
- chmod 0755 /sys/kernel/tracing/events/oom/oom_score_adj_update
- chmod 0755 /sys/kernel/tracing/events/power
- chmod 0755 /sys/kernel/tracing/events/power/clock_disable
- chmod 0755 /sys/kernel/tracing/events/power/clock_enable
- chmod 0755 /sys/kernel/tracing/events/power/clock_set_rate
- chmod 0755 /sys/kernel/tracing/events/power/cpu_frequency
- chmod 0755 /sys/kernel/tracing/events/power/cpu_frequency_limits
- chmod 0755 /sys/kernel/tracing/events/power/cpu_idle
- chmod 0755 /sys/kernel/tracing/events/power/gpu_frequency
- chmod 0755 /sys/kernel/tracing/events/power/suspend_resume
- chmod 0755 /sys/kernel/tracing/events/sched
- chmod 0755 /sys/kernel/tracing/events/sched/sched_blocked_reason
- chmod 0755 /sys/kernel/tracing/events/sched/sched_cpu_hotplug
- chmod 0755 /sys/kernel/tracing/events/sched/sched_pi_setprio
- chmod 0755 /sys/kernel/tracing/events/sched/sched_process_exit
- chmod 0755 /sys/kernel/tracing/events/sched/sched_process_free
- chmod 0755 /sys/kernel/tracing/events/sched/sched_switch
- chmod 0755 /sys/kernel/tracing/events/sched/sched_wakeup
- chmod 0755 /sys/kernel/tracing/events/sched/sched_wakeup_new
- chmod 0755 /sys/kernel/tracing/events/sched/sched_waking
- chmod 0755 /sys/kernel/tracing/events/signal
- chmod 0755 /sys/kernel/tracing/events/signal/signal_deliver
- chmod 0755 /sys/kernel/tracing/events/signal/signal_generate
- chmod 0755 /sys/kernel/tracing/events/sync
- chmod 0755 /sys/kernel/tracing/events/task
- chmod 0755 /sys/kernel/tracing/events/task/task_newtask
- chmod 0755 /sys/kernel/tracing/events/task/task_rename
- chmod 0755 /sys/kernel/tracing/events/thermal
- chmod 0755 /sys/kernel/tracing/events/thermal/cdev_update
- chmod 0755 /sys/kernel/tracing/events/thermal/thermal_temperature
- chmod 0755 /sys/kernel/tracing/events/vmscan
- chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin
- chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_direct_reclaim_end
- chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_sleep
- chmod 0755 /sys/kernel/tracing/events/vmscan/mm_vmscan_kswapd_wake
- chmod 0755 /sys/kernel/tracing/options
- chmod 0755 /sys/kernel/tracing/per_cpu
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu0
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu1
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu2
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu3
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu4
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu5
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu6
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu7
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu8
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu9
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu10
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu11
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu12
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu13
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu14
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu15
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu16
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu17
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu18
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu19
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu20
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu21
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu22
- chmod 0755 /sys/kernel/tracing/per_cpu/cpu23
chmod 0666 /sys/kernel/debug/tracing/trace_clock
chmod 0666 /sys/kernel/tracing/trace_clock
chmod 0666 /sys/kernel/debug/tracing/buffer_size_kb
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index faa8485..00babc3 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -28,6 +28,7 @@
"dexopt.cpp",
"execv_helper.cpp",
"globals.cpp",
+ "restorable_file.cpp",
"run_dex2oat.cpp",
"unique_file.cpp",
"utils.cpp",
@@ -80,7 +81,7 @@
"-cert-err58-cpp",
],
tidy_flags: [
- "-warnings-as-errors=clang-analyzer-security*,cert-*"
+ "-warnings-as-errors=clang-analyzer-security*,cert-*",
],
}
@@ -132,7 +133,10 @@
"unique_file.cpp",
"execv_helper.cpp",
],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libbase",
"server_configurable_flags",
@@ -170,7 +174,7 @@
// Needs to be wherever installd is as it's execed by
// installd.
- required: [ "migrate_legacy_obb_data.sh" ],
+ required: ["migrate_legacy_obb_data.sh"],
}
// OTA chroot tool
@@ -194,7 +198,7 @@
"libutils",
],
required: [
- "apexd"
+ "apexd",
],
}
@@ -213,7 +217,7 @@
name: "libotapreoptparameters",
cflags: [
"-Wall",
- "-Werror"
+ "-Werror",
],
srcs: ["otapreopt_parameters.cpp"],
@@ -237,7 +241,7 @@
name: "otapreopt",
cflags: [
"-Wall",
- "-Werror"
+ "-Werror",
],
srcs: [
@@ -246,6 +250,7 @@
"globals.cpp",
"otapreopt.cpp",
"otapreopt_utils.cpp",
+ "restorable_file.cpp",
"run_dex2oat.cpp",
"unique_file.cpp",
"utils.cpp",
@@ -296,5 +301,5 @@
// Script to migrate legacy obb data.
sh_binary {
name: "migrate_legacy_obb_data.sh",
- src: "migrate_legacy_obb_data.sh"
+ src: "migrate_legacy_obb_data.sh",
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 2935c6a..d4c17fe 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -419,10 +419,17 @@
int res = 0;
char* before = nullptr;
char* after = nullptr;
+ if (!existing) {
+ if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
+ SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
+ PLOG(ERROR) << "Failed recursive restorecon for " << path;
+ goto fail;
+ }
+ return res;
+ }
// Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by
// libselinux. Not needed here.
-
if (lgetfilecon(path.c_str(), &before) < 0) {
PLOG(ERROR) << "Failed before getfilecon for " << path;
goto fail;
@@ -459,12 +466,6 @@
return res;
}
-static int restorecon_app_data_lazy(const std::string& parent, const char* name,
- const std::string& seInfo, uid_t uid, bool existing) {
- return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid,
- existing);
-}
-
static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
PLOG(ERROR) << "Failed to prepare " << path;
@@ -610,8 +611,14 @@
int32_t uid, int32_t* previousUid, int32_t cacheGid,
const std::string& seInfo, mode_t targetMode) {
struct stat st{};
- bool existing = (stat(path.c_str(), &st) == 0);
- if (existing) {
+ bool parent_dir_exists = (stat(path.c_str(), &st) == 0);
+
+ auto cache_path = StringPrintf("%s/%s", path.c_str(), "cache");
+ auto code_cache_path = StringPrintf("%s/%s", path.c_str(), "code_cache");
+ bool cache_exists = (access(cache_path.c_str(), F_OK) == 0);
+ bool code_cache_exists = (access(code_cache_path.c_str(), F_OK) == 0);
+
+ if (parent_dir_exists) {
if (*previousUid < 0) {
// If previousAppId is -1 in CreateAppDataArgs, we will assume the current owner
// of the directory as previousUid. This is required because it is not always possible
@@ -625,6 +632,7 @@
}
}
+ // Prepare only the parent app directory
if (prepare_app_dir(path, targetMode, uid) ||
prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
@@ -632,12 +640,23 @@
}
// Consider restorecon over contents if label changed
- if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
- restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
- restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
+ if (restorecon_app_data_lazy(path, seInfo, uid, parent_dir_exists)) {
return error("Failed to restorecon " + path);
}
+ // If the parent dir exists, the restorecon would already have been done
+ // as a part of the recursive restorecon above
+ if (parent_dir_exists && !cache_exists
+ && restorecon_app_data_lazy(cache_path, seInfo, uid, false)) {
+ return error("Failed to restorecon " + cache_path);
+ }
+
+ // If the parent dir exists, the restorecon would already have been done
+ // as a part of the recursive restorecon above
+ if (parent_dir_exists && !code_cache_exists
+ && restorecon_app_data_lazy(code_cache_path, seInfo, uid, false)) {
+ return error("Failed to restorecon " + code_cache_path);
+ }
return ok();
}
@@ -2863,7 +2882,6 @@
binder::Status InstalldNativeService::rmPackageDir(const std::string& packageName,
const std::string& packageDir) {
ENFORCE_UID(AID_SYSTEM);
- CHECK_ARGUMENT_PACKAGE_NAME(packageName);
CHECK_ARGUMENT_PATH(packageDir);
LOCK_PACKAGE();
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 2bcf2d4..b6f42ad 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -58,9 +58,10 @@
#include "dexopt_return_codes.h"
#include "execv_helper.h"
#include "globals.h"
-#include "installd_deps.h"
#include "installd_constants.h"
+#include "installd_deps.h"
#include "otapreopt_utils.h"
+#include "restorable_file.h"
#include "run_dex2oat.h"
#include "unique_file.h"
#include "utils.h"
@@ -309,12 +310,6 @@
return profile_boot_class_path == "true";
}
-static void UnlinkIgnoreResult(const std::string& path) {
- if (unlink(path.c_str()) < 0) {
- PLOG(ERROR) << "Failed to unlink " << path;
- }
-}
-
/*
* Whether dexopt should use a swap file when compiling an APK.
*
@@ -988,42 +983,34 @@
}
// (re)Creates the app image if needed.
-UniqueFile maybe_open_app_image(const std::string& out_oat_path,
- bool generate_app_image, bool is_public, int uid, bool is_secondary_dex) {
-
+RestorableFile maybe_open_app_image(const std::string& out_oat_path, bool generate_app_image,
+ bool is_public, int uid, bool is_secondary_dex) {
const std::string image_path = create_image_filename(out_oat_path);
if (image_path.empty()) {
// Happens when the out_oat_path has an unknown extension.
- return UniqueFile();
+ return RestorableFile();
}
- // In case there is a stale image, remove it now. Ignore any error.
- unlink(image_path.c_str());
-
// Not enabled, exit.
if (!generate_app_image) {
- return UniqueFile();
+ RestorableFile::RemoveAllFiles(image_path);
+ return RestorableFile();
}
std::string app_image_format = GetProperty("dalvik.vm.appimageformat", "");
if (app_image_format.empty()) {
- return UniqueFile();
+ RestorableFile::RemoveAllFiles(image_path);
+ return RestorableFile();
}
- // Recreate is true since we do not want to modify a mapped image. If the app is
- // already running and we modify the image file, it can cause crashes (b/27493510).
- UniqueFile image_file(
- open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
- image_path,
- UnlinkIgnoreResult);
+ // If the app is already running and we modify the image file, it can cause crashes
+ // (b/27493510).
+ RestorableFile image_file = RestorableFile::CreateWritableFile(image_path,
+ /*permissions*/ 0600);
if (image_file.fd() < 0) {
// Could not create application image file. Go on since we can compile without it.
LOG(ERROR) << "installd could not create '" << image_path
<< "' for image file during dexopt";
- // If we have a valid image file path but no image fd, explicitly erase the image file.
- if (unlink(image_path.c_str()) < 0) {
- if (errno != ENOENT) {
- PLOG(ERROR) << "Couldn't unlink image file " << image_path;
- }
- }
+ // If we have a valid image file path but cannot create tmp file, reset it.
+ image_file.reset();
} else if (!set_permissions_and_ownership(
image_file.fd(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
@@ -1097,9 +1084,9 @@
// Opens the vdex files and assigns the input fd to in_vdex_wrapper and the output fd to
// out_vdex_wrapper. Returns true for success or false in case of errors.
bool open_vdex_files_for_dex2oat(const char* apk_path, const char* out_oat_path, int dexopt_needed,
- const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
- bool profile_guided, UniqueFile* in_vdex_wrapper,
- UniqueFile* out_vdex_wrapper) {
+ const char* instruction_set, bool is_public, int uid,
+ bool is_secondary_dex, bool profile_guided,
+ UniqueFile* in_vdex_wrapper, RestorableFile* out_vdex_wrapper) {
CHECK(in_vdex_wrapper != nullptr);
CHECK(out_vdex_wrapper != nullptr);
// Open the existing VDEX. We do this before creating the new output VDEX, which will
@@ -1114,6 +1101,14 @@
return false;
}
+ // Create work file first. All files will be deleted when it fails.
+ *out_vdex_wrapper = RestorableFile::CreateWritableFile(out_vdex_path_str,
+ /*permissions*/ 0644);
+ if (out_vdex_wrapper->fd() < 0) {
+ ALOGE("installd cannot open vdex '%s' during dexopt\n", out_vdex_path_str.c_str());
+ return false;
+ }
+
bool update_vdex_in_place = false;
if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
// Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
@@ -1145,41 +1140,19 @@
(dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
!profile_guided;
if (update_vdex_in_place) {
+ // dex2oat marks it invalid anyway. So delete it and set work file fd.
+ unlink(in_vdex_path_str.c_str());
// Open the file read-write to be able to update it.
- in_vdex_wrapper->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0),
- in_vdex_path_str);
- if (in_vdex_wrapper->fd() == -1) {
- // If we failed to open the file, we cannot update it in place.
- update_vdex_in_place = false;
- }
+ in_vdex_wrapper->reset(out_vdex_wrapper->fd(), in_vdex_path_str);
+ // Disable auto close for the in wrapper fd (it will be done when destructing the out
+ // wrapper).
+ in_vdex_wrapper->DisableAutoClose();
} else {
in_vdex_wrapper->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0),
in_vdex_path_str);
}
}
- // If we are updating the vdex in place, we do not need to recreate a vdex,
- // and can use the same existing one.
- if (update_vdex_in_place) {
- // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
- // have bogus stale vdex files.
- out_vdex_wrapper->reset(
- in_vdex_wrapper->fd(),
- out_vdex_path_str,
- UnlinkIgnoreResult);
- // Disable auto close for the in wrapper fd (it will be done when destructing the out
- // wrapper).
- in_vdex_wrapper->DisableAutoClose();
- } else {
- out_vdex_wrapper->reset(
- open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
- out_vdex_path_str,
- UnlinkIgnoreResult);
- if (out_vdex_wrapper->fd() < 0) {
- ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
- return false;
- }
- }
if (!set_permissions_and_ownership(out_vdex_wrapper->fd(), is_public, uid,
out_vdex_path_str.c_str(), is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
@@ -1191,16 +1164,13 @@
}
// Opens the output oat file for the given apk.
-UniqueFile open_oat_out_file(const char* apk_path, const char* oat_dir,
- bool is_public, int uid, const char* instruction_set, bool is_secondary_dex) {
+RestorableFile open_oat_out_file(const char* apk_path, const char* oat_dir, bool is_public, int uid,
+ const char* instruction_set, bool is_secondary_dex) {
char out_oat_path[PKG_PATH_MAX];
if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
- return UniqueFile();
+ return RestorableFile();
}
- UniqueFile oat(
- open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
- out_oat_path,
- UnlinkIgnoreResult);
+ RestorableFile oat = RestorableFile::CreateWritableFile(out_oat_path, /*permissions*/ 0644);
if (oat.fd() < 0) {
PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
} else if (!set_permissions_and_ownership(
@@ -1839,6 +1809,7 @@
if (sec_dex_result == kSecondaryDexOptProcessOk) {
oat_dir = oat_dir_str.c_str();
if (dexopt_needed == NO_DEXOPT_NEEDED) {
+ *completed = true;
return 0; // Nothing to do, report success.
}
} else if (sec_dex_result == kSecondaryDexOptProcessCancelled) {
@@ -1874,8 +1845,8 @@
}
// Create the output OAT file.
- UniqueFile out_oat = open_oat_out_file(dex_path, oat_dir, is_public, uid,
- instruction_set, is_secondary_dex);
+ RestorableFile out_oat =
+ open_oat_out_file(dex_path, oat_dir, is_public, uid, instruction_set, is_secondary_dex);
if (out_oat.fd() < 0) {
*error_msg = "Could not open out oat file.";
return -1;
@@ -1883,7 +1854,7 @@
// Open vdex files.
UniqueFile in_vdex;
- UniqueFile out_vdex;
+ RestorableFile out_vdex;
if (!open_vdex_files_for_dex2oat(dex_path, out_oat.path().c_str(), dexopt_needed,
instruction_set, is_public, uid, is_secondary_dex, profile_guided, &in_vdex,
&out_vdex)) {
@@ -1919,8 +1890,8 @@
}
// Create the app image file if needed.
- UniqueFile out_image = maybe_open_app_image(
- out_oat.path(), generate_app_image, is_public, uid, is_secondary_dex);
+ RestorableFile out_image = maybe_open_app_image(out_oat.path(), generate_app_image, is_public,
+ uid, is_secondary_dex);
UniqueFile dex_metadata;
if (dex_metadata_path != nullptr) {
@@ -1953,30 +1924,18 @@
LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
RunDex2Oat runner(dex2oat_bin, execv_helper.get());
- runner.Initialize(out_oat,
- out_vdex,
- out_image,
- in_dex,
- in_vdex,
- dex_metadata,
- reference_profile,
- class_loader_context,
- join_fds(context_input_fds),
- swap_fd.get(),
- instruction_set,
- compiler_filter,
- debuggable,
- boot_complete,
- for_restore,
- target_sdk_version,
- enable_hidden_api_checks,
- generate_compact_dex,
- use_jitzygote_image,
+ runner.Initialize(out_oat.GetUniqueFile(), out_vdex.GetUniqueFile(), out_image.GetUniqueFile(),
+ in_dex, in_vdex, dex_metadata, reference_profile, class_loader_context,
+ join_fds(context_input_fds), swap_fd.get(), instruction_set, compiler_filter,
+ debuggable, boot_complete, for_restore, target_sdk_version,
+ enable_hidden_api_checks, generate_compact_dex, use_jitzygote_image,
compilation_reason);
bool cancelled = false;
pid_t pid = dexopt_status_->check_cancellation_and_fork(&cancelled);
if (cancelled) {
+ *completed = false;
+ reference_profile.DisableCleanup();
return 0;
}
if (pid == 0) {
@@ -2004,6 +1963,7 @@
LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- cancelled";
// cancelled, not an error
*completed = false;
+ reference_profile.DisableCleanup();
return 0;
}
LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- status=0x"
@@ -2013,13 +1973,42 @@
}
}
- // TODO(b/156537504) Implement SWAP of completed files
- // We've been successful, don't delete output.
- out_oat.DisableCleanup();
- out_vdex.DisableCleanup();
- out_image.DisableCleanup();
+ // dex2oat ran successfully, so profile is safe to keep.
reference_profile.DisableCleanup();
+ // We've been successful, commit work files.
+ // If committing (=renaming tmp to regular) fails, try to restore backup files.
+ // If restoring fails as well, as a last resort, remove all files.
+ if (!out_oat.CreateBackupFile() || !out_vdex.CreateBackupFile() ||
+ !out_image.CreateBackupFile()) {
+ // Renaming failure can mean that the original file may not be accessible from installd.
+ LOG(ERROR) << "Cannot create backup file from existing file, file in wrong state?"
+ << ", out_oat:" << out_oat.path() << " ,out_vdex:" << out_vdex.path()
+ << " ,out_image:" << out_image.path();
+ out_oat.ResetAndRemoveAllFiles();
+ out_vdex.ResetAndRemoveAllFiles();
+ out_image.ResetAndRemoveAllFiles();
+ return -1;
+ }
+ if (!out_oat.CommitWorkFile() || !out_vdex.CommitWorkFile() || !out_image.CommitWorkFile()) {
+ LOG(ERROR) << "Cannot commit, out_oat:" << out_oat.path()
+ << " ,out_vdex:" << out_vdex.path() << " ,out_image:" << out_image.path();
+ if (!out_oat.RestoreBackupFile() || !out_vdex.RestoreBackupFile() ||
+ !out_image.RestoreBackupFile()) {
+ LOG(ERROR) << "Cannot cancel commit, out_oat:" << out_oat.path()
+ << " ,out_vdex:" << out_vdex.path() << " ,out_image:" << out_image.path();
+ // Restoring failed.
+ out_oat.ResetAndRemoveAllFiles();
+ out_vdex.ResetAndRemoveAllFiles();
+ out_image.ResetAndRemoveAllFiles();
+ }
+ return -1;
+ }
+ // Now remove remaining backup files.
+ out_oat.RemoveBackupFile();
+ out_vdex.RemoveBackupFile();
+ out_image.RemoveBackupFile();
+
*completed = true;
return 0;
}
diff --git a/cmds/installd/restorable_file.cpp b/cmds/installd/restorable_file.cpp
new file mode 100644
index 0000000..fd54a23
--- /dev/null
+++ b/cmds/installd/restorable_file.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "restorable_file.h"
+
+#include <string>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+namespace {
+
+constexpr char kTmpFileSuffix[] = ".tmp";
+constexpr char kBackupFileSuffix[] = ".backup";
+
+std::string GetTmpFilePath(const std::string& path) {
+ return android::base::StringPrintf("%s%s", path.c_str(), kTmpFileSuffix);
+}
+
+std::string GetBackupFilePath(const std::string& path) {
+ return android::base::StringPrintf("%s%s", path.c_str(), kBackupFileSuffix);
+}
+
+void UnlinkPossiblyNonExistingFile(const std::string& path) {
+ if (unlink(path.c_str()) < 0) {
+ if (errno != ENOENT && errno != EROFS) { // EROFS reported even if it does not exist.
+ PLOG(ERROR) << "Cannot unlink: " << path;
+ }
+ }
+}
+
+// Check if file for the given path exists
+bool FileExists(const std::string& path) {
+ struct stat st;
+ return ::stat(path.c_str(), &st) == 0;
+}
+
+} // namespace
+
+namespace android {
+namespace installd {
+
+RestorableFile::RestorableFile() : RestorableFile(-1, "") {}
+
+RestorableFile::RestorableFile(int value, const std::string& path) : unique_file_(value, path) {
+ // As cleanup is null, this does not make much difference but use unique_file_ only for closing
+ // tmp file.
+ unique_file_.DisableCleanup();
+}
+
+RestorableFile::~RestorableFile() {
+ reset();
+}
+
+void RestorableFile::reset() {
+ // need to copy before reset clears it.
+ std::string path(unique_file_.path());
+ unique_file_.reset();
+ if (!path.empty()) {
+ UnlinkPossiblyNonExistingFile(GetTmpFilePath(path));
+ }
+}
+
+bool RestorableFile::CreateBackupFile() {
+ if (path().empty() || !FileExists(path())) {
+ return true;
+ }
+ std::string backup = GetBackupFilePath(path());
+ UnlinkPossiblyNonExistingFile(backup);
+ if (rename(path().c_str(), backup.c_str()) < 0) {
+ PLOG(ERROR) << "Cannot rename " << path() << " to " << backup;
+ return false;
+ }
+ return true;
+}
+
+bool RestorableFile::CommitWorkFile() {
+ std::string path(unique_file_.path());
+ // Keep the path with Commit for debugging purpose.
+ unique_file_.reset(-1, path);
+ if (!path.empty()) {
+ if (rename(GetTmpFilePath(path).c_str(), path.c_str()) < 0) {
+ PLOG(ERROR) << "Cannot rename " << GetTmpFilePath(path) << " to " << path;
+ // Remove both files as renaming can fail due to the original file as well.
+ UnlinkPossiblyNonExistingFile(path);
+ UnlinkPossiblyNonExistingFile(GetTmpFilePath(path));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool RestorableFile::RestoreBackupFile() {
+ std::string backup = GetBackupFilePath(path());
+ if (path().empty() || !FileExists(backup)) {
+ return true;
+ }
+ UnlinkPossiblyNonExistingFile(path());
+ if (rename(backup.c_str(), path().c_str()) < 0) {
+ PLOG(ERROR) << "Cannot rename " << backup << " to " << path();
+ return false;
+ }
+ return true;
+}
+
+void RestorableFile::RemoveBackupFile() {
+ UnlinkPossiblyNonExistingFile(GetBackupFilePath(path()));
+}
+
+const UniqueFile& RestorableFile::GetUniqueFile() const {
+ return unique_file_;
+}
+
+void RestorableFile::ResetAndRemoveAllFiles() {
+ std::string path(unique_file_.path());
+ reset();
+ RemoveAllFiles(path);
+}
+
+RestorableFile RestorableFile::CreateWritableFile(const std::string& path, int permissions) {
+ std::string tmp_file_path = GetTmpFilePath(path);
+ // If old tmp file exists, delete it.
+ UnlinkPossiblyNonExistingFile(tmp_file_path);
+ int fd = -1;
+ if (!path.empty()) {
+ fd = open(tmp_file_path.c_str(), O_RDWR | O_CREAT, permissions);
+ if (fd < 0) {
+ PLOG(ERROR) << "Cannot create file: " << tmp_file_path;
+ }
+ }
+ RestorableFile rf(fd, path);
+ return rf;
+}
+
+void RestorableFile::RemoveAllFiles(const std::string& path) {
+ UnlinkPossiblyNonExistingFile(GetTmpFilePath(path));
+ UnlinkPossiblyNonExistingFile(GetBackupFilePath(path));
+ UnlinkPossiblyNonExistingFile(path);
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/restorable_file.h b/cmds/installd/restorable_file.h
new file mode 100644
index 0000000..eda2292
--- /dev/null
+++ b/cmds/installd/restorable_file.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INSTALLD_RESTORABLE_FILE_H
+#define ANDROID_INSTALLD_RESTORABLE_FILE_H
+
+#include <functional>
+#include <string>
+
+#include "unique_file.h"
+
+namespace android {
+namespace installd {
+
+// This is a file abstraction which allows restoring to the original file while temporary work
+// file is updated.
+//
+// Typical flow for this API will be:
+// RestorableFile rf = RestorableFile::CreateWritableFile(...)
+// write to file using file descriptor acquired from: rf.fd()
+// Make work file into a regular file with: rf.CommitWorkFile()
+// Or throw away the work file by destroying the instance without calling CommitWorkFile().
+// The temporary work file is closed / removed when an instance is destroyed without calling
+// CommitWorkFile(). The original file, if CommitWorkFile() is not called, will be kept.
+//
+// For safer restoration of original file when commit fails, following 3 steps can be taken:
+// 1. CreateBackupFile(): This renames an existing regular file into a separate backup file.
+// 2. CommitWorkFile(): Rename the work file into the regular file.
+// 3. RemoveBackupFile(): Removes the backup file
+// If CommitWorkFile fails, client can call RestoreBackupFile() which will restore regular file from
+// the backup.
+class RestorableFile {
+public:
+ // Creates invalid instance with no fd (=-1) and empty path.
+ RestorableFile();
+ RestorableFile(RestorableFile&& other) = default;
+ ~RestorableFile();
+
+ // Passes all contents of other file into the current file.
+ // Files kept for the current file will be either deleted or committed depending on
+ // CommitWorkFile() and DisableCleanUp() calls made before this.
+ RestorableFile& operator=(RestorableFile&& other) = default;
+
+ // Gets file descriptor for backing work (=temporary) file. If work file does not exist, it will
+ // return -1.
+ int fd() const { return unique_file_.fd(); }
+
+ // Gets the path name for the regular file (not temporary file).
+ const std::string& path() const { return unique_file_.path(); }
+
+ // Closes work file, deletes it and resets all internal states into default states.
+ void reset();
+
+ // Closes work file and closes all files including work file, backup file and regular file.
+ void ResetAndRemoveAllFiles();
+
+ // Creates a backup file by renaming existing regular file. This will return false if renaming
+ // fails. If regular file for renaming does not exist, it will return true.
+ bool CreateBackupFile();
+
+ // Closes existing work file and makes it a regular file.
+ // Note that the work file is closed and fd() will return -1 after this. path() will still
+ // return the original path.
+ // This will return false when committing fails (=cannot rename). Both the regular file and tmp
+ // file will be deleted when it fails.
+ bool CommitWorkFile();
+
+ // Cancels the commit and restores the backup file into the regular one. If renaming fails,
+ // it will return false. This returns true if the backup file does not exist.
+ bool RestoreBackupFile();
+
+ // Removes the backup file.
+ void RemoveBackupFile();
+
+ // Gets UniqueFile with the same path and fd() pointing to the work file.
+ const UniqueFile& GetUniqueFile() const;
+
+ // Creates writable RestorableFile. This involves creating tmp file for writing.
+ static RestorableFile CreateWritableFile(const std::string& path, int permissions);
+
+ // Removes the specified file together with tmp file generated as RestorableFile.
+ static void RemoveAllFiles(const std::string& path);
+
+private:
+ RestorableFile(int value, const std::string& path);
+
+ // Used as a storage for work file fd and path string.
+ UniqueFile unique_file_;
+};
+
+} // namespace installd
+} // namespace android
+
+#endif // ANDROID_INSTALLD_RESTORABLE_FILE_H
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 4cde7e3..51f7716 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -188,3 +188,23 @@
"libotapreoptparameters",
],
}
+
+cc_test {
+ name: "installd_file_test",
+ test_suites: ["device-tests"],
+ clang: true,
+ srcs: ["installd_file_test.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libutils",
+ ],
+ static_libs: [
+ "libinstalld",
+ "liblog",
+ ],
+}
diff --git a/cmds/installd/tests/installd_file_test.cpp b/cmds/installd/tests/installd_file_test.cpp
new file mode 100644
index 0000000..00fb308
--- /dev/null
+++ b/cmds/installd/tests/installd_file_test.cpp
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "restorable_file.h"
+#include "unique_file.h"
+#include "utils.h"
+
+#undef LOG_TAG
+#define LOG_TAG "installd_file_test"
+
+namespace {
+
+constexpr char kFileTestDir[] = "/data/local/tmp/installd_file_test_data";
+constexpr char kTmpFileSuffix[] = ".tmp";
+constexpr char kBackupFileSuffix[] = ".backup";
+
+void UnlinkWithAssert(const std::string& path) {
+ ASSERT_EQ(0, unlink(path.c_str()));
+}
+
+} // namespace
+
+namespace android {
+namespace installd {
+
+// Add these as macros as functions make it hard to tell where the failure has happened.
+#define ASSERT_FILE_NOT_EXISTING(path) \
+ { \
+ struct stat st; \
+ ASSERT_NE(0, ::stat(path.c_str(), &st)); \
+ }
+#define ASSERT_FILE_EXISTING(path) \
+ { \
+ struct stat st; \
+ ASSERT_EQ(0, ::stat(path.c_str(), &st)); \
+ }
+#define ASSERT_FILE_CONTENT(path, expectedContent) ASSERT_EQ(expectedContent, ReadTestFile(path))
+#define ASSERT_FILE_OPEN(path, fd) \
+ { \
+ fd = open(path.c_str(), O_RDWR); \
+ ASSERT_TRUE(fd >= 0); \
+ }
+#define ASSERT_WRITE_TO_FD(fd, content) \
+ ASSERT_TRUE(android::base::WriteStringToFd(content, android::base::borrowed_fd(fd)))
+
+class FileTest : public testing::Test {
+protected:
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
+
+ ASSERT_EQ(0, create_dir_if_needed(kFileTestDir, 0777));
+ }
+
+ virtual void TearDown() {
+ system(android::base::StringPrintf("rm -rf %s", kFileTestDir).c_str());
+ }
+
+ std::string GetTestFilePath(const std::string& fileName) {
+ return android::base::StringPrintf("%s/%s", kFileTestDir, fileName.c_str());
+ }
+
+ void CreateTestFileWithContents(const std::string& path, const std::string& content) {
+ ALOGI("CreateTestFileWithContents:%s", path.c_str());
+ ASSERT_TRUE(android::base::WriteStringToFile(content, path));
+ }
+
+ std::string GetTestName() {
+ std::string name(testing::UnitTest::GetInstance()->current_test_info()->name());
+ return name;
+ }
+
+ std::string ReadTestFile(const std::string& path) {
+ std::string content;
+ bool r = android::base::ReadFileToString(path, &content);
+ if (!r) {
+ PLOG(ERROR) << "Cannot read file:" << path;
+ }
+ return content;
+ }
+};
+
+TEST_F(FileTest, TestUniqueFileMoveConstruction) {
+ const int fd = 101;
+ std::string testFile = GetTestFilePath(GetTestName());
+ UniqueFile uf1(fd, testFile);
+ uf1.DisableAutoClose();
+
+ UniqueFile uf2(std::move(uf1));
+
+ ASSERT_EQ(fd, uf2.fd());
+ ASSERT_EQ(testFile, uf2.path());
+}
+
+TEST_F(FileTest, TestUniqueFileAssignment) {
+ const int fd1 = 101;
+ const int fd2 = 102;
+ std::string testFile1 = GetTestFilePath(GetTestName());
+ std::string testFile2 = GetTestFilePath(GetTestName() + "2");
+
+ UniqueFile uf1(fd1, testFile1);
+ uf1.DisableAutoClose();
+
+ UniqueFile uf2(fd2, testFile2);
+ uf2.DisableAutoClose();
+
+ ASSERT_EQ(fd2, uf2.fd());
+ ASSERT_EQ(testFile2, uf2.path());
+
+ uf2 = std::move(uf1);
+
+ ASSERT_EQ(fd1, uf2.fd());
+ ASSERT_EQ(testFile1, uf2.path());
+}
+
+TEST_F(FileTest, TestUniqueFileCleanup) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ int fd;
+ ASSERT_FILE_OPEN(testFile, fd);
+
+ { UniqueFile uf = UniqueFile(fd, testFile, UnlinkWithAssert); }
+
+ ASSERT_FILE_NOT_EXISTING(testFile);
+}
+
+TEST_F(FileTest, TestUniqueFileNoCleanup) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ int fd;
+ ASSERT_FILE_OPEN(testFile, fd);
+
+ {
+ UniqueFile uf = UniqueFile(fd, testFile, UnlinkWithAssert);
+ uf.DisableCleanup();
+ }
+
+ ASSERT_FILE_CONTENT(testFile, "OriginalContent");
+}
+
+TEST_F(FileTest, TestUniqueFileFd) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ int fd;
+ ASSERT_FILE_OPEN(testFile, fd);
+
+ UniqueFile uf(fd, testFile, UnlinkWithAssert);
+
+ ASSERT_EQ(fd, uf.fd());
+
+ uf.reset();
+
+ ASSERT_EQ(-1, uf.fd());
+}
+
+TEST_F(FileTest, TestRestorableFileMoveConstruction) {
+ std::string testFile = GetTestFilePath(GetTestName());
+
+ RestorableFile rf1 = RestorableFile::CreateWritableFile(testFile, 0600);
+ int fd = rf1.fd();
+
+ RestorableFile rf2(std::move(rf1));
+
+ ASSERT_EQ(fd, rf2.fd());
+ ASSERT_EQ(testFile, rf2.path());
+}
+
+TEST_F(FileTest, TestRestorableFileAssignment) {
+ std::string testFile1 = GetTestFilePath(GetTestName());
+ std::string testFile2 = GetTestFilePath(GetTestName() + "2");
+
+ RestorableFile rf1 = RestorableFile::CreateWritableFile(testFile1, 0600);
+ int fd1 = rf1.fd();
+
+ RestorableFile rf2 = RestorableFile::CreateWritableFile(testFile2, 0600);
+ int fd2 = rf2.fd();
+
+ ASSERT_EQ(fd2, rf2.fd());
+ ASSERT_EQ(testFile2, rf2.path());
+
+ rf2 = std::move(rf1);
+
+ ASSERT_EQ(fd1, rf2.fd());
+ ASSERT_EQ(testFile1, rf2.path());
+}
+
+TEST_F(FileTest, TestRestorableFileVerifyUniqueFileWithReset) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+ ASSERT_FILE_EXISTING(tmpFile);
+
+ const UniqueFile& uf = rf.GetUniqueFile();
+
+ ASSERT_EQ(rf.fd(), uf.fd());
+ ASSERT_EQ(rf.path(), uf.path());
+
+ rf.reset();
+
+ ASSERT_EQ(rf.fd(), uf.fd());
+ ASSERT_EQ(rf.path(), uf.path());
+ ASSERT_EQ(-1, rf.fd());
+ ASSERT_TRUE(rf.path().empty());
+ }
+}
+
+TEST_F(FileTest, TestRestorableFileVerifyUniqueFileWithCommit) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+ ASSERT_FILE_EXISTING(tmpFile);
+
+ const UniqueFile& uf = rf.GetUniqueFile();
+
+ ASSERT_EQ(rf.fd(), uf.fd());
+ ASSERT_EQ(rf.path(), uf.path());
+
+ ASSERT_TRUE(rf.CreateBackupFile());
+
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+
+ rf.CommitWorkFile();
+
+ ASSERT_EQ(rf.fd(), uf.fd());
+ ASSERT_EQ(rf.path(), uf.path());
+ ASSERT_EQ(-1, rf.fd());
+ ASSERT_EQ(testFile, rf.path());
+ }
+}
+
+TEST_F(FileTest, TestRestorableFileNewFileNotCommitted) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+ ASSERT_FILE_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+ ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+}
+
+TEST_F(FileTest, TestRestorableFileNotCommittedWithOriginal) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+ ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+ ASSERT_FILE_EXISTING(testFile);
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_CONTENT(testFile, "OriginalContent");
+}
+
+TEST_F(FileTest, TestRestorableFileNotCommittedWithOriginalAndOldTmp) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+ CreateTestFileWithContents(testFile + kTmpFileSuffix, "OldTmp");
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+ ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+ ASSERT_FILE_EXISTING(testFile);
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_CONTENT(testFile, "OriginalContent");
+}
+
+TEST_F(FileTest, TestRestorableFileNewFileCommitted) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+
+ ASSERT_FILE_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+ ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+
+ ASSERT_TRUE(rf.CreateBackupFile());
+
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+
+ ASSERT_TRUE(rf.CommitWorkFile());
+ rf.RemoveBackupFile();
+
+ ASSERT_FILE_CONTENT(testFile, "NewContent");
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+ ASSERT_FILE_CONTENT(testFile, "NewContent");
+}
+
+TEST_F(FileTest, TestRestorableFileCommittedWithOriginal) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+ ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+
+ ASSERT_TRUE(rf.CreateBackupFile());
+
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_EXISTING(backupFile);
+
+ ASSERT_TRUE(rf.CommitWorkFile());
+
+ ASSERT_FILE_EXISTING(backupFile);
+ ASSERT_FILE_CONTENT(testFile, "NewContent");
+
+ rf.RemoveBackupFile();
+
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_CONTENT(testFile, "NewContent");
+}
+
+TEST_F(FileTest, TestRestorableFileCommittedWithOriginalAndOldTmp) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+ CreateTestFileWithContents(testFile + kTmpFileSuffix, "OldTmp");
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+ ASSERT_FILE_CONTENT(tmpFile, "NewContent");
+
+ ASSERT_TRUE(rf.CommitWorkFile());
+
+ ASSERT_FILE_CONTENT(testFile, "NewContent");
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_CONTENT(testFile, "NewContent");
+}
+
+TEST_F(FileTest, TestRestorableFileCommitFailureNoOriginal) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+ ASSERT_TRUE(rf.CreateBackupFile());
+
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+
+ // Now remove tmp file to force commit failure.
+ close(rf.fd());
+ ASSERT_EQ(0, unlink(tmpFile.c_str()));
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+
+ ASSERT_FALSE(rf.CommitWorkFile());
+
+ ASSERT_EQ(-1, rf.fd());
+ ASSERT_EQ(testFile, rf.path());
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+
+ ASSERT_TRUE(rf.RestoreBackupFile());
+ }
+
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileCommitFailureAndRollback) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+ ASSERT_TRUE(rf.CreateBackupFile());
+
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_EXISTING(backupFile);
+
+ // Now remove tmp file to force commit failure.
+ close(rf.fd());
+ ASSERT_EQ(0, unlink(tmpFile.c_str()));
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+
+ ASSERT_FALSE(rf.CommitWorkFile());
+
+ ASSERT_EQ(-1, rf.fd());
+ ASSERT_EQ(testFile, rf.path());
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_EXISTING(backupFile);
+
+ ASSERT_TRUE(rf.RestoreBackupFile());
+ }
+
+ ASSERT_FILE_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileResetAndRemoveAllFiles) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ {
+ RestorableFile rf = RestorableFile::CreateWritableFile(testFile, 0600);
+ ASSERT_WRITE_TO_FD(rf.fd(), "NewContent");
+
+ ASSERT_TRUE(rf.CreateBackupFile());
+
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_EXISTING(backupFile);
+
+ rf.ResetAndRemoveAllFiles();
+
+ ASSERT_EQ(-1, rf.fd());
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+ }
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileRemoveFileAndTmpFileWithContentFile) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+
+ RestorableFile::RemoveAllFiles(testFile);
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+TEST_F(FileTest, TestRestorableFileRemoveFileAndTmpFileWithContentAndTmpFile) {
+ std::string testFile = GetTestFilePath(GetTestName());
+ std::string tmpFile = testFile + kTmpFileSuffix;
+ std::string backupFile = testFile + kBackupFileSuffix;
+ CreateTestFileWithContents(testFile, "OriginalContent");
+ CreateTestFileWithContents(testFile + kTmpFileSuffix, "TmpContent");
+
+ RestorableFile::RemoveAllFiles(testFile);
+
+ ASSERT_FILE_NOT_EXISTING(tmpFile);
+ ASSERT_FILE_NOT_EXISTING(testFile);
+ ASSERT_FILE_NOT_EXISTING(backupFile);
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/tests/installd_file_test.xml b/cmds/installd/tests/installd_file_test.xml
new file mode 100644
index 0000000..5ec6e3f
--- /dev/null
+++ b/cmds/installd/tests/installd_file_test.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- Note: this is derived from the autogenerated configuration. We require
+ root support. -->
+<configuration description="Runs installd_file_test.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push"
+ value="installd_file_test->/data/local/tmp/installd_file_test" />
+ </target_preparer>
+
+ <!-- The test requires root for file access (rollback. -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="installd_file_test" />
+ </test>
+</configuration>
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index 0dd29e0..e5d689f 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -6,8 +6,8 @@
onrestart restart apexd
onrestart restart audioserver
onrestart restart gatekeeperd
- onrestart class_restart main
- onrestart class_restart hal
- onrestart class_restart early_hal
+ onrestart class_restart --only-enabled main
+ onrestart class_restart --only-enabled hal
+ onrestart class_restart --only-enabled early_hal
task_profiles ServiceCapacityLow
shutdown critical
diff --git a/data/etc/android.hardware.telephony.calling.xml b/data/etc/android.hardware.telephony.calling.xml
new file mode 100644
index 0000000..3e92a66
--- /dev/null
+++ b/data/etc/android.hardware.telephony.calling.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard set of features for devices to support Telephony Calling API. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.software.telecom" />
+ <feature name="android.hardware.telephony.radio" />
+ <feature name="android.hardware.telephony.subscription" />
+ <feature name="android.hardware.telephony.calling" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.cdma.xml b/data/etc/android.hardware.telephony.cdma.xml
index 082378d..c81cf06 100644
--- a/data/etc/android.hardware.telephony.cdma.xml
+++ b/data/etc/android.hardware.telephony.cdma.xml
@@ -4,9 +4,9 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,5 +17,11 @@
<!-- This is the standard set of telephony features for a CDMA phone. -->
<permissions>
<feature name="android.hardware.telephony" />
+ <feature name="android.software.telecom" />
+ <feature name="android.hardware.telephony.radio" />
+ <feature name="android.hardware.telephony.subscription" />
<feature name="android.hardware.telephony.cdma" />
+ <feature name="android.hardware.telephony.calling" />
+ <feature name="android.hardware.telephony.data" />
+ <feature name="android.hardware.telephony.messaging" />
</permissions>
diff --git a/data/etc/android.hardware.telephony.data.xml b/data/etc/android.hardware.telephony.data.xml
new file mode 100644
index 0000000..2716152
--- /dev/null
+++ b/data/etc/android.hardware.telephony.data.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard set of features for devices to support Telephony Data API. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.radio" />
+ <feature name="android.hardware.telephony.subscription" />
+ <feature name="android.hardware.telephony.data" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.gsm.xml b/data/etc/android.hardware.telephony.gsm.xml
index 7927fa8..e368a06 100644
--- a/data/etc/android.hardware.telephony.gsm.xml
+++ b/data/etc/android.hardware.telephony.gsm.xml
@@ -4,9 +4,9 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,5 +17,11 @@
<!-- This is the standard set of telephony features for a GSM phone. -->
<permissions>
<feature name="android.hardware.telephony" />
+ <feature name="android.software.telecom" />
+ <feature name="android.hardware.telephony.radio" />
+ <feature name="android.hardware.telephony.subscription" />
<feature name="android.hardware.telephony.gsm" />
+ <feature name="android.hardware.telephony.calling" />
+ <feature name="android.hardware.telephony.data" />
+ <feature name="android.hardware.telephony.messaging" />
</permissions>
diff --git a/data/etc/android.hardware.telephony.radio.xml b/data/etc/android.hardware.telephony.radio.xml
new file mode 100644
index 0000000..4377705
--- /dev/null
+++ b/data/etc/android.hardware.telephony.radio.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard set of features for devices to support Telephony Radio Access API. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.radio" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.subscription.xml b/data/etc/android.hardware.telephony.subscription.xml
new file mode 100644
index 0000000..449a2a6
--- /dev/null
+++ b/data/etc/android.hardware.telephony.subscription.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard set of features for devices to support Telephony Subscription API. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.subscription" />
+</permissions>
diff --git a/data/etc/android.software.telecom.xml b/data/etc/android.software.telecom.xml
new file mode 100644
index 0000000..db28ba6
--- /dev/null
+++ b/data/etc/android.software.telecom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- This is the standard set of features for devices that support the Telecom API. -->
+<permissions>
+ <feature name="android.software.telecom" />
+</permissions>
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index cc0ee82..95b8110 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -38,7 +38,7 @@
<feature name="android.hardware.security.model.compatible" />
<!-- basic system services -->
- <feature name="android.software.connectionservice" />
+ <feature name="android.software.telecom" />
<feature name="android.software.voice_recognizers" notLowRam="true" />
<feature name="android.software.home_screen" />
<feature name="android.software.companion_device_setup" />
diff --git a/data/etc/go_handheld_core_hardware.xml b/data/etc/go_handheld_core_hardware.xml
index e6db4ad..d601931 100644
--- a/data/etc/go_handheld_core_hardware.xml
+++ b/data/etc/go_handheld_core_hardware.xml
@@ -37,7 +37,7 @@
<feature name="android.hardware.security.model.compatible" />
<!-- basic system services -->
- <feature name="android.software.connectionservice" />
+ <feature name="android.software.telecom" />
<feature name="android.software.backup" />
<feature name="android.software.home_screen" />
<feature name="android.software.input_methods" />
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 41f1514..68b8def 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -42,7 +42,7 @@
<!-- basic system services -->
<feature name="android.software.app_widgets" />
- <feature name="android.software.connectionservice" />
+ <feature name="android.software.telecom" />
<feature name="android.software.voice_recognizers" notLowRam="true" />
<feature name="android.software.backup" />
<feature name="android.software.home_screen" />
diff --git a/include/android/input.h b/include/android/input.h
index 27587ce..fbd61b5 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -1386,12 +1386,15 @@
void AInputQueue_finishEvent(AInputQueue* queue, AInputEvent* event, int handled);
/**
- * Supplies the AInputQueue* object associated with the supplied Java InputQueue
- * object.
+ * Returns the AInputQueue* object associated with the supplied Java InputQueue
+ * object. The returned native object holds a weak reference to the Java object,
+ * and is only valid as long as the Java object has not yet been disposed. You
+ * should ensure that there is a strong reference to the Java object and that it
+ * has not been disposed before using the returned object.
*
* Available since API level 33.
*/
-AInputQueue* AInputQueue_fromJava(jobject inputQueue) __INTRODUCED_IN(33);
+AInputQueue* AInputQueue_fromJava(JNIEnv* env, jobject inputQueue) __INTRODUCED_IN(33);
#ifdef __cplusplus
}
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 059bc41..3a13104 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -595,6 +595,15 @@
bool enableBackPressure)
__INTRODUCED_IN(31);
+/**
+ * Sets the frame timeline to use.
+ *
+ * \param vsyncId The vsync ID received from AChoreographer, setting the frame's present target to
+ * the corresponding expected present time and deadline from the frame to be rendered.
+ */
+void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* transaction,
+ int64_t vsyncId) __INTRODUCED_IN(33);
+
__END_DECLS
#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h
index 2c6eacb..dfb0ff5 100644
--- a/include/powermanager/PowerHalWrapper.h
+++ b/include/powermanager/PowerHalWrapper.h
@@ -201,10 +201,8 @@
std::array<std::atomic<HalSupport>,
static_cast<int32_t>(hardware::power::Boost::DISPLAY_UPDATE_IMMINENT) + 1>
mBoostSupportedArray GUARDED_BY(mBoostMutex) = {HalSupport::UNKNOWN};
- // Android framework only sends mode upto DISPLAY_INACTIVE.
- // Need to increase the array if more mode supported.
std::array<std::atomic<HalSupport>,
- static_cast<int32_t>(hardware::power::Mode::DISPLAY_INACTIVE) + 1>
+ static_cast<int32_t>(*(android::enum_range<hardware::power::Mode>().end() - 1)) + 1>
mModeSupportedArray GUARDED_BY(mModeMutex) = {HalSupport::UNKNOWN};
};
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 4f21cda..9abe4b5 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -176,6 +176,11 @@
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
+ if (mMaxThreads == 0) {
+ ALOGW("Extra binder thread started, but 0 threads requested. Do not use "
+ "*startThreadPool when zero threads are requested.");
+ }
+
mThreadPoolStarted = true;
spawnPooledThread(true);
}
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 9670d7b..8dbdc1d 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -16,6 +16,7 @@
#pragma once
+#include <array>
#include <map> // for legacy reasons
#include <string>
#include <type_traits>
@@ -224,6 +225,15 @@
return writeData(val);
}
+ template <typename T, size_t N>
+ status_t writeFixedArray(const std::array<T, N>& val) {
+ return writeData(val);
+ }
+ template <typename T, size_t N>
+ status_t writeFixedArray(const std::optional<std::array<T, N>>& val) {
+ return writeData(val);
+ }
+
// Write an Enum vector with underlying type int8_t.
// Does not use padding; each byte is contiguous.
template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
@@ -487,6 +497,15 @@
std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const __attribute__((deprecated("use std::optional version instead")));
status_t readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
+ template <typename T, size_t N>
+ status_t readFixedArray(std::array<T, N>* val) const {
+ return readData(val);
+ }
+ template <typename T, size_t N>
+ status_t readFixedArray(std::optional<std::array<T, N>>* val) const {
+ return readData(val);
+ }
+
template<typename T>
status_t read(Flattenable<T>& val) const;
@@ -818,6 +837,16 @@
|| is_specialization_v<T, std::unique_ptr>
|| is_specialization_v<T, std::shared_ptr>;
+ // Tells if T is a fixed-size array.
+ template <typename T>
+ struct is_fixed_array : std::false_type {};
+
+ template <typename T, size_t N>
+ struct is_fixed_array<std::array<T, N>> : std::true_type {};
+
+ template <typename T>
+ static inline constexpr bool is_fixed_array_v = is_fixed_array<T>::value;
+
// special int32 value to indicate NonNull or Null parcelables
// This is fixed to be only 0 or 1 by contract, do not change.
static constexpr int32_t kNonNullParcelableFlag = 1;
@@ -922,7 +951,9 @@
if (!c) return writeData(static_cast<int32_t>(kNullVectorSize));
} else if constexpr (std::is_base_of_v<Parcelable, T>) {
if (!c) return writeData(static_cast<int32_t>(kNullParcelableFlag));
- } else /* constexpr */ { // could define this, but raise as error.
+ } else if constexpr (is_fixed_array_v<T>) {
+ if (!c) return writeData(static_cast<int32_t>(kNullVectorSize));
+ } else /* constexpr */ { // could define this, but raise as error.
static_assert(dependent_false_v<CT>);
}
return writeData(*c);
@@ -961,6 +992,23 @@
return OK;
}
+ template <typename T, size_t N>
+ status_t writeData(const std::array<T, N>& val) {
+ static_assert(N <= std::numeric_limits<int32_t>::max());
+ status_t status = writeData(static_cast<int32_t>(N));
+ if (status != OK) return status;
+ if constexpr (is_pointer_equivalent_array_v<T>) {
+ static_assert(N <= std::numeric_limits<size_t>::max() / sizeof(T));
+ return write(val.data(), val.size() * sizeof(T));
+ } else /* constexpr */ {
+ for (const auto& t : val) {
+ status = writeData(t);
+ if (status != OK) return status;
+ }
+ return OK;
+ }
+ }
+
// readData function overloads.
// Implementation detail: Function overloading improves code readability over
// template overloading, but prevents readData<T> from being used for those types.
@@ -1053,9 +1101,8 @@
int32_t peek;
status_t status = readData(&peek);
if (status != OK) return status;
- if constexpr (is_specialization_v<T, std::vector>
- || std::is_same_v<T, String16>
- || std::is_same_v<T, std::string>) {
+ if constexpr (is_specialization_v<T, std::vector> || is_fixed_array_v<T> ||
+ std::is_same_v<T, String16> || std::is_same_v<T, std::string>) {
if (peek == kNullVectorSize) {
c->reset();
return OK;
@@ -1065,12 +1112,15 @@
c->reset();
return OK;
}
- } else /* constexpr */ { // could define this, but raise as error.
+ } else /* constexpr */ { // could define this, but raise as error.
static_assert(dependent_false_v<CT>);
}
// create a new object.
if constexpr (is_specialization_v<CT, std::optional>) {
- c->emplace();
+ // Call default constructor explicitly
+ // - Clang bug: https://bugs.llvm.org/show_bug.cgi?id=35748
+ // std::optional::emplace() doesn't work with nested types.
+ c->emplace(T());
} else /* constexpr */ {
T* const t = new (std::nothrow) T; // contents read from Parcel below.
if (t == nullptr) return NO_MEMORY;
@@ -1079,7 +1129,7 @@
// rewind data ptr to reread (this is pretty quick), otherwise we could
// pass an optional argument to readData to indicate a peeked value.
setDataPosition(startPos);
- if constexpr (is_specialization_v<T, std::vector>) {
+ if constexpr (is_specialization_v<T, std::vector> || is_fixed_array_v<T>) {
return readData(&**c, READ_FLAG_SP_NULLABLE); // nullable sp<> allowed now
} else {
return readData(&**c);
@@ -1142,6 +1192,41 @@
return OK;
}
+ template <typename T, size_t N>
+ status_t readData(std::array<T, N>* val, ReadFlags readFlags = READ_FLAG_NONE) const {
+ static_assert(N <= std::numeric_limits<int32_t>::max());
+ int32_t size;
+ status_t status = readInt32(&size);
+ if (status != OK) return status;
+ if (size < 0) return UNEXPECTED_NULL;
+ if (size != static_cast<int32_t>(N)) return BAD_VALUE;
+ if constexpr (is_pointer_equivalent_array_v<T>) {
+ auto data = reinterpret_cast<const T*>(readInplace(N * sizeof(T)));
+ if (data == nullptr) return BAD_VALUE;
+ memcpy(val->data(), data, N * sizeof(T));
+ } else if constexpr (is_specialization_v<T, sp>) {
+ for (auto& t : *val) {
+ if (readFlags & READ_FLAG_SP_NULLABLE) {
+ status = readNullableStrongBinder(&t); // allow nullable
+ } else {
+ status = readStrongBinder(&t);
+ }
+ if (status != OK) return status;
+ }
+ } else if constexpr (is_fixed_array_v<T>) { // pass readFlags down to nested arrays
+ for (auto& t : *val) {
+ status = readData(&t, readFlags);
+ if (status != OK) return status;
+ }
+ } else /* constexpr */ {
+ for (auto& t : *val) {
+ status = readData(&t);
+ if (status != OK) return status;
+ }
+ }
+ return OK;
+ }
+
//-----------------------------------------------------------------------------
private:
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 6949c2c..28e3ff4 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -799,3 +799,12 @@
void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) {
binder->asABBinder()->setMinSchedulerPolicy(policy, priority);
}
+
+void AIBinder_setInheritRt(AIBinder* binder, bool inheritRt) {
+ ABBinder* localBinder = binder->asABBinder();
+ if (localBinder == nullptr) {
+ LOG(FATAL) << "AIBinder_setInheritRt must be called on a local binder";
+ }
+
+ localBinder->setInheritRt(inheritRt);
+}
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
index aa3b978..972eca7 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -46,6 +46,18 @@
AParcelableHolder() = delete;
explicit AParcelableHolder(parcelable_stability_t stability)
: mParcel(AParcel_create()), mStability(stability) {}
+
+#if __ANDROID_API__ >= 31
+ AParcelableHolder(const AParcelableHolder& other)
+ : mParcel(AParcel_create()), mStability(other.mStability) {
+ // AParcelableHolder has been introduced in 31.
+ if (__builtin_available(android 31, *)) {
+ AParcel_appendFrom(other.mParcel.get(), this->mParcel.get(), 0,
+ AParcel_getDataSize(other.mParcel.get()));
+ }
+ }
+#endif
+
AParcelableHolder(AParcelableHolder&& other) = default;
virtual ~AParcelableHolder() = default;
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index b0217c4..0549198 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -68,4 +68,15 @@
*/
void AIBinder_setMinSchedulerPolicy(AIBinder* binder, int policy, int priority) __INTRODUCED_IN(33);
+/**
+ * Allow the binder to inherit realtime scheduling policies from its caller.
+ *
+ * This must be called before the object is sent to another process. Not thread
+ * safe.
+ *
+ * \param inheritRt whether to inherit realtime scheduling policies (default is
+ * false).
+ */
+void AIBinder_setInheritRt(AIBinder* binder, bool inheritRt) __INTRODUCED_IN(33);
+
__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 197c0a1..3824a1b 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -146,6 +146,7 @@
AIBinder_Class_disableInterfaceTokenHeader;
AIBinder_DeathRecipient_setOnUnlinked;
AIBinder_isHandlingTransaction;
+ AIBinder_setInheritRt; # llndk
AIBinder_setMinSchedulerPolicy; # llndk
AParcel_marshal;
AParcel_unmarshal;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 499f88e..58fa13a 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -505,6 +505,31 @@
}
};
+TEST(NdkBinder, SetInheritRt) {
+ // functional test in binderLibTest
+ sp<IFoo> foo = sp<MyTestFoo>::make();
+ AIBinder* binder = foo->getBinder();
+
+ // does not abort
+ AIBinder_setInheritRt(binder, true);
+ AIBinder_setInheritRt(binder, false);
+ AIBinder_setInheritRt(binder, true);
+
+ AIBinder_decStrong(binder);
+}
+
+TEST(NdkBinder, SetInheritRtNonLocal) {
+ AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+ ASSERT_NE(binder, nullptr);
+
+ ASSERT_TRUE(AIBinder_isRemote(binder));
+
+ EXPECT_DEATH(AIBinder_setInheritRt(binder, true), "");
+ EXPECT_DEATH(AIBinder_setInheritRt(binder, false), "");
+
+ AIBinder_decStrong(binder);
+}
+
TEST(NdkBinder, AddNullService) {
EXPECT_EQ(EX_ILLEGAL_ARGUMENT, AServiceManager_addService(nullptr, "any-service-name"));
}
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index b0dea94..4d3d59a 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -60,6 +60,16 @@
}
}
+impl PartialEq for ParcelFileDescriptor {
+ // Since ParcelFileDescriptors own the FD, if this function ever returns true (and it is used to
+ // compare two different objects), then it would imply that an FD is double-owned.
+ fn eq(&self, other: &Self) -> bool {
+ self.as_raw_fd() == other.as_raw_fd()
+ }
+}
+
+impl Eq for ParcelFileDescriptor {}
+
impl Serialize for ParcelFileDescriptor {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
let fd = self.0.as_raw_fd();
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 9007cba..61f88b6 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -652,6 +652,39 @@
}
}
+impl<T: SerializeArray, const N: usize> Serialize for [T; N] {
+ fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
+ // forwards to T::serialize_array.
+ SerializeArray::serialize_array(self, parcel)
+ }
+}
+
+impl<T: SerializeArray, const N: usize> SerializeOption for [T; N] {
+ fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
+ SerializeOption::serialize_option(this.map(|arr| &arr[..]), parcel)
+ }
+}
+
+impl<T: SerializeArray, const N: usize> SerializeArray for [T; N] {}
+
+impl<T: DeserializeArray, const N: usize> Deserialize for [T; N] {
+ fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
+ let vec = DeserializeArray::deserialize_array(parcel)
+ .transpose()
+ .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))?;
+ vec.try_into().or(Err(StatusCode::BAD_VALUE))
+ }
+}
+
+impl<T: DeserializeArray, const N: usize> DeserializeOption for [T; N] {
+ fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
+ let vec = DeserializeArray::deserialize_array(parcel)?;
+ vec.map(|v| v.try_into().or(Err(StatusCode::BAD_VALUE))).transpose()
+ }
+}
+
+impl<T: DeserializeArray, const N: usize> DeserializeArray for [T; N] {}
+
impl Serialize for Stability {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
i32::from(*self).serialize(parcel)
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 32406e5..077d915 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -233,6 +233,32 @@
PARCEL_READ_WITH_STATUS(std::optional<std::vector<std::optional<std::string>>>, readUtf8VectorFromUtf16Vector),
PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
+#define COMMA ,
+ PARCEL_READ_WITH_STATUS(std::array<uint8_t COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<uint8_t COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<char16_t COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<char16_t COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<std::string COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<std::optional<std::string> COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<android::String16 COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<std::optional<android::String16> COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<android::sp<android::IBinder> COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<android::sp<android::IBinder> COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<ExampleParcelable COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<std::optional<ExampleParcelable> COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<ByteEnum COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<ByteEnum COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<IntEnum COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<IntEnum COMMA 3>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<LongEnum COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<LongEnum COMMA 3>>, readFixedArray),
+ // nested arrays
+ PARCEL_READ_WITH_STATUS(std::array<std::array<uint8_t COMMA 3> COMMA 4>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<uint8_t COMMA 3> COMMA 4>>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::array<ExampleParcelable COMMA 3>, readFixedArray),
+ PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<std::optional<ExampleParcelable> COMMA 3> COMMA 4>>, readFixedArray),
+#undef COMMA
+
[] (const android::Parcel& p, uint8_t /*len*/) {
FUZZ_LOG() << "about to read flattenable";
ExampleFlattenable f;
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index 570af71..1fd2c62 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -12,7 +12,7 @@
srcs: ["cputimeinstate.cpp"],
shared_libs: [
"libbase",
- "libbpf",
+ "libbpf_bcc",
"libbpf_android",
"liblog",
"libnetdutils"
@@ -31,7 +31,7 @@
srcs: ["testtimeinstate.cpp"],
shared_libs: [
"libbase",
- "libbpf",
+ "libbpf_bcc",
"libbpf_android",
"libtimeinstate",
"libnetdutils",
diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp
index 9231a57..3800b88 100644
--- a/libs/gui/FrameTimelineInfo.cpp
+++ b/libs/gui/FrameTimelineInfo.cpp
@@ -33,12 +33,14 @@
status_t FrameTimelineInfo::write(Parcel& output) const {
SAFE_PARCEL(output.writeInt64, vsyncId);
SAFE_PARCEL(output.writeInt32, inputEventId);
+ SAFE_PARCEL(output.writeInt64, startTimeNanos);
return NO_ERROR;
}
status_t FrameTimelineInfo::read(const Parcel& input) {
SAFE_PARCEL(input.readInt64, &vsyncId);
SAFE_PARCEL(input.readInt32, &inputEventId);
+ SAFE_PARCEL(input.readInt64, &startTimeNanos);
return NO_ERROR;
}
@@ -48,16 +50,19 @@
if (other.vsyncId > vsyncId) {
vsyncId = other.vsyncId;
inputEventId = other.inputEventId;
+ startTimeNanos = other.startTimeNanos;
}
} else if (vsyncId == INVALID_VSYNC_ID) {
vsyncId = other.vsyncId;
inputEventId = other.inputEventId;
+ startTimeNanos = other.startTimeNanos;
}
}
void FrameTimelineInfo::clear() {
vsyncId = INVALID_VSYNC_ID;
inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID;
+ startTimeNanos = 0;
}
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 353a91d..20c4146 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1846,9 +1846,10 @@
ATRACE_CALL();
auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
+ auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t));
ALOGV("Surface::%s", __func__);
- return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
+ return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId, startTimeNanos});
}
bool Surface::transformToDisplayInverse() const {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index aafa5e4..cf04ec8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1104,7 +1104,8 @@
}
if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) ||
(mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot) ||
- (mask & layer_state_t::eEnableBackpressure)) {
+ (mask & layer_state_t::eEnableBackpressure) ||
+ (mask & layer_state_t::eLayerIsDisplayDecoration)) {
s->what |= layer_state_t::eFlagsChanged;
}
s->flags &= ~mask;
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
index a23c202..255ce56 100644
--- a/libs/gui/include/gui/FrameTimelineInfo.h
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -36,6 +36,9 @@
// not directly vendor available.
int32_t inputEventId = 0;
+ // The current time in nanoseconds the application started to render the frame.
+ int64_t startTimeNanos = 0;
+
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index b01eed4..a0d3162 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -109,6 +109,7 @@
// set. This blocks the client until all the buffers have been presented. If the buffers
// have presentation timestamps, then we may drop buffers.
eEnableBackpressure = 0x100, // ENABLE_BACKPRESSURE
+ eLayerIsDisplayDecoration = 0x200, // DISPLAY_DECORATION
};
enum {
diff --git a/libs/gui/include/gui/TraceUtils.h b/libs/gui/include/gui/TraceUtils.h
index b9ec14a..e5d2684 100644
--- a/libs/gui/include/gui/TraceUtils.h
+++ b/libs/gui/include/gui/TraceUtils.h
@@ -16,6 +16,8 @@
#pragma once
+#include <stdarg.h>
+
#include <cutils/trace.h>
#include <utils/Trace.h>
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 0bc2b5d..a319769 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1025,10 +1025,11 @@
}
static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
- int64_t frameTimelineVsyncId,
- int32_t inputEventId) {
- return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO,
- frameTimelineVsyncId, inputEventId);
+ int64_t frameTimelineVsyncId,
+ int32_t inputEventId,
+ int64_t startTimeNanos) {
+ return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, frameTimelineVsyncId,
+ inputEventId, startTimeNanos);
}
// ------------------------------------------------------------------------------------------------
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 3d446e8..08fc814 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -178,6 +178,10 @@
void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
ATRACE_CALL();
+ // This is a no-op in SkiaRenderEngine.
+ if (getRenderEngineType() != RenderEngineType::THREADED) {
+ return;
+ }
std::promise<void> resultPromise;
std::future<void> resultFuture = resultPromise.get_future();
{
@@ -194,6 +198,10 @@
void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
ATRACE_CALL();
+ // This is a no-op in SkiaRenderEngine.
+ if (getRenderEngineType() != RenderEngineType::THREADED) {
+ return;
+ }
std::promise<void> resultPromise;
std::future<void> resultFuture = resultPromise.get_future();
{
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index a7b5900..936e653 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -138,6 +138,7 @@
"HdrCapabilities.cpp",
"PixelFormat.cpp",
"PublicFormat.cpp",
+ "StaticAsserts.cpp",
"StaticDisplayInfo.cpp",
],
diff --git a/libs/ui/StaticAsserts.cpp b/libs/ui/StaticAsserts.cpp
new file mode 100644
index 0000000..85da64f
--- /dev/null
+++ b/libs/ui/StaticAsserts.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/PixelFormat.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+
+// Ideally, PIXEL_FORMAT_R_8 would simply be defined to match the aidl PixelFormat, but
+// PixelFormat.h (where PIXEL_FORMAT_R_8 is defined) is pulled in by builds for
+// which there is no aidl build (e.g. Windows).
+static_assert(android::PIXEL_FORMAT_R_8 ==static_cast<int32_t>(
+ aidl::android::hardware::graphics::common::PixelFormat::R_8));
diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp
index 830e53d..24087ac 100644
--- a/services/gpuservice/gpumem/Android.bp
+++ b/services/gpuservice/gpumem/Android.bp
@@ -28,7 +28,7 @@
],
shared_libs: [
"libbase",
- "libbpf",
+ "libbpf_bcc",
"libbpf_android",
"libcutils",
"liblog",
diff --git a/services/gpuservice/gpuservice.rc b/services/gpuservice/gpuservice.rc
index 65a5c27..0da8bd3 100644
--- a/services/gpuservice/gpuservice.rc
+++ b/services/gpuservice/gpuservice.rc
@@ -1,4 +1,4 @@
service gpu /system/bin/gpuservice
class core
user gpu_service
- group graphics
+ group graphics readtracefs
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 6d87c45..5b69f96 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -34,7 +34,7 @@
],
shared_libs: [
"libbase",
- "libbpf",
+ "libbpf_bcc",
"libbpf_android",
"libcutils",
"libgfxstats",
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index f50c9e1..b0fa678 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -6319,4 +6319,19 @@
mDispatcher.onWindowInfosChanged(windowInfos, displayInfos);
}
+void InputDispatcher::cancelCurrentTouch() {
+ {
+ std::scoped_lock _l(mLock);
+ ALOGD("Canceling all ongoing pointer gestures on all displays.");
+ CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
+ "cancel current touch");
+ synthesizeCancelationEventsForAllConnectionsLocked(options);
+
+ mTouchStatesByDisplay.clear();
+ mLastHoverWindowHandle.clear();
+ }
+ // Wake up poll loop since there might be work to do.
+ mLooper->wake();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 8a551cf..e9591e4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -146,6 +146,8 @@
void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos,
const std::vector<android::gui::DisplayInfo>& displayInfos);
+ void cancelCurrentTouch() override;
+
private:
enum class DropReason {
NOT_DROPPED,
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 714e7a0..c469ec3 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -211,6 +211,11 @@
* Called when a display has been removed from the system.
*/
virtual void displayRemoved(int32_t displayId) = 0;
+
+ /*
+ * Abort the current touch stream.
+ */
+ virtual void cancelCurrentTouch() = 0;
};
} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 2c64271..3c6f1ff 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -3796,6 +3796,49 @@
secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT);
}
+TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
+ FakeMonitorReceiver monitorInPrimary =
+ FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT);
+ FakeMonitorReceiver monitorInSecondary =
+ FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID);
+
+ // Test touch down on primary display.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT);
+
+ // Test touch down on second display.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
+ monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
+
+ // Trigger cancel touch.
+ mDispatcher->cancelCurrentTouch();
+ windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT);
+ monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT);
+ windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
+ monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
+
+ // Test inject a move motion event, no window/monitor should receive the event.
+ ASSERT_EQ(InputEventInjectionResult::FAILED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {110, 200}))
+ << "Inject motion event should return InputEventInjectionResult::FAILED";
+ windowInPrimary->assertNoEvents();
+ monitorInPrimary.assertNoEvents();
+
+ ASSERT_EQ(InputEventInjectionResult::FAILED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ SECOND_DISPLAY_ID, {110, 200}))
+ << "Inject motion event should return InputEventInjectionResult::FAILED";
+ windowInSecondary->assertNoEvents();
+ monitorInSecondary.assertNoEvents();
+}
+
class InputFilterTest : public InputDispatcherTest {
protected:
void testNotifyMotion(int32_t displayId, bool expectToBeFiltered,
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index d828aa9..6fbba3f 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -24,11 +24,11 @@
],
aidl: {
- local_include_dirs: ["include"],
- include_dirs: [
- "frameworks/base/core/java/android/os",
- ],
- export_aidl_headers: true
+ local_include_dirs: ["include"],
+ include_dirs: [
+ "frameworks/base/core/java/android/os",
+ ],
+ export_aidl_headers: true,
},
shared_libs: [
@@ -38,7 +38,7 @@
"libutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V3-cpp",
],
cflags: [
@@ -50,6 +50,6 @@
local_include_dirs: ["include"],
export_include_dirs: [
- "include",
+ "include",
],
}
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
index 3997929..fcb012f 100644
--- a/services/powermanager/benchmarks/Android.bp
+++ b/services/powermanager/benchmarks/Android.bp
@@ -38,7 +38,7 @@
"libutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V3-cpp",
],
static_libs: [
"libtestUtil",
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
index 659b2d2..2d1558a 100644
--- a/services/powermanager/tests/Android.bp
+++ b/services/powermanager/tests/Android.bp
@@ -46,7 +46,7 @@
"libutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
- "android.hardware.power-V2-cpp",
+ "android.hardware.power-V3-cpp",
],
static_libs: [
"libgmock",
diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
index d890f5c..cb1a77a 100644
--- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
+++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp
@@ -183,6 +183,10 @@
auto result = mWrapper->setMode(Mode::LAUNCH, true);
ASSERT_TRUE(result.isUnsupported());
+
+ EXPECT_CALL(*mMockHal.get(), isModeSupported(Eq(Mode::CAMERA_STREAMING_HIGH), _))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status())));
result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true);
ASSERT_TRUE(result.isUnsupported());
}
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index b596708..dccbeb0 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -15,6 +15,7 @@
"CorrectedGyroSensor.cpp",
"Fusion.cpp",
"GravitySensor.cpp",
+ "HidlSensorHalWrapper.cpp",
"LinearAccelerationSensor.cpp",
"OrientationSensor.cpp",
"RecentEventLogger.cpp",
diff --git a/services/sensorservice/HidlSensorHalWrapper.cpp b/services/sensorservice/HidlSensorHalWrapper.cpp
new file mode 100644
index 0000000..dbb3da1
--- /dev/null
+++ b/services/sensorservice/HidlSensorHalWrapper.cpp
@@ -0,0 +1,562 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "HidlSensorHalWrapper.h"
+#include "android/hardware/sensors/2.0/types.h"
+#include "android/hardware/sensors/2.1/ISensorsCallback.h"
+#include "android/hardware/sensors/2.1/types.h"
+#include "convertV2_1.h"
+
+#include <android-base/logging.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::sensors::V1_0::RateLevel;
+using android::hardware::sensors::V1_0::Result;
+using android::hardware::sensors::V1_0::SharedMemFormat;
+using android::hardware::sensors::V1_0::SharedMemInfo;
+using android::hardware::sensors::V1_0::SharedMemType;
+using android::hardware::sensors::V2_0::EventQueueFlagBits;
+using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
+using android::hardware::sensors::V2_1::Event;
+using android::hardware::sensors::V2_1::ISensorsCallback;
+using android::hardware::sensors::V2_1::implementation::convertFromSensorEvent;
+using android::hardware::sensors::V2_1::implementation::convertToNewEvents;
+using android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
+using android::hardware::sensors::V2_1::implementation::convertToSensor;
+using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV1_0;
+using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_0;
+using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_1;
+
+namespace android {
+
+namespace {
+
+status_t statusFromResult(Result result) {
+ switch (result) {
+ case Result::OK:
+ return OK;
+ case Result::BAD_VALUE:
+ return BAD_VALUE;
+ case Result::PERMISSION_DENIED:
+ return PERMISSION_DENIED;
+ case Result::INVALID_OPERATION:
+ return INVALID_OPERATION;
+ case Result::NO_MEMORY:
+ return NO_MEMORY;
+ }
+}
+
+template <typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
+ return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+enum EventQueueFlagBitsInternal : uint32_t {
+ INTERNAL_WAKE = 1 << 16,
+};
+
+} // anonymous namespace
+
+void SensorsHalDeathReceiver::serviceDied(
+ uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
+ ALOGW("Sensors HAL died, attempting to reconnect.");
+ mHidlSensorHalWrapper->prepareForReconnect();
+}
+
+struct SensorsCallback : public ISensorsCallback {
+ using Result = ::android::hardware::sensors::V1_0::Result;
+ using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
+
+ SensorsCallback(ISensorHalWrapper::SensorDeviceCallback* sensorDeviceCallback) {
+ mSensorDeviceCallback = sensorDeviceCallback;
+ }
+
+ Return<void> onDynamicSensorsConnected_2_1(
+ const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
+ std::vector<sensor_t> sensors;
+ for (const android::hardware::sensors::V2_1::SensorInfo& info : dynamicSensorsAdded) {
+ sensor_t sensor;
+ convertToSensor(info, &sensor);
+ sensors.push_back(sensor);
+ }
+
+ mSensorDeviceCallback->onDynamicSensorsConnected(sensors);
+ return Return<void>();
+ }
+
+ Return<void> onDynamicSensorsConnected(
+ const hidl_vec<android::hardware::sensors::V1_0::SensorInfo>& dynamicSensorsAdded)
+ override {
+ return onDynamicSensorsConnected_2_1(convertToNewSensorInfos(dynamicSensorsAdded));
+ }
+
+ Return<void> onDynamicSensorsDisconnected(
+ const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
+ mSensorDeviceCallback->onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved);
+ return Return<void>();
+ }
+
+private:
+ ISensorHalWrapper::SensorDeviceCallback* mSensorDeviceCallback;
+};
+
+bool HidlSensorHalWrapper::supportsPolling() {
+ return mSensors->supportsPolling();
+}
+
+bool HidlSensorHalWrapper::supportsMessageQueues() {
+ return mSensors->supportsMessageQueues();
+}
+
+bool HidlSensorHalWrapper::connect(SensorDeviceCallback* callback) {
+ mSensorDeviceCallback = callback;
+ bool ret = connectHidlService();
+ if (mEventQueueFlag != nullptr) {
+ mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+ }
+ return ret;
+}
+
+void HidlSensorHalWrapper::prepareForReconnect() {
+ mReconnecting = true;
+ if (mEventQueueFlag != nullptr) {
+ mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+ }
+}
+
+ssize_t HidlSensorHalWrapper::poll(sensors_event_t* buffer, size_t count) {
+ ssize_t err;
+ int numHidlTransportErrors = 0;
+ bool hidlTransportError = false;
+
+ do {
+ auto ret = mSensors->poll(
+ count, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+ if (result == Result::OK) {
+ convertToSensorEventsAndQuantize(convertToNewEvents(events),
+ convertToNewSensorInfos(
+ dynamicSensorsAdded),
+ buffer);
+ err = (ssize_t)events.size();
+ } else {
+ err = statusFromResult(result);
+ }
+ });
+
+ if (ret.isOk()) {
+ hidlTransportError = false;
+ } else {
+ hidlTransportError = true;
+ numHidlTransportErrors++;
+ if (numHidlTransportErrors > 50) {
+ // Log error and bail
+ ALOGE("Max Hidl transport errors this cycle : %d", numHidlTransportErrors);
+ handleHidlDeath(ret.description());
+ } else {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ }
+ } while (hidlTransportError);
+
+ if (numHidlTransportErrors > 0) {
+ ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
+ HidlTransportErrorLog errLog(time(nullptr), numHidlTransportErrors);
+ mHidlTransportErrors.add(errLog);
+ mTotalHidlTransportErrors++;
+ }
+
+ return err;
+}
+
+ssize_t HidlSensorHalWrapper::pollFmq(sensors_event_t* buffer, size_t maxNumEventsToRead) {
+ ssize_t eventsRead = 0;
+ size_t availableEvents = mSensors->getEventQueue()->availableToRead();
+
+ if (availableEvents == 0) {
+ uint32_t eventFlagState = 0;
+
+ // Wait for events to become available. This is necessary so that the Event FMQ's read() is
+ // able to be called with the correct number of events to read. If the specified number of
+ // events is not available, then read() would return no events, possibly introducing
+ // additional latency in delivering events to applications.
+ if (mEventQueueFlag != nullptr) {
+ mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS) |
+ asBaseType(INTERNAL_WAKE),
+ &eventFlagState);
+ }
+ availableEvents = mSensors->getEventQueue()->availableToRead();
+
+ if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
+ ALOGD("Event FMQ internal wake, returning from poll with no events");
+ return DEAD_OBJECT;
+ }
+ }
+
+ size_t eventsToRead = std::min({availableEvents, maxNumEventsToRead, mEventBuffer.size()});
+ if (eventsToRead > 0) {
+ if (mSensors->getEventQueue()->read(mEventBuffer.data(), eventsToRead)) {
+ // Notify the Sensors HAL that sensor events have been read. This is required to support
+ // the use of writeBlocking by the Sensors HAL.
+ if (mEventQueueFlag != nullptr) {
+ mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
+ }
+
+ for (size_t i = 0; i < eventsToRead; i++) {
+ convertToSensorEvent(mEventBuffer[i], &buffer[i]);
+ android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
+ getResolutionForSensor(
+ buffer[i].sensor));
+ }
+ eventsRead = eventsToRead;
+ } else {
+ ALOGW("Failed to read %zu events, currently %zu events available", eventsToRead,
+ availableEvents);
+ }
+ }
+
+ return eventsRead;
+}
+
+std::vector<sensor_t> HidlSensorHalWrapper::getSensorsList() {
+ std::vector<sensor_t> sensorsFound;
+ if (mSensors != nullptr) {
+ checkReturn(mSensors->getSensorsList([&](const auto& list) {
+ for (size_t i = 0; i < list.size(); i++) {
+ sensor_t sensor;
+ convertToSensor(list[i], &sensor);
+ sensorsFound.push_back(sensor);
+
+ // Only disable all sensors on HAL 1.0 since HAL 2.0
+ // handles this in its initialize method
+ if (!mSensors->supportsMessageQueues()) {
+ checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
+ }
+ }
+ }));
+ }
+
+ return sensorsFound;
+}
+
+status_t HidlSensorHalWrapper::setOperationMode(SensorService::Mode mode) {
+ if (mSensors == nullptr) return NO_INIT;
+ return checkReturnAndGetStatus(
+ mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+}
+
+status_t HidlSensorHalWrapper::activate(int32_t sensorHandle, bool enabled) {
+ if (mSensors == nullptr) return NO_INIT;
+ return checkReturnAndGetStatus(mSensors->activate(sensorHandle, enabled));
+}
+
+status_t HidlSensorHalWrapper::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) {
+ if (mSensors == nullptr) return NO_INIT;
+ return checkReturnAndGetStatus(
+ mSensors->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs));
+}
+
+status_t HidlSensorHalWrapper::flush(int32_t sensorHandle) {
+ if (mSensors == nullptr) return NO_INIT;
+ return checkReturnAndGetStatus(mSensors->flush(sensorHandle));
+}
+
+status_t HidlSensorHalWrapper::injectSensorData(const sensors_event_t* event) {
+ if (mSensors == nullptr) return NO_INIT;
+
+ Event ev;
+ convertFromSensorEvent(*event, &ev);
+ return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
+}
+
+status_t HidlSensorHalWrapper::registerDirectChannel(const sensors_direct_mem_t* memory,
+ int32_t* /*channelHandle*/) {
+ if (mSensors == nullptr) return NO_INIT;
+
+ SharedMemType type;
+ switch (memory->type) {
+ case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
+ type = SharedMemType::ASHMEM;
+ break;
+ case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
+ type = SharedMemType::GRALLOC;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ SharedMemFormat format;
+ if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
+ return BAD_VALUE;
+ }
+ format = SharedMemFormat::SENSORS_EVENT;
+
+ SharedMemInfo mem = {
+ .type = type,
+ .format = format,
+ .size = static_cast<uint32_t>(memory->size),
+ .memoryHandle = memory->handle,
+ };
+
+ status_t ret;
+ checkReturn(mSensors->registerDirectChannel(mem, [&ret](auto result, auto channelHandle) {
+ if (result == Result::OK) {
+ ret = channelHandle;
+ } else {
+ ret = statusFromResult(result);
+ }
+ }));
+ return ret;
+}
+
+status_t HidlSensorHalWrapper::unregisterDirectChannel(int32_t channelHandle) {
+ if (mSensors == nullptr) return NO_INIT;
+ return checkReturnAndGetStatus(mSensors->unregisterDirectChannel(channelHandle));
+}
+
+status_t HidlSensorHalWrapper::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+ const struct sensors_direct_cfg_t* config) {
+ if (mSensors == nullptr) return NO_INIT;
+
+ RateLevel rate;
+ switch (config->rate_level) {
+ case SENSOR_DIRECT_RATE_STOP:
+ rate = RateLevel::STOP;
+ break;
+ case SENSOR_DIRECT_RATE_NORMAL:
+ rate = RateLevel::NORMAL;
+ break;
+ case SENSOR_DIRECT_RATE_FAST:
+ rate = RateLevel::FAST;
+ break;
+ case SENSOR_DIRECT_RATE_VERY_FAST:
+ rate = RateLevel::VERY_FAST;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ status_t ret;
+ checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
+ [&ret, rate](auto result, auto token) {
+ if (rate == RateLevel::STOP) {
+ ret = statusFromResult(result);
+ } else {
+ if (result == Result::OK) {
+ ret = token;
+ } else {
+ ret = statusFromResult(result);
+ }
+ }
+ }));
+
+ return ret;
+}
+
+void HidlSensorHalWrapper::writeWakeLockHandled(uint32_t count) {
+ if (mWakeLockQueue->write(&count)) {
+ mWakeLockQueueFlag->wake(asBaseType(WakeLockQueueFlagBits::DATA_WRITTEN));
+ } else {
+ ALOGW("Failed to write wake lock handled");
+ }
+}
+
+status_t HidlSensorHalWrapper::checkReturnAndGetStatus(const hardware::Return<Result>& ret) {
+ checkReturn(ret);
+ return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
+}
+
+void HidlSensorHalWrapper::handleHidlDeath(const std::string& detail) {
+ if (!mSensors->supportsMessageQueues()) {
+ // restart is the only option at present.
+ LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
+ } else {
+ ALOGD("ISensors HAL died, death recipient will attempt reconnect");
+ }
+}
+
+bool HidlSensorHalWrapper::connectHidlService() {
+ HalConnectionStatus status = connectHidlServiceV2_1();
+ if (status == HalConnectionStatus::DOES_NOT_EXIST) {
+ status = connectHidlServiceV2_0();
+ }
+
+ if (status == HalConnectionStatus::DOES_NOT_EXIST) {
+ status = connectHidlServiceV1_0();
+ }
+ return (status == HalConnectionStatus::CONNECTED);
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::connectHidlServiceV1_0() {
+ // SensorDevice will wait for HAL service to start if HAL is declared in device manifest.
+ size_t retry = 10;
+ HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+
+ while (retry-- > 0) {
+ sp<android::hardware::sensors::V1_0::ISensors> sensors =
+ android::hardware::sensors::V1_0::ISensors::getService();
+ if (sensors == nullptr) {
+ // no sensor hidl service found
+ connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
+ break;
+ }
+
+ mSensors = new ISensorsWrapperV1_0(sensors);
+ mRestartWaiter->reset();
+ // Poke ISensor service. If it has lingering connection from previous generation of
+ // system server, it will kill itself. There is no intention to handle the poll result,
+ // which will be done since the size is 0.
+ if (mSensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
+ // ok to continue
+ connectionStatus = HalConnectionStatus::CONNECTED;
+ break;
+ }
+
+ // hidl service is restarting, pointer is invalid.
+ mSensors = nullptr;
+ connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
+ ALOGI("%s unsuccessful, remaining retry %zu.", __FUNCTION__, retry);
+ mRestartWaiter->wait();
+ }
+
+ return connectionStatus;
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::connectHidlServiceV2_0() {
+ HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+ sp<android::hardware::sensors::V2_0::ISensors> sensors =
+ android::hardware::sensors::V2_0::ISensors::getService();
+
+ if (sensors == nullptr) {
+ connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
+ } else {
+ mSensors = new ISensorsWrapperV2_0(sensors);
+ connectionStatus = initializeHidlServiceV2_X();
+ }
+
+ return connectionStatus;
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::connectHidlServiceV2_1() {
+ HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+ sp<android::hardware::sensors::V2_1::ISensors> sensors =
+ android::hardware::sensors::V2_1::ISensors::getService();
+
+ if (sensors == nullptr) {
+ connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
+ } else {
+ mSensors = new ISensorsWrapperV2_1(sensors);
+ connectionStatus = initializeHidlServiceV2_X();
+ }
+
+ return connectionStatus;
+}
+
+ISensorHalWrapper::HalConnectionStatus HidlSensorHalWrapper::initializeHidlServiceV2_X() {
+ HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
+
+ mWakeLockQueue =
+ std::make_unique<WakeLockQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
+ true /* configureEventFlagWord */);
+
+ hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
+ hardware::EventFlag::createEventFlag(mSensors->getEventQueue()->getEventFlagWord(),
+ &mEventQueueFlag);
+
+ hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+ hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakeLockQueueFlag);
+
+ CHECK(mSensors != nullptr && mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
+ mWakeLockQueueFlag != nullptr);
+
+ mCallback = new SensorsCallback(mSensorDeviceCallback);
+ status_t status =
+ checkReturnAndGetStatus(mSensors->initialize(*mWakeLockQueue->getDesc(), mCallback));
+
+ if (status != NO_ERROR) {
+ connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
+ ALOGE("Failed to initialize Sensors HAL (%s)", strerror(-status));
+ } else {
+ connectionStatus = HalConnectionStatus::CONNECTED;
+ mSensorsHalDeathReceiver = new SensorsHalDeathReceiver(this);
+ mSensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);
+ }
+
+ return connectionStatus;
+}
+
+void HidlSensorHalWrapper::convertToSensorEvent(const Event& src, sensors_event_t* dst) {
+ android::hardware::sensors::V2_1::implementation::convertToSensorEvent(src, dst);
+
+ if (src.sensorType == android::hardware::sensors::V2_1::SensorType::DYNAMIC_SENSOR_META) {
+ const hardware::sensors::V1_0::DynamicSensorInfo& dyn = src.u.dynamic;
+
+ dst->dynamic_sensor_meta.connected = dyn.connected;
+ dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
+ if (dyn.connected) {
+ std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
+ // Give MAX_DYN_SENSOR_WAIT_SEC for onDynamicSensorsConnected to be invoked since it
+ // can be received out of order from this event due to a bug in the HIDL spec that
+ // marks it as oneway.
+ auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+ if (it == mConnectedDynamicSensors.end()) {
+ mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT, [&, dyn] {
+ return mConnectedDynamicSensors.find(dyn.sensorHandle) !=
+ mConnectedDynamicSensors.end();
+ });
+ it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+ CHECK(it != mConnectedDynamicSensors.end());
+ }
+
+ dst->dynamic_sensor_meta.sensor = &it->second;
+
+ memcpy(dst->dynamic_sensor_meta.uuid, dyn.uuid.data(),
+ sizeof(dst->dynamic_sensor_meta.uuid));
+ }
+ }
+}
+
+void HidlSensorHalWrapper::convertToSensorEventsAndQuantize(
+ const hidl_vec<Event>& src, const hidl_vec<SensorInfo>& dynamicSensorsAdded,
+ sensors_event_t* dst) {
+ if (dynamicSensorsAdded.size() > 0 && mCallback != nullptr) {
+ mCallback->onDynamicSensorsConnected_2_1(dynamicSensorsAdded);
+ }
+
+ for (size_t i = 0; i < src.size(); ++i) {
+ android::hardware::sensors::V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
+ android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
+ getResolutionForSensor(
+ dst[i].sensor));
+ }
+}
+
+float HidlSensorHalWrapper::getResolutionForSensor(int sensorHandle) {
+ for (size_t i = 0; i < mSensorList.size(); i++) {
+ if (sensorHandle == mSensorList[i].handle) {
+ return mSensorList[i].resolution;
+ }
+ }
+
+ auto it = mConnectedDynamicSensors.find(sensorHandle);
+ if (it != mConnectedDynamicSensors.end()) {
+ return it->second.resolution;
+ }
+
+ return 0;
+}
+
+} // namespace android
diff --git a/services/sensorservice/HidlSensorHalWrapper.h b/services/sensorservice/HidlSensorHalWrapper.h
new file mode 100644
index 0000000..030247f
--- /dev/null
+++ b/services/sensorservice/HidlSensorHalWrapper.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HIDL_SENSOR_HAL_WRAPPER_H
+#define ANDROID_HIDL_SENSOR_HAL_WRAPPER_H
+
+#include <sensor/SensorEventQueue.h>
+#include <utils/Singleton.h>
+
+#include "ISensorHalWrapper.h"
+
+#include "ISensorsWrapper.h"
+#include "SensorDeviceUtils.h"
+
+namespace android {
+
+using android::hardware::sensors::V1_0::Result;
+using android::hardware::sensors::V2_1::Event;
+using android::hardware::sensors::V2_1::SensorInfo;
+
+class HidlTransportErrorLog {
+public:
+ HidlTransportErrorLog() {
+ mTs = 0;
+ mCount = 0;
+ }
+
+ HidlTransportErrorLog(time_t ts, int count) {
+ mTs = ts;
+ mCount = count;
+ }
+
+ String8 toString() const {
+ String8 result;
+ struct tm* timeInfo = localtime(&mTs);
+ result.appendFormat("%02d:%02d:%02d :: %d", timeInfo->tm_hour, timeInfo->tm_min,
+ timeInfo->tm_sec, mCount);
+ return result;
+ }
+
+private:
+ time_t mTs; // timestamp of the error
+ int mCount; // number of transport errors observed
+};
+
+class SensorsHalDeathReceiver : public android::hardware::hidl_death_recipient {
+public:
+ SensorsHalDeathReceiver(ISensorHalWrapper* wrapper) : mHidlSensorHalWrapper(wrapper) {}
+
+ virtual void serviceDied(uint64_t cookie,
+ const wp<::android::hidl::base::V1_0::IBase>& service) override;
+
+private:
+ ISensorHalWrapper* mHidlSensorHalWrapper;
+};
+
+class HidlSensorHalWrapper : public ISensorHalWrapper {
+public:
+ HidlSensorHalWrapper()
+ : mHidlTransportErrors(20),
+ mTotalHidlTransportErrors(0),
+ mRestartWaiter(new SensorDeviceUtils::HidlServiceRegistrationWaiter()),
+ mEventQueueFlag(nullptr),
+ mWakeLockQueueFlag(nullptr) {}
+
+ ~HidlSensorHalWrapper() override {
+ if (mEventQueueFlag != nullptr) {
+ hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
+ mEventQueueFlag = nullptr;
+ }
+ if (mWakeLockQueueFlag != nullptr) {
+ hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+ mWakeLockQueueFlag = nullptr;
+ }
+ }
+ virtual bool connect(SensorDeviceCallback* callback) override;
+
+ virtual void prepareForReconnect() override;
+
+ virtual bool supportsPolling() override;
+
+ virtual bool supportsMessageQueues() override;
+
+ virtual ssize_t poll(sensors_event_t* buffer, size_t count) override;
+
+ virtual ssize_t pollFmq(sensors_event_t* buffer, size_t count) override;
+
+ virtual std::vector<sensor_t> getSensorsList() override;
+
+ virtual status_t setOperationMode(SensorService::Mode mode) override;
+
+ virtual status_t activate(int32_t sensorHandle, bool enabled) override;
+
+ virtual status_t batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) override;
+
+ virtual status_t flush(int32_t sensorHandle) override;
+
+ virtual status_t injectSensorData(const sensors_event_t* event) override;
+
+ virtual status_t registerDirectChannel(const sensors_direct_mem_t* memory,
+ int32_t* channelHandle) override;
+
+ virtual status_t unregisterDirectChannel(int32_t channelHandle) override;
+
+ virtual status_t configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
+ const struct sensors_direct_cfg_t* config) override;
+
+ virtual void writeWakeLockHandled(uint32_t count) override;
+
+private:
+ sp<::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase> mSensors;
+ sp<::android::hardware::sensors::V2_1::ISensorsCallback> mCallback;
+ std::vector<sensor_t> mSensorList;
+ std::unordered_map<int32_t, sensor_t> mConnectedDynamicSensors;
+
+ std::mutex mDynamicSensorsMutex;
+ std::condition_variable mDynamicSensorsCv;
+ static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
+
+ // Keep track of any hidl transport failures
+ SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
+ int mTotalHidlTransportErrors;
+
+ SensorDeviceCallback* mSensorDeviceCallback = nullptr;
+
+ // TODO(b/67425500): remove waiter after bug is resolved.
+ sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
+
+ template <typename T>
+ void checkReturn(const hardware::Return<T>& ret) {
+ if (!ret.isOk()) {
+ handleHidlDeath(ret.description());
+ }
+ }
+
+ status_t checkReturnAndGetStatus(const hardware::Return<Result>& ret);
+
+ void handleHidlDeath(const std::string& detail);
+
+ void convertToSensorEvent(const Event& src, sensors_event_t* dst);
+
+ void convertToSensorEventsAndQuantize(const hardware::hidl_vec<Event>& src,
+ const hardware::hidl_vec<SensorInfo>& dynamicSensorsAdded,
+ sensors_event_t* dst);
+
+ bool connectHidlService();
+
+ HalConnectionStatus connectHidlServiceV1_0();
+ HalConnectionStatus connectHidlServiceV2_0();
+ HalConnectionStatus connectHidlServiceV2_1();
+ HalConnectionStatus initializeHidlServiceV2_X();
+
+ typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue;
+ std::unique_ptr<WakeLockQueue> mWakeLockQueue;
+
+ float getResolutionForSensor(int sensorHandle);
+
+ hardware::EventFlag* mEventQueueFlag;
+ hardware::EventFlag* mWakeLockQueueFlag;
+
+ std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
+
+ sp<SensorsHalDeathReceiver> mSensorsHalDeathReceiver;
+};
+
+} // namespace android
+
+#endif // ANDROID_HIDL_SENSOR_HAL_WRAPPER_H
diff --git a/services/sensorservice/ISensorHalWrapper.h b/services/sensorservice/ISensorHalWrapper.h
index c9e089e..3d33540 100644
--- a/services/sensorservice/ISensorHalWrapper.h
+++ b/services/sensorservice/ISensorHalWrapper.h
@@ -30,26 +30,45 @@
*/
class ISensorHalWrapper {
public:
- class ICallback : public ISensorsCallback {
-
- void onDynamicSensorsConnected(
+ class SensorDeviceCallback {
+ public:
+ virtual void onDynamicSensorsConnected(
const std::vector<sensor_t> &dynamicSensorsAdded) = 0;
- void onDynamicSensorsDisconnected(
+ virtual void onDynamicSensorsDisconnected(
const std::vector<int32_t> &dynamicSensorHandlesRemoved) = 0;
+
+ virtual ~SensorDeviceCallback(){};
};
+ enum HalConnectionStatus {
+ CONNECTED, // Successfully connected to the HAL
+ DOES_NOT_EXIST, // Could not find the HAL
+ FAILED_TO_CONNECT, // Found the HAL but failed to connect/initialize
+ UNKNOWN,
+ };
+
+ virtual ~ISensorHalWrapper(){};
+
/**
* Connects to the underlying sensors HAL. This should also be used for any reconnections
* due to HAL resets.
*/
- virtual bool connect(ICallback *callback) = 0;
+ virtual bool connect(SensorDeviceCallback *callback) = 0;
+
+ virtual void prepareForReconnect() = 0;
+
+ virtual bool supportsPolling() = 0;
+
+ virtual bool supportsMessageQueues() = 0;
/**
* Polls for available sensor events. This could be using the traditional sensors
* polling or from a FMQ.
*/
- virtual ssize_t poll(sensors_event_t* buffer, size_t count) = 0;
+ virtual ssize_t poll(sensors_event_t *buffer, size_t count) = 0;
+
+ virtual ssize_t pollFmq(sensors_event_t *buffer, size_t maxNumEventsToRead) = 0;
/**
* The below functions directly mirrors the sensors HAL definitions.
@@ -70,11 +89,15 @@
virtual status_t registerDirectChannel(const sensors_direct_mem_t *memory,
int32_t *channelHandle) = 0;
- virtual void unregisterDirectChannel(int32_t channelHandle) = 0;
+ virtual status_t unregisterDirectChannel(int32_t channelHandle) = 0;
virtual status_t configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
const struct sensors_direct_cfg_t *config) = 0;
-}
+
+ virtual void writeWakeLockHandled(uint32_t count) = 0;
+
+ std::atomic_bool mReconnecting = false;
+};
} // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c67acbf..84a1076 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -17,7 +17,6 @@
#include "SensorDevice.h"
#include "android/hardware/sensors/2.0/types.h"
-#include "android/hardware/sensors/2.1/ISensorsCallback.h"
#include "android/hardware/sensors/2.1/types.h"
#include "convertV2_1.h"
@@ -35,21 +34,7 @@
#include <thread>
using namespace android::hardware::sensors;
-using namespace android::hardware::sensors::V1_0;
-using namespace android::hardware::sensors::V1_0::implementation;
-using android::hardware::hidl_vec;
using android::hardware::Return;
-using android::hardware::sensors::V2_0::EventQueueFlagBits;
-using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
-using android::hardware::sensors::V2_1::ISensorsCallback;
-using android::hardware::sensors::V2_1::implementation::convertToNewEvents;
-using android::hardware::sensors::V2_1::implementation::convertToNewSensorInfos;
-using android::hardware::sensors::V2_1::implementation::convertToOldSensorInfo;
-using android::hardware::sensors::V2_1::implementation::convertToSensor;
-using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV1_0;
-using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_0;
-using android::hardware::sensors::V2_1::implementation::ISensorsWrapperV2_1;
-using android::SensorDeviceUtils::HidlServiceRegistrationWaiter;
using android::util::ProtoOutputStream;
namespace android {
@@ -59,21 +44,6 @@
namespace {
-status_t statusFromResult(Result result) {
- switch (result) {
- case Result::OK:
- return OK;
- case Result::BAD_VALUE:
- return BAD_VALUE;
- case Result::PERMISSION_DENIED:
- return PERMISSION_DENIED;
- case Result::INVALID_OPERATION:
- return INVALID_OPERATION;
- case Result::NO_MEMORY:
- return NO_MEMORY;
- }
-}
-
template <typename EnumType>
constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
return static_cast<typename std::underlying_type<EnumType>::type>(value);
@@ -85,245 +55,98 @@
INTERNAL_WAKE = 1 << 16,
};
-} // anonymous namespace
-
-void SensorsHalDeathReceivier::serviceDied(
- uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* service */) {
- ALOGW("Sensors HAL died, attempting to reconnect.");
- SensorDevice::getInstance().prepareForReconnect();
-}
-
-struct SensorsCallback : public ISensorsCallback {
- using Result = ::android::hardware::sensors::V1_0::Result;
- using SensorInfo = ::android::hardware::sensors::V2_1::SensorInfo;
-
- Return<void> onDynamicSensorsConnected_2_1(
- const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
- std::vector<sensor_t> sensors;
- for (const V2_1::SensorInfo& info : dynamicSensorsAdded) {
- sensor_t sensor;
- convertToSensor(info, &sensor);
- sensors.push_back(sensor);
- }
-
- SensorDevice::getInstance().onDynamicSensorsConnected(sensors);
- return Return<void>();
- }
-
- Return<void> onDynamicSensorsConnected(
- const hidl_vec<V1_0::SensorInfo>& dynamicSensorsAdded) override {
- return onDynamicSensorsConnected_2_1(convertToNewSensorInfos(dynamicSensorsAdded));
- }
-
- Return<void> onDynamicSensorsDisconnected(
- const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
- SensorDevice::getInstance().onDynamicSensorsDisconnected(dynamicSensorHandlesRemoved);
- return Return<void>();
- }
+enum DevicePrivateBase : int32_t {
+ DEVICE_PRIVATE_BASE = 65536,
};
-SensorDevice::SensorDevice()
- : mHidlTransportErrors(20),
- mRestartWaiter(new HidlServiceRegistrationWaiter()),
- mEventQueueFlag(nullptr),
- mWakeLockQueueFlag(nullptr),
- mReconnecting(false) {
- if (!connectHidlService()) {
+} // anonymous namespace
+
+SensorDevice::SensorDevice() {
+ if (!connectHalService()) {
return;
}
initializeSensorList();
- mIsDirectReportSupported =
- (checkReturnAndGetStatus(mSensors->unregisterDirectChannel(-1)) != INVALID_OPERATION);
+ mIsDirectReportSupported = (mHalWrapper->unregisterDirectChannel(-1) != INVALID_OPERATION);
}
void SensorDevice::initializeSensorList() {
- checkReturn(mSensors->getSensorsList([&](const auto& list) {
- const size_t count = list.size();
+ if (mHalWrapper == nullptr) {
+ return;
+ }
- mActivationCount.setCapacity(count);
- Info model;
- for (size_t i = 0; i < count; i++) {
- sensor_t sensor;
- convertToSensor(list[i], &sensor);
+ auto list = mHalWrapper->getSensorsList();
+ const size_t count = list.size();
- if (sensor.type < static_cast<int>(SensorType::DEVICE_PRIVATE_BASE)) {
- sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
+ mActivationCount.setCapacity(count);
+ Info model;
+ for (size_t i = 0; i < count; i++) {
+ sensor_t sensor = list[i];
- // Some sensors don't have a default resolution and will be left at 0.
- // Don't crash in this case since CTS will verify that devices don't go to
- // production with a resolution of 0.
- if (sensor.resolution != 0) {
- float quantizedRange = sensor.maxRange;
- SensorDeviceUtils::quantizeValue(&quantizedRange, sensor.resolution,
- /*factor=*/1);
- // Only rewrite maxRange if the requantization produced a "significant"
- // change, which is fairly arbitrarily defined as resolution / 8.
- // Smaller deltas are permitted, as they may simply be due to floating
- // point representation error, etc.
- if (fabsf(sensor.maxRange - quantizedRange) > sensor.resolution / 8) {
- ALOGW("%s's max range %.12f is not a multiple of the resolution "
- "%.12f - updated to %.12f",
- sensor.name, sensor.maxRange, sensor.resolution, quantizedRange);
- sensor.maxRange = quantizedRange;
- }
- } else {
- // Don't crash here or the device will go into a crashloop.
- ALOGW("%s should have a non-zero resolution", sensor.name);
+ if (sensor.type < DEVICE_PRIVATE_BASE) {
+ sensor.resolution = SensorDeviceUtils::resolutionForSensor(sensor);
+
+ // Some sensors don't have a default resolution and will be left at 0.
+ // Don't crash in this case since CTS will verify that devices don't go to
+ // production with a resolution of 0.
+ if (sensor.resolution != 0) {
+ float quantizedRange = sensor.maxRange;
+ SensorDeviceUtils::quantizeValue(&quantizedRange, sensor.resolution,
+ /*factor=*/1);
+ // Only rewrite maxRange if the requantization produced a "significant"
+ // change, which is fairly arbitrarily defined as resolution / 8.
+ // Smaller deltas are permitted, as they may simply be due to floating
+ // point representation error, etc.
+ if (fabsf(sensor.maxRange - quantizedRange) > sensor.resolution / 8) {
+ ALOGW("%s's max range %.12f is not a multiple of the resolution "
+ "%.12f - updated to %.12f",
+ sensor.name, sensor.maxRange, sensor.resolution, quantizedRange);
+ sensor.maxRange = quantizedRange;
}
- }
-
- // Check and clamp power if it is 0 (or close)
- constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
- if (sensor.power < MIN_POWER_MA) {
- ALOGI("%s's reported power %f invalid, clamped to %f", sensor.name, sensor.power,
- MIN_POWER_MA);
- sensor.power = MIN_POWER_MA;
- }
- mSensorList.push_back(sensor);
-
- mActivationCount.add(list[i].sensorHandle, model);
-
- // Only disable all sensors on HAL 1.0 since HAL 2.0
- // handles this in its initialize method
- if (!mSensors->supportsMessageQueues()) {
- checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* enabled */));
+ } else {
+ // Don't crash here or the device will go into a crashloop.
+ ALOGW("%s should have a non-zero resolution", sensor.name);
}
}
- }));
-}
-SensorDevice::~SensorDevice() {
- if (mEventQueueFlag != nullptr) {
- hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
- mEventQueueFlag = nullptr;
- }
-
- if (mWakeLockQueueFlag != nullptr) {
- hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
- mWakeLockQueueFlag = nullptr;
- }
-}
-
-bool SensorDevice::connectHidlService() {
- HalConnectionStatus status = connectHidlServiceV2_1();
- if (status == HalConnectionStatus::DOES_NOT_EXIST) {
- status = connectHidlServiceV2_0();
- }
-
- if (status == HalConnectionStatus::DOES_NOT_EXIST) {
- status = connectHidlServiceV1_0();
- }
- return (status == HalConnectionStatus::CONNECTED);
-}
-
-SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV1_0() {
- // SensorDevice will wait for HAL service to start if HAL is declared in device manifest.
- size_t retry = 10;
- HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
-
- while (retry-- > 0) {
- sp<V1_0::ISensors> sensors = V1_0::ISensors::getService();
- if (sensors == nullptr) {
- // no sensor hidl service found
- connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
- break;
+ // Check and clamp power if it is 0 (or close)
+ constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
+ if (sensor.power < MIN_POWER_MA) {
+ ALOGI("%s's reported power %f invalid, clamped to %f", sensor.name, sensor.power,
+ MIN_POWER_MA);
+ sensor.power = MIN_POWER_MA;
}
+ mSensorList.push_back(sensor);
- mSensors = new ISensorsWrapperV1_0(sensors);
- mRestartWaiter->reset();
- // Poke ISensor service. If it has lingering connection from previous generation of
- // system server, it will kill itself. There is no intention to handle the poll result,
- // which will be done since the size is 0.
- if (mSensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
- // ok to continue
- connectionStatus = HalConnectionStatus::CONNECTED;
- break;
+ mActivationCount.add(list[i].handle, model);
+
+ // Only disable all sensors on HAL 1.0 since HAL 2.0
+ // handles this in its initialize method
+ if (!mHalWrapper->supportsMessageQueues()) {
+ mHalWrapper->activate(list[i].handle, 0 /* enabled */);
}
-
- // hidl service is restarting, pointer is invalid.
- mSensors = nullptr;
- connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
- ALOGI("%s unsuccessful, remaining retry %zu.", __FUNCTION__, retry);
- mRestartWaiter->wait();
}
-
- return connectionStatus;
}
-SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV2_0() {
- HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
- sp<V2_0::ISensors> sensors = V2_0::ISensors::getService();
+SensorDevice::~SensorDevice() {}
- if (sensors == nullptr) {
- connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
- } else {
- mSensors = new ISensorsWrapperV2_0(sensors);
- connectionStatus = initializeHidlServiceV2_X();
+bool SensorDevice::connectHalService() {
+ std::unique_ptr<ISensorHalWrapper> hidl_wrapper = std::make_unique<HidlSensorHalWrapper>();
+ if (hidl_wrapper->connect(this)) {
+ mHalWrapper = std::move(hidl_wrapper);
+ return true;
}
-
- return connectionStatus;
-}
-
-SensorDevice::HalConnectionStatus SensorDevice::connectHidlServiceV2_1() {
- HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
- sp<V2_1::ISensors> sensors = V2_1::ISensors::getService();
-
- if (sensors == nullptr) {
- connectionStatus = HalConnectionStatus::DOES_NOT_EXIST;
- } else {
- mSensors = new ISensorsWrapperV2_1(sensors);
- connectionStatus = initializeHidlServiceV2_X();
- }
-
- return connectionStatus;
-}
-
-SensorDevice::HalConnectionStatus SensorDevice::initializeHidlServiceV2_X() {
- HalConnectionStatus connectionStatus = HalConnectionStatus::UNKNOWN;
-
- mWakeLockQueue =
- std::make_unique<WakeLockQueue>(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
- true /* configureEventFlagWord */);
-
- hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
- hardware::EventFlag::createEventFlag(mSensors->getEventQueue()->getEventFlagWord(),
- &mEventQueueFlag);
-
- hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
- hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakeLockQueueFlag);
-
- CHECK(mSensors != nullptr && mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
- mWakeLockQueueFlag != nullptr);
-
- mCallback = new SensorsCallback();
- status_t status =
- checkReturnAndGetStatus(mSensors->initialize(*mWakeLockQueue->getDesc(), mCallback));
-
- if (status != NO_ERROR) {
- connectionStatus = HalConnectionStatus::FAILED_TO_CONNECT;
- ALOGE("Failed to initialize Sensors HAL (%s)", strerror(-status));
- } else {
- connectionStatus = HalConnectionStatus::CONNECTED;
- mSensorsHalDeathReceiver = new SensorsHalDeathReceivier();
- mSensors->linkToDeath(mSensorsHalDeathReceiver, 0 /* cookie */);
- }
-
- return connectionStatus;
+ // TODO: check aidl connection;
+ return false;
}
void SensorDevice::prepareForReconnect() {
- mReconnecting = true;
-
- // Wake up the polling thread so it returns and allows the SensorService to initiate
- // a reconnect.
- mEventQueueFlag->wake(asBaseType(INTERNAL_WAKE));
+ mHalWrapper->prepareForReconnect();
}
void SensorDevice::reconnect() {
Mutex::Autolock _l(mLock);
- mSensors = nullptr;
auto previousActivations = mActivationCount;
auto previousSensorList = mSensorList;
@@ -331,7 +154,7 @@
mActivationCount.clear();
mSensorList.clear();
- if (connectHidlService()) {
+ if (mHalWrapper->connect(this)) {
initializeSensorList();
if (sensorHandlesChanged(previousSensorList, mSensorList)) {
@@ -340,7 +163,7 @@
reactivateSensors(previousActivations);
}
}
- mReconnecting = false;
+ mHalWrapper->mReconnecting = false;
}
bool SensorDevice::sensorHandlesChanged(const std::vector<sensor_t>& oldSensorList,
@@ -422,14 +245,14 @@
if (connected) {
Info model;
mActivationCount.add(handle, model);
- checkReturn(mSensors->activate(handle, 0 /* enabled */));
+ mHalWrapper->activate(handle, 0 /* enabled */);
} else {
mActivationCount.removeItem(handle);
}
}
std::string SensorDevice::dump() const {
- if (mSensors == nullptr) return "HAL not initialized\n";
+ if (mHalWrapper == nullptr) return "HAL not initialized\n";
String8 result;
result.appendFormat("Total %zu h/w sensors, %zu running %zu disabled clients:\n",
@@ -476,7 +299,7 @@
*/
void SensorDevice::dump(ProtoOutputStream* proto) const {
using namespace service::SensorDeviceProto;
- if (mSensors == nullptr) {
+ if (mHalWrapper == nullptr) {
proto->write(INITIALIZED, false);
return;
}
@@ -511,17 +334,17 @@
}
status_t SensorDevice::initCheck() const {
- return mSensors != nullptr ? NO_ERROR : NO_INIT;
+ return mHalWrapper != nullptr ? NO_ERROR : NO_INIT;
}
ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
- if (mSensors == nullptr) return NO_INIT;
+ if (mHalWrapper == nullptr) return NO_INIT;
ssize_t eventsRead = 0;
- if (mSensors->supportsMessageQueues()) {
- eventsRead = pollFmq(buffer, count);
- } else if (mSensors->supportsPolling()) {
- eventsRead = pollHal(buffer, count);
+ if (mHalWrapper->supportsMessageQueues()) {
+ eventsRead = mHalWrapper->pollFmq(buffer, count);
+ } else if (mHalWrapper->supportsPolling()) {
+ eventsRead = mHalWrapper->poll(buffer, count);
} else {
ALOGE("Must support polling or FMQ");
eventsRead = -1;
@@ -529,95 +352,6 @@
return eventsRead;
}
-ssize_t SensorDevice::pollHal(sensors_event_t* buffer, size_t count) {
- ssize_t err;
- int numHidlTransportErrors = 0;
- bool hidlTransportError = false;
-
- do {
- auto ret = mSensors->poll(
- count, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
- if (result == Result::OK) {
- convertToSensorEventsAndQuantize(convertToNewEvents(events),
- convertToNewSensorInfos(
- dynamicSensorsAdded),
- buffer);
- err = (ssize_t)events.size();
- } else {
- err = statusFromResult(result);
- }
- });
-
- if (ret.isOk()) {
- hidlTransportError = false;
- } else {
- hidlTransportError = true;
- numHidlTransportErrors++;
- if (numHidlTransportErrors > 50) {
- // Log error and bail
- ALOGE("Max Hidl transport errors this cycle : %d", numHidlTransportErrors);
- handleHidlDeath(ret.description());
- } else {
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- }
- } while (hidlTransportError);
-
- if (numHidlTransportErrors > 0) {
- ALOGE("Saw %d Hidl transport failures", numHidlTransportErrors);
- HidlTransportErrorLog errLog(time(nullptr), numHidlTransportErrors);
- mHidlTransportErrors.add(errLog);
- mTotalHidlTransportErrors++;
- }
-
- return err;
-}
-
-ssize_t SensorDevice::pollFmq(sensors_event_t* buffer, size_t maxNumEventsToRead) {
- ssize_t eventsRead = 0;
- size_t availableEvents = mSensors->getEventQueue()->availableToRead();
-
- if (availableEvents == 0) {
- uint32_t eventFlagState = 0;
-
- // Wait for events to become available. This is necessary so that the Event FMQ's read() is
- // able to be called with the correct number of events to read. If the specified number of
- // events is not available, then read() would return no events, possibly introducing
- // additional latency in delivering events to applications.
- mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS) |
- asBaseType(INTERNAL_WAKE),
- &eventFlagState);
- availableEvents = mSensors->getEventQueue()->availableToRead();
-
- if ((eventFlagState & asBaseType(INTERNAL_WAKE)) && mReconnecting) {
- ALOGD("Event FMQ internal wake, returning from poll with no events");
- return DEAD_OBJECT;
- }
- }
-
- size_t eventsToRead = std::min({availableEvents, maxNumEventsToRead, mEventBuffer.size()});
- if (eventsToRead > 0) {
- if (mSensors->getEventQueue()->read(mEventBuffer.data(), eventsToRead)) {
- // Notify the Sensors HAL that sensor events have been read. This is required to support
- // the use of writeBlocking by the Sensors HAL.
- mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ));
-
- for (size_t i = 0; i < eventsToRead; i++) {
- convertToSensorEvent(mEventBuffer[i], &buffer[i]);
- android::SensorDeviceUtils::quantizeSensorEventValues(&buffer[i],
- getResolutionForSensor(
- buffer[i].sensor));
- }
- eventsRead = eventsToRead;
- } else {
- ALOGW("Failed to read %zu events, currently %zu events available", eventsToRead,
- availableEvents);
- }
- }
-
- return eventsRead;
-}
-
void SensorDevice::onDynamicSensorsConnected(const std::vector<sensor_t>& dynamicSensorsAdded) {
std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
@@ -641,12 +375,8 @@
}
void SensorDevice::writeWakeLockHandled(uint32_t count) {
- if (mSensors != nullptr && mSensors->supportsMessageQueues()) {
- if (mWakeLockQueue->write(&count)) {
- mWakeLockQueueFlag->wake(asBaseType(WakeLockQueueFlagBits::DATA_WRITTEN));
- } else {
- ALOGW("Failed to write wake lock handled");
- }
+ if (mHalWrapper != nullptr && mHalWrapper->supportsMessageQueues()) {
+ mHalWrapper->writeWakeLockHandled(count);
}
}
@@ -665,7 +395,7 @@
}
status_t SensorDevice::activate(void* ident, int handle, int enabled) {
- if (mSensors == nullptr) return NO_INIT;
+ if (mHalWrapper == nullptr) return NO_INIT;
Mutex::Autolock _l(mLock);
return activateLocked(ident, handle, enabled);
@@ -724,8 +454,8 @@
// events, and the best effort batch parameters might have changed.
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w batch 0x%08x %" PRId64 " %" PRId64,
handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
- checkReturn(mSensors->batch(handle, info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch));
+ mHalWrapper->batch(handle, info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch);
}
} else {
// sensor wasn't enabled for this ident
@@ -756,7 +486,7 @@
status_t SensorDevice::doActivateHardwareLocked(int handle, bool enabled) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle,
enabled);
- status_t err = checkReturnAndGetStatus(mSensors->activate(handle, enabled));
+ status_t err = mHalWrapper->activate(handle, enabled);
ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
strerror(-err));
return err;
@@ -764,7 +494,7 @@
status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs) {
- if (mSensors == nullptr) return NO_INIT;
+ if (mHalWrapper == nullptr) return NO_INIT;
if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
@@ -801,8 +531,8 @@
status_t err = updateBatchParamsLocked(handle, info);
if (err != NO_ERROR) {
- ALOGE("sensor batch failed %p 0x%08x %" PRId64 " %" PRId64 " err=%s", mSensors.get(),
- handle, info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch, strerror(-err));
+ ALOGE("sensor batch failed 0x%08x %" PRId64 " %" PRId64 " err=%s", handle,
+ info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch, strerror(-err));
info.removeBatchParamsForIdent(ident);
}
@@ -825,8 +555,8 @@
if (prevBestBatchParams != info.bestBatchParams && info.numActiveClients() > 0) {
ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH 0x%08x %" PRId64 " %" PRId64, handle,
info.bestBatchParams.mTSample, info.bestBatchParams.mTBatch);
- err = checkReturnAndGetStatus(mSensors->batch(handle, info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch));
+ err = mHalWrapper->batch(handle, info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch);
}
return err;
@@ -837,15 +567,12 @@
}
int SensorDevice::getHalDeviceVersion() const {
- if (mSensors == nullptr) return -1;
+ if (mHalWrapper == nullptr) return -1;
return SENSORS_DEVICE_API_VERSION_1_4;
}
-status_t SensorDevice::flush(void* ident, int handle) {
- if (mSensors == nullptr) return NO_INIT;
- if (isClientDisabled(ident)) return INVALID_OPERATION;
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
- return checkReturnAndGetStatus(mSensors->flush(handle));
+status_t SensorDevice::flush(void* /*ident*/, int handle) {
+ return mHalWrapper->flush(handle);
}
bool SensorDevice::isClientDisabled(void* ident) const {
@@ -928,7 +655,7 @@
}
void SensorDevice::enableAllSensors() {
- if (mSensors == nullptr) return;
+ if (mHalWrapper == nullptr) return;
Mutex::Autolock _l(mLock);
for (void* client : getDisabledClientsLocked()) {
@@ -943,13 +670,12 @@
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ",
sensor_handle);
- status_t err = checkReturnAndGetStatus(mSensors->batch(sensor_handle,
- info.bestBatchParams.mTSample,
- info.bestBatchParams.mTBatch));
+ status_t err = mHalWrapper->batch(sensor_handle, info.bestBatchParams.mTSample,
+ info.bestBatchParams.mTBatch);
ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err));
if (err == NO_ERROR) {
- err = checkReturnAndGetStatus(mSensors->activate(sensor_handle, 1 /* enabled */));
+ err = mHalWrapper->activate(sensor_handle, 1 /* enabled */);
ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err));
}
@@ -960,7 +686,7 @@
}
void SensorDevice::disableAllSensors() {
- if (mSensors == nullptr) return;
+ if (mHalWrapper == nullptr) return;
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(i);
@@ -969,7 +695,7 @@
const int sensor_handle = mActivationCount.keyAt(i);
ALOGD_IF(DEBUG_CONNECTIONS, "\t>> actuating h/w sensor disable handle=%d ",
sensor_handle);
- checkReturn(mSensors->activate(sensor_handle, 0 /* enabled */));
+ mHalWrapper->activate(sensor_handle, 0 /* enabled */);
// Add all the connections that were registered for this sensor to the disabled
// clients list.
@@ -985,110 +711,29 @@
}
status_t SensorDevice::injectSensorData(const sensors_event_t* injected_sensor_event) {
- if (mSensors == nullptr) return NO_INIT;
- ALOGD_IF(DEBUG_CONNECTIONS,
- "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
- injected_sensor_event->sensor, injected_sensor_event->timestamp,
- injected_sensor_event->data[0], injected_sensor_event->data[1],
- injected_sensor_event->data[2], injected_sensor_event->data[3],
- injected_sensor_event->data[4], injected_sensor_event->data[5]);
-
- Event ev;
- V2_1::implementation::convertFromSensorEvent(*injected_sensor_event, &ev);
-
- return checkReturnAndGetStatus(mSensors->injectSensorData(ev));
+ return mHalWrapper->injectSensorData(injected_sensor_event);
}
status_t SensorDevice::setMode(uint32_t mode) {
- if (mSensors == nullptr) return NO_INIT;
- return checkReturnAndGetStatus(
- mSensors->setOperationMode(static_cast<hardware::sensors::V1_0::OperationMode>(mode)));
+ if (mHalWrapper == nullptr) return NO_INIT;
+ return mHalWrapper->setOperationMode(static_cast<SensorService::Mode>(mode));
}
int32_t SensorDevice::registerDirectChannel(const sensors_direct_mem_t* memory) {
- if (mSensors == nullptr) return NO_INIT;
Mutex::Autolock _l(mLock);
- SharedMemType type;
- switch (memory->type) {
- case SENSOR_DIRECT_MEM_TYPE_ASHMEM:
- type = SharedMemType::ASHMEM;
- break;
- case SENSOR_DIRECT_MEM_TYPE_GRALLOC:
- type = SharedMemType::GRALLOC;
- break;
- default:
- return BAD_VALUE;
- }
-
- SharedMemFormat format;
- if (memory->format != SENSOR_DIRECT_FMT_SENSORS_EVENT) {
- return BAD_VALUE;
- }
- format = SharedMemFormat::SENSORS_EVENT;
-
- SharedMemInfo mem = {
- .type = type,
- .format = format,
- .size = static_cast<uint32_t>(memory->size),
- .memoryHandle = memory->handle,
- };
-
- int32_t ret;
- checkReturn(mSensors->registerDirectChannel(mem, [&ret](auto result, auto channelHandle) {
- if (result == Result::OK) {
- ret = channelHandle;
- } else {
- ret = statusFromResult(result);
- }
- }));
- return ret;
+ return mHalWrapper->registerDirectChannel(memory, nullptr);
}
void SensorDevice::unregisterDirectChannel(int32_t channelHandle) {
- if (mSensors == nullptr) return;
- Mutex::Autolock _l(mLock);
- checkReturn(mSensors->unregisterDirectChannel(channelHandle));
+ mHalWrapper->unregisterDirectChannel(channelHandle);
}
int32_t SensorDevice::configureDirectChannel(int32_t sensorHandle, int32_t channelHandle,
const struct sensors_direct_cfg_t* config) {
- if (mSensors == nullptr) return NO_INIT;
Mutex::Autolock _l(mLock);
- RateLevel rate;
- switch (config->rate_level) {
- case SENSOR_DIRECT_RATE_STOP:
- rate = RateLevel::STOP;
- break;
- case SENSOR_DIRECT_RATE_NORMAL:
- rate = RateLevel::NORMAL;
- break;
- case SENSOR_DIRECT_RATE_FAST:
- rate = RateLevel::FAST;
- break;
- case SENSOR_DIRECT_RATE_VERY_FAST:
- rate = RateLevel::VERY_FAST;
- break;
- default:
- return BAD_VALUE;
- }
-
- int32_t ret;
- checkReturn(mSensors->configDirectReport(sensorHandle, channelHandle, rate,
- [&ret, rate](auto result, auto token) {
- if (rate == RateLevel::STOP) {
- ret = statusFromResult(result);
- } else {
- if (result == Result::OK) {
- ret = token;
- } else {
- ret = statusFromResult(result);
- }
- }
- }));
-
- return ret;
+ return mHalWrapper->configureDirectChannel(sensorHandle, channelHandle, config);
}
// ---------------------------------------------------------------------------
@@ -1153,52 +798,6 @@
return mIsDirectReportSupported;
}
-void SensorDevice::convertToSensorEvent(const Event& src, sensors_event_t* dst) {
- V2_1::implementation::convertToSensorEvent(src, dst);
-
- if (src.sensorType == V2_1::SensorType::DYNAMIC_SENSOR_META) {
- const DynamicSensorInfo& dyn = src.u.dynamic;
-
- dst->dynamic_sensor_meta.connected = dyn.connected;
- dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
- if (dyn.connected) {
- std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
- // Give MAX_DYN_SENSOR_WAIT_SEC for onDynamicSensorsConnected to be invoked since it
- // can be received out of order from this event due to a bug in the HIDL spec that
- // marks it as oneway.
- auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
- if (it == mConnectedDynamicSensors.end()) {
- mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT, [&, dyn] {
- return mConnectedDynamicSensors.find(dyn.sensorHandle) !=
- mConnectedDynamicSensors.end();
- });
- it = mConnectedDynamicSensors.find(dyn.sensorHandle);
- CHECK(it != mConnectedDynamicSensors.end());
- }
-
- dst->dynamic_sensor_meta.sensor = &it->second;
-
- memcpy(dst->dynamic_sensor_meta.uuid, dyn.uuid.data(),
- sizeof(dst->dynamic_sensor_meta.uuid));
- }
- }
-}
-
-void SensorDevice::convertToSensorEventsAndQuantize(const hidl_vec<Event>& src,
- const hidl_vec<SensorInfo>& dynamicSensorsAdded,
- sensors_event_t* dst) {
- if (dynamicSensorsAdded.size() > 0 && mCallback != nullptr) {
- mCallback->onDynamicSensorsConnected_2_1(dynamicSensorsAdded);
- }
-
- for (size_t i = 0; i < src.size(); ++i) {
- V2_1::implementation::convertToSensorEvent(src[i], &dst[i]);
- android::SensorDeviceUtils::quantizeSensorEventValues(&dst[i],
- getResolutionForSensor(
- dst[i].sensor));
- }
-}
-
float SensorDevice::getResolutionForSensor(int sensorHandle) {
for (size_t i = 0; i < mSensorList.size(); i++) {
if (sensorHandle == mSensorList[i].handle) {
@@ -1214,19 +813,5 @@
return 0;
}
-void SensorDevice::handleHidlDeath(const std::string& detail) {
- if (!mSensors->supportsMessageQueues()) {
- // restart is the only option at present.
- LOG_ALWAYS_FATAL("Abort due to ISensors hidl service failure, detail: %s.", detail.c_str());
- } else {
- ALOGD("ISensors HAL died, death recipient will attempt reconnect");
- }
-}
-
-status_t SensorDevice::checkReturnAndGetStatus(const Return<Result>& ret) {
- checkReturn(ret);
- return (!ret.isOk()) ? DEAD_OBJECT : statusFromResult(ret);
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 314ddb8..80e77d9 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -17,12 +17,14 @@
#ifndef ANDROID_SENSOR_DEVICE_H
#define ANDROID_SENSOR_DEVICE_H
+#include "HidlSensorHalWrapper.h"
+#include "ISensorHalWrapper.h"
+
#include "ISensorsWrapper.h"
#include "SensorDeviceUtils.h"
#include "SensorService.h"
#include "SensorServiceUtils.h"
-#include <fmq/MessageQueue.h>
#include <sensor/Sensor.h>
#include <sensor/SensorEventQueue.h>
#include <stdint.h>
@@ -43,41 +45,12 @@
namespace android {
-using Result = ::android::hardware::sensors::V1_0::Result;
-
// ---------------------------------------------------------------------------
-class SensorsHalDeathReceivier : public android::hardware::hidl_death_recipient {
- virtual void serviceDied(uint64_t cookie,
- const wp<::android::hidl::base::V1_0::IBase>& service) override;
-};
-class SensorDevice : public Singleton<SensorDevice>, public SensorServiceUtil::Dumpable {
+class SensorDevice : public Singleton<SensorDevice>,
+ public SensorServiceUtil::Dumpable,
+ public ISensorHalWrapper::SensorDeviceCallback {
public:
- class HidlTransportErrorLog {
- public:
- HidlTransportErrorLog() {
- mTs = 0;
- mCount = 0;
- }
-
- HidlTransportErrorLog(time_t ts, int count) {
- mTs = ts;
- mCount = count;
- }
-
- String8 toString() const {
- String8 result;
- struct tm* timeInfo = localtime(&mTs);
- result.appendFormat("%02d:%02d:%02d :: %d", timeInfo->tm_hour, timeInfo->tm_min,
- timeInfo->tm_sec, mCount);
- return result;
- }
-
- private:
- time_t mTs; // timestamp of the error
- int mCount; // number of transport errors observed
- };
-
~SensorDevice();
void prepareForReconnect();
void reconnect();
@@ -112,12 +85,15 @@
status_t injectSensorData(const sensors_event_t* event);
void notifyConnectionDestroyed(void* ident);
- void onDynamicSensorsConnected(const std::vector<sensor_t>& dynamicSensorsAdded);
- void onDynamicSensorsDisconnected(const std::vector<int32_t>& dynamicSensorHandlesRemoved);
+ // SensorDeviceCallback
+ virtual void onDynamicSensorsConnected(
+ const std::vector<sensor_t>& dynamicSensorsAdded) override;
+ virtual void onDynamicSensorsDisconnected(
+ const std::vector<int32_t>& dynamicSensorHandlesRemoved) override;
void setUidStateForConnection(void* ident, SensorService::UidState state);
- bool isReconnecting() const { return mReconnecting; }
+ bool isReconnecting() const { return mHalWrapper->mReconnecting; }
bool isSensorActive(int handle) const;
@@ -132,8 +108,8 @@
private:
friend class Singleton<SensorDevice>;
- sp<::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase> mSensors;
- sp<::android::hardware::sensors::V2_1::ISensorsCallback> mCallback;
+ std::unique_ptr<ISensorHalWrapper> mHalWrapper;
+
std::vector<sensor_t> mSensorList;
std::unordered_map<int32_t, sensor_t> mConnectedDynamicSensors;
@@ -143,7 +119,6 @@
// HAL implementations.
std::mutex mDynamicSensorsMutex;
std::condition_variable mDynamicSensorsCv;
- static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
mutable Mutex mLock; // protect mActivationCount[].batchParams
@@ -203,8 +178,6 @@
};
DefaultKeyedVector<int, Info> mActivationCount;
- // Keep track of any hidl transport failures
- SensorServiceUtil::RingBuffer<HidlTransportErrorLog> mHidlTransportErrors;
int mTotalHidlTransportErrors;
/**
@@ -228,26 +201,13 @@
void removeDisabledReasonForIdentLocked(void* ident, DisabledReason reason);
SensorDevice();
- bool connectHidlService();
+ bool connectHalService();
void initializeSensorList();
void reactivateSensors(const DefaultKeyedVector<int, Info>& previousActivations);
static bool sensorHandlesChanged(const std::vector<sensor_t>& oldSensorList,
const std::vector<sensor_t>& newSensorList);
static bool sensorIsEquivalent(const sensor_t& prevSensor, const sensor_t& newSensor);
- enum HalConnectionStatus {
- CONNECTED, // Successfully connected to the HAL
- DOES_NOT_EXIST, // Could not find the HAL
- FAILED_TO_CONNECT, // Found the HAL but failed to connect/initialize
- UNKNOWN,
- };
- HalConnectionStatus connectHidlServiceV1_0();
- HalConnectionStatus connectHidlServiceV2_0();
- HalConnectionStatus connectHidlServiceV2_1();
- HalConnectionStatus initializeHidlServiceV2_X();
-
- ssize_t pollHal(sensors_event_t* buffer, size_t count);
- ssize_t pollFmq(sensors_event_t* buffer, size_t count);
status_t activateLocked(void* ident, int handle, int enabled);
status_t batchLocked(void* ident, int handle, int flags, int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs);
@@ -255,47 +215,15 @@
status_t updateBatchParamsLocked(int handle, Info& info);
status_t doActivateHardwareLocked(int handle, bool enable);
- void handleHidlDeath(const std::string& detail);
- template <typename T>
- void checkReturn(const Return<T>& ret) {
- if (!ret.isOk()) {
- handleHidlDeath(ret.description());
- }
- }
-
- status_t checkReturnAndGetStatus(const Return<Result>& ret);
- // TODO(b/67425500): remove waiter after bug is resolved.
- sp<SensorDeviceUtils::HidlServiceRegistrationWaiter> mRestartWaiter;
-
bool isClientDisabled(void* ident) const;
bool isClientDisabledLocked(void* ident) const;
std::vector<void*> getDisabledClientsLocked() const;
bool clientHasNoAccessLocked(void* ident) const;
- using Event = hardware::sensors::V2_1::Event;
- using SensorInfo = hardware::sensors::V2_1::SensorInfo;
-
- void convertToSensorEvent(const Event& src, sensors_event_t* dst);
-
- void convertToSensorEventsAndQuantize(const hardware::hidl_vec<Event>& src,
- const hardware::hidl_vec<SensorInfo>& dynamicSensorsAdded,
- sensors_event_t* dst);
-
float getResolutionForSensor(int sensorHandle);
bool mIsDirectReportSupported;
-
- typedef hardware::MessageQueue<uint32_t, hardware::kSynchronizedReadWrite> WakeLockQueue;
- std::unique_ptr<WakeLockQueue> mWakeLockQueue;
-
- hardware::EventFlag* mEventQueueFlag;
- hardware::EventFlag* mWakeLockQueueFlag;
-
- std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
-
- sp<SensorsHalDeathReceivier> mSensorsHalDeathReceiver;
- std::atomic_bool mReconnecting;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index e26c763..d61a4cb 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -295,6 +295,9 @@
compositionState->compositionType =
aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;
return;
+ } else if ((mDrawingState.flags & layer_state_t::eLayerIsDisplayDecoration) != 0) {
+ compositionState->compositionType =
+ aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
} else {
// Normal buffer layers
compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index 93586ed..f201751 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -85,6 +85,9 @@
// to prevent an early presentation of a frame.
std::shared_ptr<FenceTime> previousPresentFence;
+ // The expected time for the next present
+ nsecs_t expectedPresentTime{0};
+
// If set, a frame has been scheduled for that time.
std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index c5b6443..c8f177b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -121,6 +121,9 @@
// to prevent an early presentation of a frame.
std::shared_ptr<FenceTime> previousPresentFence;
+ // The expected time for the next present
+ nsecs_t expectedPresentTime{0};
+
// Current display brightness
float displayBrightnessNits{-1.f};
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 3571319..5543ad5 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -227,7 +227,8 @@
if (status_t result =
hwc.getDeviceCompositionChanges(*halDisplayId, anyLayersRequireClientComposition(),
getState().earliestPresentTime,
- getState().previousPresentFence, &changes);
+ getState().previousPresentFence,
+ getState().expectedPresentTime, &changes);
result != NO_ERROR) {
ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
strerror(-result));
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index d503153..6833584 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -728,6 +728,7 @@
editState().earliestPresentTime = refreshArgs.earliestPresentTime;
editState().previousPresentFence = refreshArgs.previousPresentFence;
+ editState().expectedPresentTime = refreshArgs.expectedPresentTime;
compositionengine::OutputLayer* peekThroughLayer = nullptr;
sp<GraphicBuffer> previousOverride = nullptr;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index e6bcec8..545e2a2 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -539,6 +539,7 @@
break;
case Composition::CURSOR:
case Composition::DEVICE:
+ case Composition::DISPLAY_DECORATION:
writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer);
break;
case Composition::INVALID:
@@ -689,6 +690,7 @@
case Composition::CURSOR:
case Composition::SIDEBAND:
+ case Composition::DISPLAY_DECORATION:
result = (to == Composition::CLIENT || to == Composition::DEVICE);
break;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
index 074673e..2d53583 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
@@ -114,6 +114,10 @@
plan.addLayerType(
aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR);
continue;
+ case 'A':
+ plan.addLayerType(aidl::android::hardware::graphics::composer3::Composition::
+ DISPLAY_DECORATION);
+ continue;
default:
return std::nullopt;
}
@@ -143,6 +147,10 @@
case aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR:
result.append("S");
break;
+ case aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION:
+ // A for "Alpha", since the decoration is an alpha layer.
+ result.append("A");
+ break;
}
}
return result;
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 3bdb2c0..88f00a5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -560,7 +560,7 @@
TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutOnHwcError) {
EXPECT_CALL(*mDisplay, anyLayersRequireClientComposition()).WillOnce(Return(false));
EXPECT_CALL(mHwComposer,
- getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _))
+ getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _, _))
.WillOnce(Return(INVALID_OPERATION));
mDisplay->chooseCompositionStrategy();
@@ -583,7 +583,7 @@
.WillOnce(Return(false));
EXPECT_CALL(mHwComposer,
- getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _))
+ getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
@@ -615,8 +615,8 @@
.WillOnce(Return(false));
EXPECT_CALL(mHwComposer,
- getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _))
- .WillOnce(DoAll(SetArgPointee<4>(changes), Return(NO_ERROR)));
+ getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
+ .WillOnce(DoAll(SetArgPointee<5>(changes), Return(NO_ERROR)));
EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1);
EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1);
EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1);
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 224dad1..0f174db 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -51,9 +51,9 @@
MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId));
MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId));
- MOCK_METHOD5(getDeviceCompositionChanges,
+ MOCK_METHOD6(getDeviceCompositionChanges,
status_t(HalDisplayId, bool, std::chrono::steady_clock::time_point,
- const std::shared_ptr<FenceTime>&,
+ const std::shared_ptr<FenceTime>&, nsecs_t,
std::optional<android::HWComposer::DeviceRequestedChanges>*));
MOCK_METHOD5(setClientTarget,
status_t(HalDisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index c9b6144..081f526 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -59,14 +59,11 @@
aidl::android::hardware::graphics::composer3::VsyncPeriodChangeConstraints;
using AidlVsyncPeriodChangeTimeline =
aidl::android::hardware::graphics::composer3::VsyncPeriodChangeTimeline;
-using AidlLayerGenericMetadataKey =
- aidl::android::hardware::graphics::composer3::LayerGenericMetadataKey;
using AidlDisplayContentSamplingAttributes =
aidl::android::hardware::graphics::composer3::DisplayContentSamplingAttributes;
using AidlFormatColorComponent = aidl::android::hardware::graphics::composer3::FormatColorComponent;
using AidlDisplayConnectionType =
aidl::android::hardware::graphics::composer3::DisplayConnectionType;
-using AidlIComposerClient = aidl::android::hardware::graphics::composer3::IComposerClient;
using AidlColorTransform = aidl::android::hardware::graphics::common::ColorTransform;
using AidlDataspace = aidl::android::hardware::graphics::common::Dataspace;
@@ -167,14 +164,6 @@
}
template <>
-IComposerClient::LayerGenericMetadataKey translate(AidlLayerGenericMetadataKey x) {
- return IComposerClient::LayerGenericMetadataKey{
- .name = x.name,
- .mandatory = x.mandatory,
- };
-}
-
-template <>
IComposerClient::ClientTargetProperty translate(ClientTargetProperty x) {
return IComposerClient::ClientTargetProperty{
.pixelFormat = translate<PixelFormat>(x.pixelFormat),
@@ -253,6 +242,14 @@
AidlComposer::~AidlComposer() = default;
+bool AidlComposer::isSupported(OptionalFeature feature) const {
+ switch (feature) {
+ case OptionalFeature::RefreshRateSwitching:
+ case OptionalFeature::ExpectedPresentTime:
+ return true;
+ }
+}
+
std::vector<IComposer::Capability> AidlComposer::getCapabilities() {
std::vector<Capability> capabilities;
const auto status = mAidlComposer->getCapabilities(&capabilities);
@@ -529,9 +526,8 @@
return Error::NONE;
}
-Error AidlComposer::setColorTransform(Display display, const float* matrix, ColorTransform hint) {
- mWriter.setColorTransform(translate<int64_t>(display), matrix,
- translate<AidlColorTransform>(hint));
+Error AidlComposer::setColorTransform(Display display, const float* matrix) {
+ mWriter.setColorTransform(translate<int64_t>(display), matrix);
return Error::NONE;
}
@@ -573,10 +569,11 @@
return Error::NONE;
}
-Error AidlComposer::validateDisplay(Display display, uint32_t* outNumTypes,
- uint32_t* outNumRequests) {
+Error AidlComposer::validateDisplay(Display display, nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes, uint32_t* outNumRequests) {
ATRACE_NAME("HwcValidateDisplay");
- mWriter.validateDisplay(translate<int64_t>(display));
+ mWriter.validateDisplay(translate<int64_t>(display),
+ ClockMonotonicTimestamp{expectedPresentTime});
Error error = execute();
if (error != Error::NONE) {
@@ -588,11 +585,12 @@
return Error::NONE;
}
-Error AidlComposer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
- uint32_t* outNumRequests, int* outPresentFence,
- uint32_t* state) {
+Error AidlComposer::presentOrValidateDisplay(Display display, nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes, uint32_t* outNumRequests,
+ int* outPresentFence, uint32_t* state) {
ATRACE_NAME("HwcPresentOrValidateDisplay");
- mWriter.presentOrvalidateDisplay(translate<int64_t>(display));
+ mWriter.presentOrvalidateDisplay(translate<int64_t>(display),
+ ClockMonotonicTimestamp{expectedPresentTime});
Error error = execute();
if (error != Error::NONE) {
@@ -980,24 +978,16 @@
return V2_4::Error::NONE;
}
-V2_4::Error AidlComposer::setLayerGenericMetadata(Display display, Layer layer,
- const std::string& key, bool mandatory,
- const std::vector<uint8_t>& value) {
- mWriter.setLayerGenericMetadata(translate<int64_t>(display), translate<int64_t>(layer), key,
- mandatory, value);
- return V2_4::Error::NONE;
+V2_4::Error AidlComposer::setLayerGenericMetadata(Display, Layer, const std::string&, bool,
+ const std::vector<uint8_t>&) {
+ // There are no users for this API. See b/209691612.
+ return V2_4::Error::UNSUPPORTED;
}
V2_4::Error AidlComposer::getLayerGenericMetadataKeys(
- std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) {
- std::vector<AidlLayerGenericMetadataKey> keys;
- const auto status = mAidlComposerClient->getLayerGenericMetadataKeys(&keys);
- if (!status.isOk()) {
- ALOGE("getLayerGenericMetadataKeys failed %s", status.getDescription().c_str());
- return static_cast<V2_4::Error>(status.getServiceSpecificError());
- }
- *outKeys = translate<IComposerClient::LayerGenericMetadataKey>(keys);
- return V2_4::Error::NONE;
+ std::vector<IComposerClient::LayerGenericMetadataKey>*) {
+ // There are no users for this API. See b/209691612.
+ return V2_4::Error::UNSUPPORTED;
}
Error AidlComposer::getClientTargetProperty(
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 057ba89..777b295 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -34,7 +34,8 @@
#include <aidl/android/hardware/graphics/composer3/IComposer.h>
#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
-#include <android/hardware/graphics/composer3/command-buffer.h>
+#include <android/hardware/graphics/composer3/ComposerClientReader.h>
+#include <android/hardware/graphics/composer3/ComposerClientWriter.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
@@ -43,8 +44,8 @@
namespace android::Hwc2 {
-using AidlCommandWriterBase = aidl::android::hardware::graphics::composer3::CommandWriterBase;
-using AidlCommandReaderBase = aidl::android::hardware::graphics::composer3::CommandReaderBase;
+using aidl::android::hardware::graphics::composer3::ComposerClientReader;
+using aidl::android::hardware::graphics::composer3::ComposerClientWriter;
class AidlIComposerCallbackWrapper;
@@ -56,6 +57,8 @@
explicit AidlComposer(const std::string& serviceName);
~AidlComposer() override;
+ bool isSupported(OptionalFeature) const;
+
std::vector<IComposer::Capability> getCapabilities() override;
std::string dumpDebugInfo() override;
@@ -113,7 +116,7 @@
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage) override;
Error setColorMode(Display display, ColorMode mode, RenderIntent renderIntent) override;
- Error setColorTransform(Display display, const float* matrix, ColorTransform hint) override;
+ Error setColorTransform(Display display, const float* matrix) override;
Error setOutputBuffer(Display display, const native_handle_t* buffer,
int releaseFence) override;
Error setPowerMode(Display display, IComposerClient::PowerMode mode) override;
@@ -121,10 +124,11 @@
Error setClientTargetSlotCount(Display display) override;
- Error validateDisplay(Display display, uint32_t* outNumTypes,
+ Error validateDisplay(Display display, nsecs_t expectedPresentTime, uint32_t* outNumTypes,
uint32_t* outNumRequests) override;
- Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes, uint32_t* outNumRequests,
+ Error presentOrValidateDisplay(Display display, nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes, uint32_t* outNumRequests,
int* outPresentFence, uint32_t* state) override;
Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override;
@@ -178,7 +182,6 @@
Error setDisplayBrightness(Display display, float brightness) override;
// Composer HAL 2.4
- bool isVsyncPeriodSwitchSupported() override { return true; }
Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) override;
V2_4::Error getDisplayConnectionType(Display display,
@@ -219,8 +222,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;
- AidlCommandWriterBase mWriter;
- AidlCommandReaderBase mReader;
+ ComposerClientWriter mWriter;
+ ComposerClientReader mReader;
// Aidl interface
using AidlIComposer = aidl::android::hardware::graphics::composer3::IComposer;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index b4ba8ab..a6a1e6f 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -75,6 +75,13 @@
virtual ~Composer() = 0;
+ enum class OptionalFeature {
+ RefreshRateSwitching,
+ ExpectedPresentTime,
+ };
+
+ virtual bool isSupported(OptionalFeature) const = 0;
+
virtual std::vector<IComposer::Capability> getCapabilities() = 0;
virtual std::string dumpDebugInfo() = 0;
@@ -132,7 +139,7 @@
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage) = 0;
virtual Error setColorMode(Display display, ColorMode mode, RenderIntent renderIntent) = 0;
- virtual Error setColorTransform(Display display, const float* matrix, ColorTransform hint) = 0;
+ virtual Error setColorTransform(Display display, const float* matrix) = 0;
virtual Error setOutputBuffer(Display display, const native_handle_t* buffer,
int releaseFence) = 0;
virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0;
@@ -140,12 +147,12 @@
virtual Error setClientTargetSlotCount(Display display) = 0;
- virtual Error validateDisplay(Display display, uint32_t* outNumTypes,
- uint32_t* outNumRequests) = 0;
+ virtual Error validateDisplay(Display display, nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes, uint32_t* outNumRequests) = 0;
- virtual Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
- uint32_t* outNumRequests, int* outPresentFence,
- uint32_t* state) = 0;
+ virtual Error presentOrValidateDisplay(Display display, nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes, uint32_t* outNumRequests,
+ int* outPresentFence, uint32_t* state) = 0;
virtual Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0;
/* see setClientTarget for the purpose of slot */
@@ -200,7 +207,6 @@
virtual Error setDisplayBrightness(Display display, float brightness) = 0;
// Composer HAL 2.4
- virtual bool isVsyncPeriodSwitchSupported() = 0;
virtual Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) = 0;
virtual V2_4::Error getDisplayConnectionType(
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 82f463e..3dcea61 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -144,7 +144,7 @@
bool Display::isVsyncPeriodSwitchSupported() const {
ALOGV("[%" PRIu64 "] isVsyncPeriodSwitchSupported()", mId);
- return mComposer.isVsyncPeriodSwitchSupported();
+ return mComposer.isSupported(android::Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
}
Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
@@ -436,8 +436,8 @@
return static_cast<Error>(intError);
}
-Error Display::setColorTransform(const android::mat4& matrix, ColorTransform hint) {
- auto intError = mComposer.setColorTransform(mId, matrix.asArray(), hint);
+Error Display::setColorTransform(const android::mat4& matrix) {
+ auto intError = mComposer.setColorTransform(mId, matrix.asArray());
return static_cast<Error>(intError);
}
@@ -492,11 +492,11 @@
return static_cast<Error>(intError);
}
-Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests)
-{
+Error Display::validate(nsecs_t expectedPresentTime, uint32_t* outNumTypes,
+ uint32_t* outNumRequests) {
uint32_t numTypes = 0;
uint32_t numRequests = 0;
- auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests);
+ auto intError = mComposer.validateDisplay(mId, expectedPresentTime, &numTypes, &numRequests);
auto error = static_cast<Error>(intError);
if (error != Error::NONE && !hasChangesError(error)) {
return error;
@@ -507,14 +507,14 @@
return error;
}
-Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
- sp<android::Fence>* outPresentFence, uint32_t* state) {
-
+Error Display::presentOrValidate(nsecs_t expectedPresentTime, uint32_t* outNumTypes,
+ uint32_t* outNumRequests, sp<android::Fence>* outPresentFence,
+ uint32_t* state) {
uint32_t numTypes = 0;
uint32_t numRequests = 0;
int32_t presentFenceFd = -1;
- auto intError = mComposer.presentOrValidateDisplay(
- mId, &numTypes, &numRequests, &presentFenceFd, state);
+ auto intError = mComposer.presentOrValidateDisplay(mId, expectedPresentTime, &numTypes,
+ &numRequests, &presentFenceFd, state);
auto error = static_cast<Error>(intError);
if (error != Error::NONE && !hasChangesError(error)) {
return error;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 1425c61..c2ebd45 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -128,16 +128,17 @@
[[clang::warn_unused_result]] virtual hal::Error setColorMode(
hal::ColorMode mode, hal::RenderIntent renderIntent) = 0;
[[clang::warn_unused_result]] virtual hal::Error setColorTransform(
- const android::mat4& matrix, hal::ColorTransform hint) = 0;
+ const android::mat4& matrix) = 0;
[[clang::warn_unused_result]] virtual hal::Error setOutputBuffer(
const android::sp<android::GraphicBuffer>& buffer,
const android::sp<android::Fence>& releaseFence) = 0;
[[clang::warn_unused_result]] virtual hal::Error setPowerMode(hal::PowerMode mode) = 0;
[[clang::warn_unused_result]] virtual hal::Error setVsyncEnabled(hal::Vsync enabled) = 0;
- [[clang::warn_unused_result]] virtual hal::Error validate(uint32_t* outNumTypes,
+ [[clang::warn_unused_result]] virtual hal::Error validate(nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes,
uint32_t* outNumRequests) = 0;
[[clang::warn_unused_result]] virtual hal::Error presentOrValidate(
- uint32_t* outNumTypes, uint32_t* outNumRequests,
+ nsecs_t expectedPresentTime, uint32_t* outNumTypes, uint32_t* outNumRequests,
android::sp<android::Fence>* outPresentFence, uint32_t* state) = 0;
[[clang::warn_unused_result]] virtual std::future<hal::Error> setDisplayBrightness(
float brightness) = 0;
@@ -197,13 +198,15 @@
const android::sp<android::Fence>& acquireFence,
hal::Dataspace dataspace) override;
hal::Error setColorMode(hal::ColorMode, hal::RenderIntent) override;
- hal::Error setColorTransform(const android::mat4& matrix, hal::ColorTransform hint) override;
+ hal::Error setColorTransform(const android::mat4& matrix) override;
hal::Error setOutputBuffer(const android::sp<android::GraphicBuffer>&,
const android::sp<android::Fence>& releaseFence) override;
hal::Error setPowerMode(hal::PowerMode) override;
hal::Error setVsyncEnabled(hal::Vsync enabled) override;
- hal::Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests) override;
- hal::Error presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
+ hal::Error validate(nsecs_t expectedPresentTime, uint32_t* outNumTypes,
+ uint32_t* outNumRequests) override;
+ hal::Error presentOrValidate(nsecs_t expectedPresentTime, uint32_t* outNumTypes,
+ uint32_t* outNumRequests,
android::sp<android::Fence>* outPresentFence,
uint32_t* state) override;
std::future<hal::Error> setDisplayBrightness(float brightness) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index d851e22..3b4fff0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -159,8 +159,10 @@
}
mRegisteredCallback = true;
+ const bool vsyncSwitchingSupported =
+ mComposer->isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
mComposer->registerCallback(
- sp<ComposerCallbackBridge>::make(callback, mComposer->isVsyncPeriodSwitchSupported()));
+ sp<ComposerCallbackBridge>::make(callback, vsyncSwitchingSupported));
}
bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort,
@@ -457,7 +459,7 @@
status_t HWComposer::getDeviceCompositionChanges(
HalDisplayId displayId, bool frameUsesClientComposition,
std::chrono::steady_clock::time_point earliestPresentTime,
- const std::shared_ptr<FenceTime>& previousPresentFence,
+ const std::shared_ptr<FenceTime>& previousPresentFence, nsecs_t expectedPresentTime,
std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) {
ATRACE_CALL();
@@ -479,16 +481,30 @@
// earliest time to present. Otherwise, we may present a frame too early.
// 2. There is no client composition. Otherwise, we first need to render the
// client target buffer.
- const bool prevFencePending =
- previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
- const bool canPresentEarly =
- !prevFencePending && std::chrono::steady_clock::now() < earliestPresentTime;
- const bool canSkipValidate = !canPresentEarly && !frameUsesClientComposition;
+ const bool canSkipValidate = [&] {
+ // We must call validate if we have client composition
+ if (frameUsesClientComposition) {
+ return false;
+ }
+
+ // If composer supports getting the expected present time, we can skip
+ // as composer will make sure to prevent early presentation
+ if (mComposer->isSupported(Hwc2::Composer::OptionalFeature::ExpectedPresentTime)) {
+ return true;
+ }
+
+ // composer doesn't support getting the expected present time. We can only
+ // skip validate if we know that we are not going to present early.
+ return std::chrono::steady_clock::now() >= earliestPresentTime ||
+ previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
+ }();
+
displayData.validateWasSkipped = false;
if (canSkipValidate) {
sp<Fence> outPresentFence;
uint32_t state = UINT32_MAX;
- error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
+ error = hwcDisplay->presentOrValidate(expectedPresentTime, &numTypes, &numRequests,
+ &outPresentFence, &state);
if (!hasChangesError(error)) {
RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
}
@@ -503,7 +519,7 @@
}
// Present failed but Validate ran.
} else {
- error = hwcDisplay->validate(&numTypes, &numRequests);
+ error = hwcDisplay->validate(expectedPresentTime, &numTypes, &numRequests);
}
ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
if (!hasChangesError(error)) {
@@ -569,9 +585,11 @@
return NO_ERROR;
}
- const bool previousFramePending =
- previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING;
- if (!previousFramePending) {
+ const bool waitForEarliestPresent =
+ !mComposer->isSupported(Hwc2::Composer::OptionalFeature::ExpectedPresentTime) &&
+ previousPresentFence->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+
+ if (waitForEarliestPresent) {
ATRACE_NAME("wait for earliest present time");
std::this_thread::sleep_until(earliestPresentTime);
}
@@ -655,11 +673,7 @@
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
- bool isIdentity = transform == mat4();
- auto error = displayData.hwcDisplay
- ->setColorTransform(transform,
- isIdentity ? hal::ColorTransform::IDENTITY
- : hal::ColorTransform::ARBITRARY_MATRIX);
+ auto error = displayData.hwcDisplay->setColorTransform(transform);
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
@@ -671,6 +685,13 @@
mPhysicalDisplayIdMap.erase(hwcDisplayId);
mDisplayData.erase(displayId);
+
+ // Reset the primary display ID if we're disconnecting it.
+ // This way isHeadless() will return false, which is necessary
+ // because getPrimaryDisplayId() will crash.
+ if (mPrimaryHwcDisplayId == hwcDisplayId) {
+ mPrimaryHwcDisplayId.reset();
+ }
}
status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index aa4abdf..b7f1064 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -134,7 +134,7 @@
virtual status_t getDeviceCompositionChanges(
HalDisplayId, bool frameUsesClientComposition,
std::chrono::steady_clock::time_point earliestPresentTime,
- const std::shared_ptr<FenceTime>& previousPresentFence,
+ const std::shared_ptr<FenceTime>& previousPresentFence, nsecs_t expectedPresentTime,
std::optional<DeviceRequestedChanges>* outChanges) = 0;
virtual status_t setClientTarget(HalDisplayId, uint32_t slot, const sp<Fence>& acquireFence,
@@ -236,9 +236,12 @@
virtual Hwc2::Composer* getComposer() const = 0;
- // Returns the first display connected at boot. It cannot be disconnected, which implies an
- // internal connection type. Its connection via HWComposer::onHotplug, which in practice is
- // immediately after HWComposer construction, must occur before any call to this function.
+ // Returns the first display connected at boot. Its connection via HWComposer::onHotplug,
+ // which in practice is immediately after HWComposer construction, must occur before any
+ // call to this function.
+ // The primary display can be temporarily disconnected from the perspective
+ // of this class. Callers must not call getPrimaryHwcDisplayId() or getPrimaryDisplayId()
+ // if isHeadless().
//
// TODO(b/182939859): Remove special cases for primary display.
virtual hal::HWDisplayId getPrimaryHwcDisplayId() const = 0;
@@ -280,7 +283,7 @@
status_t getDeviceCompositionChanges(
HalDisplayId, bool frameUsesClientComposition,
std::chrono::steady_clock::time_point earliestPresentTime,
- const std::shared_ptr<FenceTime>& previousPresentFence,
+ const std::shared_ptr<FenceTime>& previousPresentFence, nsecs_t expectedPresentTime,
std::optional<DeviceRequestedChanges>* outChanges) override;
status_t setClientTarget(HalDisplayId, uint32_t slot, const sp<Fence>& acquireFence,
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 77e704f..7236868 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -111,6 +111,8 @@
return "Cursor";
case aidl::android::hardware::graphics::composer3::Composition::SIDEBAND:
return "Sideband";
+ case aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION:
+ return "DisplayDecoration";
default:
return "Unknown";
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 18f24c1..96f4496 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -30,6 +30,7 @@
#include <hidl/HidlTransportUtils.h>
#include <log/log.h>
#include <utils/Trace.h>
+#include "Hal.h"
#include <algorithm>
#include <cinttypes>
@@ -153,6 +154,15 @@
}
}
+bool HidlComposer::isSupported(OptionalFeature feature) const {
+ switch (feature) {
+ case OptionalFeature::RefreshRateSwitching:
+ return mClient_2_4 != nullptr;
+ case OptionalFeature::ExpectedPresentTime:
+ return false;
+ }
+}
+
std::vector<IComposer::Capability> HidlComposer::getCapabilities() {
std::vector<IComposer::Capability> capabilities;
mComposer->getCapabilities(
@@ -497,9 +507,12 @@
return unwrapRet(ret);
}
-Error HidlComposer::setColorTransform(Display display, const float* matrix, ColorTransform hint) {
+Error HidlComposer::setColorTransform(Display display, const float* matrix) {
mWriter.selectDisplay(display);
- mWriter.setColorTransform(matrix, hint);
+ const bool isIdentity = (mat4(matrix) == mat4());
+ mWriter.setColorTransform(matrix,
+ isIdentity ? ColorTransform::IDENTITY
+ : ColorTransform::ARBITRARY_MATRIX);
return Error::NONE;
}
@@ -532,8 +545,8 @@
return unwrapRet(ret);
}
-Error HidlComposer::validateDisplay(Display display, uint32_t* outNumTypes,
- uint32_t* outNumRequests) {
+Error HidlComposer::validateDisplay(Display display, nsecs_t /*expectedPresentTime*/,
+ uint32_t* outNumTypes, uint32_t* outNumRequests) {
ATRACE_NAME("HwcValidateDisplay");
mWriter.selectDisplay(display);
mWriter.validateDisplay();
@@ -548,9 +561,9 @@
return Error::NONE;
}
-Error HidlComposer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
- uint32_t* outNumRequests, int* outPresentFence,
- uint32_t* state) {
+Error HidlComposer::presentOrValidateDisplay(Display display, nsecs_t /*expectedPresentTime*/,
+ uint32_t* outNumTypes, uint32_t* outNumRequests,
+ int* outPresentFence, uint32_t* state) {
ATRACE_NAME("HwcPresentOrValidateDisplay");
mWriter.selectDisplay(display);
mWriter.presentOrvalidateDisplay();
@@ -620,6 +633,11 @@
static IComposerClient::Composition to_hidl_type(
aidl::android::hardware::graphics::composer3::Composition type) {
+ LOG_ALWAYS_FATAL_IF(static_cast<int32_t>(type) >
+ static_cast<int32_t>(IComposerClient::Composition::SIDEBAND),
+ "Trying to use %s, which is not supported by HidlComposer!",
+ android::to_string(type).c_str());
+
return static_cast<IComposerClient::Composition>(type);
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 5b2219e..8190c17 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -168,6 +168,8 @@
explicit HidlComposer(const std::string& serviceName);
~HidlComposer() override;
+ bool isSupported(OptionalFeature) const;
+
std::vector<IComposer::Capability> getCapabilities() override;
std::string dumpDebugInfo() override;
@@ -225,7 +227,7 @@
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage) override;
Error setColorMode(Display display, ColorMode mode, RenderIntent renderIntent) override;
- Error setColorTransform(Display display, const float* matrix, ColorTransform hint) override;
+ Error setColorTransform(Display display, const float* matrix) override;
Error setOutputBuffer(Display display, const native_handle_t* buffer,
int releaseFence) override;
Error setPowerMode(Display display, IComposerClient::PowerMode mode) override;
@@ -233,10 +235,11 @@
Error setClientTargetSlotCount(Display display) override;
- Error validateDisplay(Display display, uint32_t* outNumTypes,
+ Error validateDisplay(Display display, nsecs_t expectedPresentTime, uint32_t* outNumTypes,
uint32_t* outNumRequests) override;
- Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes, uint32_t* outNumRequests,
+ Error presentOrValidateDisplay(Display display, nsecs_t expectedPresentTime,
+ uint32_t* outNumTypes, uint32_t* outNumRequests,
int* outPresentFence, uint32_t* state) override;
Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override;
@@ -290,7 +293,6 @@
Error setDisplayBrightness(Display display, float brightness) override;
// Composer HAL 2.4
- bool isVsyncPeriodSwitchSupported() override { return mClient_2_4 != nullptr; }
Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) override;
V2_4::Error getDisplayConnectionType(Display display,
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 0c4e112..86e96d7 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -667,7 +667,8 @@
packet->set_timestamp(
static_cast<uint64_t>(endTime - kPredictionExpiredStartTimeDelta));
} else {
- packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
+ packet->set_timestamp(static_cast<uint64_t>(
+ mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime));
}
auto* event = packet->set_frame_timeline_event();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6e9138c..5948a78 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1263,6 +1263,7 @@
getSequence(), mName,
mTransactionName,
/*isBuffer*/ false, getGameMode());
+ surfaceFrame->setActualStartTime(info.startTimeNanos);
// For Transactions, the post time is considered to be both queue and acquire fence time.
surfaceFrame->setActualQueueTime(postTime);
surfaceFrame->setAcquireFenceTime(postTime);
@@ -1280,6 +1281,7 @@
mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
getSequence(), mName, debugName,
/*isBuffer*/ true, getGameMode());
+ surfaceFrame->setActualStartTime(info.startTimeNanos);
// For buffers, acquire fence time will set during latch.
surfaceFrame->setActualQueueTime(queueTime);
const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4f38588..4d7e4d9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -269,6 +269,7 @@
enum Permission {
ACCESS_SURFACE_FLINGER = 0x1,
ROTATE_SURFACE_FLINGER = 0x2,
+ INTERNAL_SYSTEM_WINDOW = 0x4,
};
struct IdleTimerConfig {
@@ -316,6 +317,7 @@
const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS");
const String16 sDump("android.permission.DUMP");
const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONTENT");
+const String16 sInternalSystemWindow("android.permission.INTERNAL_SYSTEM_WINDOW");
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
@@ -358,6 +360,13 @@
PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid);
}
+bool callingThreadHasInternalSystemWindowAccess() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ return PermissionCache::checkPermission(sInternalSystemWindow, pid, uid);
+}
+
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
: mFactory(factory),
mPid(getpid()),
@@ -2101,11 +2110,13 @@
refreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::milliseconds(mDebugFlashDelay);
}
- const auto prevVsyncTime = mScheduler->getPreviousVsyncFrom(mExpectedPresentTime);
+ const auto expectedPresentTime = mExpectedPresentTime.load();
+ const auto prevVsyncTime = mScheduler->getPreviousVsyncFrom(expectedPresentTime);
const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration;
refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime;
refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime();
+ refreshArgs.expectedPresentTime = expectedPresentTime;
// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
@@ -3673,7 +3684,7 @@
const std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>&
bufferLayersReadyToPresent,
bool allowLatchUnsignaled) const {
- ATRACE_CALL();
+ ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId);
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
// Do not present if the desiredPresentTime has not passed unless it is more than one second
// in the future. We ignore timestamps more than 1 second in the future for stability reasons.
@@ -3810,6 +3821,10 @@
permissions |= Permission::ROTATE_SURFACE_FLINGER;
}
+ if (callingThreadHasInternalSystemWindowAccess()) {
+ permissions |= Permission::INTERNAL_SYSTEM_WINDOW;
+ }
+
if (!(permissions & Permission::ACCESS_SURFACE_FLINGER) &&
(flags & (eEarlyWakeupStart | eEarlyWakeupEnd))) {
ALOGE("Only WindowManager is allowed to use eEarlyWakeup[Start|End] flags");
@@ -4147,8 +4162,15 @@
flags |= eTraversalNeeded;
}
if (what & layer_state_t::eFlagsChanged) {
- if (layer->setFlags(s.flags, s.mask))
- flags |= eTraversalNeeded;
+ auto changedFlags = s.flags;
+ if (changedFlags & layer_state_t::eLayerIsDisplayDecoration) {
+ if ((permissions & Permission::INTERNAL_SYSTEM_WINDOW) == 0) {
+ changedFlags &= ~layer_state_t::eLayerIsDisplayDecoration;
+ ALOGE("Attempt to use eLayerIsDisplayDecoration without permission "
+ "INTERNAL_SYSTEM_WINDOW!");
+ }
+ }
+ if (layer->setFlags(changedFlags, s.mask)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eCornerRadiusChanged) {
if (layer->setCornerRadius(s.cornerRadius))
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 554e454..89a517f 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -87,6 +87,11 @@
constexpr int DEFAULT_SIDEBAND_STREAM = 51;
+MATCHER(IsIdentityMatrix, "") {
+ constexpr auto kIdentity = mat4();
+ return (mat4(arg) == kIdentity);
+}
+
class CompositionTest : public testing::Test {
public:
CompositionTest() {
@@ -325,9 +330,7 @@
template <typename Case>
static void setupCommonCompositionCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mComposer,
- setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY))
- .Times(1);
+ EXPECT_CALL(*test->mComposer, setColorTransform(HWC_DISPLAY, IsIdentityMatrix())).Times(1);
EXPECT_CALL(*test->mComposer, getDisplayRequests(HWC_DISPLAY, _, _, _)).Times(1);
EXPECT_CALL(*test->mComposer, acceptDisplayChanges(HWC_DISPLAY)).Times(1);
EXPECT_CALL(*test->mComposer, presentDisplay(HWC_DISPLAY, _)).Times(1);
@@ -367,7 +370,8 @@
}
static void setupHwcCompositionCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _)).Times(1);
+ EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _, _))
+ .Times(1);
EXPECT_CALL(*test->mDisplaySurface,
prepareFrame(compositionengine::DisplaySurface::CompositionType::Hwc))
@@ -375,11 +379,12 @@
}
static void setupHwcClientCompositionCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _)).Times(1);
+ EXPECT_CALL(*test->mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _, _))
+ .Times(1);
}
static void setupHwcForcedClientCompositionCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mComposer, validateDisplay(HWC_DISPLAY, _, _)).Times(1);
+ EXPECT_CALL(*test->mComposer, validateDisplay(HWC_DISPLAY, _, _, _)).Times(1);
}
static void setupRECompositionCallExpectations(CompositionTest* test) {
@@ -446,9 +451,7 @@
template <typename Case>
static void setupCommonCompositionCallExpectations(CompositionTest* test) {
// TODO: This seems like an unnecessary call if display is powered off.
- EXPECT_CALL(*test->mComposer,
- setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY))
- .Times(1);
+ EXPECT_CALL(*test->mComposer, setColorTransform(HWC_DISPLAY, IsIdentityMatrix())).Times(1);
// TODO: This seems like an unnecessary call if display is powered off.
Case::CompositionType::setupHwcSetCallExpectations(test);
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 655baf8..765dec3 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -36,6 +36,7 @@
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
+#include "DisplayIdentificationTest.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockHWC2.h"
@@ -57,6 +58,29 @@
using ::testing::SetArgPointee;
using ::testing::StrictMock;
+TEST(HWComposerTest, isHeadless) {
+ Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
+ impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
+ ASSERT_TRUE(hwc.isHeadless());
+
+ const hal::HWDisplayId hwcId = 1;
+
+ EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
+ .WillOnce(DoAll(SetArgPointee<2>(getExternalEdid()),
+ Return(hardware::graphics::composer::V2_1::Error::NONE)));
+
+ EXPECT_CALL(*mHal, setVsyncEnabled(_, _));
+ EXPECT_CALL(*mHal, setClientTargetSlotCount(_));
+
+ auto info = hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
+ ASSERT_TRUE(info);
+ auto displayId = info->id;
+ ASSERT_FALSE(hwc.isHeadless());
+
+ hwc.disconnectDisplay(displayId);
+ ASSERT_TRUE(hwc.isHeadless());
+}
+
struct MockHWC2ComposerCallback final : StrictMock<HWC2::ComposerCallback> {
MOCK_METHOD2(onComposerHalHotplug, void(hal::HWDisplayId, hal::Connection));
MOCK_METHOD1(onComposerHalRefresh, void(hal::HWDisplayId));
@@ -86,7 +110,8 @@
}),
Return(hardware::graphics::composer::V2_4::Error::NONE)));
EXPECT_CALL(*mHal, registerCallback(_));
- EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported()).WillOnce(Return(false));
+ EXPECT_CALL(*mHal, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
+ .WillOnce(Return(false));
impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
hwc.setCallback(&mCallback);
@@ -104,7 +129,8 @@
EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_))
.WillOnce(Return(hardware::graphics::composer::V2_4::Error::UNSUPPORTED));
EXPECT_CALL(*mHal, registerCallback(_));
- EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported()).WillOnce(Return(false));
+ EXPECT_CALL(*mHal, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
+ .WillOnce(Return(false));
impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
hwc.setCallback(&mCallback);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 9796a70..56a0506 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -52,7 +52,8 @@
// isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy
// will call setActiveConfig instead of setActiveConfigWithConstraints.
- ON_CALL(*mComposer, isVsyncPeriodSwitchSupported()).WillByDefault(Return(true));
+ ON_CALL(*mComposer, isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching))
+ .WillByDefault(Return(true));
}
protected:
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index c3250d5..a1aacc0 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -48,6 +48,7 @@
Composer();
~Composer() override;
+ MOCK_METHOD(bool, isSupported, (OptionalFeature), (const, override));
MOCK_METHOD0(getCapabilities, std::vector<IComposer::Capability>());
MOCK_METHOD0(dumpDebugInfo, std::string());
MOCK_METHOD1(registerCallback, void(const sp<IComposerCallback>&));
@@ -83,13 +84,14 @@
Error(Display, uint32_t, const sp<GraphicBuffer>&, int, Dataspace,
const std::vector<IComposerClient::Rect>&));
MOCK_METHOD3(setColorMode, Error(Display, ColorMode, RenderIntent));
- MOCK_METHOD3(setColorTransform, Error(Display, const float*, ColorTransform));
+ MOCK_METHOD2(setColorTransform, Error(Display, const float*));
MOCK_METHOD3(setOutputBuffer, Error(Display, const native_handle_t*, int));
MOCK_METHOD2(setPowerMode, Error(Display, IComposerClient::PowerMode));
MOCK_METHOD2(setVsyncEnabled, Error(Display, IComposerClient::Vsync));
MOCK_METHOD1(setClientTargetSlotCount, Error(Display));
- MOCK_METHOD3(validateDisplay, Error(Display, uint32_t*, uint32_t*));
- MOCK_METHOD5(presentOrValidateDisplay, Error(Display, uint32_t*, uint32_t*, int*, uint32_t*));
+ MOCK_METHOD4(validateDisplay, Error(Display, nsecs_t, uint32_t*, uint32_t*));
+ MOCK_METHOD6(presentOrValidateDisplay,
+ Error(Display, nsecs_t, uint32_t*, uint32_t*, int*, uint32_t*));
MOCK_METHOD4(setCursorPosition, Error(Display, Layer, int32_t, int32_t));
MOCK_METHOD5(setLayerBuffer, Error(Display, Layer, uint32_t, const sp<GraphicBuffer>&, int));
MOCK_METHOD3(setLayerSurfaceDamage,
@@ -119,7 +121,6 @@
MOCK_METHOD3(setLayerPerFrameMetadataBlobs,
Error(Display, Layer, const std::vector<IComposerClient::PerFrameMetadataBlob>&));
MOCK_METHOD2(setDisplayBrightness, Error(Display, float));
- MOCK_METHOD0(isVsyncPeriodSwitchSupported, bool());
MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*));
MOCK_METHOD2(getDisplayConnectionType,
V2_4::Error(Display, IComposerClient::DisplayConnectionType*));
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index d4fefee..b43bc0e 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -68,16 +68,16 @@
const android::sp<android::Fence> &, hal::Dataspace),
(override));
MOCK_METHOD(hal::Error, setColorMode, (hal::ColorMode, hal::RenderIntent), (override));
- MOCK_METHOD(hal::Error, setColorTransform, (const android::mat4 &, hal::ColorTransform),
- (override));
+ MOCK_METHOD(hal::Error, setColorTransform, (const android::mat4 &), (override));
MOCK_METHOD(hal::Error, setOutputBuffer,
(const android::sp<android::GraphicBuffer> &, const android::sp<android::Fence> &),
(override));
MOCK_METHOD(hal::Error, setPowerMode, (hal::PowerMode), (override));
MOCK_METHOD(hal::Error, setVsyncEnabled, (hal::Vsync), (override));
- MOCK_METHOD(hal::Error, validate, (uint32_t *, uint32_t *), (override));
+ MOCK_METHOD(hal::Error, validate, (nsecs_t, uint32_t *, uint32_t *), (override));
MOCK_METHOD(hal::Error, presentOrValidate,
- (uint32_t *, uint32_t *, android::sp<android::Fence> *, uint32_t *), (override));
+ (nsecs_t, uint32_t *, uint32_t *, android::sp<android::Fence> *, uint32_t *),
+ (override));
MOCK_METHOD(std::future<hal::Error>, setDisplayBrightness, (float), (override));
MOCK_METHOD(hal::Error, setActiveConfigWithConstraints,
(hal::HWConfigId, const hal::VsyncPeriodChangeConstraints &,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index eb4befd..4a6b4f1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1222,18 +1222,26 @@
swap_interval ? create_info->minImageCount : mailbox_num_images;
uint32_t num_images = requested_images - 1 + min_undequeued_buffers;
- // Lower layer insists that we have at least two buffers. This is wasteful
- // and we'd like to relax it in the shared case, but not all the pieces are
- // in place for that to work yet. Note we only lie to the lower layer-- we
- // don't want to give the app back a swapchain with extra images (which they
- // can't actually use!).
- err = native_window_set_buffer_count(window, std::max(2u, num_images));
+ // Lower layer insists that we have at least min_undequeued_buffers + 1
+ // buffers. This is wasteful and we'd like to relax it in the shared case,
+ // but not all the pieces are in place for that to work yet. Note we only
+ // lie to the lower layer--we don't want to give the app back a swapchain
+ // with extra images (which they can't actually use!).
+ uint32_t min_buffer_count = min_undequeued_buffers + 1;
+ err = native_window_set_buffer_count(
+ window, std::max(min_buffer_count, num_images));
if (err != android::OK) {
ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
strerror(-err), err);
return VK_ERROR_SURFACE_LOST_KHR;
}
+ // In shared mode the num_images must be one regardless of how many
+ // buffers were allocated for the buffer queue.
+ if (swapchain_image_usage & VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID) {
+ num_images = 1;
+ }
+
int32_t legacy_usage = 0;
if (dispatch.GetSwapchainGrallocUsage2ANDROID) {
uint64_t consumer_usage, producer_usage;