diff options
342 files changed, 7618 insertions, 2613 deletions
diff --git a/Android.bp b/Android.bp index 9829c7fbad..6fe0246753 100644 --- a/Android.bp +++ b/Android.bp @@ -1,3 +1,41 @@ +package { + default_applicable_licenses: ["frameworks_native_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// +// large-scale-change filtered out the below license kinds as false-positives: +// SPDX-license-identifier-LGPL +// SPDX-license-identifier-LGPL-2.1 +// SPDX-license-identifier-LGPL-3.0 +// See: http://go/android-license-faq +license { + name: "frameworks_native_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "SPDX-license-identifier-BSD", + "SPDX-license-identifier-MIT", + "SPDX-license-identifier-Unicode-DFS", + "legacy_notice", + ], + license_text: [ + "NOTICE", + ], +} + ndk_headers { name: "libandroid_headers", from: "include/android", diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp index e7d0ad0549..aa0ef253bf 100644 --- a/cmds/atrace/Android.bp +++ b/cmds/atrace/Android.bp @@ -1,5 +1,22 @@ // Copyright 2012 The Android Open Source Project +package { + default_applicable_licenses: ["frameworks_native_cmds_atrace_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_cmds_atrace_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_binary { name: "atrace", srcs: ["atrace.cpp"], diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc index 994375b30e..006e5329cd 100644 --- a/cmds/atrace/atrace.rc +++ b/cmds/atrace/atrace.rc @@ -37,12 +37,18 @@ on late-init chmod 0666 /sys/kernel/tracing/events/sched/sched_process_exit/enable chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_waking/enable chmod 0666 /sys/kernel/tracing/events/sched/sched_waking/enable + chmod 0666 /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/enable + chmod 0666 /sys/kernel/tracing/events/sched/sched_wakeup_new/enable chmod 0666 /sys/kernel/debug/tracing/events/cgroup/enable chmod 0666 /sys/kernel/tracing/events/cgroup/enable chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency/enable chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_idle/enable chmod 0666 /sys/kernel/tracing/events/power/cpu_idle/enable + chmod 0666 /sys/kernel/debug/tracing/events/power/clock_enable/enable + chmod 0666 /sys/kernel/tracing/events/power/clock_enable/enable + chmod 0666 /sys/kernel/debug/tracing/events/power/clock_disable/enable + chmod 0666 /sys/kernel/tracing/events/power/clock_disable/enable chmod 0666 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable chmod 0666 /sys/kernel/tracing/events/power/clock_set_rate/enable chmod 0666 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable @@ -79,6 +85,8 @@ on late-init chmod 0666 /sys/kernel/tracing/events/binder/binder_locked/enable chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable chmod 0666 /sys/kernel/tracing/events/binder/binder_unlock/enable + chmod 0666 /sys/kernel/debug/tracing/events/binder/binder_set_priority/enable + chmod 0666 /sys/kernel/tracing/events/binder/binder_set_priority/enable chmod 0666 /sys/kernel/debug/tracing/events/i2c/enable chmod 0666 /sys/kernel/tracing/events/i2c/enable chmod 0666 /sys/kernel/debug/tracing/events/i2c/i2c_read/enable @@ -125,12 +133,48 @@ on late-init chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable chmod 0666 /sys/kernel/debug/tracing/events/oom/oom_score_adj_update/enable chmod 0666 /sys/kernel/tracing/events/oom/oom_score_adj_update/enable + chmod 0666 /sys/kernel/debug/tracing/events/oom/mark_victim/enable + chmod 0666 /sys/kernel/tracing/events/oom/mark_victim/enable chmod 0666 /sys/kernel/debug/tracing/events/task/task_rename/enable chmod 0666 /sys/kernel/tracing/events/task/task_rename/enable chmod 0666 /sys/kernel/debug/tracing/events/task/task_newtask/enable chmod 0666 /sys/kernel/tracing/events/task/task_newtask/enable chmod 0666 /sys/kernel/debug/tracing/events/gpu_mem/gpu_mem_total/enable chmod 0666 /sys/kernel/tracing/events/gpu_mem/gpu_mem_total/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/enable + chmod 0666 /sys/kernel/tracing/events/irq/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/irq_handler_entry/enable + chmod 0666 /sys/kernel/tracing/events/irq/irq_handler_entry/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/irq_handler_exit/enable + chmod 0666 /sys/kernel/tracing/events/irq/irq_handler_exit/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_entry/enable + chmod 0666 /sys/kernel/tracing/events/irq/softirq_entry/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_exit/enable + chmod 0666 /sys/kernel/tracing/events/irq/softirq_exit/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/softirq_raise/enable + chmod 0666 /sys/kernel/tracing/events/irq/softirq_raise/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_entry/enable + chmod 0666 /sys/kernel/tracing/events/irq/tasklet_entry/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_exit/enable + chmod 0666 /sys/kernel/tracing/events/irq/tasklet_exit/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_hi_entry/enable + chmod 0666 /sys/kernel/tracing/events/irq/tasklet_hi_entry/enable + chmod 0666 /sys/kernel/debug/tracing/events/irq/tasklet_hi_exit/enable + chmod 0666 /sys/kernel/tracing/events/irq/tasklet_hi_exit/enable + chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable + chmod 0666 /sys/kernel/tracing/events/ipi/enable + chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_entry/enable + chmod 0666 /sys/kernel/tracing/events/ipi/ipi_entry/enable + chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_exit/enable + chmod 0666 /sys/kernel/tracing/events/ipi/ipi_exit/enable + chmod 0666 /sys/kernel/debug/tracing/events/ipi/ipi_raise/enable + chmod 0666 /sys/kernel/tracing/events/ipi/ipi_raise/enable + chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_enable/enable + chmod 0666 /sys/kernel/tracing/events/clk/clk_disable/enable + chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_disable/enable + chmod 0666 /sys/kernel/tracing/events/clk/clk_enable/enable + chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable + chmod 0666 /sys/kernel/tracing/events/clk/clk_set_rate/enable # disk chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable @@ -220,6 +264,67 @@ on late-init chmod 0666 /sys/kernel/debug/tracing/per_cpu/cpu15/trace chmod 0666 /sys/kernel/tracing/per_cpu/cpu15/trace +on post-fs-data +# Create MM Events Tracing Instance for Kmem Activity Trigger + mkdir /sys/kernel/debug/tracing/instances/mm_events 0755 system system + mkdir /sys/kernel/tracing/instances/mm_events 0755 system system + +# Read and set per CPU buffer size + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/buffer_size_kb + chmod 0666 /sys/kernel/tracing/instances/mm_events/buffer_size_kb + +# Read and enable tracing + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/tracing_on + chmod 0666 /sys/kernel/tracing/instances/mm_events/tracing_on + +# Read and truncate kernel trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/trace + +# Enable trace events + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/events/vmscan/mm_vmscan_direct_reclaim_begin/enable + chmod 0666 /sys/kernel/tracing/instances/mm_events/events/vmscan/mm_vmscan_direct_reclaim_begin/enable + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/events/vmscan/mm_vmscan_kswapd_wake/enable + chmod 0666 /sys/kernel/tracing/instances/mm_events/events/vmscan/mm_vmscan_kswapd_wake/enable + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/events/compaction/mm_compaction_begin/enable + chmod 0666 /sys/kernel/tracing/instances/mm_events/events/compaction/mm_compaction_begin/enable + +# Read and clear per-CPU raw kernel trace +# Cannot use wildcards in .rc files. Update this if there is a phone with +# more CPUs. + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu0/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu0/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu1/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu1/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu2/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu2/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu3/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu3/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu4/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu4/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu5/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu5/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu6/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu6/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu7/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu7/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu8/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu8/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu9/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu9/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu10/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu10/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu11/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu11/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu12/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu12/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu13/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu13/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu14/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu14/trace + chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu15/trace + chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu15/trace + on property:persist.debug.atrace.boottrace=1 start boottrace diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc index 6c86c21387..9186514d0a 100644 --- a/cmds/atrace/atrace_userdebug.rc +++ b/cmds/atrace/atrace_userdebug.rc @@ -18,8 +18,3 @@ on post-fs chmod 0666 /sys/kernel/tracing/events/filemap/enable chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable - # irq - chmod 0666 /sys/kernel/tracing/events/irq/enable - chmod 0666 /sys/kernel/debug/tracing/events/irq/enable - chmod 0666 /sys/kernel/tracing/events/ipi/enable - chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable diff --git a/cmds/bugreport/Android.bp b/cmds/bugreport/Android.bp index 24044a64b0..8262aed97b 100644 --- a/cmds/bugreport/Android.bp +++ b/cmds/bugreport/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "bugreport", srcs: ["bugreport.cpp"], diff --git a/cmds/bugreport/OWNERS b/cmds/bugreport/OWNERS index 1ba7cffa0e..2a9b681318 100644 --- a/cmds/bugreport/OWNERS +++ b/cmds/bugreport/OWNERS @@ -1,6 +1,4 @@ set noparent -felipeal@google.com nandana@google.com jsharkey@android.com -enh@google.com diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp index 924a3a351b..332f858e92 100644 --- a/cmds/bugreportz/Android.bp +++ b/cmds/bugreportz/Android.bp @@ -1,5 +1,14 @@ // bugreportz // ========== +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "bugreportz", diff --git a/cmds/bugreportz/OWNERS b/cmds/bugreportz/OWNERS index 1ba7cffa0e..2a9b681318 100644 --- a/cmds/bugreportz/OWNERS +++ b/cmds/bugreportz/OWNERS @@ -1,6 +1,4 @@ set noparent -felipeal@google.com nandana@google.com jsharkey@android.com -enh@google.com diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp index 8ea71cd048..c900a24e15 100644 --- a/cmds/cmd/Android.bp +++ b/cmds/cmd/Android.bp @@ -1,3 +1,20 @@ +package { + default_applicable_licenses: ["frameworks_native_cmds_cmd_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_cmds_cmd_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_static { name: "libcmd", diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index 80d14ac3c4..f48f1fb6f8 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -13,6 +13,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "dumpstate_cflag_defaults", cflags: [ @@ -112,6 +121,7 @@ cc_binary { ], required: [ "atrace", + "dmabuf_dump", "ip", "iptables", "librank", diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp index bfcc058c1b..ba25a5a603 100644 --- a/cmds/dumpstate/DumpstateService.cpp +++ b/cmds/dumpstate/DumpstateService.cpp @@ -39,8 +39,13 @@ struct DumpstateInfo { std::string calling_package; }; -static binder::Status exception(uint32_t code, const std::string& msg) { - MYLOGE("%s (%d) ", msg.c_str(), code); +static binder::Status exception(uint32_t code, const std::string& msg, + const std::string& extra_msg = "") { + if (extra_msg.empty()) { + MYLOGE("%s (%d) ", msg.c_str(), code); + } else { + MYLOGE("%s %s (%d) ", msg.c_str(), extra_msg.c_str(), code); + } return binder::Status::fromExceptionCode(code, String8(msg.c_str())); } @@ -60,7 +65,7 @@ static binder::Status exception(uint32_t code, const std::string& msg) { } // namespace -DumpstateService::DumpstateService() : ds_(nullptr) { +DumpstateService::DumpstateService() : ds_(nullptr), calling_uid_(-1), calling_package_() { } char const* DumpstateService::getServiceName() { @@ -131,6 +136,10 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, ds_->SetOptions(std::move(options)); ds_->listener_ = listener; + // Track caller info for cancellation purposes. + calling_uid_ = calling_uid; + calling_package_ = calling_package; + DumpstateInfo* ds_info = new DumpstateInfo(); ds_info->ds = ds_; ds_info->calling_uid = calling_uid; @@ -149,8 +158,20 @@ binder::Status DumpstateService::startBugreport(int32_t calling_uid, return binder::Status::ok(); } -binder::Status DumpstateService::cancelBugreport() { +binder::Status DumpstateService::cancelBugreport(int32_t calling_uid, + const std::string& calling_package) { std::lock_guard<std::mutex> lock(lock_); + if (calling_uid != calling_uid_ || calling_package != calling_package_) { + // Note: we use a SecurityException to prevent BugreportManagerServiceImpl from killing the + // report in progress (from another caller). + return exception( + binder::Status::EX_SECURITY, + StringPrintf("Cancellation requested by %d/%s does not match report in " + "progress", + calling_uid, calling_package.c_str()), + // Sharing the owner of the BR is a (minor) leak, so leave it out of the app's exception + StringPrintf("started by %d/%s", calling_uid_, calling_package_.c_str())); + } ds_->Cancel(); return binder::Status::ok(); } diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h index ac8d3acbb5..3ec8471c04 100644 --- a/cmds/dumpstate/DumpstateService.h +++ b/cmds/dumpstate/DumpstateService.h @@ -44,8 +44,7 @@ class DumpstateService : public BinderService<DumpstateService>, public BnDumpst const sp<IDumpstateListener>& listener, bool is_screenshot_requested) override; - // No-op - binder::Status cancelBugreport(); + binder::Status cancelBugreport(int32_t calling_uid, const std::string& calling_package); private: // Dumpstate object which contains all the bugreporting logic. @@ -53,6 +52,8 @@ class DumpstateService : public BinderService<DumpstateService>, public BnDumpst // one bugreport. // This service does not own this object. Dumpstate* ds_; + int32_t calling_uid_; + std::string calling_package_; std::mutex lock_; }; diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp index eeaa5a3de0..c833d0e6bd 100644 --- a/cmds/dumpstate/DumpstateUtil.cpp +++ b/cmds/dumpstate/DumpstateUtil.cpp @@ -124,6 +124,12 @@ CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Re return *this; } +CommandOptions::CommandOptionsBuilder& +CommandOptions::CommandOptionsBuilder::CloseAllFileDescriptorsOnExec() { + values.close_all_fds_on_exec_ = true; + return *this; +} + CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::Log( const std::string& message) { values.logging_message_ = message; @@ -137,6 +143,7 @@ CommandOptions CommandOptions::CommandOptionsBuilder::Build() { CommandOptions::CommandOptionsValues::CommandOptionsValues(int64_t timeout_ms) : timeout_ms_(timeout_ms), always_(false), + close_all_fds_on_exec_(false), account_mode_(DONT_DROP_ROOT), output_mode_(NORMAL_OUTPUT), logging_message_("") { @@ -157,6 +164,10 @@ bool CommandOptions::Always() const { return values.always_; } +bool CommandOptions::ShouldCloseAllFileDescriptorsOnExec() const { + return values.close_all_fds_on_exec_; +} + PrivilegeMode CommandOptions::PrivilegeMode() const { return values.account_mode_; } @@ -277,7 +288,8 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri MYLOGI(logging_message.c_str(), command_string.c_str()); } - bool silent = (options.OutputMode() == REDIRECT_TO_STDERR); + bool silent = (options.OutputMode() == REDIRECT_TO_STDERR || + options.ShouldCloseAllFileDescriptorsOnExec()); bool redirecting_to_fd = STDOUT_FILENO != fd; if (PropertiesHelper::IsDryRun() && !options.Always()) { @@ -314,7 +326,27 @@ int RunCommandToFd(int fd, const std::string& title, const std::vector<std::stri return -1; } - if (silent) { + if (options.ShouldCloseAllFileDescriptorsOnExec()) { + int devnull_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY)); + TEMP_FAILURE_RETRY(dup2(devnull_fd, STDIN_FILENO)); + close(devnull_fd); + devnull_fd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY)); + TEMP_FAILURE_RETRY(dup2(devnull_fd, STDOUT_FILENO)); + TEMP_FAILURE_RETRY(dup2(devnull_fd, STDERR_FILENO)); + close(devnull_fd); + // This is to avoid leaking FDs that, accidentally, have not been + // marked as O_CLOEXEC. Leaking FDs across exec can cause failures + // when execing a process that has a SELinux auto_trans rule. + // Here we assume that the dumpstate process didn't open more than + // 1000 FDs. In theory we could iterate through /proc/self/fd/, but + // doing that in a fork-safe way is too complex and not worth it + // (opendir()/readdir() do heap allocations and take locks). + for (int i = 0; i < 1000; i++) { + if (i != STDIN_FILENO && i!= STDOUT_FILENO && i != STDERR_FILENO) { + close(i); + } + } + } else if (silent) { // Redirects stdout to stderr TEMP_FAILURE_RETRY(dup2(STDERR_FILENO, STDOUT_FILENO)); } else if (redirecting_to_fd) { diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h index b099443e32..b00c46e0db 100644 --- a/cmds/dumpstate/DumpstateUtil.h +++ b/cmds/dumpstate/DumpstateUtil.h @@ -80,6 +80,7 @@ class CommandOptions { int64_t timeout_ms_; bool always_; + bool close_all_fds_on_exec_; PrivilegeMode account_mode_; OutputMode output_mode_; std::string logging_message_; @@ -112,6 +113,13 @@ class CommandOptions { CommandOptionsBuilder& DropRoot(); /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */ CommandOptionsBuilder& RedirectStderr(); + /* Closes all file descriptors before exec-ing the target process. This + * includes also stdio pipes, which are dup-ed on /dev/null. It prevents + * leaking opened FDs to the target process, which in turn can hit + * selinux denials in presence of auto_trans rules. + */ + CommandOptionsBuilder& CloseAllFileDescriptorsOnExec(); + /* When not empty, logs a message before executing the command. * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ CommandOptionsBuilder& Log(const std::string& message); @@ -130,6 +138,8 @@ class CommandOptions { int64_t TimeoutInMs() const; /* Checks whether the command should always be run, even on dry-run mode. */ bool Always() const; + /* Checks whether all FDs should be closed prior to the exec() calls. */ + bool ShouldCloseAllFileDescriptorsOnExec() const; /** Gets the PrivilegeMode of the command. */ PrivilegeMode PrivilegeMode() const; /** Gets the OutputMode of the command. */ diff --git a/cmds/dumpstate/OWNERS b/cmds/dumpstate/OWNERS index 1ba7cffa0e..2a9b681318 100644 --- a/cmds/dumpstate/OWNERS +++ b/cmds/dumpstate/OWNERS @@ -1,6 +1,4 @@ set noparent -felipeal@google.com nandana@google.com jsharkey@android.com -enh@google.com diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl index ba008bb27e..0793f0b95f 100644 --- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl +++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2016, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,9 +19,9 @@ package android.os; import android.os.IDumpstateListener; /** - * Binder interface for the currently running dumpstate process. - * {@hide} - */ + * Binder interface for the currently running dumpstate process. + * {@hide} + */ interface IDumpstate { // NOTE: If you add to or change these modes, please also change the corresponding enums @@ -49,10 +49,10 @@ interface IDumpstate { // Default mode. const int BUGREPORT_MODE_DEFAULT = 6; - /* + /** * Starts a bugreport in the background. * - *<p>Shows the user a dialog to get consent for sharing the bugreport with the calling + * <p>Shows the user a dialog to get consent for sharing the bugreport with the calling * application. If they deny {@link IDumpstateListener#onError} will be called. If they * consent and bugreport generation is successful artifacts will be copied to the given fds and * {@link IDumpstateListener#onFinished} will be called. If there @@ -71,8 +71,15 @@ interface IDumpstate { int bugreportMode, IDumpstateListener listener, boolean isScreenshotRequested); - /* + /** * Cancels the bugreport currently in progress. + * + * <p>The caller must match the original caller of {@link #startBugreport} in order for the + * report to actually be cancelled. A {@link SecurityException} is reported if a mismatch is + * detected. + * + * @param callingUid UID of the original application that requested the cancellation. + * @param callingPackage package of the original application that requested the cancellation. */ - void cancelBugreport(); + void cancelBugreport(int callingUid, @utf8InCpp String callingPackage); } diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl index 85e6969180..50c1624dc2 100644 --- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl +++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl @@ -21,8 +21,6 @@ package android.os; * * <p>When bugreport creation is complete one of {@code onError} or {@code onFinished} is called. * - * <p>These methods are synchronous by design in order to make dumpstate's lifecycle simpler - * to handle. * * {@hide} */ @@ -54,10 +52,8 @@ interface IDumpstateListener { /** * Called on an error condition with one of the error codes listed above. - * This is not an asynchronous method since it can race with dumpstate exiting, thus triggering - * death recipient. */ - void onError(int errorCode); + oneway void onError(int errorCode); /** * Called when taking bugreport finishes successfully. diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 9c5b8833d7..f5536970cc 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/mount.h> #include <sys/poll.h> #include <sys/prctl.h> #include <sys/resource.h> @@ -174,6 +175,7 @@ void add_mountinfo(); #define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log" #define LINKERCONFIG_DIR "/linkerconfig" #define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list" +#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace" // TODO(narayan): Since this information has to be kept in sync // with tombstoned, we should just put it in a common header. @@ -1052,6 +1054,24 @@ static void DumpIncidentReport() { } } +static void MaybeAddSystemTraceToZip() { + // This function copies into the .zip the system trace that was snapshotted + // by the early call to MaybeSnapshotSystemTrace(), if any background + // tracing was happening. + if (!ds.IsZipping()) { + MYLOGD("Not dumping system trace because it's not a zipped bugreport\n"); + return; + } + if (!ds.has_system_trace_) { + // No background trace was happening at the time dumpstate was invoked. + return; + } + ds.AddZipEntry( + ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT, + SYSTEM_TRACE_SNAPSHOT); + android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT); +} + static void DumpVisibleWindowViews() { if (!ds.IsZipping()) { MYLOGD("Not dumping visible views because it's not a zipped bugreport\n"); @@ -1188,10 +1208,6 @@ static void DumpBlockStatFiles() { static void DumpPacketStats() { DumpFile("NETWORK DEV INFO", "/proc/net/dev"); - DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all"); - DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt"); - DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl"); - DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats"); } static void DumpIpAddrAndRules() { @@ -1548,7 +1564,7 @@ static void DumpAppInfos(int out_fd = STDOUT_FILENO) { dprintf(out_fd, "========================================================\n"); RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"}, - DUMPSYS_COMPONENTS_OPTIONS, out_fd); + DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd); dprintf(out_fd, "========================================================\n"); dprintf(out_fd, "== Running Application Providers (non-platform)\n"); @@ -1636,8 +1652,6 @@ static Dumpstate::RunStatus dumpstate() { for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)"); - /* Dump Bluetooth HCI logs */ - ds.AddDir("/data/misc/bluetooth/logs", true); /* Dump Nfc NCI logs */ ds.AddDir("/data/misc/nfc/logs", true); @@ -1648,6 +1662,8 @@ static Dumpstate::RunStatus dumpstate() { AddAnrTraceFiles(); + MaybeAddSystemTraceToZip(); + // NOTE: tombstones are always added as separate entries in the zip archive // and are not interspersed with the main report. const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(), @@ -1721,6 +1737,9 @@ static Dumpstate::RunStatus dumpstate() { RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal); + /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */ + ds.AddDir("/data/misc/bluetooth/logs", true); + if (ds.dump_pool_) { WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_); } else { @@ -1823,10 +1842,8 @@ Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() { RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"}); // Gather shared memory buffer info if the product implements it - struct stat st; - if (!stat("/product/bin/dmabuf_dump", &st)) { - RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"}); - } + RunCommand("Dmabuf dump", {"dmabuf_dump"}); + RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"}); DumpFile("PSI cpu", "/proc/pressure/cpu"); DumpFile("PSI memory", "/proc/pressure/memory"); @@ -2039,7 +2056,7 @@ static void DumpstateWifiOnly() { } Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) { - const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX"; + const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX"; const size_t buf_size = temp_file_pattern.length() + 1; std::unique_ptr<char[]> file_name_buf(new char[buf_size]); memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size); @@ -2156,6 +2173,22 @@ void Dumpstate::DumpstateBoard(int out_fd) { return; } + /* + * mount debugfs for non-user builds which launch with S and unmount it + * after invoking dumpstateBoard_* methods. This is to enable debug builds + * to not have debugfs mounted during runtime. It will also ensure that + * debugfs is only accessed by the dumpstate HAL. + */ + auto api_level = android::base::GetIntProperty("ro.product.first_api_level", 0); + bool mount_debugfs = !PropertiesHelper::IsUserBuild() && api_level >= 31; + + if (mount_debugfs) { + RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"}, + AS_ROOT_20); + RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, + AS_ROOT_20); + } + std::vector<std::string> paths; std::vector<android::base::ScopeGuard<std::function<void()>>> remover; for (int i = 0; i < NUM_OF_DUMPS; i++) { @@ -2255,6 +2288,10 @@ void Dumpstate::DumpstateBoard(int out_fd) { "there might be racing in content\n", killing_timeout_sec); } + if (mount_debugfs) { + RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20); + } + auto file_sizes = std::make_unique<ssize_t[]>(paths.size()); for (size_t i = 0; i < paths.size(); i++) { struct stat s; @@ -2865,6 +2902,17 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, RunDumpsysCritical(); } MaybeTakeEarlyScreenshot(); + + if (!is_dumpstate_restricted) { + // Snapshot the system trace now (if running) to avoid that dumpstate's + // own activity pushes out interesting data from the trace ring buffer. + // The trace file is added to the zip by MaybeAddSystemTraceToZip(). + MaybeSnapshotSystemTrace(); + + // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later + // from WMTRACE_DATA_DIR. + MaybeSnapshotWinTrace(); + } onUiIntensiveBugreportDumpsFinished(calling_uid); MaybeCheckUserConsent(calling_uid, calling_package); if (options_->telephony_only) { @@ -2955,6 +3003,34 @@ void Dumpstate::MaybeTakeEarlyScreenshot() { TakeScreenshot(); } +void Dumpstate::MaybeSnapshotSystemTrace() { + // If a background system trace is happening and is marked as "suitable for + // bugreport" (i.e. bugreport_score > 0 in the trace config), this command + // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely) + // case that no trace is ongoing, this command is a no-op. + // Note: this should not be enqueued as we need to freeze the trace before + // dumpstate starts. Otherwise the trace ring buffers will contain mostly + // the dumpstate's own activity which is irrelevant. + int res = RunCommand( + "SERIALIZE PERFETTO TRACE", + {"perfetto", "--save-for-bugreport"}, + CommandOptions::WithTimeout(10) + .DropRoot() + .CloseAllFileDescriptorsOnExec() + .Build()); + has_system_trace_ = res == 0; + // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip + // file in the later stages. +} + +void Dumpstate::MaybeSnapshotWinTrace() { + RunCommand( + // Empty name because it's not intended to be classified as a bugreport section. + // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport. + "", {"cmd", "window", "tracing", "save-for-bugreport"}, + CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build()); +} + void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) { if (calling_uid == AID_SHELL || !CalledByApi()) { return; @@ -2999,6 +3075,9 @@ void Dumpstate::CleanupTmpFiles() { android::os::UnlinkAndLogOnError(tmp_path_); android::os::UnlinkAndLogOnError(screenshot_path_); android::os::UnlinkAndLogOnError(path_); + if (dump_traces_path != nullptr) { + android::os::UnlinkAndLogOnError(dump_traces_path); + } } void Dumpstate::EnableParallelRunIfNeeded() { diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 255243f7e3..83e6787ebf 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -458,6 +458,11 @@ class Dumpstate { // Whether it should take an screenshot earlier in the process. bool do_early_screenshot_ = false; + // This is set to true when the trace snapshot request in the early call to + // MaybeSnapshotSystemTrace(). When this is true, the later stages of + // dumpstate will append the trace to the zip archive. + bool has_system_trace_ = false; + std::unique_ptr<Progress> progress_; // When set, defines a socket file-descriptor use to report progress to bugreportz @@ -543,6 +548,8 @@ class Dumpstate { RunStatus DumpstateDefaultAfterCritical(); void MaybeTakeEarlyScreenshot(); + void MaybeSnapshotSystemTrace(); + void MaybeSnapshotWinTrace(); void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid); diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp index fe6a34a514..c62d302214 100644 --- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp @@ -310,8 +310,12 @@ TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) { // FS/proc/*/mountinfo size > 0 FileExists("FS/proc/1/mountinfo", 0U, 100000U); - // FS/data/misc/profiles/cur/0/*/primary.prof size > 0 - FileExists("FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", 0U, 100000U); + // FS/data/misc/profiles/cur/0/*/primary.prof should exist. Also, since dumpstate only adds + // profiles to the zip in the non-user build, a build checking is necessary here. + if (!PropertiesHelper::IsUserBuild()) { + ZipEntry entry; + GetEntry(handle, "FS/data/misc/profiles/cur/0/com.android.phone/primary.prof", &entry); + } } /** @@ -319,6 +323,16 @@ TEST_F(ZippedBugReportContentsTest, ContainsSomeFileSystemFiles) { */ class BugreportSectionTest : public Test { public: + ZipArchiveHandle handle; + + void SetUp() { + ASSERT_EQ(OpenArchive(ZippedBugreportGenerationTest::getZipFilePath().c_str(), &handle), 0); + } + + void TearDown() { + CloseArchive(handle); + } + static void SetUpTestCase() { ParseSections(ZippedBugreportGenerationTest::getZipFilePath().c_str(), ZippedBugreportGenerationTest::sections.get()); @@ -343,6 +357,19 @@ class BugreportSectionTest : public Test { } FAIL() << sectionName << " not found."; } + + /** + * Whether or not the content of the section is injected by other commands. + */ + bool IsContentInjectedByOthers(const std::string& line) { + // Command header such as `------ APP ACTIVITIES (/system/bin/dumpsys activity -v) ------`. + static const std::regex kCommandHeader = std::regex{"------ .+ \\(.+\\) ------"}; + std::smatch match; + if (std::regex_match(line, match, kCommandHeader)) { + return true; + } + return false; + } }; TEST_F(BugreportSectionTest, Atleast3CriticalDumpsysSectionsGenerated) { @@ -400,6 +427,28 @@ TEST_F(BugreportSectionTest, DISABLED_WifiSectionGenerated) { SectionExists("wifi", /* bytes= */ 100000); } +TEST_F(BugreportSectionTest, NoInjectedContentByOtherCommand) { + // Extract the main entry to a temp file + TemporaryFile tmp_binary; + ASSERT_NE(-1, tmp_binary.fd); + ExtractBugreport(&handle, tmp_binary.fd); + + // Read line by line and identify sections + std::ifstream ifs(tmp_binary.path, std::ifstream::in); + std::string line; + std::string current_section_name; + while (std::getline(ifs, line)) { + std::string section_name; + if (IsSectionStart(line, §ion_name)) { + current_section_name = section_name; + } else if (IsSectionEnd(line)) { + current_section_name = ""; + } else if (!current_section_name.empty()) { + EXPECT_FALSE(IsContentInjectedByOthers(line)); + } + } +} + class DumpstateBinderTest : public Test { protected: void SetUp() override { diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp index f99588ffc8..91aa018451 100644 --- a/cmds/dumpsys/Android.bp +++ b/cmds/dumpsys/Android.bp @@ -1,3 +1,20 @@ +package { + default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_cmds_dumpsys_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "dumpsys_defaults", diff --git a/cmds/dumpsys/OWNERS b/cmds/dumpsys/OWNERS index 1ba7cffa0e..2a9b681318 100644 --- a/cmds/dumpsys/OWNERS +++ b/cmds/dumpsys/OWNERS @@ -1,6 +1,4 @@ set noparent -felipeal@google.com nandana@google.com jsharkey@android.com -enh@google.com diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp index e182b9d287..6854c7550e 100644 --- a/cmds/dumpsys/tests/Android.bp +++ b/cmds/dumpsys/tests/Android.bp @@ -1,4 +1,13 @@ // Build the unit tests for dumpsys +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_cmds_dumpsys_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"], +} + cc_test { name: "dumpsys_test", test_suites: ["device-tests"], diff --git a/cmds/flatland/Android.mk b/cmds/flatland/Android.mk index 7aa111c7ae..754a99caf6 100644 --- a/cmds/flatland/Android.mk +++ b/cmds/flatland/Android.mk @@ -11,6 +11,9 @@ LOCAL_SRC_FILES:= \ LOCAL_CFLAGS := -Wall -Werror LOCAL_MODULE:= flatland +LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS:= notice +LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE LOCAL_MODULE_TAGS := tests diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp index 402767a426..99e0f4ceba 100644 --- a/cmds/idlcli/Android.bp +++ b/cmds/idlcli/Android.bp @@ -12,10 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "idlcli-defaults", shared_libs: [ - "android.hardware.vibrator-ndk_platform", + "android.hardware.vibrator-V1-ndk_platform", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp index 523115f476..cf23f8af08 100644 --- a/cmds/installd/Android.bp +++ b/cmds/installd/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "installd_defaults", @@ -38,6 +47,9 @@ cc_defaults { "libutils", "server_configurable_flags", ], + export_shared_lib_headers: [ + "libbinder", + ], product_variables: { arc: { diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp index e0802911ca..60271392e9 100644 --- a/cmds/installd/QuotaUtils.cpp +++ b/cmds/installd/QuotaUtils.cpp @@ -35,7 +35,7 @@ std::recursive_mutex mMountsLock; /* Map of all quota mounts from target to source */ std::unordered_map<std::string, std::string> mQuotaReverseMounts; -std::string& FindQuotaDeviceForUuid(const std::string& uuid) { +std::string FindQuotaDeviceForUuid(const std::string& uuid) { std::lock_guard<std::recursive_mutex> lock(mMountsLock); auto path = create_data_path(uuid.empty() ? nullptr : uuid.c_str()); return mQuotaReverseMounts[path]; diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index 65fc46ecaf..0cf50a3e32 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -1130,23 +1130,6 @@ bool maybe_open_oat_and_vdex_file(const std::string& apk_path, return true; } -// Updates the access times of out_oat_path based on those from apk_path. -void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) { - struct stat input_stat; - memset(&input_stat, 0, sizeof(input_stat)); - if (stat(apk_path, &input_stat) != 0) { - PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt"; - return; - } - - struct utimbuf ut; - ut.actime = input_stat.st_atime; - ut.modtime = input_stat.st_mtime; - if (utime(out_oat_path, &ut) != 0) { - PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt"; - } -} - // Runs (execv) dexoptanalyzer on the given arguments. // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter. // If this is for a profile guided compilation, profile_was_updated will tell whether or not @@ -1843,8 +1826,6 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins } } - update_out_oat_access_times(dex_path, out_oat.path().c_str()); - // We've been successful, don't delete output. out_oat.DisableCleanup(); out_vdex.DisableCleanup(); @@ -2131,8 +2112,9 @@ static bool move_ab_path(const std::string& b_path, const std::string& a_path) { { struct stat s; if (stat(b_path.c_str(), &s) != 0) { - // Silently ignore for now. The service calling this isn't smart enough to understand - // lack of artifacts at the moment. + // Ignore for now. The service calling this isn't smart enough to + // understand lack of artifacts at the moment. + LOG(VERBOSE) << "A/B artifact " << b_path << " does not exist!"; return false; } if (!S_ISREG(s.st_mode)) { diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp index 443821c3b9..ed31ad9cfa 100644 --- a/cmds/installd/otapreopt.cpp +++ b/cmds/installd/otapreopt.cpp @@ -175,8 +175,10 @@ class OTAPreoptService { private: bool ReadSystemProperties() { + // TODO This file does not have a stable format. It should be read by + // code shared by init and otapreopt. See b/181182967#comment80 static constexpr const char* kPropertyFiles[] = { - "/default.prop", "/system/build.prop" + "/system/build.prop" }; for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) { @@ -193,28 +195,38 @@ private: // export NAME VALUE // For simplicity, don't respect string quotation. The values we are interested in can be // encoded without them. + // init.environ.rc and etc/classpath have the same format for + // environment variable exports and can be matched by the same regex. + // TODO Just like with the system-properties above we really should have + // common code between init and otapreopt to deal with reading these + // things. See b/181182967 + static constexpr const char* kEnvironmentVariableSources[] = { + "/init.environ.rc", "/etc/classpath" + }; + std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)"); - bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) { - std::smatch export_match; - if (!std::regex_match(line, export_match, export_regex)) { - return true; - } + for (const char* env_vars_file : kEnvironmentVariableSources) { + bool parse_result = ParseFile(env_vars_file, [&](const std::string& line) { + std::smatch export_match; + if (!std::regex_match(line, export_match, export_regex)) { + return true; + } - if (export_match.size() != 3) { - return true; - } + if (export_match.size() != 3) { + return true; + } - std::string name = export_match[1].str(); - std::string value = export_match[2].str(); + std::string name = export_match[1].str(); + std::string value = export_match[2].str(); - system_properties_.SetProperty(name, value); + system_properties_.SetProperty(name, value); - return true; - }); - if (!parse_result) { - return false; + return true; + }); + if (!parse_result) { + return false; + } } - if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) { return false; } @@ -337,9 +349,6 @@ private: } } - // Clear cached artifacts. - ClearDirectory(isa_path); - // Check whether we have a boot image. // TODO: check that the files are correct wrt/ jars. std::string preopted_boot_art_path = @@ -383,37 +392,6 @@ private: return false; } - static void ClearDirectory(const std::string& dir) { - DIR* c_dir = opendir(dir.c_str()); - if (c_dir == nullptr) { - PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents"; - return; - } - - for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) { - const char* name = de->d_name; - if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { - continue; - } - // We only want to delete regular files and symbolic links. - std::string file = StringPrintf("%s/%s", dir.c_str(), name); - if (de->d_type != DT_REG && de->d_type != DT_LNK) { - LOG(WARNING) << "Unexpected file " - << file - << " of type " - << std::hex - << de->d_type - << " encountered."; - } else { - // Try to unlink the file. - if (unlink(file.c_str()) != 0) { - PLOG(ERROR) << "Unable to unlink " << file; - } - } - } - CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory."; - } - static const char* ParseNull(const char* arg) { return (strcmp(arg, "!") == 0) ? nullptr : arg; } @@ -473,24 +451,29 @@ private: // Run dexopt with the parameters of parameters_. // TODO(calin): embed the profile name in the parameters. int Dexopt() { - std::string dummy; - return dexopt(parameters_.apk_path, - parameters_.uid, - parameters_.pkgName, - parameters_.instruction_set, - parameters_.dexopt_needed, - parameters_.oat_dir, - parameters_.dexopt_flags, - parameters_.compiler_filter, - parameters_.volume_uuid, - parameters_.shared_libraries, - parameters_.se_info, - parameters_.downgrade, - parameters_.target_sdk_version, - parameters_.profile_name, - parameters_.dex_metadata_path, - parameters_.compilation_reason, - &dummy); + std::string error; + int res = dexopt(parameters_.apk_path, + parameters_.uid, + parameters_.pkgName, + parameters_.instruction_set, + parameters_.dexopt_needed, + parameters_.oat_dir, + parameters_.dexopt_flags, + parameters_.compiler_filter, + parameters_.volume_uuid, + parameters_.shared_libraries, + parameters_.se_info, + parameters_.downgrade, + parameters_.target_sdk_version, + parameters_.profile_name, + parameters_.dex_metadata_path, + parameters_.compilation_reason, + &error); + if (res != 0) { + LOG(ERROR) << "During preopt of " << parameters_.apk_path << " got result " << res + << " error: " << error; + } + return res; } int RunPreopt() { diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp index 72c03bf14b..379cf92043 100644 --- a/cmds/installd/otapreopt_chroot.cpp +++ b/cmds/installd/otapreopt_chroot.cpp @@ -20,14 +20,19 @@ #include <sys/stat.h> #include <sys/wait.h> +#include <fstream> #include <sstream> +#include <android-base/file.h> #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/stringprintf.h> +#include <android-base/unique_fd.h> #include <libdm/dm.h> #include <selinux/android.h> +#include <apex_file_repository.h> +#include <apex_constants.h> #include <apexd.h> #include "installd_constants.h" @@ -64,15 +69,34 @@ static std::vector<apex::ApexFile> ActivateApexPackages() { // system/apex/apexd/apexd.cpp. // // Only scan the APEX directory under /system, /system_ext and /vendor (within the chroot dir). - std::vector<const char*> apex_dirs{apex::kApexPackageSystemDir, apex::kApexPackageSystemExtDir, + std::vector<std::string> apex_dirs{apex::kApexPackageSystemDir, apex::kApexPackageSystemExtDir, apex::kApexPackageVendorDir}; + // Initialize ApexFileRepository used internally in ScanPackagesDirAndActivate. + // This is a quick fix to fix apex activation in otapreopt_chroot. + apex::ApexFileRepository::GetInstance().AddPreInstalledApex(apex_dirs); for (const auto& dir : apex_dirs) { // Cast call to void to suppress warn_unused_result. - static_cast<void>(apex::ScanPackagesDirAndActivate(dir)); + static_cast<void>(apex::ScanPackagesDirAndActivate(dir.c_str())); } return apex::GetActivePackages(); } +static void CreateApexInfoList(const std::vector<apex::ApexFile>& apex_files) { + // Setup the apex-info-list.xml file + const std::string apex_info_file = std::string(apex::kApexRoot) + "/" + apex::kApexInfoList; + std::fstream xml(apex_info_file.c_str(), std::ios::out | std::ios::trunc); + if (!xml.is_open()) { + PLOG(ERROR) << "Failed to open " << apex_info_file; + exit(216); + } + + // we do not care about inactive apexs + std::vector<apex::ApexFile> inactive; + apex::CollectApexInfoList(xml, apex_files, inactive); + xml.flush(); + xml.close(); +} + static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) { for (const apex::ApexFile& apex_file : active_packages) { const std::string& package_path = apex_file.GetPath(); @@ -181,6 +205,13 @@ static int otapreopt_chroot(const int argc, char **arg) { // want it for product APKs. Same notes as vendor above. TryExtraMount("product", arg[2], "/postinstall/product"); + constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig"; + // Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot + if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) { + PLOG(ERROR) << "Failed to mount a tmpfs for " << kPostInstallLinkerconfig; + exit(215); + } + // Setup APEX mount point and its security context. static constexpr const char* kPostinstallApexDir = "/postinstall/apex"; // The following logic is similar to the one in system/core/rootdir/init.rc: @@ -239,17 +270,37 @@ static int otapreopt_chroot(const int argc, char **arg) { // Try to mount APEX packages in "/apex" in the chroot dir. We need at least // the ART APEX, as it is required by otapreopt to run dex2oat. std::vector<apex::ApexFile> active_packages = ActivateApexPackages(); + CreateApexInfoList(active_packages); // Check that an ART APEX has been activated; clean up and exit // early otherwise. - if (std::none_of(active_packages.begin(), - active_packages.end(), - [](const apex::ApexFile& package){ - return package.GetManifest().name() == "com.android.art"; - })) { - LOG(FATAL_WITHOUT_ABORT) << "No activated com.android.art APEX package."; - DeactivateApexPackages(active_packages); - exit(217); + static constexpr const std::string_view kRequiredApexs[] = { + "com.android.art", + "com.android.runtime", + }; + for (std::string_view apex : kRequiredApexs) { + if (std::none_of(active_packages.begin(), active_packages.end(), + [&](const apex::ApexFile& package) { + return package.GetManifest().name() == apex; + })) { + LOG(FATAL_WITHOUT_ABORT) << "No activated " << apex << " APEX package."; + DeactivateApexPackages(active_packages); + exit(217); + } + } + + // Setup /linkerconfig. Doing it after the chroot means it doesn't need its own category + if (selinux_android_restorecon("/linkerconfig", 0) < 0) { + PLOG(ERROR) << "Failed to restorecon /linkerconfig"; + exit(219); + } + std::vector<std::string> linkerconfig_cmd{"/apex/com.android.runtime/bin/linkerconfig", + "--target", "/linkerconfig"}; + std::string linkerconfig_error_msg; + bool linkerconfig_exec_result = Exec(linkerconfig_cmd, &linkerconfig_error_msg); + if (!linkerconfig_exec_result) { + LOG(ERROR) << "Running linkerconfig failed: " << linkerconfig_error_msg; + exit(218); } // Now go on and run otapreopt. diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp index 7c9e3b2e38..f67ab812fa 100644 --- a/cmds/installd/tests/Android.bp +++ b/cmds/installd/tests/Android.bp @@ -1,4 +1,13 @@ // Build the unit tests for installd +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "installd_utils_test", test_suites: ["device-tests"], @@ -157,4 +166,3 @@ cc_test { "libotapreoptparameters" ], } - diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk index e1e2204233..396ae9db04 100644 --- a/cmds/ip-up-vpn/Android.mk +++ b/cmds/ip-up-vpn/Android.mk @@ -21,6 +21,9 @@ LOCAL_SRC_FILES := ip-up-vpn.c LOCAL_CFLAGS := -Wall -Werror LOCAL_SHARED_LIBRARIES := libcutils liblog LOCAL_MODULE := ip-up-vpn +LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 +LOCAL_LICENSE_CONDITIONS := notice +LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp LOCAL_MODULE_TAGS := optional diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp index 0cbb80feb2..649e53a8aa 100644 --- a/cmds/lshal/Android.bp +++ b/cmds/lshal/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "liblshal", shared_libs: [ diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp index 72958bd2a9..ccf1ab1e8a 100644 --- a/cmds/lshal/DebugCommand.cpp +++ b/cmds/lshal/DebugCommand.cpp @@ -28,7 +28,7 @@ std::string DebugCommand::getName() const { } std::string DebugCommand::getSimpleDescription() const { - return "Debug a specified HAL."; + return "Debug a specified HIDL HAL."; } Status DebugCommand::parseArgs(const Arg &arg) { @@ -78,7 +78,7 @@ void DebugCommand::usage() const { "debug:\n" " lshal debug [-E] <interface> [options [options [...]]] \n" " Print debug information of a specified interface.\n" - " -E: excludes debug output if HAL is actually a subclass.\n" + " -E: excludes debug output if HIDL HAL is actually a subclass.\n" " <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n" " If instance name is missing `default` is used.\n" " options: space separated options to IBase::debug.\n"; diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp index 22268aceea..d5110f6203 100644 --- a/cmds/lshal/ListCommand.cpp +++ b/cmds/lshal/ListCommand.cpp @@ -81,7 +81,7 @@ std::string ListCommand::GetName() { return "list"; } std::string ListCommand::getSimpleDescription() const { - return "List HALs."; + return "List HIDL HALs."; } std::string ListCommand::parseCmdline(pid_t pid) const { @@ -295,21 +295,21 @@ void ListCommand::postprocess() { } mServicesTable.setDescription( - "| All binderized services (registered with hwservicemanager)"); + "| All HIDL binderized services (registered with hwservicemanager)"); mPassthroughRefTable.setDescription( - "| All interfaces that getService() has ever returned as a passthrough interface;\n" + "| All HIDL interfaces getService() has ever returned as a passthrough interface;\n" "| PIDs / processes shown below might be inaccurate because the process\n" "| might have relinquished the interface or might have died.\n" "| The Server / Server CMD column can be ignored.\n" "| The Clients / Clients CMD column shows all process that have ever dlopen'ed \n" "| the library and successfully fetched the passthrough implementation."); mImplementationsTable.setDescription( - "| All available passthrough implementations (all -impl.so files).\n" + "| All available HIDL passthrough implementations (all -impl.so files).\n" "| These may return subclasses through their respective HIDL_FETCH_I* functions."); mManifestHalsTable.setDescription( - "| All HALs that are in VINTF manifest."); + "| All HIDL HALs that are in VINTF manifest."); mLazyHalsTable.setDescription( - "| All HALs that are declared in VINTF manifest:\n" + "| All HIDL HALs that are declared in VINTF manifest:\n" "| - as hwbinder HALs but are not registered to hwservicemanager, and\n" "| - as hwbinder/passthrough HALs with no implementation."); } @@ -903,11 +903,11 @@ void ListCommand::registerAllOptions() { thiz->mSelectedColumns.push_back(TableColumnType::VINTF); return OK; }, "print VINTF info. This column contains a comma-separated list of:\n" - " - DM: if the HAL is in the device manifest\n" - " - DC: if the HAL is in the device compatibility matrix\n" - " - FM: if the HAL is in the framework manifest\n" - " - FC: if the HAL is in the framework compatibility matrix\n" - " - X: if the HAL is in none of the above lists"}); + " - DM: if the HIDL HAL is in the device manifest\n" + " - DC: if the HIDL HAL is in the device compatibility matrix\n" + " - FM: if the HIDL HAL is in the framework manifest\n" + " - FC: if the HIDL HAL is in the framework compatibility matrix\n" + " - X: if the HIDL HAL is in none of the above lists"}); mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) { thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS); return OK; diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp index 99cb93afe2..bc99f4d473 100644 --- a/cmds/lshal/Lshal.cpp +++ b/cmds/lshal/Lshal.cpp @@ -59,7 +59,8 @@ void Lshal::forEachCommand(const std::function<void(const Command* c)>& f) const } void Lshal::usage() { - err() << "lshal: List and debug HALs." << std::endl << std::endl + err() << "lshal: List and debug HIDL HALs." << std::endl + << " (for AIDL HALs, see `dumpsys`)" << std::endl << std::endl << "commands:" << std::endl; size_t nameMaxLength = 0; diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp index 65b41b95d2..437a66ae2f 100644 --- a/cmds/lshal/WaitCommand.cpp +++ b/cmds/lshal/WaitCommand.cpp @@ -29,7 +29,7 @@ std::string WaitCommand::getName() const { } std::string WaitCommand::getSimpleDescription() const { - return "Wait for HAL to start if it is not already started."; + return "Wait for HIDL HAL to start if it is not already started."; } Status WaitCommand::parseArgs(const Arg &arg) { diff --git a/cmds/lshal/libprocpartition/Android.bp b/cmds/lshal/libprocpartition/Android.bp index 9592111796..cbfbdc9223 100644 --- a/cmds/lshal/libprocpartition/Android.bp +++ b/cmds/lshal/libprocpartition/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libprocpartition", shared_libs: [ diff --git a/cmds/rawbu/Android.bp b/cmds/rawbu/Android.bp index 363ffc1aaf..e34119d1d1 100644 --- a/cmds/rawbu/Android.bp +++ b/cmds/rawbu/Android.bp @@ -1,5 +1,22 @@ // Copyright 2009 The Android Open Source Project +package { + default_applicable_licenses: ["frameworks_native_cmds_rawbu_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_cmds_rawbu_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_binary { name: "rawbu", diff --git a/cmds/rss_hwm_reset/Android.bp b/cmds/rss_hwm_reset/Android.bp index 15f10efdee..cd335d44cc 100644 --- a/cmds/rss_hwm_reset/Android.bp +++ b/cmds/rss_hwm_reset/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "rss_hwm_reset", diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp index a5b1ac5c5f..3e8e3f67f8 100644 --- a/cmds/service/Android.bp +++ b/cmds/service/Android.bp @@ -1,3 +1,20 @@ +package { + default_applicable_licenses: ["frameworks_native_cmds_service_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_cmds_service_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_binary { name: "service", diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp index b1392515a2..9de344a820 100644 --- a/cmds/servicemanager/Android.bp +++ b/cmds/servicemanager/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "servicemanager_defaults", diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index b21010d49a..0dbab4e055 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -623,4 +623,21 @@ Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IB return Status::ok(); } +Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) { + if (!mAccess->canList(mAccess->getCallingContext())) { + return Status::fromExceptionCode(Status::EX_SECURITY); + } + + outReturn->reserve(mNameToService.size()); + for (auto const& [name, service] : mNameToService) { + ServiceDebugInfo info; + info.name = name; + info.debugPid = service.debugPid; + + outReturn->push_back(std::move(info)); + } + + return Status::ok(); +} + } // namespace android diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h index 9f43eb4f58..c0891152e6 100644 --- a/cmds/servicemanager/ServiceManager.h +++ b/cmds/servicemanager/ServiceManager.h @@ -26,6 +26,7 @@ namespace android { using os::IClientCallback; using os::IServiceCallback; +using os::ServiceDebugInfo; class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient { public: @@ -48,6 +49,7 @@ public: binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, const sp<IClientCallback>& cb) override; binder::Status tryUnregisterService(const std::string& name, const sp<IBinder>& binder) override; + binder::Status getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) override; void binderDied(const wp<IBinder>& who) override; void handleClientCallbacks(); diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp index b1bc6dc7d5..627dfe6382 100644 --- a/cmds/servicemanager/main.cpp +++ b/cmds/servicemanager/main.cpp @@ -45,10 +45,6 @@ public: IPCThreadState::self()->setupPolling(&binder_fd); LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd); - // Flush after setupPolling(), to make sure the binder driver - // knows about this thread handling commands. - IPCThreadState::self()->flushCommands(); - int ret = looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp index d4c037ab7d..34fc8b10ea 100644 --- a/cmds/surfacereplayer/Android.bp +++ b/cmds/surfacereplayer/Android.bp @@ -1,4 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + subdirs = [ "proto", "replayer", -]
\ No newline at end of file +] diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp index 71a5e23a9e..dae976e3df 100644 --- a/cmds/surfacereplayer/proto/Android.bp +++ b/cmds/surfacereplayer/proto/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libtrace_proto", srcs: [ diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp index 7632311906..3985230f08 100644 --- a/cmds/surfacereplayer/replayer/Android.bp +++ b/cmds/surfacereplayer/replayer/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libsurfacereplayer", srcs: [ diff --git a/data/etc/android.hardware.keystore.app_attest_key.xml b/data/etc/android.hardware.keystore.app_attest_key.xml new file mode 100644 index 0000000000..8adc4399d3 --- /dev/null +++ b/data/etc/android.hardware.keystore.app_attest_key.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Feature for devices that support app attestation keys (i.e. KeyMint 1.0). --> +<permissions> + <feature name="android.hardware.keystore.app_attest_key" /> +</permissions> diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml new file mode 100644 index 0000000000..5217086715 --- /dev/null +++ b/data/etc/android.hardware.keystore.limited_use_key.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Feature for devices with KeyMint that can enforce limited use key + in hardware with any max usage count (including count equals to 1). --> +<permissions> + <feature name="android.hardware.keystore.limited_use_key" /> +</permissions>
\ No newline at end of file diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml new file mode 100644 index 0000000000..40e80aaa9b --- /dev/null +++ b/data/etc/android.hardware.keystore.single_use_key.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Feature for devices with KeyMint that only can enforce limited use key + in hardware with max usage count equals to 1. --> +<permissions> + <feature name="android.hardware.keystore.single_use_key" /> +</permissions>
\ No newline at end of file diff --git a/data/etc/android.hardware.telephony.ims.singlereg.xml b/data/etc/android.hardware.telephony.ims.singlereg.xml new file mode 100644 index 0000000000..9a6cec0a1e --- /dev/null +++ b/data/etc/android.hardware.telephony.ims.singlereg.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2021 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Feature for devices that have an IMS service that supports all IMS + applications using a single IMS registration. --> +<permissions> + <feature name="android.hardware.telephony.ims" /> + <feature name="android.hardware.telephony.ims.singlereg" /> +</permissions> diff --git a/headers/Android.bp b/headers/Android.bp index 8f41c2b75b..7481a230c3 100644 --- a/headers/Android.bp +++ b/headers/Android.bp @@ -1,3 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "media_plugin_headers", vendor_available: true, diff --git a/include/OWNERS b/include/OWNERS index db52850fe8..c98e87aa74 100644 --- a/include/OWNERS +++ b/include/OWNERS @@ -1,3 +1,4 @@ +alecmouri@google.com alexeykuzmin@google.com dangittik@google.com jreck@google.com @@ -8,7 +9,6 @@ nona@google.com racarr@google.com romainguy@android.com santoscordon@google.com -stoza@google.com svv@google.com # For multinetwork.h only. diff --git a/include/android/bitmap.h b/include/android/bitmap.h index f19539913e..a70dffd756 100644 --- a/include/android/bitmap.h +++ b/include/android/bitmap.h @@ -28,8 +28,13 @@ #include <stdbool.h> #include <stdint.h> +#include <stddef.h> #include <jni.h> +#if !defined(__INTRODUCED_IN) +#define __INTRODUCED_IN(__api_level) /* nothing */ +#endif + #ifdef __cplusplus extern "C" { #endif @@ -117,8 +122,6 @@ typedef struct { int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, AndroidBitmapInfo* info); -#if __ANDROID_API__ >= 30 - /** * Given a java bitmap object, return its {@link ADataSpace}. * @@ -130,8 +133,6 @@ int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, */ int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) __INTRODUCED_IN(30); -#endif // __ANDROID_API__ >= 30 - /** * Given a java bitmap object, attempt to lock the pixel address. * Locking will ensure that the memory for the pixels will not move @@ -152,8 +153,6 @@ int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr); */ int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap); -#if __ANDROID_API__ >= 30 - // Note: these values match android.graphics.Bitmap#compressFormat. /** @@ -254,8 +253,6 @@ typedef struct AHardwareBuffer AHardwareBuffer; int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap, AHardwareBuffer** outBuffer) __INTRODUCED_IN(30); -#endif // __ANDROID_API__ >= 30 - #ifdef __cplusplus } #endif diff --git a/include/android/choreographer.h b/include/android/choreographer.h index e9f559cd8e..8039bb0d79 100644 --- a/include/android/choreographer.h +++ b/include/android/choreographer.h @@ -61,8 +61,6 @@ typedef void (*AChoreographer_frameCallback64)(int64_t frameTimeNanos, void* dat */ typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data); -#if __ANDROID_API__ >= 24 - /** * Get the AChoreographer instance for the current thread. This must be called * on an ALooper thread. @@ -86,10 +84,6 @@ void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, long delayMillis) __INTRODUCED_IN(24) __DEPRECATED_IN(29); -#endif /* __ANDROID_API__ >= 24 */ - -#if __ANDROID_API__ >= 29 - /** * Power a callback to be run on the next frame. The data pointer provided will * be passed to the callback function when it's called. @@ -111,10 +105,6 @@ void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer, AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) __INTRODUCED_IN(29); -#endif /* __ANDROID_API__ >= 29 */ - -#if __ANDROID_API__ >= 30 - /** * Registers a callback to be run when the display refresh rate changes. The * data pointer provided will be passed to the callback function when it's @@ -160,7 +150,6 @@ void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, AChoreographer_refreshRateCallback, void* data) __INTRODUCED_IN(30); -#endif /* __ANDROID_API__ >= 30 */ __END_DECLS diff --git a/include/android/configuration.h b/include/android/configuration.h index ccf3e59066..88019ae054 100644 --- a/include/android/configuration.h +++ b/include/android/configuration.h @@ -645,14 +645,12 @@ int32_t AConfiguration_getScreenLong(AConfiguration* config); */ void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong); -#if __ANDROID_API__ >= 30 /** * Return the current ACONFIGURATION_SCREENROUND_* set in the configuration. * * Available since API level 30. */ int32_t AConfiguration_getScreenRound(AConfiguration* config) __INTRODUCED_IN(30); -#endif /** * Set the current screen round in the configuration. @@ -712,7 +710,6 @@ int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config); */ void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value); -#if __ANDROID_API__ >= 17 /** * Return the configuration's layout direction, or * ACONFIGURATION_LAYOUTDIR_ANY if not set. @@ -727,7 +724,6 @@ int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_I * Available since API level 17. */ void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17); -#endif /* __ANDROID_API__ >= 17 */ /** * Perform a diff between two configurations. Returns a bit mask of diff --git a/include/android/font.h b/include/android/font.h index 1618096d69..a172618829 100644 --- a/include/android/font.h +++ b/include/android/font.h @@ -51,8 +51,6 @@ __BEGIN_DECLS -#if __ANDROID_API__ >= 29 - enum { /** The minimum value fot the font weight value. */ AFONT_WEIGHT_MIN = 0, @@ -297,8 +295,6 @@ uint32_t AFont_getAxisTag(const AFont* _Nonnull font, uint32_t axisIndex) float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex) __INTRODUCED_IN(29); -#endif // __ANDROID_API__ >= 29 - __END_DECLS #endif // ANDROID_FONT_H diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h index d4bd892bf6..49e478c2f3 100644 --- a/include/android/font_matcher.h +++ b/include/android/font_matcher.h @@ -97,8 +97,6 @@ __BEGIN_DECLS -#if __ANDROID_API__ >= 29 - enum { /** A family variant value for the system default variant. */ AFAMILY_VARIANT_DEFAULT = 0, @@ -217,8 +215,6 @@ AFont* _Nonnull AFontMatcher_match( const uint32_t textLength, uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29); -#endif // __ANDROID_API__ >= 29 - __END_DECLS #endif // ANDROID_FONT_MATCHER_H diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h index d7e6e4118f..1298c624dd 100644 --- a/include/android/imagedecoder.h +++ b/include/android/imagedecoder.h @@ -51,14 +51,16 @@ #include <android/rect.h> #include <stdint.h> +#if !defined(__INTRODUCED_IN) +#define __INTRODUCED_IN(__api_level) /* nothing */ +#endif + #ifdef __cplusplus extern "C" { #endif struct AAsset; -#if __ANDROID_API__ >= 30 - /** * {@link AImageDecoder} functions result code. Many functions will return one of these * to indicate success ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason @@ -527,8 +529,6 @@ int AImageDecoder_decodeImage(AImageDecoder* decoder, void* pixels, size_t stride, size_t size) __INTRODUCED_IN(30); -#endif // __ANDROID_API__ >= 30 - #ifdef __cplusplus } #endif diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h index c6d1c94c0a..424299d664 100644 --- a/include/android/multinetwork.h +++ b/include/android/multinetwork.h @@ -60,8 +60,6 @@ typedef uint64_t net_handle_t; * on failure with an appropriate errno value set. */ -#if __ANDROID_API__ >= 23 - /** * Set the network to be used by the given socket file descriptor. * @@ -111,10 +109,6 @@ int android_getaddrinfofornetwork(net_handle_t network, const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23); -#endif /* __ANDROID_API__ >= 23 */ - -#if __ANDROID_API__ >= 29 - /** * Possible values of the flags argument to android_res_nsend and android_res_nquery. * Values are ORed together. @@ -187,8 +181,6 @@ int android_res_nresult(int fd, */ void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29); -#endif /* __ANDROID_API__ >= 29 */ - __END_DECLS #endif // ANDROID_MULTINETWORK_H diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h index 3a77ffe86b..071ec798b4 100644 --- a/include/android/native_window_jni.h +++ b/include/android/native_window_jni.h @@ -44,7 +44,6 @@ extern "C" { */ ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface); -#if __ANDROID_API__ >= 26 /** * Return a Java Surface object derived from the ANativeWindow, for interacting * with it through Java code. The returned Java object acquires a reference on @@ -55,7 +54,6 @@ ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface); * Available since API level 26. */ jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26); -#endif #ifdef __cplusplus }; diff --git a/include/android/sensor.h b/include/android/sensor.h index eb407794d1..6447844b06 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -52,6 +52,13 @@ #include <math.h> #include <stdint.h> +#if !defined(__INTRODUCED_IN) +#define __INTRODUCED_IN(__api_level) /* nothing */ +#endif +#if !defined(__DEPRECATED_IN) +#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__)) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -553,13 +560,8 @@ typedef ASensorRef const* ASensorList; * ASensorManager* sensorManager = ASensorManager_getInstance(); * */ -#if __ANDROID_API__ >= 26 -__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance(); -#else -ASensorManager* ASensorManager_getInstance(); -#endif +ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26); -#if __ANDROID_API__ >= 26 /** * Get a reference to the sensor manager. ASensorManager is a singleton * per package as different packages may have access to different sensors. @@ -571,7 +573,6 @@ ASensorManager* ASensorManager_getInstance(); * Available since API level 26. */ ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26); -#endif /** * Returns the list of available sensors. @@ -584,7 +585,6 @@ int ASensorManager_getSensorList(ASensorManager* manager, ASensorList* list); */ ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type); -#if __ANDROID_API__ >= 21 /** * Returns the default sensor with the given type and wakeUp properties or NULL if no sensor * of this type and wakeUp properties exists. @@ -592,7 +592,6 @@ ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type * Available since API level 21. */ ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21); -#endif /** * Creates a new sensor event queue and associate it with a looper. @@ -609,7 +608,6 @@ ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager, */ int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue); -#if __ANDROID_API__ >= 26 /** * Create direct channel based on shared memory * @@ -706,7 +704,6 @@ void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId) */ int ASensorManager_configureDirectReport(ASensorManager* manager, ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26); -#endif /* __ANDROID_API__ >= 26 */ /*****************************************************************************/ @@ -795,7 +792,6 @@ int ASensorEventQueue_hasEvents(ASensorEventQueue* queue); */ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count); -#if __ANDROID_API__ >= 29 /** * Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on * the given {@link ASensorEventQueue}. @@ -819,7 +815,6 @@ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* even * \return 0 on success or a negative error code on failure */ int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29); -#endif /* __ANDROID_API__ >= 29 */ /*****************************************************************************/ @@ -850,7 +845,6 @@ float ASensor_getResolution(ASensor const* sensor); */ int ASensor_getMinDelay(ASensor const* sensor); -#if __ANDROID_API__ >= 21 /** * Returns the maximum size of batches for this sensor. Batches will often be * smaller, as the hardware fifo might be used for other sensors. @@ -886,9 +880,7 @@ int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21); * Available since API level 21. */ bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21); -#endif /* __ANDROID_API__ >= 21 */ -#if __ANDROID_API__ >= 26 /** * Test if sensor supports a certain type of direct channel. * @@ -914,9 +906,7 @@ bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType * does not support direct report. */ int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26); -#endif /* __ANDROID_API__ >= 26 */ -#if __ANDROID_API__ >= 29 /** * Returns the sensor's handle. * @@ -934,7 +924,6 @@ int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_ * Available since API level 29. */ int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29); -#endif /* __ANDROID_API__ >= 29 */ #ifdef __cplusplus }; diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h index 5f74682b40..7994aa9914 100644 --- a/include/android/sharedmem.h +++ b/include/android/sharedmem.h @@ -50,8 +50,6 @@ extern "C" { #endif -#if __ANDROID_API__ >= 26 - /** * Create a shared memory region. * @@ -121,8 +119,6 @@ size_t ASharedMemory_getSize(int fd) __INTRODUCED_IN(26); */ int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26); -#endif // __ANDROID_API__ >= 26 - #ifdef __cplusplus }; #endif diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h index 13e56e6f09..bbac785a33 100644 --- a/include/android/sharedmem_jni.h +++ b/include/android/sharedmem_jni.h @@ -52,8 +52,6 @@ extern "C" { #endif -#if __ANDROID_API__ >= 27 - /** * Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file * descriptor has all the same properties & capabilities as the FD returned from @@ -72,8 +70,6 @@ extern "C" { */ int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27); -#endif // __ANDROID_API__ >= 27 - #ifdef __cplusplus }; #endif diff --git a/include/android/surface_control.h b/include/android/surface_control.h index cbcf6ec5c0..27b880d2e1 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -35,8 +35,6 @@ __BEGIN_DECLS -#if __ANDROID_API__ >= 29 - struct ASurfaceControl; /** @@ -405,10 +403,6 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio struct AHdrMetadata_cta861_3* metadata) __INTRODUCED_IN(29); -#endif // __ANDROID_API__ >= 29 - -#if __ANDROID_API__ >= 30 - /** * Sets the intended frame rate for |surface_control|. * @@ -435,8 +429,6 @@ void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, float frameRate, int8_t compatibility) __INTRODUCED_IN(30); -#endif // __ANDROID_API__ >= 30 - __END_DECLS #endif // ANDROID_SURFACE_CONTROL_H diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h index dde7eaa0b6..b227b324f8 100644 --- a/include/android/surface_texture.h +++ b/include/android/surface_texture.h @@ -59,8 +59,6 @@ struct ASurfaceTexture; */ typedef struct ASurfaceTexture ASurfaceTexture; -#if __ANDROID_API__ >= 28 - /** * Release the reference to the native ASurfaceTexture acquired with * ASurfaceTexture_fromSurfaceTexture(). @@ -175,8 +173,6 @@ void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) __IN */ int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28); -#endif /* __ANDROID_API__ >= 28 */ - __END_DECLS #endif /* ANDROID_NATIVE_SURFACE_TEXTURE_H */ diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h index 2266d541f6..e40686d96c 100644 --- a/include/android/surface_texture_jni.h +++ b/include/android/surface_texture_jni.h @@ -32,8 +32,6 @@ __BEGIN_DECLS -#if __ANDROID_API__ >= 28 - /** * Get a reference to the native ASurfaceTexture from the corresponding java object. * @@ -52,8 +50,6 @@ __BEGIN_DECLS */ ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28); -#endif - __END_DECLS #endif /* ANDROID_NATIVE_SURFACE_TEXTURE_JNI_H */ diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h index 6fd7d2c0ab..b0bbb954a9 100644 --- a/include/android/system_fonts.h +++ b/include/android/system_fonts.h @@ -87,8 +87,6 @@ __BEGIN_DECLS -#if __ANDROID_API__ >= 29 - /** * ASystemFontIterator provides access to the system font configuration. * @@ -128,8 +126,6 @@ void ASystemFontIterator_close(ASystemFontIterator* _Nullable iterator) __INTROD */ AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29); -#endif // __ANDROID_API__ >= 29 - __END_DECLS #endif // ANDROID_SYSTEM_FONTS_H diff --git a/include/android/thermal.h b/include/android/thermal.h index 83582d6791..6ec68d99fc 100644 --- a/include/android/thermal.h +++ b/include/android/thermal.h @@ -53,7 +53,7 @@ #include <sys/types.h> #if !defined(__INTRODUCED_IN) -#define __INTRODUCED_IN(30) /* Introduced in API level 30 */ +#define __INTRODUCED_IN(__api_level) /* nothing */ #endif #ifdef __cplusplus @@ -109,8 +109,6 @@ typedef struct AThermalManager AThermalManager; */ typedef void (*AThermal_StatusCallback)(void *data, AThermalStatus status); -#if __ANDROID_API__ >= 30 - /** * Acquire an instance of the thermal manager. This must be freed using * {@link AThermal_releaseManager}. @@ -179,8 +177,6 @@ int AThermal_registerThermalStatusListener(AThermalManager *manager, int AThermal_unregisterThermalStatusListener(AThermalManager *manager, AThermal_StatusCallback callback, void *data) __INTRODUCED_IN(30); -#endif // __ANDROID_API__ >= 30 - #ifdef __cplusplus } #endif diff --git a/include/android/trace.h b/include/android/trace.h index dbad6f6f21..dcefffb20d 100644 --- a/include/android/trace.h +++ b/include/android/trace.h @@ -40,8 +40,6 @@ extern "C" { #endif -#if __ANDROID_API__ >= 23 - /** * Returns true if tracing is enabled. Use this to avoid expensive computation only necessary * when tracing is enabled. @@ -72,10 +70,6 @@ void ATrace_beginSection(const char* sectionName) __INTRODUCED_IN(23); */ void ATrace_endSection() __INTRODUCED_IN(23); -#endif /* __ANDROID_API__ >= 23 */ - -#if __ANDROID_API__ >= 29 - /** * Writes a trace message to indicate that a given section of code has * begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same @@ -112,8 +106,6 @@ void ATrace_endAsyncSection(const char* sectionName, int32_t cookie) __INTRODUCE */ void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29); -#endif /* __ANDROID_API__ >= 29 */ - #ifdef __cplusplus } #endif diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp index 8883c0478a..16cded8141 100644 --- a/libs/adbd_auth/Android.bp +++ b/libs/adbd_auth/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libadbd_auth", cflags: [ diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h index 8f834df62b..1dcf540cf3 100644 --- a/libs/adbd_auth/include/adbd_auth.h +++ b/libs/adbd_auth/include/adbd_auth.h @@ -26,7 +26,6 @@ #endif __BEGIN_DECLS -#if !defined(__ANDROID__) || __ANDROID_API__ >= 30 // The transport type of the device connection. enum AdbTransportType : int32_t { @@ -186,5 +185,4 @@ enum AdbdAuthFeature : int32_t { */ bool adbd_auth_supports_feature(AdbdAuthFeature feature); -#endif //!__ANDROID__ || __ANDROID_API__ >= 30 __END_DECLS diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp index cdd776480c..b74923cbfc 100644 --- a/libs/android_runtime_lazy/Android.bp +++ b/libs/android_runtime_lazy/Android.bp @@ -30,6 +30,15 @@ // instead of libandroid_runtime. When they are used by a vendor process, // depending on libandroid_runtime is meaningless. In this case, // they can depend on libandroid_runtime_lazy. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libandroid_runtime_lazy", vendor_available: true, diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp index 80aa8916da..bb40f5146e 100644 --- a/libs/arect/Android.bp +++ b/libs/arect/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_native_libs_arect_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_arect_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + ndk_headers { name: "libarect_headers_for_ndk", from: "include/android", diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 08b984ea1b..776d59474d 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libbinder_headers", export_include_dirs: ["include"], @@ -22,14 +31,21 @@ cc_library_headers { header_libs: [ "libbase_headers", + "libbinder_headers_platform_shared", "libcutils_headers", "libutils_headers", ], export_header_lib_headers: [ "libbase_headers", + "libbinder_headers_platform_shared", "libcutils_headers", "libutils_headers", ], + apex_available: [ + "//apex_available:platform", + "com.android.media", + "com.android.media.swcodec", + ], min_sdk_version: "29", target: { darwin: { @@ -181,16 +197,32 @@ cc_library { "--header-filter=^.*frameworks/native/libs/binder/.*.h$", ], tidy_checks_as_errors: [ - "*", + // Explicitly list the checks that should not occur in this module. + "abseil-*", + "android-*", + "bugprone-*", + "cert-*", + "clang-analyzer-*", "-clang-analyzer-core.CallAndMessage", "-clang-analyzer-core.uninitialized.Assign", - "-clang-analyzer-unix.Malloc,", + "-clang-analyzer-unix.Malloc", "-clang-analyzer-deadcode.DeadStores", "-clang-analyzer-optin.cplusplus.UninitializedObject", + "google-*", + "-google-readability-*", + "-google-runtime-references", + "misc-*", "-misc-no-recursion", "-misc-redundant-expression", "-misc-unused-using-decls", + "performance*", + "portability*", ], + + pgo: { + sampling: true, + profile_file: "libbinder/libbinder.profdata", + }, } // AIDL interface between libbinder and framework.jar @@ -203,6 +235,7 @@ filegroup { "aidl/android/os/IClientCallback.aidl", "aidl/android/os/IServiceCallback.aidl", "aidl/android/os/IServiceManager.aidl", + "aidl/android/os/ServiceDebugInfo.aidl", ], path: "aidl", } diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index bf4387a0a1..ddda024a40 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -228,8 +228,9 @@ status_t BpBinder::transact( : Stability::getLocalLevel(); if (CC_UNLIKELY(!Stability::check(category, required))) { - ALOGE("Cannot do a user transaction on a %s binder in a %s context.", + ALOGE("Cannot do a user transaction on a %s binder (%s) in a %s context.", category.debugString().c_str(), + String8(getInterfaceDescriptor()).c_str(), Stability::levelString(required).c_str()); return BAD_TYPE; } diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp index 88c85bfadc..349658ecfa 100644 --- a/libs/binder/BufferedTextOutput.cpp +++ b/libs/binder/BufferedTextOutput.cpp @@ -15,7 +15,6 @@ */ #include "BufferedTextOutput.h" -#include <binder/Debug.h> #include <cutils/atomic.h> #include <utils/Log.h> @@ -26,6 +25,7 @@ #include <stdio.h> #include <stdlib.h> +#include "Debug.h" #include "Static.h" // --------------------------------------------------------------------------- diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp index 3a620590ab..e4ac4b49a4 100644 --- a/libs/binder/Debug.cpp +++ b/libs/binder/Debug.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include <binder/Debug.h> +#include "Debug.h" + #include <binder/ProcessState.h> #include <utils/misc.h> diff --git a/libs/binder/include/binder/Debug.h b/libs/binder/Debug.h index ac71e003c4..ac71e003c4 100644 --- a/libs/binder/include/binder/Debug.h +++ b/libs/binder/Debug.h diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 7d01e0b1c3..79a11d22bd 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -486,15 +486,30 @@ void IPCThreadState::flushCommands() } } +bool IPCThreadState::flushIfNeeded() +{ + if (mIsLooper || mServingStackPointer != nullptr) { + return false; + } + // In case this thread is not a looper and is not currently serving a binder transaction, + // there's no guarantee that this thread will call back into the kernel driver any time + // soon. Therefore, flush pending commands such as BC_FREE_BUFFER, to prevent them from getting + // stuck in this thread's out buffer. + flushCommands(); + return true; +} + void IPCThreadState::blockUntilThreadAvailable() { pthread_mutex_lock(&mProcess->mThreadCountLock); + mProcess->mWaitingForThreads++; while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) { ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n", static_cast<unsigned long>(mProcess->mExecutingThreadsCount), static_cast<unsigned long>(mProcess->mMaxThreads)); pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock); } + mProcess->mWaitingForThreads--; pthread_mutex_unlock(&mProcess->mThreadCountLock); } @@ -534,7 +549,12 @@ status_t IPCThreadState::getAndExecuteCommand() } mProcess->mStarvationStartTimeMs = 0; } - pthread_cond_broadcast(&mProcess->mThreadCountDecrement); + + // Cond broadcast can be expensive, so don't send it every time a binder + // call is processed. b/168806193 + if (mProcess->mWaitingForThreads > 0) { + pthread_cond_broadcast(&mProcess->mThreadCountDecrement); + } pthread_mutex_unlock(&mProcess->mThreadCountLock); } @@ -591,12 +611,19 @@ void IPCThreadState::processPostWriteDerefs() mPostWriteStrongDerefs.clear(); } +void IPCThreadState::createTransactionReference(RefBase* ref) +{ + ref->incStrong(mProcess.get()); + mPostWriteStrongDerefs.push(ref); +} + void IPCThreadState::joinThreadPool(bool isMain) { LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); + mIsLooper = true; status_t result; do { processPendingDerefs(); @@ -619,6 +646,7 @@ void IPCThreadState::joinThreadPool(bool isMain) (void*)pthread_self(), getpid(), result); mOut.writeInt32(BC_EXIT_LOOPER); + mIsLooper = false; talkWithDriver(false); } @@ -629,6 +657,7 @@ status_t IPCThreadState::setupPolling(int* fd) } mOut.writeInt32(BC_ENTER_LOOPER); + flushCommands(); *fd = mProcess->mDriverFD; return 0; } @@ -731,9 +760,11 @@ void IPCThreadState::incStrongHandle(int32_t handle, BpBinder *proxy) LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle); mOut.writeInt32(BC_ACQUIRE); mOut.writeInt32(handle); - // Create a temp reference until the driver has handled this command. - proxy->incStrong(mProcess.get()); - mPostWriteStrongDerefs.push(proxy); + if (!flushIfNeeded()) { + // Create a temp reference until the driver has handled this command. + proxy->incStrong(mProcess.get()); + mPostWriteStrongDerefs.push(proxy); + } } void IPCThreadState::decStrongHandle(int32_t handle) @@ -741,6 +772,7 @@ void IPCThreadState::decStrongHandle(int32_t handle) LOG_REMOTEREFS("IPCThreadState::decStrongHandle(%d)\n", handle); mOut.writeInt32(BC_RELEASE); mOut.writeInt32(handle); + flushIfNeeded(); } void IPCThreadState::incWeakHandle(int32_t handle, BpBinder *proxy) @@ -748,9 +780,11 @@ void IPCThreadState::incWeakHandle(int32_t handle, BpBinder *proxy) LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle); mOut.writeInt32(BC_INCREFS); mOut.writeInt32(handle); - // Create a temp reference until the driver has handled this command. - proxy->getWeakRefs()->incWeak(mProcess.get()); - mPostWriteWeakDerefs.push(proxy->getWeakRefs()); + if (!flushIfNeeded()) { + // Create a temp reference until the driver has handled this command. + proxy->getWeakRefs()->incWeak(mProcess.get()); + mPostWriteWeakDerefs.push(proxy->getWeakRefs()); + } } void IPCThreadState::decWeakHandle(int32_t handle) @@ -758,6 +792,7 @@ void IPCThreadState::decWeakHandle(int32_t handle) LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle); mOut.writeInt32(BC_DECREFS); mOut.writeInt32(handle); + flushIfNeeded(); } status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) @@ -813,6 +848,7 @@ IPCThreadState::IPCThreadState() mServingStackPointer(nullptr), mWorkSource(kUnsetWorkSource), mPropagateWorkSource(false), + mIsLooper(false), mStrictModePolicy(0), mLastTransactionBinderFlags(0), mCallRestriction(mProcess->mCallRestriction) @@ -1393,6 +1429,7 @@ void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, IPCThreadState* state = self(); state->mOut.writeInt32(BC_FREE_BUFFER); state->mOut.writePointer((uintptr_t)data); + state->flushIfNeeded(); } } // namespace android diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp index 8d622668cc..4edc493f11 100644 --- a/libs/binder/IpPrefix.cpp +++ b/libs/binder/IpPrefix.cpp @@ -24,12 +24,10 @@ #include <log/log.h> #include <utils/Errors.h> -using android::BAD_TYPE; using android::BAD_VALUE; using android::NO_ERROR; using android::Parcel; using android::status_t; -using android::UNEXPECTED_NULL; namespace android { diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp index 325e204203..f96b6bb4eb 100644 --- a/libs/binder/LazyServiceRegistrar.cpp +++ b/libs/binder/LazyServiceRegistrar.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "log/log_main.h" #define LOG_TAG "AidlLazyServiceRegistrar" #include <binder/LazyServiceRegistrar.h> @@ -29,18 +30,20 @@ namespace internal { using AidlServiceManager = android::os::IServiceManager; -class ClientCounterCallback : public ::android::os::BnClientCallback { +class ClientCounterCallbackImpl : public ::android::os::BnClientCallback { public: - ClientCounterCallback() : mNumConnectedServices(0), mForcePersist(false) {} + ClientCounterCallbackImpl() : mNumConnectedServices(0), mForcePersist(false) {} bool registerService(const sp<IBinder>& service, const std::string& name, bool allowIsolated, int dumpFlags); - - /** - * Set a flag to prevent services from automatically shutting down - */ void forcePersist(bool persist); + void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback); + + bool tryUnregister(); + + void reRegister(); + protected: Status onClients(const sp<IBinder>& service, bool clients) override; @@ -53,6 +56,7 @@ private: // whether, based on onClients calls, we know we have a client for this // service or not bool clients = false; + bool registered = true; }; /** @@ -66,16 +70,52 @@ private: */ void tryShutdown(); + /** + * Try to shutdown the process, unless: + * - 'forcePersist' is 'true', or + * - The active services count callback returns 'true', or + * - Some services have clients. + */ + void maybeTryShutdown(); + // count of services with clients size_t mNumConnectedServices; + // previous value passed to the active services callback + std::optional<bool> mPreviousHasClients; + // map of registered names and services std::map<std::string, Service> mRegisteredServices; bool mForcePersist; + + // Callback used to report if there are services with clients + std::function<bool(bool)> mActiveServicesCallback; }; -bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name, +class ClientCounterCallback { +public: + ClientCounterCallback(); + + bool registerService(const sp<IBinder>& service, const std::string& name, + bool allowIsolated, int dumpFlags); + + /** + * Set a flag to prevent services from automatically shutting down + */ + void forcePersist(bool persist); + + void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback); + + bool tryUnregister(); + + void reRegister(); + +private: + sp<ClientCounterCallbackImpl> mImpl; +}; + +bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, const std::string& name, bool allowIsolated, int dumpFlags) { auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); @@ -89,7 +129,7 @@ bool ClientCounterCallback::registerService(const sp<IBinder>& service, const st } if (!reRegister) { - if (!manager->registerClientCallback(name, service, this).isOk()) { + if(!manager->registerClientCallback(name, service, this).isOk()) { ALOGE("Failed to add client callback for service %s", name.c_str()); return false; } @@ -105,7 +145,7 @@ bool ClientCounterCallback::registerService(const sp<IBinder>& service, const st return true; } -std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCallback::assertRegisteredService(const sp<IBinder>& service) { +std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounterCallbackImpl::assertRegisteredService(const sp<IBinder>& service) { LOG_ALWAYS_FATAL_IF(service == nullptr, "Got onClients callback for null service"); for (auto it = mRegisteredServices.begin(); it != mRegisteredServices.end(); ++it) { auto const& [name, registered] = *it; @@ -117,10 +157,66 @@ std::map<std::string, ClientCounterCallback::Service>::iterator ClientCounterCal __builtin_unreachable(); } -void ClientCounterCallback::forcePersist(bool persist) { +void ClientCounterCallbackImpl::forcePersist(bool persist) { mForcePersist = persist; - if(!mForcePersist) { + if (!mForcePersist) { // Attempt a shutdown in case the number of clients hit 0 while the flag was on + maybeTryShutdown(); + } +} + +bool ClientCounterCallbackImpl::tryUnregister() { + auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); + + for (auto& [name, entry] : mRegisteredServices) { + bool success = manager->tryUnregisterService(name, entry.service).isOk(); + + if (!success) { + ALOGI("Failed to unregister service %s", name.c_str()); + return false; + } + entry.registered = false; + } + + return true; +} + +void ClientCounterCallbackImpl::reRegister() { + for (auto& [name, entry] : mRegisteredServices) { + // re-register entry if not already registered + if (entry.registered) { + continue; + } + + if (!registerService(entry.service, name, entry.allowIsolated, + entry.dumpFlags)) { + // Must restart. Otherwise, clients will never be able to get a hold of this service. + LOG_ALWAYS_FATAL("Bad state: could not re-register services"); + } + + entry.registered = true; + } +} + +void ClientCounterCallbackImpl::maybeTryShutdown() { + if (mForcePersist) { + ALOGI("Shutdown prevented by forcePersist override flag."); + return; + } + + bool handledInCallback = false; + if (mActiveServicesCallback != nullptr) { + bool hasClients = mNumConnectedServices != 0; + if (hasClients != mPreviousHasClients) { + handledInCallback = mActiveServicesCallback(hasClients); + mPreviousHasClients = hasClients; + } + } + + // If there is no callback defined or the callback did not handle this + // client count change event, try to shutdown the process if its services + // have no clients. + if (!handledInCallback && mNumConnectedServices == 0) { tryShutdown(); } } @@ -129,7 +225,7 @@ void ClientCounterCallback::forcePersist(bool persist) { * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple * invocations could occur on different threads however. */ -Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients) { +Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool clients) { auto & [name, registered] = *assertRegisteredService(service); if (registered.clients == clients) { LOG_ALWAYS_FATAL("Process already thought %s had clients: %d but servicemanager has " @@ -150,54 +246,50 @@ Status ClientCounterCallback::onClients(const sp<IBinder>& service, bool clients ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d", mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients); - tryShutdown(); + maybeTryShutdown(); return Status::ok(); } -void ClientCounterCallback::tryShutdown() { - if(mNumConnectedServices > 0) { - // Should only shut down if there are no clients - return; - } + void ClientCounterCallbackImpl::tryShutdown() { + ALOGI("Trying to shut down the service. No clients in use for any service in process."); - if(mForcePersist) { - ALOGI("Shutdown prevented by forcePersist override flag."); - return; - } - - ALOGI("Trying to shut down the service. No clients in use for any service in process."); + if (tryUnregister()) { + ALOGI("Unregistered all clients and exiting"); + exit(EXIT_SUCCESS); + } - auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager())); + reRegister(); +} - auto unRegisterIt = mRegisteredServices.begin(); - for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) { - auto& entry = (*unRegisterIt); +void ClientCounterCallbackImpl::setActiveServicesCallback(const std::function<bool(bool)>& + activeServicesCallback) { + mActiveServicesCallback = activeServicesCallback; +} - bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk(); +ClientCounterCallback::ClientCounterCallback() { + mImpl = sp<ClientCounterCallbackImpl>::make(); +} +bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name, + bool allowIsolated, int dumpFlags) { + return mImpl->registerService(service, name, allowIsolated, dumpFlags); +} - if (!success) { - ALOGI("Failed to unregister service %s", entry.first.c_str()); - break; - } - } +void ClientCounterCallback::forcePersist(bool persist) { + mImpl->forcePersist(persist); +} - if (unRegisterIt == mRegisteredServices.end()) { - ALOGI("Unregistered all clients and exiting"); - exit(EXIT_SUCCESS); - } +void ClientCounterCallback::setActiveServicesCallback(const std::function<bool(bool)>& + activeServicesCallback) { + mImpl->setActiveServicesCallback(activeServicesCallback); +} - for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt; - reRegisterIt++) { - auto& entry = (*reRegisterIt); +bool ClientCounterCallback::tryUnregister() { + return mImpl->tryUnregister(); +} - // re-register entry - if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated, - entry.second.dumpFlags)) { - // Must restart. Otherwise, clients will never be able to get a hold of this service. - ALOGE("Bad state: could not re-register services"); - } - } +void ClientCounterCallback::reRegister() { + mImpl->reRegister(); } } // namespace internal @@ -223,5 +315,18 @@ void LazyServiceRegistrar::forcePersist(bool persist) { mClientCC->forcePersist(persist); } +void LazyServiceRegistrar::setActiveServicesCallback(const std::function<bool(bool)>& + activeServicesCallback) { + mClientCC->setActiveServicesCallback(activeServicesCallback); +} + +bool LazyServiceRegistrar::tryUnregister() { + return mClientCC->tryUnregister(); +} + +void LazyServiceRegistrar::reRegister() { + mClientCC->reRegister(); +} + } // namespace hardware } // namespace android diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 9bba369ee4..1a4ede1940 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -769,200 +769,116 @@ status_t Parcel::writeUtf8AsUtf16(const std::string& str) { return NO_ERROR; } -status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) { - if (!str) { - return writeInt32(-1); - } - return writeUtf8AsUtf16(*str); -} - -status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) { - if (!str) { - return writeInt32(-1); - } - return writeUtf8AsUtf16(*str); -} - -status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) { - if (size > std::numeric_limits<int32_t>::max()) { - return BAD_VALUE; - } - - status_t status = writeInt32(size); - if (status != OK) { - return status; - } - - return write(data, size); -} - -status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { - return writeByteVectorInternal(val.data(), val.size()); -} - -status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val) -{ - if (!val) return writeInt32(-1); - return writeByteVectorInternal(val->data(), val->size()); -} - -status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) -{ - if (!val) return writeInt32(-1); - return writeByteVectorInternal(val->data(), val->size()); -} - -status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { - return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size()); -} - -status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val) -{ - if (!val) return writeInt32(-1); - return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size()); -} - -status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val) -{ - if (!val) return writeInt32(-1); - return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size()); -} - -status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) -{ - return writeTypedVector(val, &Parcel::writeInt32); -} - -status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeInt32); -} - -status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeInt32); -} - -status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val) -{ - return writeTypedVector(val, &Parcel::writeInt64); -} - -status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeInt64); -} - -status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeInt64); -} - -status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val) -{ - return writeTypedVector(val, &Parcel::writeUint64); -} - -status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeUint64); -} - -status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeUint64); -} - -status_t Parcel::writeFloatVector(const std::vector<float>& val) -{ - return writeTypedVector(val, &Parcel::writeFloat); -} - -status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeFloat); -} - -status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeFloat); -} - -status_t Parcel::writeDoubleVector(const std::vector<double>& val) -{ - return writeTypedVector(val, &Parcel::writeDouble); -} - -status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeDouble); -} - -status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeDouble); -} - -status_t Parcel::writeBoolVector(const std::vector<bool>& val) -{ - return writeTypedVector(val, &Parcel::writeBool); -} - -status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeBool); -} - -status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeBool); -} - -status_t Parcel::writeCharVector(const std::vector<char16_t>& val) -{ - return writeTypedVector(val, &Parcel::writeChar); -} - -status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeChar); -} - -status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeChar); -} - -status_t Parcel::writeString16Vector(const std::vector<String16>& val) -{ - return writeTypedVector(val, &Parcel::writeString16); -} +status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) { return writeData(str); } +status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) { return writeData(str); } + +status_t Parcel::writeString16(const std::optional<String16>& str) { return writeData(str); } +status_t Parcel::writeString16(const std::unique_ptr<String16>& str) { return writeData(str); } + +status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { return writeData(val); } +status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val) { return writeData(val); } +status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) { return writeData(val); } +status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { return writeData(val); } +status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val) { return writeData(val); } +status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val){ return writeData(val); } +status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) { return writeData(val); } +status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val) { return writeData(val); } +status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) { return writeData(val); } +status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val) { return writeData(val); } +status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val) { return writeData(val); } +status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) { return writeData(val); } +status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val) { return writeData(val); } +status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val) { return writeData(val); } +status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) { return writeData(val); } +status_t Parcel::writeFloatVector(const std::vector<float>& val) { return writeData(val); } +status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val) { return writeData(val); } +status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val) { return writeData(val); } +status_t Parcel::writeDoubleVector(const std::vector<double>& val) { return writeData(val); } +status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val) { return writeData(val); } +status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) { return writeData(val); } +status_t Parcel::writeBoolVector(const std::vector<bool>& val) { return writeData(val); } +status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val) { return writeData(val); } +status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) { return writeData(val); } +status_t Parcel::writeCharVector(const std::vector<char16_t>& val) { return writeData(val); } +status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val) { return writeData(val); } +status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) { return writeData(val); } + +status_t Parcel::writeString16Vector(const std::vector<String16>& val) { return writeData(val); } status_t Parcel::writeString16Vector( - const std::optional<std::vector<std::optional<String16>>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeString16); -} - + const std::optional<std::vector<std::optional<String16>>>& val) { return writeData(val); } status_t Parcel::writeString16Vector( - const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeString16); -} - + const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) { return writeData(val); } status_t Parcel::writeUtf8VectorAsUtf16Vector( - const std::optional<std::vector<std::optional<std::string>>>& val) { - return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16); -} - + const std::optional<std::vector<std::optional<std::string>>>& val) { return writeData(val); } status_t Parcel::writeUtf8VectorAsUtf16Vector( - const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) { - return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16); -} + const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) { return writeData(val); } +status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) { return writeData(val); } + +status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) { return writeData(val); } +status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) { return writeData(val); } +status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) { return writeData(val); } + +status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) { return writeData(val); } +status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val) { return writeData(val); } +status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) { return writeData(val); } + +status_t Parcel::writeParcelable(const Parcelable& parcelable) { return writeData(parcelable); } + +status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const { return readData(str); } +status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { return readData(str); } + +status_t Parcel::readString16(std::optional<String16>* pArg) const { return readData(pArg); } +status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const { return readData(pArg); } + +status_t Parcel::readByteVector(std::vector<int8_t>* val) const { return readData(val); } +status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { return readData(val); } +status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const { return readData(val); } +status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { return readData(val); } +status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const { return readData(val); } +status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { return readData(val); } +status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const { return readData(val); } +status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { return readData(val); } +status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const { return readData(val); } +status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const { return readData(val); } +status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const { return readData(val); } +status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const { return readData(val); } +status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const { return readData(val); } +status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const { return readData(val); } +status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const { return readData(val); } +status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const { return readData(val); } +status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const { return readData(val); } +status_t Parcel::readFloatVector(std::vector<float>* val) const { return readData(val); } +status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const { return readData(val); } +status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const { return readData(val); } +status_t Parcel::readDoubleVector(std::vector<double>* val) const { return readData(val); } +status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { return readData(val); } +status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { return readData(val); } +status_t Parcel::readBoolVector(std::vector<bool>* val) const { return readData(val); } +status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const { return readData(val); } +status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const { return readData(val); } +status_t Parcel::readCharVector(std::vector<char16_t>* val) const { return readData(val); } -status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) { - return writeTypedVector(val, &Parcel::writeUtf8AsUtf16); -} +status_t Parcel::readString16Vector( + std::optional<std::vector<std::optional<String16>>>* val) const { return readData(val); } +status_t Parcel::readString16Vector( + std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const { return readData(val); } +status_t Parcel::readString16Vector(std::vector<String16>* val) const { return readData(val); } +status_t Parcel::readUtf8VectorFromUtf16Vector( + std::optional<std::vector<std::optional<std::string>>>* val) const { return readData(val); } +status_t Parcel::readUtf8VectorFromUtf16Vector( + std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const { return readData(val); } +status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const { return readData(val); } + +status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const { return readData(val); } +status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const { return readData(val); } +status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const { return readData(val); } + +status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const { return readData(val); } +status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const { return readData(val); } +status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const { return readData(val); } + +status_t Parcel::readParcelable(Parcelable* parcelable) const { return readData(parcelable); } status_t Parcel::writeInt32(int32_t val) { @@ -1091,24 +1007,6 @@ status_t Parcel::writeString8(const char* str, size_t len) return err; } -status_t Parcel::writeString16(const std::optional<String16>& str) -{ - if (!str) { - return writeInt32(-1); - } - - return writeString16(*str); -} - -status_t Parcel::writeString16(const std::unique_ptr<String16>& str) -{ - if (!str) { - return writeInt32(-1); - } - - return writeString16(*str); -} - status_t Parcel::writeString16(const String16& str) { return writeString16(str.string(), str.size()); @@ -1138,32 +1036,6 @@ status_t Parcel::writeStrongBinder(const sp<IBinder>& val) return flattenBinder(val); } -status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) -{ - return writeTypedVector(val, &Parcel::writeStrongBinder); -} - -status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeStrongBinder); -} - -status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) -{ - return writeNullableTypedVector(val, &Parcel::writeStrongBinder); -} - -status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const { - return readNullableTypedVector(val, &Parcel::readNullableStrongBinder); -} - -status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const { - return readNullableTypedVector(val, &Parcel::readNullableStrongBinder); -} - -status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const { - return readTypedVector(val, &Parcel::readStrongBinder); -} status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) { if (!parcelable) { @@ -1173,14 +1045,6 @@ status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) { return writeParcelable(*parcelable); } -status_t Parcel::writeParcelable(const Parcelable& parcelable) { - status_t status = writeInt32(1); // parcelable is not null. - if (status != OK) { - return status; - } - return parcelable.writeToParcel(this); -} - status_t Parcel::writeNativeHandle(const native_handle* handle) { if (!handle || handle->version != sizeof(native_handle)) @@ -1251,18 +1115,6 @@ status_t Parcel::writeUniqueFileDescriptor(const base::unique_fd& fd) { return writeDupFileDescriptor(fd.get()); } -status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) { - return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor); -} - -status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) { - return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor); -} - -status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) { - return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor); -} - status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob) { if (len > INT32_MAX) { @@ -1580,236 +1432,6 @@ restart_write: return err; } -status_t Parcel::readByteVector(std::vector<int8_t>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - return readByteVectorInternal(val, size); -} - -status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - return readByteVectorInternal(val, size); -} - -status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - if (!*val) { - // reserveOutVector does not create the out vector if size is < 0. - // This occurs when writing a null byte vector. - return OK; - } - return readByteVectorInternal(&**val, size); -} - -status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - if (val->get() == nullptr) { - // reserveOutVector does not create the out vector if size is < 0. - // This occurs when writing a null byte vector. - return OK; - } - return readByteVectorInternal(val->get(), size); -} - -status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - if (!*val) { - // reserveOutVector does not create the out vector if size is < 0. - // This occurs when writing a null byte vector. - return OK; - } - return readByteVectorInternal(&**val, size); -} - -status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - if (val->get() == nullptr) { - // reserveOutVector does not create the out vector if size is < 0. - // This occurs when writing a null byte vector. - return OK; - } - return readByteVectorInternal(val->get(), size); -} - -status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readInt32); -} - -status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readInt32); -} - -status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const { - return readTypedVector(val, &Parcel::readInt32); -} - -status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readInt64); -} - -status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readInt64); -} - -status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const { - return readTypedVector(val, &Parcel::readInt64); -} - -status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readUint64); -} - -status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readUint64); -} - -status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const { - return readTypedVector(val, &Parcel::readUint64); -} - -status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const { - return readNullableTypedVector(val, &Parcel::readFloat); -} - -status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const { - return readNullableTypedVector(val, &Parcel::readFloat); -} - -status_t Parcel::readFloatVector(std::vector<float>* val) const { - return readTypedVector(val, &Parcel::readFloat); -} - -status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const { - return readNullableTypedVector(val, &Parcel::readDouble); -} - -status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const { - return readNullableTypedVector(val, &Parcel::readDouble); -} - -status_t Parcel::readDoubleVector(std::vector<double>* val) const { - return readTypedVector(val, &Parcel::readDouble); -} - -status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { - const int32_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - val->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - val->emplace(); - - status = readBoolVector(&**val); - - if (status != OK) { - val->reset(); - } - - return status; -} - -status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { - const int32_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - val->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - val->reset(new (std::nothrow) std::vector<bool>()); - - status = readBoolVector(val->get()); - - if (status != OK) { - val->reset(); - } - - return status; -} - -status_t Parcel::readBoolVector(std::vector<bool>* val) const { - int32_t size; - status_t status = readInt32(&size); - - if (status != OK) { - return status; - } - - if (size < 0) { - return UNEXPECTED_NULL; - } - - val->resize(size); - - /* C++ bool handling means a vector of bools isn't necessarily addressable - * (we might use individual bits) - */ - bool data; - for (int32_t i = 0; i < size; ++i) { - status = readBool(&data); - (*val)[i] = data; - - if (status != OK) { - return status; - } - } - - return OK; -} - -status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readChar); -} - -status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const { - return readNullableTypedVector(val, &Parcel::readChar); -} - -status_t Parcel::readCharVector(std::vector<char16_t>* val) const { - return readTypedVector(val, &Parcel::readChar); -} - -status_t Parcel::readString16Vector( - std::optional<std::vector<std::optional<String16>>>* val) const { - return readNullableTypedVector(val, &Parcel::readString16); -} - -status_t Parcel::readString16Vector( - std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const { - return readNullableTypedVector(val, &Parcel::readString16); -} - -status_t Parcel::readString16Vector(std::vector<String16>* val) const { - return readTypedVector(val, &Parcel::readString16); -} - -status_t Parcel::readUtf8VectorFromUtf16Vector( - std::optional<std::vector<std::optional<std::string>>>* val) const { - return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16); -} - -status_t Parcel::readUtf8VectorFromUtf16Vector( - std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const { - return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16); -} - -status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const { - return readTypedVector(val, &Parcel::readUtf8FromUtf16); -} - status_t Parcel::readInt32(int32_t *pArg) const { return readAligned(pArg); @@ -1982,36 +1604,6 @@ status_t Parcel::readUtf8FromUtf16(std::string* str) const { return NO_ERROR; } -status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const { - const int32_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - str->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - str->emplace(); - return readUtf8FromUtf16(&**str); -} - -status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { - const int32_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - str->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - str->reset(new (std::nothrow) std::string()); - return readUtf8FromUtf16(str->get()); -} - const char* Parcel::readCString() const { if (mDataPos < mDataSize) { @@ -2059,7 +1651,10 @@ const char* Parcel::readString8Inplace(size_t* outLen) const *outLen = size; const char* str = (const char*)readInplace(size+1); if (str != nullptr) { - return str; + if (str[size] == '\0') { + return str; + } + android_errorWriteLog(0x534e4554, "172655291"); } } *outLen = 0; @@ -2075,51 +1670,6 @@ String16 Parcel::readString16() const return String16(); } -status_t Parcel::readString16(std::optional<String16>* pArg) const -{ - const int32_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - pArg->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - pArg->emplace(); - - status = readString16(&**pArg); - - if (status != OK) { - pArg->reset(); - } - - return status; -} - -status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const -{ - const int32_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - pArg->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - pArg->reset(new (std::nothrow) String16()); - - status = readString16(pArg->get()); - - if (status != OK) { - pArg->reset(); - } - - return status; -} status_t Parcel::readString16(String16* pArg) const { @@ -2142,7 +1692,10 @@ const char16_t* Parcel::readString16Inplace(size_t* outLen) const *outLen = size; const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t)); if (str != nullptr) { - return str; + if (str[size] == u'\0') { + return str; + } + android_errorWriteLog(0x534e4554, "172655291"); } } *outLen = 0; @@ -2173,18 +1726,6 @@ sp<IBinder> Parcel::readStrongBinder() const return val; } -status_t Parcel::readParcelable(Parcelable* parcelable) const { - int32_t have_parcelable = 0; - status_t status = readInt32(&have_parcelable); - if (status != OK) { - return status; - } - if (!have_parcelable) { - return UNEXPECTED_NULL; - } - return parcelable->readFromParcel(this); -} - int32_t Parcel::readExceptionCode() const { binder::Status status; @@ -2260,7 +1801,7 @@ int Parcel::readParcelFileDescriptor() const ssize_t written = TEMP_FAILURE_RETRY( ::write(comm, &message, sizeof(message))); - if (written == -1 || written != sizeof(message)) { + if (written != sizeof(message)) { ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s", written, strerror(errno)); return BAD_TYPE; @@ -2303,18 +1844,6 @@ status_t Parcel::readUniqueParcelFileDescriptor(base::unique_fd* val) const return OK; } -status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const { - return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor); -} - -status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const { - return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor); -} - -status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const { - return readTypedVector(val, &Parcel::readUniqueFileDescriptor); -} - status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const { int32_t blobType; diff --git a/libs/binder/ParcelableHolder.cpp b/libs/binder/ParcelableHolder.cpp index b2b86716d5..2e86b7415a 100644 --- a/libs/binder/ParcelableHolder.cpp +++ b/libs/binder/ParcelableHolder.cpp @@ -37,7 +37,7 @@ status_t ParcelableHolder::writeToParcel(Parcel* p) const { size_t sizePos = p->dataPosition(); RETURN_ON_FAILURE(p->writeInt32(0)); size_t dataStartPos = p->dataPosition(); - RETURN_ON_FAILURE(p->writeUtf8AsUtf16(this->mParcelableName)); + RETURN_ON_FAILURE(p->writeString16(this->mParcelableName)); this->mParcelable->writeToParcel(p); size_t dataSize = p->dataPosition() - dataStartPos; diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp index c807cfe89a..406fee0227 100644 --- a/libs/binder/PersistableBundle.cpp +++ b/libs/binder/PersistableBundle.cpp @@ -31,7 +31,6 @@ using android::BAD_TYPE; using android::BAD_VALUE; using android::NO_ERROR; using android::Parcel; -using android::sp; using android::status_t; using android::UNEXPECTED_NULL; diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index b5e4dfe4df..c38249ef7c 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -399,6 +399,7 @@ ProcessState::ProcessState(const char *driver) , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER) , mThreadCountDecrement(PTHREAD_COND_INITIALIZER) , mExecutingThreadsCount(0) + , mWaitingForThreads(0) , mMaxThreads(DEFAULT_MAX_BINDER_THREADS) , mStarvationStartTimeMs(0) , mThreadPoolStarted(false) diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index 97e282e783..1fbaa13887 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -10,6 +10,9 @@ "name": "binderAllocationLimits" }, { + "name": "binderClearBufTest" + }, + { "name": "binderDriverInterfaceTest" }, { @@ -19,10 +22,6 @@ "name": "binderParcelTest" }, { - "name": "binderParcelTest", - "host": true - }, - { "name": "binderLibTest" }, { @@ -62,6 +61,9 @@ }, { "name": "binderRustNdkInteropTest" + }, + { + "name": "rustBinderSerializationTest" } ] } diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp index 684a7dcc51..a0ade50efb 100644 --- a/libs/binder/TextOutput.cpp +++ b/libs/binder/TextOutput.cpp @@ -16,7 +16,7 @@ #include <binder/TextOutput.h> -#include <binder/Debug.h> +#include "Debug.h" #include <utils/String8.h> #include <utils/String16.h> diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index 2b1e49283f..2fabf947cd 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -18,6 +18,7 @@ package android.os; import android.os.IClientCallback; import android.os.IServiceCallback; +import android.os.ServiceDebugInfo; /** * Basic interface for finding and publishing system services. @@ -42,9 +43,9 @@ interface IServiceManager { */ const int DUMP_FLAG_PRIORITY_DEFAULT = 1 << 3; - const int DUMP_FLAG_PRIORITY_ALL = 15; - // DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH - // | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT; + const int DUMP_FLAG_PRIORITY_ALL = + DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH + | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PRIORITY_DEFAULT; /* Allows services to dump sections in protobuf format. */ const int DUMP_FLAG_PROTO = 1 << 4; @@ -116,4 +117,9 @@ interface IServiceManager { * Attempt to unregister and remove a service. Will fail if the service is still in use. */ void tryUnregisterService(@utf8InCpp String name, IBinder service); + + /** + * Get debug information for all currently registered services. + */ + ServiceDebugInfo[] getServiceDebugInfo(); } diff --git a/libs/binder/aidl/android/os/ServiceDebugInfo.aidl b/libs/binder/aidl/android/os/ServiceDebugInfo.aidl new file mode 100644 index 0000000000..b95d222394 --- /dev/null +++ b/libs/binder/aidl/android/os/ServiceDebugInfo.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** + * Debug information associated with a registered service + * @hide + */ +parcelable ServiceDebugInfo { + /** + * Service name (see IServiceManager.addService/checkService/getService) + */ + @utf8InCpp String name; + /** + * PID of service at the time of registration (may no longer be valid). + */ + int debugPid; +} diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h index c8fb448a2d..31f63c86b8 100644 --- a/libs/binder/include/binder/IBinder.h +++ b/libs/binder/include/binder/IBinder.h @@ -60,6 +60,15 @@ public: EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'), DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'), + // See android.os.IBinder.TWEET_TRANSACTION + // Most importantly, messages can be anything not exceeding 130 UTF-8 + // characters, and callees should exclaim "jolly good message old boy!" + TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'), + + // See android.os.IBinder.LIKE_TRANSACTION + // Improve binder self-esteem. + LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'), + // Corresponds to TF_ONE_WAY -- an asynchronous call. FLAG_ONEWAY = 0x00000001, diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h index 4da8aa1dfe..23a0cb0148 100644 --- a/libs/binder/include/binder/IPCThreadState.h +++ b/libs/binder/include/binder/IPCThreadState.h @@ -110,6 +110,7 @@ public: status_t setupPolling(int* fd); status_t handlePolledCommands(); void flushCommands(); + bool flushIfNeeded(); void joinThreadPool(bool isMain = true); @@ -161,6 +162,12 @@ public: // This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java // side. static const int32_t kUnsetWorkSource = -1; + + // Create a temp reference until commands in queue flushed to driver + // Internal only. + // @internal + void createTransactionReference(RefBase* ref); + private: IPCThreadState(); ~IPCThreadState(); @@ -204,6 +211,7 @@ private: int32_t mWorkSource; // Whether the work source should be propagated. bool mPropagateWorkSource; + bool mIsLooper; int32_t mStrictModePolicy; int32_t mLastTransactionBinderFlags; CallRestriction mCallRestriction; diff --git a/libs/binder/include/binder/LazyServiceRegistrar.h b/libs/binder/include/binder/LazyServiceRegistrar.h index d18c88ec0e..96597320f6 100644 --- a/libs/binder/include/binder/LazyServiceRegistrar.h +++ b/libs/binder/include/binder/LazyServiceRegistrar.h @@ -16,6 +16,8 @@ #pragma once +#include <functional> + #include <binder/IServiceManager.h> #include <binder/Status.h> #include <utils/StrongPointer.h> @@ -53,6 +55,39 @@ class LazyServiceRegistrar { */ void forcePersist(bool persist); + /** + * Set a callback that is invoked when the active service count (i.e. services with clients) + * registered with this process drops to zero (or becomes nonzero). + * The callback takes a boolean argument, which is 'true' if there is + * at least one service with clients. + * + * Callback return value: + * - false: Default behavior for lazy services (shut down the process if there + * are no clients). + * - true: Don't shut down the process even if there are no clients. + * + * This callback gives a chance to: + * 1 - Perform some additional operations before exiting; + * 2 - Prevent the process from exiting by returning "true" from the + * callback. + * + * This method should be called before 'registerService' to avoid races. + */ + void setActiveServicesCallback(const std::function<bool(bool)>& activeServicesCallback); + + /** + * Try to unregister all services previously registered with 'registerService'. + * Returns 'true' if successful. + */ + bool tryUnregister(); + + /** + * Re-register services that were unregistered by 'tryUnregister'. + * This method should be called in the case 'tryUnregister' fails + * (and should be called on the same thread). + */ + void reRegister(); + private: std::shared_ptr<internal::ClientCounterCallback> mClientCC; LazyServiceRegistrar(); diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index b49951b448..7b298f5b39 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -190,34 +190,47 @@ public: // Write an Enum vector with underlying type int8_t. // Does not use padding; each byte is contiguous. template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t writeEnumVector(const std::vector<T>& val); + status_t writeEnumVector(const std::vector<T>& val) + { return writeData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t writeEnumVector(const std::optional<std::vector<T>>& val); + status_t writeEnumVector(const std::optional<std::vector<T>>& val) + { return writeData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead"))); + status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead"))) + { return writeData(val); } // Write an Enum vector with underlying type != int8_t. template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t writeEnumVector(const std::vector<T>& val); + status_t writeEnumVector(const std::vector<T>& val) + { return writeData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t writeEnumVector(const std::optional<std::vector<T>>& val); + status_t writeEnumVector(const std::optional<std::vector<T>>& val) + { return writeData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead"))); + status_t writeEnumVector(const std::unique_ptr<std::vector<T>>& val) __attribute__((deprecated("use std::optional version instead"))) + { return writeData(val); } template<typename T> - status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val); + status_t writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val) + { return writeData(val); } template<typename T> - status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead"))); + status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead"))) + { return writeData(val); } template<typename T> - status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead"))); + status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) __attribute__((deprecated("use std::optional version instead"))) + { return writeData(val); } template<typename T> - status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val); + status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val) + { return writeData(val); } template<typename T> - status_t writeParcelableVector(const std::vector<T>& val); + status_t writeParcelableVector(const std::vector<T>& val) + { return writeData(val); } template<typename T> - status_t writeNullableParcelable(const std::optional<T>& parcelable); + status_t writeNullableParcelable(const std::optional<T>& parcelable) + { return writeData(parcelable); } template<typename T> - status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead"))); + status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead"))) + { return writeData(parcelable); } status_t writeParcelable(const Parcelable& parcelable); @@ -335,35 +348,48 @@ public: // Read an Enum vector with underlying type int8_t. // Does not use padding; each byte is contiguous. template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t readEnumVector(std::vector<T>* val) const; + status_t readEnumVector(std::vector<T>* val) const + { return readData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead"))); + status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead"))) + { return readData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t readEnumVector(std::optional<std::vector<T>>* val) const; + status_t readEnumVector(std::optional<std::vector<T>>* val) const + { return readData(val); } // Read an Enum vector with underlying type != int8_t. template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t readEnumVector(std::vector<T>* val) const; + status_t readEnumVector(std::vector<T>* val) const + { return readData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead"))); + status_t readEnumVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead"))) + { return readData(val); } template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> - status_t readEnumVector(std::optional<std::vector<T>>* val) const; + status_t readEnumVector(std::optional<std::vector<T>>* val) const + { return readData(val); } template<typename T> status_t readParcelableVector( - std::optional<std::vector<std::optional<T>>>* val) const; + std::optional<std::vector<std::optional<T>>>* val) const + { return readData(val); } template<typename T> status_t readParcelableVector( - std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead"))); + std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const __attribute__((deprecated("use std::optional version instead"))) + { return readData(val); } template<typename T> - status_t readParcelableVector(std::vector<T>* val) const; + status_t readParcelableVector(std::vector<T>* val) const + { return readData(val); } status_t readParcelable(Parcelable* parcelable) const; template<typename T> - status_t readParcelable(std::optional<T>* parcelable) const; + status_t readParcelable(std::optional<T>* parcelable) const + { return readData(parcelable); } template<typename T> - status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead"))); + status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead"))) + { return readData(parcelable); } + // If strong binder would be nullptr, readStrongBinder() returns an error. + // TODO: T must be derived from IInterface, fix for clarity. template<typename T> status_t readStrongBinder(sp<T>* val) const; @@ -418,20 +444,13 @@ public: template<typename T> status_t read(LightFlattenable<T>& val) const; + // resizeOutVector is used to resize AIDL out vector parameters. template<typename T> status_t resizeOutVector(std::vector<T>* val) const; template<typename T> status_t resizeOutVector(std::optional<std::vector<T>>* val) const; template<typename T> status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const __attribute__((deprecated("use std::optional version instead"))); - template<typename T> - status_t reserveOutVector(std::vector<T>* val, size_t* size) const; - template<typename T> - status_t reserveOutVector(std::optional<std::vector<T>>* val, - size_t* size) const; - template<typename T> - status_t reserveOutVector(std::unique_ptr<std::vector<T>>* val, - size_t* size) const __attribute__((deprecated("use std::optional version instead"))); // Like Parcel.java's readExceptionCode(). Reads the first int32 // off of a Parcel's header, returning 0 or the negative error @@ -517,6 +536,7 @@ private: void initState(); void scanForFds() const; status_t validateReadData(size_t len) const; + void updateWorkSourceRequestHeaderPosition() const; status_t finishFlattenBinder(const sp<IBinder>& binder); @@ -535,53 +555,544 @@ private: status_t writeRawNullableParcelable(const Parcelable* parcelable); - template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0> - status_t writeEnum(const T& val); - template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0> - status_t writeEnum(const T& val); + //----------------------------------------------------------------------------- + // Generic type read and write methods for Parcel: + // + // readData(T *value) will read a value from the Parcel. + // writeData(const T& value) will write a value to the Parcel. + // + // Our approach to parceling is based on two overloaded functions + // readData() and writeData() that generate parceling code for an + // object automatically based on its type. The code from templates are generated at + // compile time (if constexpr), and decomposes an object through a call graph matching + // recursive descent of the template typename. + // + // This approach unifies handling of complex objects, + // resulting in fewer lines of code, greater consistency, + // extensibility to nested types, efficiency (decisions made at compile time), + // and better code maintainability and optimization. + // + // Design decision: Incorporate the read and write code into Parcel rather than + // as a non-intrusive serializer that emits a byte stream, as we have + // active objects, alignment, legacy code, and historical idiosyncrasies. + // + // --- Overview + // + // Parceling is a way of serializing objects into a sequence of bytes for communication + // between processes, as part of marshaling data for remote procedure calls. + // + // The Parcel instance contains objects serialized as bytes, such as the following: + // + // 1) Ordinary primitive data such as int, float. + // 2) Established structured data such as String16, std::string. + // 3) Parcelables, which are C++ objects that derive from Parcelable (and thus have a + // readFromParcel and writeToParcel method). (Similar for Java) + // 4) A std::vector<> of such data. + // 5) Nullable objects contained in std::optional, std::unique_ptr, or std::shared_ptr. + // + // And active objects from the Android ecosystem such as: + // 6) File descriptors, base::unique_fd (kernel object handles) + // 7) Binder objects, sp<IBinder> (active Android RPC handles) + // + // Objects from (1) through (5) serialize into the mData buffer. + // Active objects (6) and (7) serialize into both mData and mObjects buffers. + // + // --- Data layout details + // + // Data is read or written to the parcel by recursively decomposing the type of the parameter + // type T through readData() and writeData() methods. + // + // We focus on writeData() here in our explanation of the data layout. + // + // 1) Alignment + // Implementation detail: Regardless of the parameter type, writeData() calls are designed + // to finish at a multiple of 4 bytes, the default alignment of the Parcel. + // + // Writes of single uint8_t, int8_t, enums based on types of size 1, char16_t, etc + // will result in 4 bytes being written. The data is widened to int32 and then written; + // hence the position of the nonzero bytes depend on the native endianness of the CPU. + // + // Writes of primitive values with 8 byte size, double, int64_t, uint64_t, + // are stored with 4 byte alignment. The ARM and x86/x64 permit unaligned reads + // and writes (albeit with potential latency/throughput penalty) which may or may + // not be observable unless the process is IO bound. + // + // 2) Parcelables + // Parcelables are detected by the type's base class, and implemented through calling + // into the Parcelable type's readFromParcel() or writeToParcel() methods. + // Historically, due to null object detection, a (int32_t) 1 is prepended to the data written. + // Parcelables must have a default constructor (i.e. one that takes no arguments). + // + // 3) Arrays + // Arrays of uint8_t and int8_t, and enums based on size 1 are written as + // a contiguous packed byte stream. Hidden zero padding is applied at the end of the byte + // stream to make a multiple of 4 bytes (and prevent info leakage when writing). + // + // All other array writes can be conceptually thought of as recursively calling + // writeData on the individual elements (though may be implemented differently for speed). + // As discussed in (1), alignment rules are therefore applied for each element + // write (not as an aggregate whole), so the wire representation of data can be + // substantially larger. + // + // Historical Note: + // Because of element-wise alignment, CharVector and BoolVector are expanded + // element-wise into integers even though they could have been optimized to be packed + // just like uint8_t, int8_t (size 1 data). + // + // 3.1) Arrays accessed by the std::vector type. This is the default for AIDL. + // + // 4) Nullables + // std::optional, std::unique_ptr, std::shared_ptr are all parceled identically + // (i.e. result in identical byte layout). + // The target of the std::optional, std::unique_ptr, or std::shared_ptr + // can either be a std::vector, String16, std::string, or a Parcelable. + // + // Detection of null relies on peeking the first int32 data and checking if the + // the peeked value is considered invalid for the object: + // (-1 for vectors, String16, std::string) (0 for Parcelables). If the peeked value + // is invalid, then a null is returned. + // + // Application Note: When to use each nullable type: + // + // std::optional: Embeds the object T by value rather than creating a new instance + // by managed pointer as std::unique_ptr or std::shared_ptr. This will save a malloc + // when creating an optional instance. + // + // Use of std::optionals by value can result in copies of the underlying value stored in it, + // so a std::move may be used to move in and move out (for example) a vector value into + // the std::optional or for the std::optional itself. + // + // std::unique_ptr, std::shared_ptr: These are preferred when the lifetime of the object is + // already managed by the application. This reduces unnecessary copying of data + // especially when the calls are local in-proc (rather than via binder rpc). + // + // 5) StrongBinder (sp<IBinder>) + // StrongBinder objects are written regardless of null. When read, null StrongBinder values + // will be interpreted as UNKNOWN_ERROR if the type is a single argument <sp<T>> + // or in a vector argument <std::vector<sp<T>>. However, they will be read without an error + // if present in a std::optional, std::unique_ptr, or std::shared_ptr vector, e.g. + // <std::optional<std::vector<sp<T>>>. + // + // See AIDL annotation @Nullable, readStrongBinder(), and readNullableStrongBinder(). + // + // Historical Note: writing a vector of StrongBinder objects <std::vector<sp<T>> + // containing a null will not cause an error. However reading such a vector will cause + // an error _and_ early termination of the read. - template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0> - status_t readEnum(T* pArg) const; - template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0> - status_t readEnum(T* pArg) const; + // --- Examples + // + // Using recursive parceling, we can parcel complex data types so long + // as they obey the rules described above. + // + // Example #1 + // Parceling of a 3D vector + // + // std::vector<std::vector<std::vector<int32_t>>> v1 { + // { {1}, {2, 3}, {4} }, + // {}, + // { {10}, {20}, {30, 40} }, + // }; + // Parcel p1; + // p1.writeData(v1); + // decltype(v1) v2; + // p1.setDataPosition(0); + // p1.readData(&v2); + // ASSERT_EQ(v1, v2); + // + // Example #2 + // Parceling of mixed shared pointers + // + // Parcel p1; + // auto sp1 = std::make_shared<std::vector<std::shared_ptr<std::vector<int>>>>(3); + // (*sp1)[2] = std::make_shared<std::vector<int>>(3); + // (*(*sp1)[2])[2] = 2; + // p1.writeData(sp1); + // decltype(sp1) sp2; + // p1.setDataPosition(0); + // p1.readData(&sp2); + // ASSERT_EQ((*sp1)[0], (*sp2)[0]); // nullptr + // ASSERT_EQ((*sp1)[1], (*sp2)[1]); // nullptr + // ASSERT_EQ(*(*sp1)[2], *(*sp2)[2]); // { 0, 0, 2} + + // --- Helper Methods + // TODO: move this to a utils header. + // + // Determine if a type is a specialization of a templated type + // Example: is_specialization_v<T, std::vector> - status_t writeByteVectorInternal(const int8_t* data, size_t size); - template<typename T> - status_t readByteVectorInternal(std::vector<T>* val, size_t size) const; + template <typename Test, template <typename...> class Ref> + struct is_specialization : std::false_type {}; - template<typename T, typename U> - status_t unsafeReadTypedVector(std::vector<T>* val, - status_t(Parcel::*read_func)(U*) const) const; - template<typename T> - status_t readNullableTypedVector(std::optional<std::vector<T>>* val, - status_t(Parcel::*read_func)(T*) const) const; - template<typename T> - status_t readNullableTypedVector(std::unique_ptr<std::vector<T>>* val, - status_t(Parcel::*read_func)(T*) const) const __attribute__((deprecated("use std::optional version instead"))); - template<typename T> - status_t readTypedVector(std::vector<T>* val, - status_t(Parcel::*read_func)(T*) const) const; - template<typename T, typename U> - status_t unsafeWriteTypedVector(const std::vector<T>& val, - status_t(Parcel::*write_func)(U)); - template<typename T> - status_t writeNullableTypedVector(const std::optional<std::vector<T>>& val, - status_t(Parcel::*write_func)(const T&)); - template<typename T> - status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val, - status_t(Parcel::*write_func)(const T&)) __attribute__((deprecated("use std::optional version instead"))); - template<typename T> - status_t writeNullableTypedVector(const std::optional<std::vector<T>>& val, - status_t(Parcel::*write_func)(T)); - template<typename T> - status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val, - status_t(Parcel::*write_func)(T)) __attribute__((deprecated("use std::optional version instead"))); - template<typename T> - status_t writeTypedVector(const std::vector<T>& val, - status_t(Parcel::*write_func)(const T&)); - template<typename T> - status_t writeTypedVector(const std::vector<T>& val, - status_t(Parcel::*write_func)(T)); + template <template <typename...> class Ref, typename... Args> + struct is_specialization<Ref<Args...>, Ref>: std::true_type {}; + + template <typename Test, template <typename...> class Ref> + static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value; + + // Get the first template type from a container, the T from MyClass<T, ...>. + template<typename T> struct first_template_type; + + template <template <typename ...> class V, typename T, typename... Args> + struct first_template_type<V<T, Args...>> { + using type_t = T; + }; + + template <typename T> + using first_template_type_t = typename first_template_type<T>::type_t; + + // For static assert(false) we need a template version to avoid early failure. + template <typename T> + static inline constexpr bool dependent_false_v = false; + + // primitive types that we consider packed and trivially copyable as an array + template <typename T> + static inline constexpr bool is_pointer_equivalent_array_v = + std::is_same_v<T, int8_t> + || std::is_same_v<T, uint8_t> + // We could support int16_t and uint16_t, but those aren't currently AIDL types. + || std::is_same_v<T, int32_t> + || std::is_same_v<T, uint32_t> + || std::is_same_v<T, float> + // are unaligned reads and write support is assumed. + || std::is_same_v<T, uint64_t> + || std::is_same_v<T, int64_t> + || std::is_same_v<T, double> + || (std::is_enum_v<T> && (sizeof(T) == 1 || sizeof(T) == 4)); // size check not type + + // allowed "nullable" types + // These are nonintrusive containers std::optional, std::unique_ptr, std::shared_ptr. + template <typename T> + static inline constexpr bool is_parcel_nullable_type_v = + is_specialization_v<T, std::optional> + || is_specialization_v<T, std::unique_ptr> + || is_specialization_v<T, std::shared_ptr>; + + // special int32 value to indicate NonNull or Null parcelables + // This is fixed to be only 0 or 1 by contract, do not change. + static constexpr int32_t kNonNullParcelableFlag = 1; + static constexpr int32_t kNullParcelableFlag = 0; + + // special int32 size representing a null vector, when applicable in Nullable data. + // This fixed as -1 by contract, do not change. + static constexpr int32_t kNullVectorSize = -1; + + // --- readData and writeData methods. + // We choose a mixture of function and template overloads to improve code readability. + // TODO: Consider C++20 concepts when they become available. + + // writeData function overloads. + // Implementation detail: Function overloading improves code readability over + // template overloading, but prevents writeData<T> from being used for those types. + + status_t writeData(bool t) { + return writeBool(t); // this writes as int32_t + } + + status_t writeData(int8_t t) { + return writeByte(t); // this writes as int32_t + } + + status_t writeData(uint8_t t) { + return writeByte(static_cast<int8_t>(t)); // this writes as int32_t + } + + status_t writeData(char16_t t) { + return writeChar(t); // this writes as int32_t + } + + status_t writeData(int32_t t) { + return writeInt32(t); + } + + status_t writeData(uint32_t t) { + return writeUint32(t); + } + + status_t writeData(int64_t t) { + return writeInt64(t); + } + + status_t writeData(uint64_t t) { + return writeUint64(t); + } + + status_t writeData(float t) { + return writeFloat(t); + } + + status_t writeData(double t) { + return writeDouble(t); + } + + status_t writeData(const String16& t) { + return writeString16(t); + } + + status_t writeData(const std::string& t) { + return writeUtf8AsUtf16(t); + } + + status_t writeData(const base::unique_fd& t) { + return writeUniqueFileDescriptor(t); + } + + status_t writeData(const Parcelable& t) { // std::is_base_of_v<Parcelable, T> + // implemented here. writeParcelable() calls this. + status_t status = writeData(static_cast<int32_t>(kNonNullParcelableFlag)); + if (status != OK) return status; + return t.writeToParcel(this); + } + + // writeData<T> template overloads. + // Written such that the first template type parameter is the complete type + // of the first function parameter. + template <typename T, + typename std::enable_if_t<std::is_enum_v<T>, bool> = true> + status_t writeData(const T& t) { + // implemented here. writeEnum() calls this. + using UT = std::underlying_type_t<T>; + return writeData(static_cast<UT>(t)); // recurse + } + + template <typename T, + typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true> + status_t writeData(const T& t) { + return writeStrongBinder(t); + } + + // std::optional, std::unique_ptr, std::shared_ptr special case. + template <typename CT, + typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true> + status_t writeData(const CT& c) { + using T = first_template_type_t<CT>; // The T in CT == C<T, ...> + if constexpr (is_specialization_v<T, std::vector> + || std::is_same_v<T, String16> + || std::is_same_v<T, std::string>) { + if (!c) return writeData(static_cast<int32_t>(kNullVectorSize)); + } else if constexpr (std::is_base_of_v<Parcelable, T>) { + if (!c) return writeData(static_cast<int32_t>(kNullParcelableFlag)); + } else /* constexpr */ { // could define this, but raise as error. + static_assert(dependent_false_v<CT>); + } + return writeData(*c); + } + + template <typename CT, + typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true> + status_t writeData(const CT& c) { + using T = first_template_type_t<CT>; // The T in CT == C<T, ...> + if (c.size() > std::numeric_limits<int32_t>::max()) return BAD_VALUE; + const auto size = static_cast<int32_t>(c.size()); + writeData(size); + if constexpr (is_pointer_equivalent_array_v<T>) { + constexpr size_t limit = std::numeric_limits<size_t>::max() / sizeof(T); + if (c.size() > limit) return BAD_VALUE; + // is_pointer_equivalent types do not have gaps which could leak info, + // which is only a concern when writing through binder. + + // TODO: Padding of the write is suboptimal when the length of the + // data is not a multiple of 4. Consider improving the write() method. + return write(c.data(), c.size() * sizeof(T)); + } else if constexpr (std::is_same_v<T, bool> + || std::is_same_v<T, char16_t>) { + // reserve data space to write to + auto data = reinterpret_cast<int32_t*>(writeInplace(c.size() * sizeof(int32_t))); + if (data == nullptr) return BAD_VALUE; + for (const auto t: c) { + *data++ = static_cast<int32_t>(t); + } + } else /* constexpr */ { + for (const auto &t : c) { + const status_t status = writeData(t); + if (status != OK) return status; + } + } + return OK; + } + + // readData function overloads. + // Implementation detail: Function overloading improves code readability over + // template overloading, but prevents readData<T> from being used for those types. + + status_t readData(bool* t) const { + return readBool(t); // this reads as int32_t + } + + status_t readData(int8_t* t) const { + return readByte(t); // this reads as int32_t + } + + status_t readData(uint8_t* t) const { + return readByte(reinterpret_cast<int8_t*>(t)); // NOTE: this reads as int32_t + } + + status_t readData(char16_t* t) const { + return readChar(t); // this reads as int32_t + } + + status_t readData(int32_t* t) const { + return readInt32(t); + } + + status_t readData(uint32_t* t) const { + return readUint32(t); + } + + status_t readData(int64_t* t) const { + return readInt64(t); + } + + status_t readData(uint64_t* t) const { + return readUint64(t); + } + + status_t readData(float* t) const { + return readFloat(t); + } + + status_t readData(double* t) const { + return readDouble(t); + } + + status_t readData(String16* t) const { + return readString16(t); + } + + status_t readData(std::string* t) const { + return readUtf8FromUtf16(t); + } + + status_t readData(base::unique_fd* t) const { + return readUniqueFileDescriptor(t); + } + + status_t readData(Parcelable* t) const { // std::is_base_of_v<Parcelable, T> + // implemented here. readParcelable() calls this. + int32_t present; + status_t status = readData(&present); + if (status != OK) return status; + if (present != kNonNullParcelableFlag) return UNEXPECTED_NULL; + return t->readFromParcel(this); + } + + // readData<T> template overloads. + // Written such that the first template type parameter is the complete type + // of the first function parameter. + + template <typename T, + typename std::enable_if_t<std::is_enum_v<T>, bool> = true> + status_t readData(T* t) const { + // implemented here. readEnum() calls this. + using UT = std::underlying_type_t<T>; + return readData(reinterpret_cast<UT*>(t)); + } + + template <typename T, + typename std::enable_if_t<is_specialization_v<T, sp>, bool> = true> + status_t readData(T* t) const { + return readStrongBinder(t); // Note: on null, returns failure + } + + + template <typename CT, + typename std::enable_if_t<is_parcel_nullable_type_v<CT>, bool> = true> + status_t readData(CT* c) const { + using T = first_template_type_t<CT>; // The T in CT == C<T, ...> + const size_t startPos = dataPosition(); + int32_t peek; + status_t status = readData(&peek); + if (status != OK) return status; + if constexpr (is_specialization_v<T, std::vector> + || std::is_same_v<T, String16> + || std::is_same_v<T, std::string>) { + if (peek == kNullVectorSize) { + c->reset(); + return OK; + } + } else if constexpr (std::is_base_of_v<Parcelable, T>) { + if (peek == kNullParcelableFlag) { + c->reset(); + return OK; + } + } else /* constexpr */ { // could define this, but raise as error. + static_assert(dependent_false_v<CT>); + } + // create a new object. + if constexpr (is_specialization_v<CT, std::optional>) { + c->emplace(); + } else /* constexpr */ { + T* const t = new (std::nothrow) T; // contents read from Parcel below. + if (t == nullptr) return NO_MEMORY; + c->reset(t); + } + // rewind data ptr to reread (this is pretty quick), otherwise we could + // pass an optional argument to readData to indicate a peeked value. + setDataPosition(startPos); + if constexpr (is_specialization_v<T, std::vector>) { + return readData(&**c, READ_FLAG_SP_NULLABLE); // nullable sp<> allowed now + } else { + return readData(&**c); + } + } + + // std::vector special case, incorporating flags whether the vector + // accepts nullable sp<> to be read. + enum ReadFlags { + READ_FLAG_NONE = 0, + READ_FLAG_SP_NULLABLE = 1 << 0, + }; + + template <typename CT, + typename std::enable_if_t<is_specialization_v<CT, std::vector>, bool> = true> + status_t readData(CT* c, ReadFlags readFlags = READ_FLAG_NONE) const { + using T = first_template_type_t<CT>; // The T in CT == C<T, ...> + int32_t size; + status_t status = readInt32(&size); + if (status != OK) return status; + if (size < 0) return UNEXPECTED_NULL; + const size_t availableBytes = dataAvail(); // coarse bound on vector size. + if (static_cast<size_t>(size) > availableBytes) return BAD_VALUE; + c->clear(); // must clear before resizing/reserving otherwise move ctors may be called. + if constexpr (is_pointer_equivalent_array_v<T>) { + // could consider POD without gaps and alignment of 4. + auto data = reinterpret_cast<const T*>( + readInplace(static_cast<size_t>(size) * sizeof(T))); + if (data == nullptr) return BAD_VALUE; + c->insert(c->begin(), data, data + size); // insert should do a reserve(). + } else if constexpr (std::is_same_v<T, bool> + || std::is_same_v<T, char16_t>) { + c->reserve(size); // avoids default initialization + auto data = reinterpret_cast<const int32_t*>( + readInplace(static_cast<size_t>(size) * sizeof(int32_t))); + if (data == nullptr) return BAD_VALUE; + for (int32_t i = 0; i < size; ++i) { + c->emplace_back(static_cast<T>(*data++)); + } + } else if constexpr (is_specialization_v<T, sp>) { + c->resize(size); // calls ctor + if (readFlags & READ_FLAG_SP_NULLABLE) { + for (auto &t : *c) { + status = readNullableStrongBinder(&t); // allow nullable + if (status != OK) return status; + } + } else { + for (auto &t : *c) { + status = readStrongBinder(&t); + if (status != OK) return status; + } + } + } else /* constexpr */ { + c->resize(size); // calls ctor + for (auto &t : *c) { + status = readData(&t); + if (status != OK) return status; + } + } + return OK; + } + + //----------------------------------------------------------------------------- + private: status_t mError; uint8_t* mData; @@ -832,61 +1343,6 @@ status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const { } template<typename T> -status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const { - int32_t read_size; - status_t err = readInt32(&read_size); - if (err != NO_ERROR) { - return err; - } - - if (read_size < 0) { - return UNEXPECTED_NULL; - } - *size = static_cast<size_t>(read_size); - val->reserve(*size); - return OK; -} - -template<typename T> -status_t Parcel::reserveOutVector(std::optional<std::vector<T>>* val, size_t* size) const { - int32_t read_size; - status_t err = readInt32(&read_size); - if (err != NO_ERROR) { - return err; - } - - if (read_size >= 0) { - *size = static_cast<size_t>(read_size); - val->emplace(); - (*val)->reserve(*size); - } else { - val->reset(); - } - - return OK; -} - -template<typename T> -status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val, - size_t* size) const { - int32_t read_size; - status_t err = readInt32(&read_size); - if (err != NO_ERROR) { - return err; - } - - if (read_size >= 0) { - *size = static_cast<size_t>(read_size); - val->reset(new std::vector<T>()); - (*val)->reserve(*size); - } else { - val->reset(); - } - - return OK; -} - -template<typename T> status_t Parcel::readStrongBinder(sp<T>* val) const { sp<IBinder> tmp; status_t ret = readStrongBinder(&tmp); @@ -918,422 +1374,6 @@ status_t Parcel::readNullableStrongBinder(sp<T>* val) const { return ret; } -template<typename T, typename U> -status_t Parcel::unsafeReadTypedVector( - std::vector<T>* val, - status_t(Parcel::*read_func)(U*) const) const { - int32_t size; - status_t status = this->readInt32(&size); - - if (status != OK) { - return status; - } - - if (size < 0) { - return UNEXPECTED_NULL; - } - - if (val->max_size() < static_cast<size_t>(size)) { - return NO_MEMORY; - } - - val->resize(static_cast<size_t>(size)); - - if (val->size() < static_cast<size_t>(size)) { - return NO_MEMORY; - } - - for (auto& v: *val) { - status = (this->*read_func)(&v); - - if (status != OK) { - return status; - } - } - - return OK; -} - -template<typename T> -status_t Parcel::readTypedVector(std::vector<T>* val, - status_t(Parcel::*read_func)(T*) const) const { - return unsafeReadTypedVector(val, read_func); -} - -template<typename T> -status_t Parcel::readNullableTypedVector(std::optional<std::vector<T>>* val, - status_t(Parcel::*read_func)(T*) const) const { - const size_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - val->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - val->emplace(); - - status = unsafeReadTypedVector(&**val, read_func); - - if (status != OK) { - val->reset(); - } - - return status; -} - -template<typename T> -status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val, - status_t(Parcel::*read_func)(T*) const) const { - const size_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - val->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - val->reset(new std::vector<T>()); - - status = unsafeReadTypedVector(val->get(), read_func); - - if (status != OK) { - val->reset(); - } - - return status; -} - -template<typename T, typename U> -status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val, - status_t(Parcel::*write_func)(U)) { - if (val.size() > std::numeric_limits<int32_t>::max()) { - return BAD_VALUE; - } - - status_t status = this->writeInt32(static_cast<int32_t>(val.size())); - - if (status != OK) { - return status; - } - - for (const auto& item : val) { - status = (this->*write_func)(item); - - if (status != OK) { - return status; - } - } - - return OK; -} - -template<typename T> -status_t Parcel::writeTypedVector(const std::vector<T>& val, - status_t(Parcel::*write_func)(const T&)) { - return unsafeWriteTypedVector(val, write_func); -} - -template<typename T> -status_t Parcel::writeTypedVector(const std::vector<T>& val, - status_t(Parcel::*write_func)(T)) { - return unsafeWriteTypedVector(val, write_func); -} - -template<typename T> -status_t Parcel::writeNullableTypedVector(const std::optional<std::vector<T>>& val, - status_t(Parcel::*write_func)(const T&)) { - if (!val) { - return this->writeInt32(-1); - } - - return unsafeWriteTypedVector(*val, write_func); -} - -template<typename T> -status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val, - status_t(Parcel::*write_func)(const T&)) { - if (val.get() == nullptr) { - return this->writeInt32(-1); - } - - return unsafeWriteTypedVector(*val, write_func); -} - -template<typename T> -status_t Parcel::writeNullableTypedVector(const std::optional<std::vector<T>>& val, - status_t(Parcel::*write_func)(T)) { - if (!val) { - return this->writeInt32(-1); - } - - return unsafeWriteTypedVector(*val, write_func); -} - -template<typename T> -status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val, - status_t(Parcel::*write_func)(T)) { - if (val.get() == nullptr) { - return this->writeInt32(-1); - } - - return unsafeWriteTypedVector(*val, write_func); -} - -template<typename T> -status_t Parcel::readParcelableVector(std::vector<T>* val) const { - return unsafeReadTypedVector<T, Parcelable>(val, &Parcel::readParcelable); -} - -template<typename T> -status_t Parcel::readParcelableVector(std::optional<std::vector<std::optional<T>>>* val) const { - const size_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - val->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - val->emplace(); - - using NullableT = std::optional<T>; - status = unsafeReadTypedVector<NullableT, NullableT>(&**val, &Parcel::readParcelable); - - if (status != OK) { - val->reset(); - } - - return status; -} - -template<typename T> -status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const { - const size_t start = dataPosition(); - int32_t size; - status_t status = readInt32(&size); - val->reset(); - - if (status != OK || size < 0) { - return status; - } - - setDataPosition(start); - val->reset(new std::vector<std::unique_ptr<T>>()); - - using NullableT = std::unique_ptr<T>; - status = unsafeReadTypedVector<NullableT, NullableT>(val->get(), &Parcel::readParcelable); - - if (status != OK) { - val->reset(); - } - - return status; -} - -template<typename T> -status_t Parcel::readParcelable(std::optional<T>* parcelable) const { - const size_t start = dataPosition(); - int32_t present; - status_t status = readInt32(&present); - parcelable->reset(); - - if (status != OK || !present) { - return status; - } - - setDataPosition(start); - parcelable->emplace(); - - status = readParcelable(&**parcelable); - - if (status != OK) { - parcelable->reset(); - } - - return status; -} - -template<typename T> -status_t Parcel::readParcelable(std::unique_ptr<T>* parcelable) const { - const size_t start = dataPosition(); - int32_t present; - status_t status = readInt32(&present); - parcelable->reset(); - - if (status != OK || !present) { - return status; - } - - setDataPosition(start); - parcelable->reset(new T()); - - status = readParcelable(parcelable->get()); - - if (status != OK) { - parcelable->reset(); - } - - return status; -} - -template<typename T> -status_t Parcel::writeNullableParcelable(const std::optional<T>& parcelable) { - return writeRawNullableParcelable(parcelable ? &*parcelable : nullptr); -} - -template<typename T> -status_t Parcel::writeNullableParcelable(const std::unique_ptr<T>& parcelable) { - return writeRawNullableParcelable(parcelable.get()); -} - -template<typename T> -status_t Parcel::writeParcelableVector(const std::vector<T>& val) { - return unsafeWriteTypedVector<T,const Parcelable&>(val, &Parcel::writeParcelable); -} - -template<typename T> -status_t Parcel::writeParcelableVector(const std::optional<std::vector<std::optional<T>>>& val) { - if (!val) { - return this->writeInt32(-1); - } - - using NullableT = std::optional<T>; - return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable); -} - -template<typename T> -status_t Parcel::writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) { - if (val.get() == nullptr) { - return this->writeInt32(-1); - } - - return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>); -} - -template<typename T> -status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) { - if (val.get() == nullptr) { - return this->writeInt32(-1); - } - - using NullableT = std::unique_ptr<T>; - return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable); -} - -template<typename T> -status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val) { - if (val.get() == nullptr) { - return this->writeInt32(-1); - } - - using NullableT = std::optional<T>; - return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable); -} - -template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>> -status_t Parcel::writeEnum(const T& val) { - return writeInt32(static_cast<int32_t>(val)); -} -template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>> -status_t Parcel::writeEnum(const T& val) { - return writeInt64(static_cast<int64_t>(val)); -} - -template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::writeEnumVector(const std::vector<T>& val) { - return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size()); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::writeEnumVector(const std::optional<std::vector<T>>& val) { - if (!val) return writeInt32(-1); - return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size()); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) { - if (!val) return writeInt32(-1); - return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size()); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::writeEnumVector(const std::vector<T>& val) { - return writeTypedVector(val, &Parcel::writeEnum); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::writeEnumVector(const std::optional<std::vector<T>>& val) { - return writeNullableTypedVector(val, &Parcel::writeEnum); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) { - return writeNullableTypedVector(val, &Parcel::writeEnum); -} - -template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>> -status_t Parcel::readEnum(T* pArg) const { - return readInt32(reinterpret_cast<int32_t *>(pArg)); -} -template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>> -status_t Parcel::readEnum(T* pArg) const { - return readInt64(reinterpret_cast<int64_t *>(pArg)); -} - -template<typename T> -inline status_t Parcel::readByteVectorInternal(std::vector<T>* val, size_t size) const { - // readByteVectorInternal expects a vector that has been reserved (but not - // resized) to have the provided size. - const T* data = reinterpret_cast<const T*>(readInplace(size)); - if (!data) return BAD_VALUE; - val->clear(); - val->insert(val->begin(), data, data+size); - return NO_ERROR; -} - -template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::readEnumVector(std::vector<T>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - return readByteVectorInternal(val, size); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::readEnumVector(std::optional<std::vector<T>>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - if (!*val) { - // reserveOutVector does not create the out vector if size is < 0. - // This occurs when writing a null Enum vector. - return OK; - } - return readByteVectorInternal(&**val, size); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const { - size_t size; - if (status_t status = reserveOutVector(val, &size); status != OK) return status; - if (val->get() == nullptr) { - // reserveOutVector does not create the out vector if size is < 0. - // This occurs when writing a null Enum vector. - return OK; - } - return readByteVectorInternal(val->get(), size); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::readEnumVector(std::vector<T>* val) const { - return readTypedVector(val, &Parcel::readEnum); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::readEnumVector(std::optional<std::vector<T>>* val) const { - return readNullableTypedVector(val, &Parcel::readEnum); -} -template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>> -status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const { - return readNullableTypedVector(val, &Parcel::readEnum); -} - // --------------------------------------------------------------------------- inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel) diff --git a/libs/binder/include/binder/ParcelRef.h b/libs/binder/include/binder/ParcelRef.h new file mode 100644 index 0000000000..497da2d215 --- /dev/null +++ b/libs/binder/include/binder/ParcelRef.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + + +#include <binder/Parcel.h> +#include <utils/RefBase.h> + +// --------------------------------------------------------------------------- +namespace android { + +/** + * internal use only + * @internal + */ +class ParcelRef : public Parcel, public RefBase +{ +public: + static sp<ParcelRef> create() { + return new ParcelRef(); + } + +private: + ParcelRef() = default; +}; + +} // namespace android + +// ---------------------------------------------------------------------------
\ No newline at end of file diff --git a/libs/binder/include/binder/ParcelableHolder.h b/libs/binder/include/binder/ParcelableHolder.h index ff0a6860f3..9e4475c947 100644 --- a/libs/binder/include/binder/ParcelableHolder.h +++ b/libs/binder/include/binder/ParcelableHolder.h @@ -18,6 +18,7 @@ #include <binder/Parcel.h> #include <binder/Parcelable.h> +#include <utils/String16.h> #include <mutex> #include <optional> #include <tuple> @@ -72,7 +73,7 @@ public: template <typename T> status_t getParcelable(std::shared_ptr<T>* ret) const { static_assert(std::is_base_of<Parcelable, T>::value, "T must be derived from Parcelable"); - const std::string& parcelableDesc = T::getParcelableDescriptor(); + const String16& parcelableDesc = T::getParcelableDescriptor(); if (!this->mParcelPtr) { if (!this->mParcelable || !this->mParcelableName) { ALOGD("empty ParcelableHolder"); @@ -80,7 +81,7 @@ public: return android::OK; } else if (parcelableDesc != *mParcelableName) { ALOGD("extension class name mismatch expected:%s actual:%s", - mParcelableName->c_str(), parcelableDesc.c_str()); + String8(*mParcelableName).c_str(), String8(parcelableDesc).c_str()); *ret = nullptr; return android::BAD_VALUE; } @@ -88,7 +89,7 @@ public: return android::OK; } this->mParcelPtr->setDataPosition(0); - status_t status = this->mParcelPtr->readUtf8FromUtf16(&this->mParcelableName); + status_t status = this->mParcelPtr->readString16(&this->mParcelableName); if (status != android::OK || parcelableDesc != this->mParcelableName) { this->mParcelableName = std::nullopt; *ret = nullptr; @@ -130,7 +131,7 @@ public: private: mutable std::shared_ptr<Parcelable> mParcelable; - mutable std::optional<std::string> mParcelableName; + mutable std::optional<String16> mParcelableName; mutable std::unique_ptr<Parcel> mParcelPtr; Stability mStability; }; diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index bab6469d12..2405ab6b9e 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -107,11 +107,14 @@ private: int mDriverFD; void* mVMStart; - // Protects thread count variable below. + // Protects thread count and wait variables below. pthread_mutex_t mThreadCountLock; + // Broadcast whenever mWaitingForThreads > 0 pthread_cond_t mThreadCountDecrement; // Number of binder threads current executing a command. size_t mExecutingThreadsCount; + // Number of threads calling IPCThreadState::blockUntilThreadAvailable() + size_t mWaitingForThreads; // Maximum number for binder threads allowed for this process. size_t mMaxThreads; // Time when thread pool was emptied diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h index 5a719b8930..157919903f 100644 --- a/libs/binder/include/private/binder/binder_module.h +++ b/libs/binder/include/private/binder/binder_module.h @@ -88,10 +88,6 @@ struct binder_frozen_status_info { }; #endif //BINDER_GET_FROZEN_INFO -enum transaction_flags_ext { - TF_CLEAR_BUF = 0x20, /* clear buffer on txn complete */ -}; - #ifdef __cplusplus } // namespace android #endif diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp index bdb74dc989..eb103d3d77 100644 --- a/libs/binder/ndk/Android.bp +++ b/libs/binder/ndk/Android.bp @@ -15,6 +15,23 @@ */ // TODO(b/31559095): bionic on host should define this +package { + default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_binder_ndk_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_defaults { name: "libbinder_ndk_host_user", target: { @@ -104,16 +121,49 @@ cc_library { "--header-filter=^.*frameworks/native/libs/binder/.*.h$", ], tidy_checks_as_errors: [ - "*", + // Explicitly list the checks that should not occur in this module. + "abseil-*", + "android-*", + "bugprone-*", + "cert-*", + "clang-analyzer-*", "-clang-analyzer-core.CallAndMessage", "-clang-analyzer-core.uninitialized.Assign", - "-clang-analyzer-unix.Malloc,", + "-clang-analyzer-unix.Malloc", "-clang-analyzer-deadcode.DeadStores", "-clang-analyzer-optin.cplusplus.UninitializedObject", + "google-*", + "-google-readability-*", + "-google-runtime-references", + "misc-*", "-misc-no-recursion", + "-misc-non-private-member-variables-in-classes", "-misc-redundant-expression", + "-misc-unused-parameters", "-misc-unused-using-decls", + "performance*", + "portability*", + ], +} + +cc_library_headers { + name: "libbinder_headers_platform_shared", + export_include_dirs: ["include_cpp"], + vendor_available: true, + host_supported: true, + // TODO(b/153609531): remove when no longer needed. + native_bridge_supported: true, + target: { + darwin: { + enabled: false, + }, + }, + apex_available: [ + "//apex_available:platform", + "com.android.media", + "com.android.media.swcodec", ], + min_sdk_version: "29", } ndk_headers { diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp index 350c6585a2..0f59de4309 100644 --- a/libs/binder/ndk/ibinder.cpp +++ b/libs/binder/ndk/ibinder.cpp @@ -181,7 +181,7 @@ status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parce binder_status_t status = getClass()->onTransact(this, code, &in, &out); return PruneStatusT(status); - } else if (code == SHELL_COMMAND_TRANSACTION && getClass()->handleShellCommand != nullptr) { + } else if (code == SHELL_COMMAND_TRANSACTION) { int in = data.readFileDescriptor(); int out = data.readFileDescriptor(); int err = data.readFileDescriptor(); @@ -301,6 +301,26 @@ AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) { return binder.get(); } +AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak) { + if (weak == nullptr) { + return nullptr; + } + + return new AIBinder_Weak{weak->binder}; +} + +bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs) { + if (lhs == nullptr || rhs == nullptr) return lhs < rhs; + + return const_cast<AIBinder*>(lhs)->getBinder() < const_cast<AIBinder*>(rhs)->getBinder(); +} + +bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) { + if (lhs == nullptr || rhs == nullptr) return lhs < rhs; + + return lhs->binder < rhs->binder; +} + AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate, AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact) @@ -577,13 +597,6 @@ binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) { return STATUS_INVALID_OPERATION; } - if (!binder->isRemote()) { - LOG(WARNING) << "A binder object at " << binder - << " is being transacted on, however, this object is in the same process as " - "its proxy. Transacting with this binder is expensive compared to just " - "calling the corresponding functionality in the same process."; - } - *in = new AParcel(binder); status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor()); binder_status_t ret = PruneStatusT(status); diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h index 6824306fbf..22cacb4e08 100644 --- a/libs/binder/ndk/ibinder_internal.h +++ b/libs/binder/ndk/ibinder_internal.h @@ -116,13 +116,13 @@ struct AIBinder_Class { const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); } // required to be non-null, implemented for every class - const AIBinder_Class_onCreate onCreate = nullptr; - const AIBinder_Class_onDestroy onDestroy = nullptr; - const AIBinder_Class_onTransact onTransact = nullptr; + const AIBinder_Class_onCreate onCreate; + const AIBinder_Class_onDestroy onDestroy; + const AIBinder_Class_onTransact onTransact; // optional methods for a class - AIBinder_onDump onDump = nullptr; - AIBinder_handleShellCommand handleShellCommand = nullptr; + AIBinder_onDump onDump; + AIBinder_handleShellCommand handleShellCommand; private: // Copy of the raw char string for when we don't have to return UTF-16 diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h index 53871f28a2..0ad400bffb 100644 --- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h @@ -259,10 +259,24 @@ class ScopedAStatus : public impl::ScopedAResource<AStatus*, AStatus_delete, nul const char* getMessage() const { return AStatus_getMessage(get()); } std::string getDescription() const { - const char* cStr = AStatus_getDescription(get()); - std::string ret = cStr; - AStatus_deleteDescription(cStr); - return ret; + if (__builtin_available(android 30, *)) { + const char* cStr = AStatus_getDescription(get()); + std::string ret = cStr; + AStatus_deleteDescription(cStr); + return ret; + } + binder_exception_t exception = getExceptionCode(); + std::string desc = std::to_string(exception); + if (exception == EX_SERVICE_SPECIFIC) { + desc += " (" + std::to_string(getServiceSpecificError()) + ")"; + } else if (exception == EX_TRANSACTION_FAILED) { + desc += " (" + std::to_string(getStatus()) + ")"; + } + if (const char* msg = getMessage(); msg != nullptr) { + desc += ": "; + desc += msg; + } + return desc; } /** diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h index a4f444192d..05eb64be2c 100644 --- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h @@ -83,7 +83,8 @@ class SharedRefBase { template <class T, class... Args> static std::shared_ptr<T> make(Args&&... args) { T* t = new T(std::forward<Args>(args)...); - return t->template ref<T>(); + // warning: Potential leak of memory pointed to by 't' [clang-analyzer-unix.Malloc] + return t->template ref<T>(); // NOLINT(clang-analyzer-unix.Malloc) } static void operator delete(void* p) { std::free(p); } @@ -246,7 +247,7 @@ AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor, // ourselves. The defaults are harmless. AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump); #ifdef HAS_BINDER_SHELL_COMMAND - if (AIBinder_Class_setHandleShellCommand != nullptr) { + if (__builtin_available(android 30, *)) { AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand); } #endif diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h index 6636a416e2..2277148285 100644 --- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h @@ -51,14 +51,27 @@ class AParcelableHolder { binder_status_t writeToParcel(AParcel* parcel) const { RETURN_ON_FAILURE(AParcel_writeInt32(parcel, static_cast<int32_t>(this->mStability))); - RETURN_ON_FAILURE(AParcel_writeInt32(parcel, AParcel_getDataSize(this->mParcel.get()))); - RETURN_ON_FAILURE(AParcel_appendFrom(this->mParcel.get(), parcel, 0, - AParcel_getDataSize(this->mParcel.get()))); + if (__builtin_available(android 31, *)) { + int32_t size = AParcel_getDataSize(this->mParcel.get()); + RETURN_ON_FAILURE(AParcel_writeInt32(parcel, size)); + } else { + return STATUS_INVALID_OPERATION; + } + if (__builtin_available(android 31, *)) { + int32_t size = AParcel_getDataSize(this->mParcel.get()); + RETURN_ON_FAILURE(AParcel_appendFrom(this->mParcel.get(), parcel, 0, size)); + } else { + return STATUS_INVALID_OPERATION; + } return STATUS_OK; } binder_status_t readFromParcel(const AParcel* parcel) { - AParcel_reset(mParcel.get()); + if (__builtin_available(android 31, *)) { + AParcel_reset(mParcel.get()); + } else { + return STATUS_INVALID_OPERATION; + } RETURN_ON_FAILURE(AParcel_readInt32(parcel, &this->mStability)); int32_t dataSize; @@ -74,7 +87,11 @@ class AParcelableHolder { return STATUS_BAD_VALUE; } - status = AParcel_appendFrom(parcel, mParcel.get(), dataStartPos, dataSize); + if (__builtin_available(android 31, *)) { + status = AParcel_appendFrom(parcel, mParcel.get(), dataStartPos, dataSize); + } else { + status = STATUS_INVALID_OPERATION; + } if (status != STATUS_OK) { return status; } @@ -86,7 +103,11 @@ class AParcelableHolder { if (this->mStability > T::_aidl_stability) { return STATUS_BAD_VALUE; } - AParcel_reset(mParcel.get()); + if (__builtin_available(android 31, *)) { + AParcel_reset(mParcel.get()); + } else { + return STATUS_INVALID_OPERATION; + } AParcel_writeString(mParcel.get(), T::descriptor, strlen(T::descriptor)); p.writeToParcel(mParcel.get()); return STATUS_OK; @@ -96,9 +117,13 @@ class AParcelableHolder { binder_status_t getParcelable(std::optional<T>* ret) const { const std::string parcelableDesc(T::descriptor); AParcel_setDataPosition(mParcel.get(), 0); - if (AParcel_getDataSize(mParcel.get()) == 0) { - *ret = std::nullopt; - return STATUS_OK; + if (__builtin_available(android 31, *)) { + if (AParcel_getDataSize(mParcel.get()) == 0) { + *ret = std::nullopt; + return STATUS_OK; + } + } else { + return STATUS_INVALID_OPERATION; } std::string parcelableDescInParcel; binder_status_t status = AParcel_readString(mParcel.get(), &parcelableDescInParcel); @@ -115,7 +140,11 @@ class AParcelableHolder { return STATUS_OK; } - void reset() { AParcel_reset(mParcel.get()); } + void reset() { + if (__builtin_available(android 31, *)) { + AParcel_reset(mParcel.get()); + } + } inline bool operator!=(const AParcelableHolder& rhs) const { return this != &rhs; } inline bool operator<(const AParcelableHolder& rhs) const { return this < &rhs; } diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h new file mode 100644 index 0000000000..ef71a81328 --- /dev/null +++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup NdkBinder + * @{ + */ + +/** + * @file binder_to_string.h + * @brief Helper for parcelable. + */ + +#pragma once + +#include <codecvt> +#include <locale> +#include <memory> +#include <optional> +#include <sstream> +#include <string> +#include <type_traits> + +#if __has_include(<utils/StrongPointer.h>) +#include <utils/StrongPointer.h> +#define HAS_STRONG_POINTER +#endif + +#if __has_include(<utils/String16.h>) +#include <utils/String16.h> +#define HAS_STRING16 +#endif + +#if __has_include(<android/binder_ibinder.h>) +#include <android/binder_auto_utils.h> +#include <android/binder_interface_utils.h> +#include <android/binder_parcelable_utils.h> +#define HAS_NDK_INTERFACE +#else +#include <binder/IBinder.h> +#include <binder/IInterface.h> +#include <binder/ParcelFileDescriptor.h> +#include <binder/ParcelableHolder.h> +#endif //_has_include + +namespace android { +namespace internal { + +// ToString is a utility to generate string representation for various AIDL-supported types. +template <typename _T> +std::string ToString(const _T& t); + +namespace details { + +// Truthy if _T has toString() method. +template <typename _T> +class HasToStringMethod { + template <typename _U> + static auto _test(int) -> decltype(std::declval<_U>().toString(), std::true_type()); + template <typename _U> + static std::false_type _test(...); + + public: + enum { value = decltype(_test<_T>(0))::value }; +}; + +// Truthy if _T has a overloaded toString(T) +template <typename _T> +class HasToStringFunction { + template <typename _U> + static auto _test(int) -> decltype(toString(std::declval<_U>()), std::true_type()); + template <typename _U> + static std::false_type _test(...); + + public: + enum { value = decltype(_test<_T>(0))::value }; +}; + +template <typename T, template <typename...> typename U> +struct IsInstantiationOf : std::false_type {}; + +template <template <typename...> typename U, typename... Args> +struct IsInstantiationOf<U<Args...>, U> : std::true_type {}; + +// Truthy if _T is like a pointer: one of sp/optional/shared_ptr +template <typename _T> +class IsPointerLike { + template <typename _U> + static std::enable_if_t< +#ifdef HAS_STRONG_POINTER + IsInstantiationOf<_U, sp>::value || // for IBinder and interface types in the C++ + // backend +#endif + IsInstantiationOf<_U, std::optional>::value || // for @nullable types in the + // C++/NDK backends + IsInstantiationOf<_U, std::shared_ptr>::value, // for interface types in the + // NDK backends + + std::true_type> + _test(int); + template <typename _U> + static std::false_type _test(...); + + public: + enum { value = decltype(_test<_T>(0))::value }; +}; + +// Truthy if _T is like a container +template <typename _T> +class IsIterable { + template <typename _U> + static auto _test(int) + -> decltype(begin(std::declval<_U>()), end(std::declval<_U>()), std::true_type()); + template <typename _U> + static std::false_type _test(...); + + public: + enum { value = decltype(_test<_T>(0))::value }; +}; + +template <typename _T> +class ToEmptyString { + template <typename _U> + static std::enable_if_t< +#ifdef HAS_NDK_INTERFACE + std::is_base_of_v<::ndk::ICInterface, _U> || + std::is_same_v<::ndk::AParcelableHolder, _U> +#else + std::is_base_of_v<IInterface, _U> || std::is_same_v<IBinder, _U> || + std::is_same_v<os::ParcelFileDescriptor, _U> || + std::is_same_v<os::ParcelableHolder, _U> +#endif + , + std::true_type> + _test(int); + template <typename _U> + static std::false_type _test(...); + + public: + enum { value = decltype(_test<_T>(0))::value }; +}; + +} // namespace details + +template <typename _T> +std::string ToString(const _T& t) { + if constexpr (details::ToEmptyString<_T>::value) { + return ""; + } else if constexpr (std::is_same_v<bool, _T>) { + return t ? "true" : "false"; + } else if constexpr (std::is_same_v<char16_t, _T>) { + return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t); + } else if constexpr (std::is_arithmetic_v<_T>) { + return std::to_string(t); + } else if constexpr (std::is_same_v<std::string, _T>) { + return t; +#ifdef HAS_NDK_INTERFACE + } else if constexpr (std::is_same_v<::ndk::SpAIBinder, _T>) { + return (t.get() == nullptr) ? "(null)" : ""; + } else if constexpr (std::is_same_v<::ndk::ScopedFileDescriptor, _T>) { + return (t.get() == -1) ? "(null)" : ""; +#endif +#ifdef HAS_STRING16 + } else if constexpr (std::is_same_v<String16, _T>) { + std::stringstream out; + out << t; + return out.str(); +#endif + } else if constexpr (details::IsPointerLike<_T>::value || std::is_pointer_v<_T>) { + if (!t) return "(null)"; + std::stringstream out; + out << ToString(*t); + return out.str(); + } else if constexpr (details::HasToStringMethod<_T>::value) { + return t.toString(); + } else if constexpr (details::HasToStringFunction<_T>::value) { + return toString(t); + } else if constexpr (details::IsIterable<_T>::value) { + std::stringstream out; + bool first = true; + out << "["; + for (const auto& e : t) { + if (first) { + first = false; + } else { + out << ", "; + } + // Use explicit type parameter in case deref of iterator has different type + // e.g. vector<bool> + out << ToString<typename _T::value_type>(e); + } + out << "]"; + return out.str(); + } else { + return "{no toString() implemented}"; + } +} + +} // namespace internal +} // namespace android + +/** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h index 5e1ed4689d..a44c261b3b 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h @@ -41,8 +41,6 @@ __BEGIN_DECLS android platform host build, you must use libbinder_ndk_host_user. #endif -#if __ANDROID_API__ >= 29 - typedef uint32_t binder_flags_t; enum { /** @@ -567,10 +565,6 @@ __attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecip */ void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29); -#endif //__ANDROID_API__ >= 29 - -#if __ANDROID_API__ >= 30 - /** * Gets the extension registered with AIBinder_setExtension. * @@ -640,10 +634,6 @@ binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INT */ binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30); -#endif //__ANDROID_API__ >= 30 - -#if __ANDROID_API__ >= 31 - /** * Retrieve the class descriptor for the class. * @@ -657,7 +647,76 @@ binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODU */ const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) __INTRODUCED_IN(31); -#endif //__ANDROID_API__ >= 31 +/** + * Whether AIBinder is less than another. + * + * This provides a per-process-unique total ordering of binders where a null + * AIBinder* object is considered to be before all other binder objects. + * For instance, two binders refer to the same object in a local or remote + * process when both AIBinder_lt(a, b) and AIBinder(b, a) are false. This API + * might be used to insert and lookup binders in binary search trees. + * + * AIBinder* pointers themselves actually also create a per-process-unique total + * ordering. However, this ordering is inconsistent with AIBinder_Weak_lt for + * remote binders. So, in general, this function should be preferred. + * + * Available since API level 31. + * + * \param lhs comparison object + * \param rhs comparison object + * + * \return whether "lhs < rhs" is true + */ +bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs); + +/** + * Clone an AIBinder_Weak. Useful because even if a weak binder promotes to a + * null value, after further binder transactions, it may no longer promote to a + * null value. + * + * Available since API level 31. + * + * \param weak Object to clone + * + * \return clone of the input parameter. This must be deleted with + * AIBinder_Weak_delete. Null if weak input parameter is also null. + */ +AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak); + +/** + * Whether AIBinder_Weak is less than another. + * + * This provides a per-process-unique total ordering of binders which is exactly + * the same as AIBinder_lt. Similarly, a null AIBinder_Weak* is considered to be + * ordered before all other weak references. + * + * This function correctly distinguishes binders even if one is deallocated. So, + * for instance, an AIBinder_Weak* entry representing a deleted binder will + * never compare as equal to an AIBinder_Weak* entry which represents a + * different allocation of a binder, even if the two binders were originally + * allocated at the same address. That is: + * + * AIBinder* a = ...; // imagine this has address 0x8 + * AIBinder_Weak* bWeak = AIBinder_Weak_new(a); + * AIBinder_decStrong(a); // a may be deleted, if this is the last reference + * AIBinder* b = ...; // imagine this has address 0x8 (same address as b) + * AIBinder_Weak* bWeak = AIBinder_Weak_new(b); + * + * Then when a/b are compared with other binders, their order will be preserved, + * and it will either be the case that AIBinder_Weak_lt(aWeak, bWeak) OR + * AIBinder_Weak_lt(bWeak, aWeak), but not both. + * + * Unlike AIBinder*, the AIBinder_Weak* addresses themselves have nothing to do + * with the underlying binder. + * + * Available since API level 31. + * + * \param lhs comparison object + * \param rhs comparison object + * + * \return whether "lhs < rhs" is true + */ +bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs); __END_DECLS diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h index cd1ff1fd79..6880d86e1a 100644 --- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h +++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h @@ -31,7 +31,6 @@ #include <jni.h> __BEGIN_DECLS -#if __ANDROID_API__ >= 29 /** * Converts an android.os.IBinder object into an AIBinder* object. @@ -67,7 +66,6 @@ __attribute__((warn_unused_result)) AIBinder* AIBinder_fromJavaBinder(JNIEnv* en __attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) __INTRODUCED_IN(29); -#endif //__ANDROID_API__ >= 29 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h index 93c3f32100..527b151457 100644 --- a/libs/binder/ndk/include_ndk/android/binder_parcel.h +++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h @@ -36,7 +36,6 @@ struct AIBinder; typedef struct AIBinder AIBinder; __BEGIN_DECLS -#if __ANDROID_API__ >= 29 /** * This object represents a package of data that can be sent between processes. When transacting, an @@ -1119,8 +1118,6 @@ binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData, // @END-PRIMITIVE-READ-WRITE -#endif //__ANDROID_API__ >= 29 -#if __ANDROID_API__ >= 31 /** * Reset the parcel to the initial status. * @@ -1166,7 +1163,6 @@ binder_status_t AParcel_appendFrom(const AParcel* from, AParcel* to, int32_t sta * \return A parcel which is not related to any IBinder objects. */ AParcel* AParcel_create() __INTRODUCED_IN(31); -#endif //__ANDROID_API__ >= 31 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h index 65e1704439..384d4f7772 100644 --- a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h +++ b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h @@ -31,7 +31,6 @@ #include <jni.h> __BEGIN_DECLS -#if __ANDROID_API__ >= 30 /** * Converts an android.os.Parcel object into an AParcel* object. @@ -50,7 +49,6 @@ __BEGIN_DECLS __attribute__((warn_unused_result)) AParcel* AParcel_fromJavaParcel(JNIEnv* env, jobject parcel) __INTRODUCED_IN(30); -#endif //__ANDROID_API__ >= 30 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h index 3a55f9480c..05b25e7c40 100644 --- a/libs/binder/ndk/include_ndk/android/binder_status.h +++ b/libs/binder/ndk/include_ndk/android/binder_status.h @@ -31,7 +31,6 @@ #include <sys/cdefs.h> __BEGIN_DECLS -#if __ANDROID_API__ >= 29 enum { STATUS_OK = 0, @@ -275,7 +274,6 @@ void AStatus_deleteDescription(const char* description) __INTRODUCED_IN(30); */ void AStatus_delete(AStatus* status) __INTRODUCED_IN(29); -#endif //__ANDROID_API__ >= 29 __END_DECLS /** @} */ diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 2784aa823d..5df0012bd3 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -31,7 +31,8 @@ __BEGIN_DECLS * * \return EX_NONE on success. */ -binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance); +__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addService( + AIBinder* binder, const char* instance); /** * Gets a binder object with this specific instance name. Will return nullptr immediately if the @@ -94,4 +95,68 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(con */ bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31); +/** + * Returns all declared instances for a particular interface. + * + * For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo' is + * passed here, then ["foo"] would be returned. + * + * See also AServiceManager_isDeclared. + * + * \param interface interface, e.g. 'android.foo.IFoo' + * \param context to pass to callback + * \param callback taking instance (e.g. 'foo') and context + */ +void AServiceManager_forEachDeclaredInstance(const char* interface, void* context, + void (*callback)(const char*, void*)) + __INTRODUCED_IN(31); + +/** + * Prevent lazy services without client from shutting down their process + * + * \param persist 'true' if the process should not exit. + */ +void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31); + +/** + * Set a callback that is invoked when the active service count (i.e. services with clients) + * registered with this process drops to zero (or becomes nonzero). + * The callback takes a boolean argument, which is 'true' if there is + * at least one service with clients. + * + * \param callback function to call when the number of services + * with clients changes. + * \param context opaque pointer passed back as second parameter to the + * callback. + * + * The callback takes two arguments. The first is a boolean that represents if there are + * services with clients (true) or not (false). + * The second is the 'context' pointer passed during the registration. + * + * Callback return value: + * - false: Default behavior for lazy services (shut down the process if there + * are no clients). + * - true: Don't shut down the process even if there are no clients. + * + * This callback gives a chance to: + * 1 - Perform some additional operations before exiting; + * 2 - Prevent the process from exiting by returning "true" from the callback. + */ +void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) + __INTRODUCED_IN(31); + +/** + * Try to unregister all services previously registered with 'registerService'. + * + * \return true on success. + */ +bool AServiceManager_tryUnregister() __INTRODUCED_IN(31); + +/** + * Re-register services that were unregistered by 'tryUnregister'. + * This method should be called in the case 'tryUnregister' fails + * (and should be called on the same thread). + */ +void AServiceManager_reRegister() __INTRODUCED_IN(31); + __END_DECLS diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index e233ffd9b4..8d08275eec 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -118,10 +118,18 @@ LIBBINDER_NDK31 { # introduced=31 AIBinder_getCallingSid; # apex AIBinder_setRequestingSid; # apex AServiceManager_isDeclared; # apex llndk + AServiceManager_forEachDeclaredInstance; # apex llndk AServiceManager_registerLazyService; # llndk AServiceManager_waitForService; # apex llndk + AServiceManager_forceLazyServicesPersist; # llndk + AServiceManager_setActiveServicesCallback; # llndk + AServiceManager_tryUnregister; # llndk + AServiceManager_reRegister; # llndk AIBinder_Class_getDescriptor; + AIBinder_Weak_clone; + AIBinder_Weak_lt; + AIBinder_lt; AParcel_appendFrom; AParcel_create; AParcel_getDataSize; diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index c782d47c1c..1ccd0d2a2b 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -19,6 +19,7 @@ #include "ibinder_internal.h" #include "status_internal.h" +#include <android-base/logging.h> #include <binder/IServiceManager.h> #include <binder/LazyServiceRegistrar.h> @@ -28,6 +29,7 @@ using ::android::IServiceManager; using ::android::sp; using ::android::status_t; using ::android::String16; +using ::android::String8; binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance) { if (binder == nullptr || instance == nullptr) { @@ -92,3 +94,33 @@ bool AServiceManager_isDeclared(const char* instance) { sp<IServiceManager> sm = defaultServiceManager(); return sm->isDeclared(String16(instance)); } +void AServiceManager_forEachDeclaredInstance(const char* interface, void* context, + void (*callback)(const char*, void*)) { + CHECK(interface != nullptr); + // context may be nullptr + CHECK(callback != nullptr); + + sp<IServiceManager> sm = defaultServiceManager(); + for (const String16& instance : sm->getDeclaredInstances(String16(interface))) { + callback(String8(instance).c_str(), context); + } +} +void AServiceManager_forceLazyServicesPersist(bool persist) { + auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); + serviceRegistrar.forcePersist(persist); +} +void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) { + auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); + std::function<bool(bool)> fn = [=](bool hasClients) -> bool { + return callback(hasClients, context); + }; + serviceRegistrar.setActiveServicesCallback(fn); +} +bool AServiceManager_tryUnregister() { + auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); + return serviceRegistrar.tryUnregister(); +} +void AServiceManager_reRegister() { + auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance(); + serviceRegistrar.reRegister(); +} diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp index 46e6270eb0..bb51bf0b5d 100644 --- a/libs/binder/ndk/tests/Android.bp +++ b/libs/binder/ndk/tests/Android.bp @@ -14,6 +14,15 @@ * limitations under the License. */ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_libs_binder_ndk_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"], +} + cc_defaults { name: "test_libbinder_ndk_defaults", shared_libs: [ diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl index dc77467d8c..ecbd6490e9 100644 --- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl +++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl @@ -28,4 +28,7 @@ interface IBinderNdkUnitTest { void forceFlushCommands(); boolean getsRequestedSid(); + + void forcePersist(boolean persist); + void setCustomActiveServicesCallback(); } diff --git a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp index ad78e319a2..f3cd21822d 100644 --- a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp +++ b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp @@ -163,7 +163,8 @@ int main(int argc, char** argv) { // LOCAL SERVERS std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>(); - AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str()); + CHECK(STATUS_OK == + AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str())); return RUN_ALL_TESTS(); } diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp index 2afe5d2058..53b5c3c320 100644 --- a/libs/binder/ndk/tests/iface.cpp +++ b/libs/binder/ndk/tests/iface.cpp @@ -118,7 +118,7 @@ IFoo::~IFoo() { AIBinder_Weak_delete(mWeakBinder); } -AIBinder* IFoo::getBinder() { +binder_status_t IFoo::addService(const char* instance) { AIBinder* binder = nullptr; if (mWeakBinder != nullptr) { @@ -132,18 +132,8 @@ AIBinder* IFoo::getBinder() { AIBinder_Weak_delete(mWeakBinder); } mWeakBinder = AIBinder_Weak_new(binder); - - // WARNING: it is important that this class does not implement debug or - // shell functions because it does not use special C++ wrapper - // functions, and so this is how we test those functions. } - return binder; -} - -binder_status_t IFoo::addService(const char* instance) { - AIBinder* binder = getBinder(); - binder_status_t status = AServiceManager_addService(binder, instance); // Strong references we care about kept by remote process AIBinder_decStrong(binder); diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h index 7408d0c5a9..244c9857ac 100644 --- a/libs/binder/ndk/tests/include/iface/iface.h +++ b/libs/binder/ndk/tests/include/iface/iface.h @@ -31,9 +31,6 @@ class IFoo : public virtual ::android::RefBase { static AIBinder_Class* kClass; - // binder representing this interface with one reference count - AIBinder* getBinder(); - // Takes ownership of IFoo binder_status_t addService(const char* instance); static ::android::sp<IFoo> getService(const char* instance, AIBinder** outBinder = nullptr); diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index b7df115819..496a915f8b 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -46,6 +46,11 @@ using namespace android; constexpr char kExistingNonNdkService[] = "SurfaceFlinger"; constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest"; constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest"; +constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService"; +constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService"; + +constexpr unsigned int kShutdownWaitTime = 10; +constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715; class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { @@ -76,6 +81,46 @@ class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { fsync(out); return STATUS_OK; } + ndk::ScopedAStatus forcePersist(bool persist) { + AServiceManager_forceLazyServicesPersist(persist); + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus setCustomActiveServicesCallback() { + AServiceManager_setActiveServicesCallback(activeServicesCallback, this); + return ndk::ScopedAStatus::ok(); + } + static bool activeServicesCallback(bool hasClients, void* context) { + if (hasClients) { + return false; + } + + // Unregister all services + if (!AServiceManager_tryUnregister()) { + // Prevent shutdown (test will fail) + return false; + } + + // Re-register all services + AServiceManager_reRegister(); + + // Unregister again before shutdown + if (!AServiceManager_tryUnregister()) { + // Prevent shutdown (test will fail) + return false; + } + + // Check if the context was passed correctly + MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context); + if (service->contextTestValue != kContextTestValue) { + // Prevent shutdown (test will fail) + return false; + } + + exit(EXIT_SUCCESS); + // Unreachable + } + + uint64_t contextTestValue = kContextTestValue; }; int generatedService() { @@ -168,6 +213,16 @@ int lazyService(const char* instance) { return 1; // should not return } +bool isServiceRunning(const char* serviceName) { + AIBinder* binder = AServiceManager_checkService(serviceName); + if (binder == nullptr) { + return false; + } + AIBinder_decStrong(binder); + + return true; +} + TEST(NdkBinder, GetServiceThatDoesntExist) { sp<IFoo> foo = IFoo::getService("asdfghkl;"); EXPECT_EQ(nullptr, foo.get()); @@ -186,26 +241,6 @@ TEST(NdkBinder, CheckServiceThatDoesExist) { AIBinder_decStrong(binder); } -TEST(NdkBinder, UnimplementedDump) { - sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName); - ASSERT_NE(foo, nullptr); - AIBinder* binder = foo->getBinder(); - EXPECT_EQ(OK, AIBinder_dump(binder, STDOUT_FILENO, nullptr, 0)); - AIBinder_decStrong(binder); -} - -TEST(NdkBinder, UnimplementedShell) { - // libbinder_ndk doesn't support calling shell, so we are calling from the - // libbinder across processes to the NDK service which doesn't implement - // shell - static const sp<android::IServiceManager> sm(android::defaultServiceManager()); - sp<IBinder> testService = sm->getService(String16(IFoo::kSomeInstanceName)); - - Vector<String16> argsVec; - EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, - argsVec, nullptr, nullptr)); -} - TEST(NdkBinder, DoubleNumber) { sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName); ASSERT_NE(foo, nullptr); @@ -215,6 +250,25 @@ TEST(NdkBinder, DoubleNumber) { EXPECT_EQ(2, out); } +void defaultInstanceCounter(const char* instance, void* context) { + if (strcmp(instance, "default") == 0) { + ++*(size_t*)(context); + } +} + +TEST(NdkBinder, GetDeclaredInstances) { + bool hasLight = AServiceManager_isDeclared("android.hardware.light.ILights/default"); + + size_t count; + AServiceManager_forEachDeclaredInstance("android.hardware.light.ILights", &count, + defaultInstanceCounter); + + // At the time of writing this test, there is no good interface guaranteed + // to be on all devices. Cuttlefish has light, so this will generally test + // things. + EXPECT_EQ(count, hasLight ? 1 : 0); +} + TEST(NdkBinder, GetLazyService) { // Not declared in the vintf manifest ASSERT_FALSE(AServiceManager_isDeclared(kLazyBinderNdkUnitTestService)); @@ -238,10 +292,51 @@ TEST(NdkBinder, CheckLazyServiceShutDown) { service = nullptr; IPCThreadState::self()->flushCommands(); // Make sure the service is dead after some time of no use - sleep(10); + sleep(kShutdownWaitTime); ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService)); } +TEST(NdkBinder, ForcedPersistenceTest) { + for (int i = 0; i < 2; i++) { + ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService)); + std::shared_ptr<aidl::IBinderNdkUnitTest> service = + aidl::IBinderNdkUnitTest::fromBinder(binder); + ASSERT_NE(service, nullptr); + ASSERT_TRUE(service->forcePersist(i == 0).isOk()); + + binder = nullptr; + service = nullptr; + IPCThreadState::self()->flushCommands(); + + sleep(kShutdownWaitTime); + + bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService); + + if (i == 0) { + ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have."; + } else { + ASSERT_FALSE(isRunning) << "Service failed to shut down."; + } + } +} + +TEST(NdkBinder, ActiveServicesCallbackTest) { + ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService)); + std::shared_ptr<aidl::IBinderNdkUnitTest> service = + aidl::IBinderNdkUnitTest::fromBinder(binder); + ASSERT_NE(service, nullptr); + ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk()); + + binder = nullptr; + service = nullptr; + IPCThreadState::self()->flushCommands(); + + sleep(kShutdownWaitTime); + + ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService)) + << "Service failed to shut down."; +} + void LambdaOnDeath(void* cookie) { auto onDeath = static_cast<std::function<void(void)>*>(cookie); (*onDeath)(); @@ -375,8 +470,7 @@ TEST(NdkBinder, ABpBinderRefCount) { AIBinder_decStrong(binder); - // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here - ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder)); + ASSERT_EQ(nullptr, AIBinder_Weak_promote(wBinder)); AIBinder_Weak_delete(wBinder); } @@ -565,10 +659,18 @@ int main(int argc, char* argv[]) { } if (fork() == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); + return lazyService(kForcePersistNdkUnitTestService); + } + if (fork() == 0) { + prctl(PR_SET_PDEATHSIG, SIGHUP); + return lazyService(kActiveServicesNdkUnitTestService); + } + if (fork() == 0) { + prctl(PR_SET_PDEATHSIG, SIGHUP); return generatedService(); } - ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications/callbacks + ABinderProcess_setThreadPoolMaxThreadCount(1); // to receive death notifications/callbacks ABinderProcess_startThreadPool(); return RUN_ALL_TESTS(); diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/parcel_fuzzer/Android.bp index 3e6fe99541..74b8eb8d93 100644 --- a/libs/binder/parcel_fuzzer/Android.bp +++ b/libs/binder/parcel_fuzzer/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_fuzz { name: "binder_parcel_fuzzer", defaults: ["libbinder_ndk_host_user"], diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index fd5f2f5d9c..e12a429cf9 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + rust_library { name: "libbinder_rs", crate_name: "binder", @@ -14,7 +23,11 @@ rust_library { darwin: { enabled: false, } - } + }, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], } rust_library { @@ -32,7 +45,11 @@ rust_library { darwin: { enabled: false, } - } + }, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], } rust_bindgen { @@ -78,6 +95,10 @@ rust_bindgen { enabled: false, }, }, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], } rust_test { diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index ed3b9ec5c3..d53a88f726 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -16,12 +16,17 @@ //! Trait definitions for binder objects -use crate::error::{status_t, Result}; +use crate::error::{status_t, Result, StatusCode}; use crate::parcel::Parcel; -use crate::proxy::{DeathRecipient, SpIBinder}; +use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder}; use crate::sys; +use std::borrow::Borrow; +use std::cmp::Ordering; use std::ffi::{c_void, CStr, CString}; +use std::fmt; +use std::marker::PhantomData; +use std::ops::Deref; use std::os::raw::c_char; use std::os::unix::io::AsRawFd; use std::ptr; @@ -44,7 +49,7 @@ pub type TransactionFlags = u32; /// interfaces) must implement this trait. /// /// This is equivalent `IInterface` in C++. -pub trait Interface { +pub trait Interface: Send { /// Convert this binder object into a generic [`SpIBinder`] reference. fn as_binder(&self) -> SpIBinder { panic!("This object was not a Binder object and cannot be converted into an SpIBinder.") @@ -230,6 +235,132 @@ impl From<InterfaceClass> for *const sys::AIBinder_Class { } } +/// Strong reference to a binder object +pub struct Strong<I: FromIBinder + ?Sized>(Box<I>); + +impl<I: FromIBinder + ?Sized> Strong<I> { + /// Create a new strong reference to the provided binder object + pub fn new(binder: Box<I>) -> Self { + Self(binder) + } + + /// Construct a new weak reference to this binder + pub fn downgrade(this: &Strong<I>) -> Weak<I> { + Weak::new(this) + } +} + +impl<I: FromIBinder + ?Sized> Clone for Strong<I> { + fn clone(&self) -> Self { + // Since we hold a strong reference, we should always be able to create + // a new strong reference to the same interface type, so try_from() + // should never fail here. + FromIBinder::try_from(self.0.as_binder()).unwrap() + } +} + +impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> { + fn borrow(&self) -> &I { + &self.0 + } +} + +impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> { + fn as_ref(&self) -> &I { + &self.0 + } +} + +impl<I: FromIBinder + ?Sized> Deref for Strong<I> { + type Target = I; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +impl<I: FromIBinder + ?Sized> Ord for Strong<I> { + fn cmp(&self, other: &Self) -> Ordering { + self.0.as_binder().cmp(&other.0.as_binder()) + } +} + +impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.0.as_binder().partial_cmp(&other.0.as_binder()) + } +} + +impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> { + fn eq(&self, other: &Self) -> bool { + self.0.as_binder().eq(&other.0.as_binder()) + } +} + +impl<I: FromIBinder + ?Sized> Eq for Strong<I> {} + +/// Weak reference to a binder object +#[derive(Debug)] +pub struct Weak<I: FromIBinder + ?Sized> { + weak_binder: WpIBinder, + interface_type: PhantomData<I>, +} + +impl<I: FromIBinder + ?Sized> Weak<I> { + /// Construct a new weak reference from a strong reference + fn new(binder: &Strong<I>) -> Self { + let weak_binder = binder.as_binder().downgrade(); + Weak { + weak_binder, + interface_type: PhantomData, + } + } + + /// Upgrade this weak reference to a strong reference if the binder object + /// is still alive + pub fn upgrade(&self) -> Result<Strong<I>> { + self.weak_binder + .promote() + .ok_or(StatusCode::DEAD_OBJECT) + .and_then(FromIBinder::try_from) + } +} + +impl<I: FromIBinder + ?Sized> Clone for Weak<I> { + fn clone(&self) -> Self { + Self { + weak_binder: self.weak_binder.clone(), + interface_type: PhantomData, + } + } +} + +impl<I: FromIBinder + ?Sized> Ord for Weak<I> { + fn cmp(&self, other: &Self) -> Ordering { + self.weak_binder.cmp(&other.weak_binder) + } +} + +impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.weak_binder.partial_cmp(&other.weak_binder) + } +} + +impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> { + fn eq(&self, other: &Self) -> bool { + self.weak_binder == other.weak_binder + } +} + +impl<I: FromIBinder + ?Sized> Eq for Weak<I> {} + /// Create a function implementing a static getter for an interface class. /// /// Each binder interface (i.e. local [`Remotable`] service or remote proxy @@ -354,12 +485,12 @@ pub trait InterfaceClassMethods { /// } /// } /// ``` -pub trait FromIBinder { +pub trait FromIBinder: Interface { /// Try to interpret a generic Binder object as this interface. /// /// Returns a trait object for the `Self` interface if this object /// implements that interface. - fn try_from(ibinder: SpIBinder) -> Result<Box<Self>>; + fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>; } /// Trait for transparent Rust wrappers around android C++ native types. @@ -534,8 +665,9 @@ macro_rules! declare_binder_interface { impl $native { /// Create a new binder service. - pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> impl $interface { - $crate::Binder::new($native(Box::new(inner))) + pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> { + let binder = $crate::Binder::new($native(Box::new(inner))); + $crate::Strong::new(Box::new(binder)) } } @@ -577,7 +709,7 @@ macro_rules! declare_binder_interface { } impl $crate::FromIBinder for dyn $interface { - fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> { + fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> { use $crate::AssociateClass; let existing_class = ibinder.get_class(); @@ -590,7 +722,7 @@ macro_rules! declare_binder_interface { // associated object as remote, because we can't cast it // into a Rust service object without a matching class // pointer. - return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); + return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); } } @@ -600,10 +732,10 @@ macro_rules! declare_binder_interface { if let Ok(service) = service { // We were able to associate with our expected class and // the service is local. - return Ok(Box::new(service)); + return Ok($crate::Strong::new(Box::new(service))); } else { // Service is remote - return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); + return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); } } @@ -613,7 +745,7 @@ macro_rules! declare_binder_interface { impl $crate::parcel::Serialize for dyn $interface + '_ where - $interface: $crate::Interface + dyn $interface: $crate::Interface { fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { let binder = $crate::Interface::as_binder(self); @@ -633,9 +765,9 @@ macro_rules! declare_binder_interface { } } - // Convert a &dyn $interface to Box<dyn $interface> + /// Convert a &dyn $interface to Strong<dyn $interface> impl std::borrow::ToOwned for dyn $interface { - type Owned = Box<dyn $interface>; + type Owned = $crate::Strong<dyn $interface>; fn to_owned(&self) -> Self::Owned { self.as_binder().into_interface() .expect(concat!("Error cloning interface ", stringify!($interface))) diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs index 4492cf72f4..2598ebc804 100644 --- a/libs/binder/rust/src/error.rs +++ b/libs/binder/rust/src/error.rs @@ -77,9 +77,7 @@ fn parse_exception_code(code: i32) -> ExceptionCode { e if e == ExceptionCode::ILLEGAL_ARGUMENT as i32 => ExceptionCode::ILLEGAL_ARGUMENT, e if e == ExceptionCode::NULL_POINTER as i32 => ExceptionCode::NULL_POINTER, e if e == ExceptionCode::ILLEGAL_STATE as i32 => ExceptionCode::ILLEGAL_STATE, - e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => { - ExceptionCode::NETWORK_MAIN_THREAD - } + e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => ExceptionCode::NETWORK_MAIN_THREAD, e if e == ExceptionCode::UNSUPPORTED_OPERATION as i32 => { ExceptionCode::UNSUPPORTED_OPERATION } @@ -96,6 +94,16 @@ fn parse_exception_code(code: i32) -> ExceptionCode { /// Used in AIDL transactions to represent failed transactions. pub struct Status(*mut sys::AStatus); +// Safety: The `AStatus` that the `Status` points to must have an entirely thread-safe API for the +// duration of the `Status` object's lifetime. We ensure this by not allowing mutation of a `Status` +// in Rust, and the NDK API says we're the owner of our `AStatus` objects so outside code should not +// be mutating them underneath us. +unsafe impl Sync for Status {} + +// Safety: `Status` always contains an owning pointer to a global, immutable, interned `AStatus`. +// A thread-local `AStatus` would not be valid. +unsafe impl Send for Status {} + impl Status { /// Create a status object representing a successful transaction. pub fn ok() -> Self { diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index edfb56a26c..43a237abf9 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -107,7 +107,8 @@ use binder_ndk_sys as sys; pub mod parcel; pub use crate::binder::{ - FromIBinder, IBinder, Interface, InterfaceClass, Remotable, TransactionCode, TransactionFlags, + FromIBinder, IBinder, Interface, InterfaceClass, Remotable, Strong, TransactionCode, + TransactionFlags, Weak, }; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::add_service; @@ -122,7 +123,8 @@ pub mod public_api { pub use super::parcel::ParcelFileDescriptor; pub use super::{add_service, get_interface}; pub use super::{ - ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, WpIBinder, + ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, + Weak, WpIBinder, }; /// Binder result containing a [`Status`] on error. diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs index 138b360861..f57788b87e 100644 --- a/libs/binder/rust/src/parcel/parcelable.rs +++ b/libs/binder/rust/src/parcel/parcelable.rs @@ -14,16 +14,18 @@ * limitations under the License. */ -use crate::binder::{AsNative, FromIBinder}; -use crate::error::{status_result, Result, Status, StatusCode}; +use crate::binder::{AsNative, FromIBinder, Strong}; +use crate::error::{status_result, status_t, Result, Status, StatusCode}; use crate::parcel::Parcel; use crate::proxy::SpIBinder; use crate::sys; use std::convert::TryInto; use std::ffi::c_void; -use std::os::raw::c_char; +use std::os::raw::{c_char, c_ulong}; +use std::mem::{self, MaybeUninit}; use std::ptr; +use std::slice; /// A struct whose instances can be written to a [`Parcel`]. // Might be able to hook this up as a serde backend in the future? @@ -49,14 +51,44 @@ pub trait Deserialize: Sized { pub trait SerializeArray: Serialize + Sized { /// Serialize an array of this type into the given [`Parcel`]. fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> { - parcel.write_slice_size(Some(slice))?; + let res = unsafe { + // Safety: Safe FFI, slice will always be a safe pointer to pass. + sys::AParcel_writeParcelableArray( + parcel.as_native_mut(), + slice.as_ptr() as *const c_void, + slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?, + Some(serialize_element::<Self>), + ) + }; + status_result(res) + } +} - for item in slice { - parcel.write(item)?; - } +/// Callback to serialize an element of a generic parcelable array. +/// +/// Safety: We are relying on binder_ndk to not overrun our slice. As long as it +/// doesn't provide an index larger than the length of the original slice in +/// serialize_array, this operation is safe. The index provided is zero-based. +unsafe extern "C" fn serialize_element<T: Serialize>( + parcel: *mut sys::AParcel, + array: *const c_void, + index: c_ulong, +) -> status_t { + // c_ulong and usize are the same, but we need the explicitly sized version + // so the function signature matches what bindgen generates. + let index = index as usize; + + let slice: &[T] = slice::from_raw_parts(array.cast(), index+1); + + let mut parcel = match Parcel::borrowed(parcel) { + None => return StatusCode::UNEXPECTED_NULL as status_t, + Some(p) => p, + }; - Ok(()) - } + slice[index].serialize(&mut parcel) + .err() + .unwrap_or(StatusCode::OK) + as status_t } /// Helper trait for types that can be deserialized as arrays. @@ -65,20 +97,61 @@ pub trait SerializeArray: Serialize + Sized { pub trait DeserializeArray: Deserialize { /// Deserialize an array of type from the given [`Parcel`]. fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> { - let len: i32 = parcel.read()?; - if len < 0 { - return Ok(None); - } - - // TODO: Assumes that usize is at least 32 bits - let mut vec = Vec::with_capacity(len as usize); + let mut vec: Option<Vec<MaybeUninit<Self>>> = None; + let res = unsafe { + // Safety: Safe FFI, vec is the correct opaque type expected by + // allocate_vec and deserialize_element. + sys::AParcel_readParcelableArray( + parcel.as_native(), + &mut vec as *mut _ as *mut c_void, + Some(allocate_vec::<Self>), + Some(deserialize_element::<Self>), + ) + }; + status_result(res)?; + let vec: Option<Vec<Self>> = unsafe { + // Safety: We are assuming that the NDK correctly initialized every + // element of the vector by now, so we know that all the + // MaybeUninits are now properly initialized. We can transmute from + // Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T> has the same + // alignment and size as T, so the pointer to the vector allocation + // will be compatible. + mem::transmute(vec) + }; + Ok(vec) + } +} - for _ in 0..len { - vec.push(parcel.read()?); - } +/// Callback to deserialize a parcelable element. +/// +/// The opaque array data pointer must be a mutable pointer to an +/// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid +/// (zero-based). +unsafe extern "C" fn deserialize_element<T: Deserialize>( + parcel: *const sys::AParcel, + array: *mut c_void, + index: c_ulong, +) -> status_t { + // c_ulong and usize are the same, but we need the explicitly sized version + // so the function signature matches what bindgen generates. + let index = index as usize; + + let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>); + let vec = match vec { + Some(v) => v, + None => return StatusCode::BAD_INDEX as status_t, + }; - Ok(Some(vec)) - } + let parcel = match Parcel::borrowed(parcel as *mut _) { + None => return StatusCode::UNEXPECTED_NULL as status_t, + Some(p) => p, + }; + let element = match parcel.read() { + Ok(e) => e, + Err(code) => return code as status_t, + }; + ptr::write(vec[index].as_mut_ptr(), element); + StatusCode::OK as status_t } /// Helper trait for types that can be nullable when serialized. @@ -115,28 +188,54 @@ pub trait DeserializeOption: Deserialize { /// Callback to allocate a vector for parcel array read functions. /// +/// This variant is for APIs which use an out buffer pointer. +/// /// # Safety /// /// The opaque data pointer passed to the array read function must be a mutable -/// pointer to an `Option<Vec<T>>`. `buffer` will be assigned a mutable pointer +/// pointer to an `Option<Vec<MaybeUninit<T>>>`. `buffer` will be assigned a mutable pointer /// to the allocated vector data if this function returns true. -unsafe extern "C" fn allocate_vec<T: Clone + Default>( +unsafe extern "C" fn allocate_vec_with_buffer<T>( data: *mut c_void, len: i32, buffer: *mut *mut T, ) -> bool { - let vec = &mut *(data as *mut Option<Vec<T>>); + let res = allocate_vec::<T>(data, len); + let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>); + if let Some(new_vec) = vec { + *buffer = new_vec.as_mut_ptr() as *mut T; + } + res +} + +/// Callback to allocate a vector for parcel array read functions. +/// +/// # Safety +/// +/// The opaque data pointer passed to the array read function must be a mutable +/// pointer to an `Option<Vec<MaybeUninit<T>>>`. +unsafe extern "C" fn allocate_vec<T>( + data: *mut c_void, + len: i32, +) -> bool { + let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>); if len < 0 { *vec = None; return true; } - let mut new_vec: Vec<T> = Vec::with_capacity(len as usize); - new_vec.resize_with(len as usize, Default::default); - *buffer = new_vec.as_mut_ptr(); - *vec = Some(new_vec); + let mut new_vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len as usize); + + // Safety: We are filling the vector with uninitialized data here, but this + // is safe because the vector contains MaybeUninit elements which can be + // uninitialized. We're putting off the actual unsafe bit, transmuting the + // vector to a Vec<T> until the contents are initialized. + new_vec.set_len(len as usize); + + ptr::write(vec, Some(new_vec)); true } + macro_rules! parcelable_primitives { { $( @@ -204,19 +303,29 @@ macro_rules! impl_parcelable { {DeserializeArray, $ty:ty, $read_array_fn:path} => { impl DeserializeArray for $ty { fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> { - let mut vec: Option<Vec<Self>> = None; + let mut vec: Option<Vec<MaybeUninit<Self>>> = None; let status = unsafe { // Safety: `Parcel` always contains a valid pointer to an // `AParcel`. `allocate_vec<T>` expects the opaque pointer to - // be of type `*mut Option<Vec<T>>`, so `&mut vec` is + // be of type `*mut Option<Vec<MaybeUninit<T>>>`, so `&mut vec` is // correct for it. $read_array_fn( parcel.as_native(), &mut vec as *mut _ as *mut c_void, - Some(allocate_vec), + Some(allocate_vec_with_buffer), ) }; status_result(status)?; + let vec: Option<Vec<Self>> = unsafe { + // Safety: We are assuming that the NDK correctly + // initialized every element of the vector by now, so we + // know that all the MaybeUninits are now properly + // initialized. We can transmute from Vec<MaybeUninit<T>> to + // Vec<T> because MaybeUninit<T> has the same alignment and + // size as T, so the pointer to the vector allocation will + // be compatible. + mem::transmute(vec) + }; Ok(vec) } } @@ -414,7 +523,7 @@ impl Deserialize for Option<String> { sys::AParcel_readString( parcel.as_native(), &mut vec as *mut _ as *mut c_void, - Some(allocate_vec), + Some(allocate_vec_with_buffer), ) }; @@ -519,26 +628,26 @@ impl Deserialize for Status { } } -impl<T: Serialize + ?Sized> Serialize for Box<T> { +impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Serialize::serialize(&**self, parcel) } } -impl<T: SerializeOption + ?Sized> SerializeOption for Box<T> { +impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(this.map(|b| &**b), parcel) } } -impl<T: FromIBinder + ?Sized> Deserialize for Box<T> { +impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; FromIBinder::try_from(ibinder) } } -impl<T: FromIBinder + ?Sized> DeserializeOption for Box<T> { +impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { let ibinder: Option<SpIBinder> = parcel.read()?; ibinder.map(FromIBinder::try_from).transpose() diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs index 17af0992e2..132e0758e1 100644 --- a/libs/binder/rust/src/proxy.rs +++ b/libs/binder/rust/src/proxy.rs @@ -17,7 +17,7 @@ //! Rust API for interacting with a remote binder service. use crate::binder::{ - AsNative, FromIBinder, IBinder, Interface, InterfaceClass, TransactionCode, TransactionFlags, + AsNative, FromIBinder, IBinder, Interface, InterfaceClass, Strong, TransactionCode, TransactionFlags, }; use crate::error::{status_result, Result, StatusCode}; use crate::parcel::{ @@ -27,6 +27,7 @@ use crate::parcel::{ use crate::sys; use std::convert::TryInto; +use std::cmp::Ordering; use std::ffi::{c_void, CString}; use std::fmt; use std::os::unix::io::AsRawFd; @@ -70,6 +71,20 @@ impl SpIBinder { ptr.as_mut().map(|p| Self(p)) } + /// Extract a raw `AIBinder` pointer from this wrapper. + /// + /// This method should _only_ be used for testing. Do not try to use the NDK + /// interface directly for anything else. + /// + /// # Safety + /// + /// The resulting pointer is valid only as long as the SpIBinder is alive. + /// The SpIBinder object retains ownership of the AIBinder and the caller + /// should not attempt to free the returned pointer. + pub unsafe fn as_raw(&self) -> *mut sys::AIBinder { + self.0 + } + /// Return true if this binder object is hosted in a different process than /// the current one. pub fn is_remote(&self) -> bool { @@ -85,7 +100,7 @@ impl SpIBinder { /// /// If this object does not implement the expected interface, the error /// `StatusCode::BAD_TYPE` is returned. - pub fn into_interface<I: FromIBinder + ?Sized>(self) -> Result<Box<I>> { + pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> { FromIBinder::try_from(self) } @@ -134,6 +149,36 @@ impl AssociateClass for SpIBinder { } } +impl Ord for SpIBinder { + fn cmp(&self, other: &Self) -> Ordering { + let less_than = unsafe { + // Safety: SpIBinder always holds a valid `AIBinder` pointer, so + // this pointer is always safe to pass to `AIBinder_lt` (null is + // also safe to pass to this function, but we should never do that). + sys::AIBinder_lt(self.0, other.0) + }; + let greater_than = unsafe { + // Safety: SpIBinder always holds a valid `AIBinder` pointer, so + // this pointer is always safe to pass to `AIBinder_lt` (null is + // also safe to pass to this function, but we should never do that). + sys::AIBinder_lt(other.0, self.0) + }; + if !less_than && !greater_than { + Ordering::Equal + } else if less_than { + Ordering::Less + } else { + Ordering::Greater + } + } +} + +impl PartialOrd for SpIBinder { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + impl PartialEq for SpIBinder { fn eq(&self, other: &Self) -> bool { ptr::eq(self.0, other.0) @@ -312,7 +357,7 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { // Safety: `SpIBinder` guarantees that `self` always contains a // valid pointer to an `AIBinder`. `recipient` can always be // converted into a valid pointer to an - // `AIBinder_DeatRecipient`. Any value is safe to pass as the + // `AIBinder_DeathRecipient`. Any value is safe to pass as the // cookie, although we depend on this value being set by // `get_cookie` when the death recipient callback is called. sys::AIBinder_linkToDeath( @@ -328,7 +373,7 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { // Safety: `SpIBinder` guarantees that `self` always contains a // valid pointer to an `AIBinder`. `recipient` can always be // converted into a valid pointer to an - // `AIBinder_DeatRecipient`. Any value is safe to pass as the + // `AIBinder_DeathRecipient`. Any value is safe to pass as the // cookie, although we depend on this value being set by // `get_cookie` when the death recipient callback is called. sys::AIBinder_unlinkToDeath( @@ -416,6 +461,62 @@ impl WpIBinder { } } +impl Clone for WpIBinder { + fn clone(&self) -> Self { + let ptr = unsafe { + // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, + // so this pointer is always safe to pass to `AIBinder_Weak_clone` + // (although null is also a safe value to pass to this API). + // + // We get ownership of the returned pointer, so can construct a new + // WpIBinder object from it. + sys::AIBinder_Weak_clone(self.0) + }; + assert!(!ptr.is_null(), "Unexpected null pointer from AIBinder_Weak_clone"); + Self(ptr) + } +} + +impl Ord for WpIBinder { + fn cmp(&self, other: &Self) -> Ordering { + let less_than = unsafe { + // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, + // so this pointer is always safe to pass to `AIBinder_Weak_lt` + // (null is also safe to pass to this function, but we should never + // do that). + sys::AIBinder_Weak_lt(self.0, other.0) + }; + let greater_than = unsafe { + // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, + // so this pointer is always safe to pass to `AIBinder_Weak_lt` + // (null is also safe to pass to this function, but we should never + // do that). + sys::AIBinder_Weak_lt(other.0, self.0) + }; + if !less_than && !greater_than { + Ordering::Equal + } else if less_than { + Ordering::Less + } else { + Ordering::Greater + } + } +} + +impl PartialOrd for WpIBinder { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl PartialEq for WpIBinder { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for WpIBinder {} + impl Drop for WpIBinder { fn drop(&mut self) { unsafe { @@ -550,7 +651,7 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { /// Retrieve an existing service for a particular interface, blocking for a few /// seconds if it doesn't yet exist. -pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Box<T>> { +pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { let service = get_service(name); match service { Some(service) => FromIBinder::try_from(service), diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp index 5ae9c53077..0bf76c696a 100644 --- a/libs/binder/rust/tests/Android.bp +++ b/libs/binder/rust/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + rust_test { name: "rustBinderTest", srcs: ["integration.rs"], @@ -79,3 +88,50 @@ rust_ffi_static { "IBinderRustNdkInteropTest-rust", ], } + +cc_test { + name: "rustBinderSerializationTest", + shared_libs: [ + "libbinder", + "libbinder_ndk", + "libutils", + "libbase", + ], + static_libs: [ + "libbinder_rs_serialization_test" + ], + srcs: [ + "serialization.cpp", + ], + auto_gen_config: true, + test_suites: ["general-tests"], +} + +rust_bindgen { + name: "libbinder_rs_serialization_bindgen", + crate_name: "binder_rs_serialization_bindgen", + wrapper_src: "serialization.hpp", + source_stem: "bindings", + cpp_std: "gnu++17", + bindgen_flags: [ + "--whitelist-type", "Transaction", + "--whitelist-var", "TESTDATA_.*", + ], + + shared_libs: [ + "libbinder", + "libc++", + ], +} + +rust_ffi_static { + name: "libbinder_rs_serialization_test", + crate_name: "binder_rs_serialization_test", + srcs: [ + "serialization.rs", + ":libbinder_rs_serialization_bindgen", + ], + rustlibs: [ + "libbinder_rs", + ], +} diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index bb8c492bdb..719229c9b7 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -209,7 +209,7 @@ mod tests { use std::thread; use std::time::Duration; - use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode}; + use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode, Strong}; use super::{BnTest, ITest, ITestSameDescriptor, RUST_SERVICE_BINARY, TestService}; @@ -271,7 +271,7 @@ mod tests { fn trivial_client() { let service_name = "trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); - let test_client: Box<dyn ITest> = + let test_client: Strong<dyn ITest> = binder::get_interface(service_name).expect("Did not get manager binder service"); assert_eq!(test_client.test().unwrap(), "trivial_client_test"); } @@ -280,7 +280,7 @@ mod tests { fn get_selinux_context() { let service_name = "get_selinux_context"; let _process = ScopedServiceProcess::new(service_name); - let test_client: Box<dyn ITest> = + let test_client: Strong<dyn ITest> = binder::get_interface(service_name).expect("Did not get manager binder service"); let expected_context = unsafe { let mut out_ptr = ptr::null_mut(); @@ -453,7 +453,7 @@ mod tests { let extension = maybe_extension.expect("Remote binder did not have an extension"); - let extension: Box<dyn ITest> = FromIBinder::try_from(extension) + let extension: Strong<dyn ITest> = FromIBinder::try_from(extension) .expect("Extension could not be converted to the expected interface"); assert_eq!(extension.test().unwrap(), extension_name); @@ -479,7 +479,7 @@ mod tests { // This should succeed although we will have to treat the service as // remote. - let _interface: Box<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder()) + let _interface: Strong<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder()) .expect("Could not re-interpret service as the ITestSameDescriptor interface"); } @@ -490,9 +490,60 @@ mod tests { let service_ibinder = BnTest::new_binder(TestService { s: service_name.to_string() }) .as_binder(); - let service: Box<dyn ITest> = service_ibinder.into_interface() + let service: Strong<dyn ITest> = service_ibinder.into_interface() .expect("Could not reassociate the generic ibinder"); assert_eq!(service.test().unwrap(), service_name); } + + #[test] + fn weak_binder_upgrade() { + let service_name = "testing_service"; + let service = BnTest::new_binder(TestService { s: service_name.to_string() }); + + let weak = Strong::downgrade(&service); + + let upgraded = weak.upgrade().expect("Could not upgrade weak binder"); + + assert_eq!(service, upgraded); + } + + #[test] + fn weak_binder_upgrade_dead() { + let service_name = "testing_service"; + let weak = { + let service = BnTest::new_binder(TestService { s: service_name.to_string() }); + + Strong::downgrade(&service) + }; + + assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT)); + } + + #[test] + fn weak_binder_clone() { + let service_name = "testing_service"; + let service = BnTest::new_binder(TestService { s: service_name.to_string() }); + + let weak = Strong::downgrade(&service); + let cloned = weak.clone(); + assert_eq!(weak, cloned); + + let upgraded = weak.upgrade().expect("Could not upgrade weak binder"); + let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder"); + + assert_eq!(service, upgraded); + assert_eq!(service, clone_upgraded); + } + + #[test] + #[allow(clippy::eq_op)] + fn binder_ord() { + let service1 = BnTest::new_binder(TestService { s: "testing_service1".to_string() }); + let service2 = BnTest::new_binder(TestService { s: "testing_service2".to_string() }); + + assert!(!(service1 < service1)); + assert!(!(service1 > service1)); + assert_eq!(service1 < service2, !(service2 < service1)); + } } diff --git a/libs/binder/rust/tests/ndk_rust_interop.rs b/libs/binder/rust/tests/ndk_rust_interop.rs index 70a6dc0788..ce75ab7125 100644 --- a/libs/binder/rust/tests/ndk_rust_interop.rs +++ b/libs/binder/rust/tests/ndk_rust_interop.rs @@ -37,7 +37,7 @@ pub unsafe extern "C" fn rust_call_ndk(service_name: *const c_char) -> c_int { // The Rust class descriptor pointer will not match the NDK one, but the // descriptor strings match so this needs to still associate. - let service: Box<dyn IBinderRustNdkInteropTest> = match binder::get_interface(service_name) { + let service: binder::Strong<dyn IBinderRustNdkInteropTest> = match binder::get_interface(service_name) { Err(e) => { eprintln!("Could not find Ndk service {}: {:?}", service_name, e); return StatusCode::NAME_NOT_FOUND as c_int; @@ -53,7 +53,7 @@ pub unsafe extern "C" fn rust_call_ndk(service_name: *const c_char) -> c_int { } // Try using the binder service through the wrong interface type - let wrong_service: Result<Box<dyn IBinderRustNdkInteropTestOther>, StatusCode> = + let wrong_service: Result<binder::Strong<dyn IBinderRustNdkInteropTestOther>, StatusCode> = binder::get_interface(service_name); match wrong_service { Err(e) if e == StatusCode::BAD_TYPE => {} diff --git a/libs/binder/rust/tests/serialization.cpp b/libs/binder/rust/tests/serialization.cpp new file mode 100644 index 0000000000..ec780f28a1 --- /dev/null +++ b/libs/binder/rust/tests/serialization.cpp @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android/binder_ibinder_platform.h> +#include <android/binder_libbinder.h> +#include <binder/IServiceManager.h> +#include <binder/Parcel.h> +#include <binder/ParcelFileDescriptor.h> +#include <binder/ProcessState.h> +#include <binder/Status.h> +#include <gtest/gtest.h> +#include <utils/Errors.h> +#include <utils/String16.h> +#include "android-base/file.h" +#include "serialization.hpp" + +#include <cmath> +#include <cstdint> +#include <iostream> +#include <optional> + +using namespace std; +using namespace android; +using android::base::unique_fd; +using android::os::ParcelFileDescriptor; + +// defined in Rust +extern "C" AIBinder *rust_service(); + + +const int8_t TESTDATA_I8[4] = {-128, 0, 117, 127}; +const uint8_t TESTDATA_U8[4] = {0, 42, 117, 255}; +const char16_t TESTDATA_CHARS[4] = {0, 42, 117, numeric_limits<char16_t>::max()}; +const int32_t TESTDATA_I32[4] = {numeric_limits<int32_t>::min(), 0, 117, numeric_limits<int32_t>::max()}; +const int64_t TESTDATA_I64[4] = {numeric_limits<int64_t>::min(), 0, 117, numeric_limits<int64_t>::max()}; +const uint64_t TESTDATA_U64[4] = {0, 42, 117, numeric_limits<uint64_t>::max()}; +const float TESTDATA_FLOAT[4] = { + numeric_limits<float>::quiet_NaN(), + -numeric_limits<float>::infinity(), + 117.0, + numeric_limits<float>::infinity(), +}; +const double TESTDATA_DOUBLE[4] = { + numeric_limits<double>::quiet_NaN(), + -numeric_limits<double>::infinity(), + 117.0, + numeric_limits<double>::infinity(), +}; +const bool TESTDATA_BOOL[4] = {true, false, false, true}; +const char* const TESTDATA_STRS[4] = {"", nullptr, "test", ""}; + +static ::testing::Environment* gEnvironment; + +class SerializationEnvironment : public ::testing::Environment { +public: + void SetUp() override { + m_server = AIBinder_toPlatformBinder(rust_service()); + } + + sp<IBinder> getServer(void) { return m_server; } + +private: + sp<IBinder> m_server; +}; + + +class SerializationTest : public ::testing::Test { +protected: + void SetUp() override { + ASSERT_NE(gEnvironment, nullptr); + m_server = static_cast<SerializationEnvironment *>(gEnvironment)->getServer(); + } + + sp<IBinder> m_server; +}; + + +TEST_F(SerializationTest, SerializeBool) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<bool> bools(begin(TESTDATA_BOOL), end(TESTDATA_BOOL)); + ASSERT_EQ(data.writeBool(true), OK); + ASSERT_EQ(data.writeBool(false), OK); + ASSERT_EQ(data.writeBoolVector(bools), OK); + ASSERT_EQ(data.writeBoolVector(nullopt), OK); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_BOOL, data, &reply), OK); + + vector<bool> read_bools; + optional<vector<bool>> maybe_bools; + ASSERT_EQ(reply.readBool(), true); + ASSERT_EQ(reply.readBool(), false); + ASSERT_EQ(reply.readBoolVector(&read_bools), OK); + ASSERT_EQ(read_bools, bools); + ASSERT_EQ(reply.readBoolVector(&maybe_bools), OK); + ASSERT_EQ(maybe_bools, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeByte) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<int8_t> i8s(begin(TESTDATA_I8), end(TESTDATA_I8)); + vector<uint8_t> u8s(begin(TESTDATA_U8), end(TESTDATA_U8)); + data.writeByte(0); + data.writeByte(1); + data.writeByte(numeric_limits<int8_t>::max()); + data.writeByteVector(i8s); + data.writeByteVector(u8s); + data.writeByteVector(optional<vector<int8_t>>({})); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_BYTE, data, &reply), OK); + + vector<int8_t> read_i8s; + vector<uint8_t> read_u8s; + optional<vector<int8_t>> maybe_i8s; + ASSERT_EQ(reply.readByte(), 0); + ASSERT_EQ(reply.readByte(), 1); + ASSERT_EQ(reply.readByte(), numeric_limits<int8_t>::max()); + ASSERT_EQ(reply.readByteVector(&read_i8s), OK); + ASSERT_EQ(read_i8s, i8s); + ASSERT_EQ(reply.readByteVector(&read_u8s), OK); + ASSERT_EQ(read_u8s, u8s); + ASSERT_EQ(reply.readByteVector(&maybe_i8s), OK); + ASSERT_EQ(maybe_i8s, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeU16) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<char16_t> chars(begin(TESTDATA_CHARS), end(TESTDATA_CHARS)); + data.writeChar(0); + data.writeChar(1); + data.writeChar(numeric_limits<char16_t>::max()); + data.writeCharVector(chars); + data.writeCharVector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_U16, data, &reply), OK); + + vector<char16_t> read_chars; + optional<vector<char16_t>> maybe_chars; + ASSERT_EQ(reply.readChar(), 0); + ASSERT_EQ(reply.readChar(), 1); + ASSERT_EQ(reply.readChar(), numeric_limits<char16_t>::max()); + ASSERT_EQ(reply.readCharVector(&read_chars), OK); + ASSERT_EQ(read_chars, chars); + ASSERT_EQ(reply.readCharVector(&maybe_chars), OK); + ASSERT_EQ(maybe_chars, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeI32) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<int32_t> i32s(begin(TESTDATA_I32), end(TESTDATA_I32)); + data.writeInt32(0); + data.writeInt32(1); + data.writeInt32(numeric_limits<int32_t>::max()); + data.writeInt32Vector(i32s); + data.writeInt32Vector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_I32, data, &reply), OK); + + vector<int32_t> read_i32s; + optional<vector<int32_t>> maybe_i32s; + ASSERT_EQ(reply.readInt32(), 0); + ASSERT_EQ(reply.readInt32(), 1); + ASSERT_EQ(reply.readInt32(), numeric_limits<int32_t>::max()); + ASSERT_EQ(reply.readInt32Vector(&read_i32s), OK); + ASSERT_EQ(read_i32s, i32s); + ASSERT_EQ(reply.readInt32Vector(&maybe_i32s), OK); + ASSERT_EQ(maybe_i32s, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeI64) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<int64_t> i64s(begin(TESTDATA_I64), end(TESTDATA_I64)); + data.writeInt64(0); + data.writeInt64(1); + data.writeInt64(numeric_limits<int64_t>::max()); + data.writeInt64Vector(i64s); + data.writeInt64Vector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_I64, data, &reply), OK); + + vector<int64_t> read_i64s; + optional<vector<int64_t>> maybe_i64s; + ASSERT_EQ(reply.readInt64(), 0); + ASSERT_EQ(reply.readInt64(), 1); + ASSERT_EQ(reply.readInt64(), numeric_limits<int64_t>::max()); + ASSERT_EQ(reply.readInt64Vector(&read_i64s), OK); + ASSERT_EQ(read_i64s, i64s); + ASSERT_EQ(reply.readInt64Vector(&maybe_i64s), OK); + ASSERT_EQ(maybe_i64s, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeU64) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<uint64_t> u64s(begin(TESTDATA_U64), end(TESTDATA_U64)); + data.writeUint64(0); + data.writeUint64(1); + data.writeUint64(numeric_limits<uint64_t>::max()); + data.writeUint64Vector(u64s); + data.writeUint64Vector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_U64, data, &reply), OK); + + vector<uint64_t> read_u64s; + optional<vector<uint64_t>> maybe_u64s; + ASSERT_EQ(reply.readUint64(), 0); + ASSERT_EQ(reply.readUint64(), 1); + ASSERT_EQ(reply.readUint64(), numeric_limits<uint64_t>::max()); + ASSERT_EQ(reply.readUint64Vector(&read_u64s), OK); + ASSERT_EQ(read_u64s, u64s); + ASSERT_EQ(reply.readUint64Vector(&maybe_u64s), OK); + ASSERT_EQ(maybe_u64s, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeF32) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<float> floats(begin(TESTDATA_FLOAT), end(TESTDATA_FLOAT)); + data.writeFloat(0); + data.writeFloatVector(floats); + data.writeFloatVector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_F32, data, &reply), OK); + + vector<float> read_floats; + optional<vector<float>> maybe_floats; + ASSERT_EQ(reply.readFloat(), 0); + ASSERT_EQ(reply.readFloatVector(&read_floats), OK); + ASSERT_TRUE(isnan(read_floats[0])); + ASSERT_EQ(read_floats[1], floats[1]); + ASSERT_EQ(read_floats[2], floats[2]); + ASSERT_EQ(read_floats[3], floats[3]); + ASSERT_EQ(reply.readFloatVector(&maybe_floats), OK); + ASSERT_EQ(maybe_floats, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeF64) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<double> doubles(begin(TESTDATA_DOUBLE), end(TESTDATA_DOUBLE)); + data.writeDouble(0); + data.writeDoubleVector(doubles); + data.writeDoubleVector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_F64, data, &reply), OK); + + vector<double> read_doubles; + optional<vector<double>> maybe_doubles; + ASSERT_EQ(reply.readDouble(), 0); + ASSERT_EQ(reply.readDoubleVector(&read_doubles), OK); + ASSERT_TRUE(isnan(read_doubles[0])); + ASSERT_EQ(read_doubles[1], doubles[1]); + ASSERT_EQ(read_doubles[2], doubles[2]); + ASSERT_EQ(read_doubles[3], doubles[3]); + ASSERT_EQ(reply.readDoubleVector(&maybe_doubles), OK); + ASSERT_EQ(maybe_doubles, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeString) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + vector<optional<String16>> strings; + for (auto I = begin(TESTDATA_STRS), E = end(TESTDATA_STRS); I != E; ++I) { + if (*I == nullptr) { + strings.push_back(optional<String16>()); + } else { + strings.emplace_back(*I); + } + } + data.writeUtf8AsUtf16(string("testing")); + data.writeString16(nullopt); + data.writeString16Vector(strings); + data.writeString16Vector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_STRING, data, &reply), OK); + + optional<String16> maybe_string; + optional<vector<optional<String16>>> read_strings; + ASSERT_EQ(reply.readString16(), String16("testing")); + ASSERT_EQ(reply.readString16(&maybe_string), OK); + ASSERT_EQ(maybe_string, nullopt); + ASSERT_EQ(reply.readString16Vector(&read_strings), OK); + ASSERT_EQ(read_strings, strings); + ASSERT_EQ(reply.readString16Vector(&read_strings), OK); + ASSERT_EQ(read_strings, nullopt); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeFileDescriptor) { + unique_fd out_file, in_file; + ASSERT_TRUE(base::Pipe(&out_file, &in_file)); + + vector<ParcelFileDescriptor> file_descriptors; + file_descriptors.push_back(ParcelFileDescriptor(std::move(out_file))); + file_descriptors.push_back(ParcelFileDescriptor(std::move(in_file))); + + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + data.writeParcelable(file_descriptors[0]); + data.writeParcelable(file_descriptors[1]); + data.writeParcelableVector(file_descriptors); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_FILE_DESCRIPTOR, data, &reply), OK); + + ParcelFileDescriptor returned_fd1, returned_fd2; + vector<ParcelFileDescriptor> returned_file_descriptors; + ASSERT_EQ(reply.readParcelable(&returned_fd1), OK); + ASSERT_EQ(reply.readParcelable(&returned_fd2), OK); + ASSERT_EQ(reply.readParcelableVector(&returned_file_descriptors), OK); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); + + base::WriteStringToFd("Testing", returned_fd2.get()); + base::WriteStringToFd("File", returned_file_descriptors[1].get()); + base::WriteStringToFd("Descriptors", file_descriptors[1].get()); + + string expected = "TestingFileDescriptors"; + vector<char> buf(expected.length()); + base::ReadFully(file_descriptors[0].release(), buf.data(), buf.size()); + ASSERT_EQ(expected, string(buf.data())); +} + +TEST_F(SerializationTest, SerializeIBinder) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + data.writeStrongBinder(m_server); + data.writeStrongBinder(nullptr); + data.writeStrongBinderVector({m_server, nullptr}); + data.writeStrongBinderVector(nullopt); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_IBINDER, data, &reply), OK); + + optional<vector<sp<IBinder>>> binders; + ASSERT_TRUE(reply.readStrongBinder()); + ASSERT_FALSE(reply.readStrongBinder()); + ASSERT_EQ(reply.readStrongBinderVector(&binders), OK); + ASSERT_EQ(binders->size(), 2); + ASSERT_TRUE((*binders)[0]); + ASSERT_FALSE((*binders)[1]); + ASSERT_EQ(reply.readStrongBinderVector(&binders), OK); + ASSERT_FALSE(binders); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +TEST_F(SerializationTest, SerializeStatus) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + + binder::Status::ok().writeToParcel(&data); + binder::Status::fromExceptionCode(binder::Status::EX_NULL_POINTER, "a status message") + .writeToParcel(&data); + binder::Status::fromServiceSpecificError(42, "a service-specific error").writeToParcel(&data); + + android::Parcel reply; + ASSERT_EQ(m_server->transact(TEST_STATUS, data, &reply), OK); + + binder::Status status; + + ASSERT_EQ(status.readFromParcel(reply), OK); + ASSERT_TRUE(status.isOk()); + + ASSERT_EQ(status.readFromParcel(reply), OK); + ASSERT_EQ(status.exceptionCode(), binder::Status::EX_NULL_POINTER); + ASSERT_EQ(status.exceptionMessage(), "a status message"); + + ASSERT_EQ(status.readFromParcel(reply), OK); + ASSERT_EQ(status.serviceSpecificErrorCode(), 42); + ASSERT_EQ(status.exceptionMessage(), "a service-specific error"); + + int32_t end; + ASSERT_EQ(reply.readInt32(&end), NOT_ENOUGH_DATA); +} + +// Test that failures from Rust properly propagate to C++ +TEST_F(SerializationTest, SerializeRustFail) { + android::Parcel data; + data.writeInterfaceToken(String16("read_parcel_test")); + ASSERT_EQ(m_server->transact(TEST_FAIL, data, nullptr), FAILED_TRANSACTION); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + gEnvironment = AddGlobalTestEnvironment(new SerializationEnvironment()); + ProcessState::self()->startThreadPool(); + return RUN_ALL_TESTS(); +} diff --git a/libs/binder/rust/tests/serialization.hpp b/libs/binder/rust/tests/serialization.hpp new file mode 100644 index 0000000000..0041608ae0 --- /dev/null +++ b/libs/binder/rust/tests/serialization.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <binder/IBinder.h> + +using namespace android; + +enum Transaction { + TEST_BOOL = IBinder::FIRST_CALL_TRANSACTION, + TEST_BYTE, + TEST_U16, + TEST_I32, + TEST_I64, + TEST_U64, + TEST_F32, + TEST_F64, + TEST_STRING, + TEST_FILE_DESCRIPTOR, + TEST_IBINDER, + TEST_STATUS, + TEST_FAIL, +}; + +extern const int8_t TESTDATA_I8[4]; +extern const uint8_t TESTDATA_U8[4]; +extern const char16_t TESTDATA_CHARS[4]; +extern const int32_t TESTDATA_I32[4]; +extern const int64_t TESTDATA_I64[4]; +extern const uint64_t TESTDATA_U64[4]; +extern const float TESTDATA_FLOAT[4]; +extern const double TESTDATA_DOUBLE[4]; +extern const bool TESTDATA_BOOL[4]; +extern const char* const TESTDATA_STRS[4]; diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs new file mode 100644 index 0000000000..f1b068ee43 --- /dev/null +++ b/libs/binder/rust/tests/serialization.rs @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//! Included as a module in the binder crate internal tests for internal API +//! access. + +use binder::declare_binder_interface; +use binder::{ + Binder, ExceptionCode, Interface, Parcel, Result, SpIBinder, Status, + StatusCode, TransactionCode, +}; +use binder::parcel::ParcelFileDescriptor; + +use std::ffi::{c_void, CStr, CString}; +use std::sync::Once; + +#[allow( + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused, + improper_ctypes, + missing_docs, + clippy::all +)] +mod bindings { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} + +macro_rules! assert_eq { + ($left:expr, $right:expr $(,)?) => { + match (&$left, &$right) { + (left, right) => { + if *left != *right { + eprintln!( + "assertion failed: `{:?}` == `{:?}`, {}:{}:{}", + &*left, + &*right, + file!(), + line!(), + column!() + ); + return Err(StatusCode::FAILED_TRANSACTION); + } + } + } + }; +} + +macro_rules! assert { + ($expr:expr) => { + if !$expr { + eprintln!( + "assertion failed: `{:?}`, {}:{}:{}", + $expr, + file!(), + line!(), + column!() + ); + return Err(StatusCode::FAILED_TRANSACTION); + } + }; +} + +static SERVICE_ONCE: Once = Once::new(); +static mut SERVICE: Option<SpIBinder> = None; + +/// Start binder service and return a raw AIBinder pointer to it. +/// +/// Safe to call multiple times, only creates the service once. +#[no_mangle] +pub extern "C" fn rust_service() -> *mut c_void { + unsafe { + SERVICE_ONCE.call_once(|| { + SERVICE = Some(BnReadParcelTest::new_binder(()).as_binder()); + }); + SERVICE.as_ref().unwrap().as_raw().cast() + } +} + +/// Empty interface just to use the declare_binder_interface macro +pub trait ReadParcelTest: Interface {} + +declare_binder_interface! { + ReadParcelTest["read_parcel_test"] { + native: BnReadParcelTest(on_transact), + proxy: BpReadParcelTest, + } +} + +impl ReadParcelTest for Binder<BnReadParcelTest> {} + +impl ReadParcelTest for BpReadParcelTest {} + +impl ReadParcelTest for () {} + +#[allow(clippy::float_cmp)] +fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode, + parcel: &Parcel, reply: &mut Parcel) -> Result<()> { + match code { + bindings::Transaction_TEST_BOOL => { + assert_eq!(parcel.read::<bool>()?, true); + assert_eq!(parcel.read::<bool>()?, false); + assert_eq!(parcel.read::<Vec<bool>>()?, unsafe { + bindings::TESTDATA_BOOL + }); + assert_eq!(parcel.read::<Option<Vec<bool>>>()?, None); + + reply.write(&true)?; + reply.write(&false)?; + reply.write(&unsafe { bindings::TESTDATA_BOOL }[..])?; + reply.write(&(None as Option<Vec<bool>>))?; + } + bindings::Transaction_TEST_BYTE => { + assert_eq!(parcel.read::<i8>()?, 0); + assert_eq!(parcel.read::<i8>()?, 1); + assert_eq!(parcel.read::<i8>()?, i8::max_value()); + assert_eq!(parcel.read::<Vec<i8>>()?, unsafe { bindings::TESTDATA_I8 }); + assert_eq!(parcel.read::<Vec<u8>>()?, unsafe { bindings::TESTDATA_U8 }); + assert_eq!(parcel.read::<Option<Vec<i8>>>()?, None); + + reply.write(&0i8)?; + reply.write(&1i8)?; + reply.write(&i8::max_value())?; + reply.write(&unsafe { bindings::TESTDATA_I8 }[..])?; + reply.write(&unsafe { bindings::TESTDATA_U8 }[..])?; + reply.write(&(None as Option<Vec<i8>>))?; + } + bindings::Transaction_TEST_U16 => { + assert_eq!(parcel.read::<u16>()?, 0); + assert_eq!(parcel.read::<u16>()?, 1); + assert_eq!(parcel.read::<u16>()?, u16::max_value()); + assert_eq!(parcel.read::<Vec<u16>>()?, unsafe { + bindings::TESTDATA_CHARS + }); + assert_eq!(parcel.read::<Option<Vec<u16>>>()?, None); + + reply.write(&0u16)?; + reply.write(&1u16)?; + reply.write(&u16::max_value())?; + reply.write(&unsafe { bindings::TESTDATA_CHARS }[..])?; + reply.write(&(None as Option<Vec<u16>>))?; + } + bindings::Transaction_TEST_I32 => { + assert_eq!(parcel.read::<i32>()?, 0); + assert_eq!(parcel.read::<i32>()?, 1); + assert_eq!(parcel.read::<i32>()?, i32::max_value()); + assert_eq!(parcel.read::<Vec<i32>>()?, unsafe { + bindings::TESTDATA_I32 + }); + assert_eq!(parcel.read::<Option<Vec<i32>>>()?, None); + + reply.write(&0i32)?; + reply.write(&1i32)?; + reply.write(&i32::max_value())?; + reply.write(&unsafe { bindings::TESTDATA_I32 }[..])?; + reply.write(&(None as Option<Vec<i32>>))?; + } + bindings::Transaction_TEST_I64 => { + assert_eq!(parcel.read::<i64>()?, 0); + assert_eq!(parcel.read::<i64>()?, 1); + assert_eq!(parcel.read::<i64>()?, i64::max_value()); + assert_eq!(parcel.read::<Vec<i64>>()?, unsafe { + bindings::TESTDATA_I64 + }); + assert_eq!(parcel.read::<Option<Vec<i64>>>()?, None); + + reply.write(&0i64)?; + reply.write(&1i64)?; + reply.write(&i64::max_value())?; + reply.write(&unsafe { bindings::TESTDATA_I64 }[..])?; + reply.write(&(None as Option<Vec<i64>>))?; + } + bindings::Transaction_TEST_U64 => { + assert_eq!(parcel.read::<u64>()?, 0); + assert_eq!(parcel.read::<u64>()?, 1); + assert_eq!(parcel.read::<u64>()?, u64::max_value()); + assert_eq!(parcel.read::<Vec<u64>>()?, unsafe { + bindings::TESTDATA_U64 + }); + assert_eq!(parcel.read::<Option<Vec<u64>>>()?, None); + + reply.write(&0u64)?; + reply.write(&1u64)?; + reply.write(&u64::max_value())?; + reply.write(&unsafe { bindings::TESTDATA_U64 }[..])?; + reply.write(&(None as Option<Vec<u64>>))?; + } + bindings::Transaction_TEST_F32 => { + assert_eq!(parcel.read::<f32>()?, 0f32); + let floats = parcel.read::<Vec<f32>>()?; + assert!(floats[0].is_nan()); + assert_eq!(floats[1..], unsafe { bindings::TESTDATA_FLOAT }[1..]); + assert_eq!(parcel.read::<Option<Vec<f32>>>()?, None); + + reply.write(&0f32)?; + reply.write(&unsafe { bindings::TESTDATA_FLOAT }[..])?; + reply.write(&(None as Option<Vec<f32>>))?; + } + bindings::Transaction_TEST_F64 => { + assert_eq!(parcel.read::<f64>()?, 0f64); + let doubles = parcel.read::<Vec<f64>>()?; + assert!(doubles[0].is_nan()); + assert_eq!(doubles[1..], unsafe { bindings::TESTDATA_DOUBLE }[1..]); + assert_eq!(parcel.read::<Option<Vec<f64>>>()?, None); + + reply.write(&0f64)?; + reply.write(&unsafe { bindings::TESTDATA_DOUBLE }[..])?; + reply.write(&(None as Option<Vec<f64>>))?; + } + bindings::Transaction_TEST_STRING => { + let s: Option<String> = parcel.read()?; + assert_eq!(s.as_deref(), Some("testing")); + let s: Option<String> = parcel.read()?; + assert_eq!(s, None); + let s: Option<Vec<Option<String>>> = parcel.read()?; + for (s, expected) in s + .unwrap() + .iter() + .zip(unsafe { bindings::TESTDATA_STRS }.iter()) + { + let expected = unsafe { + expected + .as_ref() + .and_then(|e| CStr::from_ptr(e).to_str().ok()) + }; + assert_eq!(s.as_deref(), expected); + } + let s: Option<Vec<Option<String>>> = parcel.read()?; + assert_eq!(s, None); + + let strings: Vec<Option<String>> = unsafe { + bindings::TESTDATA_STRS + .iter() + .map(|s| { + s.as_ref().map(|s| { + CStr::from_ptr(s) + .to_str() + .expect("String was not UTF-8") + .to_owned() + }) + }) + .collect() + }; + + reply.write("testing")?; + reply.write(&(None as Option<String>))?; + reply.write(&strings)?; + reply.write(&(None as Option<Vec<String>>))?; + } + bindings::Transaction_TEST_FILE_DESCRIPTOR => { + let file1 = parcel.read::<ParcelFileDescriptor>()?; + let file2 = parcel.read::<ParcelFileDescriptor>()?; + let files = parcel.read::<Vec<Option<ParcelFileDescriptor>>>()?; + + reply.write(&file1)?; + reply.write(&file2)?; + reply.write(&files)?; + } + bindings::Transaction_TEST_IBINDER => { + assert!(parcel.read::<Option<SpIBinder>>()?.is_some()); + assert!(parcel.read::<Option<SpIBinder>>()?.is_none()); + let ibinders = parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.unwrap(); + assert_eq!(ibinders.len(), 2); + assert!(ibinders[0].is_some()); + assert!(ibinders[1].is_none()); + assert!(parcel.read::<Option<Vec<Option<SpIBinder>>>>()?.is_none()); + + let service = unsafe { + SERVICE + .as_ref() + .expect("Global binder service not initialized") + .clone() + }; + reply.write(&service)?; + reply.write(&(None as Option<&SpIBinder>))?; + reply.write(&[Some(&service), None][..])?; + reply.write(&(None as Option<Vec<Option<&SpIBinder>>>))?; + } + bindings::Transaction_TEST_STATUS => { + let status: Status = parcel.read()?; + assert!(status.is_ok()); + let status: Status = parcel.read()?; + assert_eq!(status.exception_code(), ExceptionCode::NULL_POINTER); + assert_eq!( + status.get_description(), + "Status(-4, EX_NULL_POINTER): 'a status message'" + ); + let status: Status = parcel.read()?; + assert_eq!(status.service_specific_error(), 42); + assert_eq!( + status.get_description(), + "Status(-8, EX_SERVICE_SPECIFIC): '42: a service-specific error'" + ); + + reply.write(&Status::ok())?; + reply.write(&Status::new_exception( + ExceptionCode::NULL_POINTER, + Some(&CString::new("a status message").unwrap()), + ))?; + reply.write(&Status::new_service_specific_error( + 42, + Some(&CString::new("a service-specific error").unwrap()), + ))?; + } + bindings::Transaction_TEST_FAIL => { + assert!(false); + } + _ => return Err(StatusCode::UNKNOWN_TRANSACTION), + } + + assert_eq!(parcel.read::<i32>(), Err(StatusCode::NOT_ENOUGH_DATA)); + Ok(()) +} diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index 87f1d45350..3bbb0b52bb 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "binder_test_defaults", cflags: [ @@ -157,6 +166,24 @@ cc_test { require_root: true, } +cc_test { + name: "binderClearBufTest", + defaults: ["binder_test_defaults"], + srcs: [ + "binderClearBufTest.cpp", + ], + + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "libutils", + ], + + test_suites: ["general-tests"], + require_root: true, +} + aidl_interface { name: "binderStabilityTestIface", unstable: true, @@ -202,3 +229,15 @@ cc_test { test_suites: ["device-tests"], require_root: true, } + +cc_benchmark { + name: "binderParcelBenchmark", + defaults: ["binder_test_defaults"], + srcs: ["binderParcelBenchmark.cpp"], + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "libutils", + ], +} diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp new file mode 100644 index 0000000000..2d30c8da45 --- /dev/null +++ b/libs/binder/tests/binderClearBufTest.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/logging.h> +#include <binder/Binder.h> +#include <binder/IBinder.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/Parcel.h> +#include <binder/Stability.h> +#include <gtest/gtest.h> + +#include <sys/prctl.h> +#include <thread> + +using namespace android; + +const String16 kServerName = String16("binderClearBuf"); + +std::string hexString(const void* bytes, size_t len) { + if (bytes == nullptr) return "<null>"; + + const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes); + char chars[] = "0123456789abcdef"; + std::string result; + result.resize(len * 2); + + for (size_t i = 0; i < len; i++) { + result[2 * i] = chars[bytes8[i] >> 4]; + result[2 * i + 1] = chars[bytes8[i] & 0xf]; + } + + return result; +} + +class FooBar : public BBinder { + public: + enum { + TRANSACTION_REPEAT_STRING = IBinder::FIRST_CALL_TRANSACTION, + }; + + std::mutex foo; + std::string last; + + status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + // not checking data, since there is no hook at the time this test is + // written to check values there are set to zero. Instead, we only check + // the reply parcel. + + switch (code) { + case TRANSACTION_REPEAT_STRING: { + const char* str = data.readCString(); + return reply->writeCString(str == nullptr ? "<null>" : str); + } + } + return BBinder::onTransact(code, data, reply, flags); + } + static std::string RepeatString(const sp<IBinder> binder, + const std::string& repeat, + std::string* outBuffer) { + Parcel data; + data.writeCString(repeat.c_str()); + std::string result; + const uint8_t* lastReply; + size_t lastReplySize; + { + Parcel reply; + binder->transact(TRANSACTION_REPEAT_STRING, data, &reply, FLAG_CLEAR_BUF); + result = reply.readCString(); + lastReply = reply.data(); + lastReplySize = reply.dataSize(); + } + *outBuffer = hexString(lastReply, lastReplySize); + return result; + } +}; + +TEST(BinderClearBuf, ClearKernelBuffer) { + sp<IBinder> binder = defaultServiceManager()->getService(kServerName); + ASSERT_NE(nullptr, binder); + + std::string replyBuffer; + std::string result = FooBar::RepeatString(binder, "foo", &replyBuffer); + EXPECT_EQ("foo", result); + + // the buffer must have at least some length for the string, but we will + // just check it has some length, to avoid assuming anything about the + // format + EXPECT_GT(replyBuffer.size(), 0); + + for (size_t i = 0; i < replyBuffer.size(); i++) { + EXPECT_EQ(replyBuffer[i], '0') << "reply buffer at " << i; + } +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + if (fork() == 0) { + prctl(PR_SET_PDEATHSIG, SIGHUP); + + sp<IBinder> server = new FooBar; + android::defaultServiceManager()->addService(kServerName, server); + + IPCThreadState::self()->joinThreadPool(true); + exit(1); // should not reach + } + + // This is not racey. Just giving these services some time to register before we call + // getService which sleeps for much longer. One alternative would be to + // start a threadpool + use waitForService, but we want to have as few + // binder things going on in this test as possible, since we are checking + // memory is zero'd which the kernel has a right to change. + usleep(100000); + + return RUN_ALL_TESTS(); +} diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index a5261e59bf..e2193fadab 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -21,6 +21,7 @@ #include <pthread.h> #include <stdio.h> #include <stdlib.h> +#include <thread> #include <gtest/gtest.h> @@ -28,6 +29,7 @@ #include <binder/IBinder.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <binder/ParcelRef.h> #include <private/binder/binder_module.h> #include <linux/sched.h> @@ -916,6 +918,36 @@ TEST_F(BinderLibTest, FreedBinder) { } } +TEST_F(BinderLibTest, ParcelAllocatedOnAnotherThread) { + sp<IBinder> server = addServer(); + ASSERT_TRUE(server != nullptr); + + Parcel data; + sp<ParcelRef> reply = ParcelRef::create(); + + // when we have a Parcel which is deleted on another thread, if it gets + // deleted, it will tell the kernel this, and it will drop strong references + // to binder, so that we can't BR_ACQUIRE would fail + IPCThreadState::self()->createTransactionReference(reply.get()); + ASSERT_EQ(NO_ERROR, server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, + data, + reply.get())); + + // we have sp to binder, but it is not actually acquired by kernel, the + // transaction is sitting on an out buffer + sp<IBinder> binder = reply->readStrongBinder(); + + std::thread([&] { + // without the transaction reference, this would cause the Parcel to be + // deallocated before the first thread flushes BR_ACQUIRE + reply = nullptr; + IPCThreadState::self()->flushCommands(); + }).join(); + + ASSERT_NE(nullptr, binder); + ASSERT_EQ(NO_ERROR, binder->pingBinder()); +} + TEST_F(BinderLibTest, CheckNoHeaderMappedInUser) { status_t ret; Parcel data, reply; diff --git a/libs/binder/tests/binderParcelBenchmark.cpp b/libs/binder/tests/binderParcelBenchmark.cpp new file mode 100644 index 0000000000..26c50ebb57 --- /dev/null +++ b/libs/binder/tests/binderParcelBenchmark.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <binder/Parcel.h> +#include <benchmark/benchmark.h> + +// Usage: atest binderParcelBenchmark + +// For static assert(false) we need a template version to avoid early failure. +// See: https://stackoverflow.com/questions/51523965/template-dependent-false +template <typename T> +constexpr bool dependent_false_v = false; + +template <template <typename ...> class V, typename T, typename... Args> +void writeVector(android::Parcel &p, const V<T, Args...> &v) { + if constexpr (std::is_same_v<T, bool>) { + p.writeBoolVector(v); + } else if constexpr (std::is_same_v<T, uint8_t>) { + p.writeByteVector(v); + } else if constexpr (std::is_same_v<T, char16_t>) { + p.writeCharVector(v); + } else if constexpr (std::is_same_v<T, int32_t>) { + p.writeInt32Vector(v); + } else if constexpr (std::is_same_v<T, int64_t>) { + p.writeInt64Vector(v); + } else { + static_assert(dependent_false_v<V<T>>); + } +} + +template <template <typename ...> class V, typename T, typename... Args> +void readVector(android::Parcel &p, V<T, Args...> *v) { + if constexpr (std::is_same_v<T, bool>) { + p.readBoolVector(v); + } else if constexpr (std::is_same_v<T, uint8_t>) { + p.readByteVector(v); + } else if constexpr (std::is_same_v<T, char16_t>) { + p.readCharVector(v); + } else if constexpr (std::is_same_v<T, int32_t>) { + p.readInt32Vector(v); + } else if constexpr (std::is_same_v<T, int64_t>) { + p.readInt64Vector(v); + } else { + static_assert(dependent_false_v<V<T>>); + } +} + +// Construct a series of args { 1 << 0, 1 << 1, ..., 1 << 10 } +static void VectorArgs(benchmark::internal::Benchmark* b) { + for (int i = 0; i < 10; ++i) { + b->Args({1 << i}); + } +} + +template <typename T> +static void BM_ParcelVector(benchmark::State& state) { + const size_t elements = state.range(0); + + std::vector<T> v1(elements); + std::vector<T> v2(elements); + android::Parcel p; + while (state.KeepRunning()) { + p.setDataPosition(0); + writeVector(p, v1); + + p.setDataPosition(0); + readVector(p, &v2); + + benchmark::DoNotOptimize(v2[0]); + benchmark::ClobberMemory(); + } + state.SetComplexityN(elements); +} + +/* + Parcel vector write than read. + The read and write vectors are fixed, no resizing required. + + Results on Crosshatch Pixel 3XL + + #BM_BoolVector/1 44 ns 44 ns 15630626 + #BM_BoolVector/2 54 ns 54 ns 12900340 + #BM_BoolVector/4 73 ns 72 ns 9749841 + #BM_BoolVector/8 107 ns 107 ns 6503326 + #BM_BoolVector/16 186 ns 185 ns 3773627 + #BM_BoolVector/32 337 ns 336 ns 2083877 + #BM_BoolVector/64 607 ns 605 ns 1154113 + #BM_BoolVector/128 1155 ns 1151 ns 608128 + #BM_BoolVector/256 2259 ns 2253 ns 310973 + #BM_BoolVector/512 4469 ns 4455 ns 157277 + #BM_ByteVector/1 41 ns 41 ns 16837425 + #BM_ByteVector/2 41 ns 41 ns 16820726 + #BM_ByteVector/4 38 ns 38 ns 18217813 + #BM_ByteVector/8 38 ns 38 ns 18290298 + #BM_ByteVector/16 38 ns 38 ns 18117817 + #BM_ByteVector/32 38 ns 38 ns 18172385 + #BM_ByteVector/64 41 ns 41 ns 16950055 + #BM_ByteVector/128 53 ns 53 ns 13170749 + #BM_ByteVector/256 69 ns 69 ns 10113626 + #BM_ByteVector/512 106 ns 106 ns 6561936 + #BM_CharVector/1 38 ns 38 ns 18074831 + #BM_CharVector/2 40 ns 40 ns 17206266 + #BM_CharVector/4 50 ns 50 ns 13785944 + #BM_CharVector/8 67 ns 67 ns 10223316 + #BM_CharVector/16 96 ns 96 ns 7297285 + #BM_CharVector/32 156 ns 155 ns 4484845 + #BM_CharVector/64 277 ns 276 ns 2536003 + #BM_CharVector/128 520 ns 518 ns 1347070 + #BM_CharVector/256 1006 ns 1003 ns 695952 + #BM_CharVector/512 1976 ns 1970 ns 354673 + #BM_Int32Vector/1 41 ns 41 ns 16951262 + #BM_Int32Vector/2 41 ns 41 ns 16916883 + #BM_Int32Vector/4 41 ns 41 ns 16761373 + #BM_Int32Vector/8 42 ns 42 ns 16553179 + #BM_Int32Vector/16 43 ns 43 ns 16200362 + #BM_Int32Vector/32 55 ns 54 ns 12724454 + #BM_Int32Vector/64 70 ns 69 ns 10049223 + #BM_Int32Vector/128 107 ns 107 ns 6525796 + #BM_Int32Vector/256 179 ns 178 ns 3922563 + #BM_Int32Vector/512 324 ns 323 ns 2160653 + #BM_Int64Vector/1 41 ns 41 ns 16909470 + #BM_Int64Vector/2 41 ns 41 ns 16740788 + #BM_Int64Vector/4 42 ns 42 ns 16564197 + #BM_Int64Vector/8 43 ns 42 ns 16284082 + #BM_Int64Vector/16 54 ns 54 ns 12839474 + #BM_Int64Vector/32 69 ns 69 ns 10011010 + #BM_Int64Vector/64 107 ns 106 ns 6557956 + #BM_Int64Vector/128 177 ns 177 ns 3925618 + #BM_Int64Vector/256 324 ns 323 ns 2163321 + #BM_Int64Vector/512 613 ns 611 ns 1140418 +*/ + +static void BM_BoolVector(benchmark::State& state) { + BM_ParcelVector<bool>(state); +} + +static void BM_ByteVector(benchmark::State& state) { + BM_ParcelVector<uint8_t>(state); +} + +static void BM_CharVector(benchmark::State& state) { + BM_ParcelVector<char16_t>(state); +} + +static void BM_Int32Vector(benchmark::State& state) { + BM_ParcelVector<int32_t>(state); +} + +static void BM_Int64Vector(benchmark::State& state) { + BM_ParcelVector<int64_t>(state); +} + +BENCHMARK(BM_BoolVector)->Apply(VectorArgs); +BENCHMARK(BM_ByteVector)->Apply(VectorArgs); +BENCHMARK(BM_CharVector)->Apply(VectorArgs); +BENCHMARK(BM_Int32Vector)->Apply(VectorArgs); +BENCHMARK(BM_Int64Vector)->Apply(VectorArgs); + +BENCHMARK_MAIN(); diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp index ce99f59d7c..b37030e7d7 100644 --- a/libs/binder/tests/binderTextOutputTest.cpp +++ b/libs/binder/tests/binderTextOutputTest.cpp @@ -26,7 +26,6 @@ #include <binder/Parcel.h> #include <binder/TextOutput.h> -#include <binder/Debug.h> static void CheckMessage(CapturedStderr& cap, const char* expected, diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/fuzzers/Android.bp index c465bed250..b1263e8d8e 100644 --- a/libs/binder/tests/fuzzers/Android.bp +++ b/libs/binder/tests/fuzzers/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "binder_fuzz_defaults", host_supported: true, @@ -69,3 +78,18 @@ cc_fuzz { defaults: ["binder_fuzz_defaults"], srcs: ["TextOutputFuzz.cpp"], } + +cc_fuzz { + name: "binder_bufferedTextOutputFuzz", + include_dirs: [ + "frameworks/native/libs/binder", + ], + defaults: ["binder_fuzz_defaults"], + srcs: ["BufferedTextOutputFuzz.cpp"], +} + +cc_fuzz { + name: "binder_memoryDealerFuzz", + defaults: ["binder_fuzz_defaults"], + srcs: ["MemoryDealerFuzz.cpp"], +} diff --git a/libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp b/libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp new file mode 100644 index 0000000000..09cb2162f7 --- /dev/null +++ b/libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <commonFuzzHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <string> +#include <vector> +#include "BufferedTextOutput.h" + +namespace android { + +class FuzzBufferedTextOutput : public BufferedTextOutput { +public: + FuzzBufferedTextOutput(uint32_t flags) : BufferedTextOutput(flags) {} + virtual status_t writeLines(const struct iovec& buf, size_t) { + size_t len = buf.iov_len; + void* tmp_buf = malloc(len); + + if (tmp_buf == NULL) { + return status_t(); + } + + // This will attempt to read data from iov_base to ensure valid params were passed. + memcpy(tmp_buf, buf.iov_base, len); + free(tmp_buf); + return status_t(); + } +}; + +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + uint32_t flags = fdp.ConsumeIntegral<uint32_t>(); + size_t push_count = 0; + std::shared_ptr<BufferedTextOutput> bTextOutput(new FuzzBufferedTextOutput(flags)); + + while (fdp.remaining_bytes() > 0) { + fdp.PickValueInArray<std::function<void()>>({ + [&]() -> void { + bTextOutput->pushBundle(); + push_count++; + }, + [&]() -> void { + std::string txt = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); + size_t len = fdp.ConsumeIntegralInRange<size_t>(0, txt.length()); + bTextOutput->print(txt.c_str(), len); + }, + [&]() -> void { + if (push_count == 0) return; + + bTextOutput->popBundle(); + push_count--; + }, + })(); + } + + return 0; +} +} // namespace android diff --git a/libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp b/libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp new file mode 100644 index 0000000000..f9dda8c558 --- /dev/null +++ b/libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <binder/MemoryDealer.h> +#include <commonFuzzHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <string> +#include <unordered_set> + +namespace android { + +static constexpr size_t kMaxBufferSize = 10000; +static constexpr size_t kMaxDealerSize = 1024 * 512; +static constexpr size_t kMaxAllocSize = 1024; + +// Fuzzer entry point. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + if (size > kMaxBufferSize) { + return 0; + } + + FuzzedDataProvider fdp(data, size); + size_t dSize = fdp.ConsumeIntegralInRange<size_t>(0, kMaxDealerSize); + std::string name = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); + uint32_t flags = fdp.ConsumeIntegral<uint32_t>(); + sp<MemoryDealer> dealer = new MemoryDealer(dSize, name.c_str(), flags); + + // This is used to track offsets that have been freed already to avoid an expected fatal log. + std::unordered_set<size_t> free_list; + + while (fdp.remaining_bytes() > 0) { + fdp.PickValueInArray<std::function<void()>>({ + [&]() -> void { dealer->getAllocationAlignment(); }, + [&]() -> void { dealer->getMemoryHeap(); }, + [&]() -> void { + size_t offset = fdp.ConsumeIntegral<size_t>(); + + // Offset has already been freed, so return instead. + if (free_list.find(offset) != free_list.end()) return; + + dealer->deallocate(offset); + free_list.insert(offset); + }, + [&]() -> void { + std::string randString = fdp.ConsumeRandomLengthString(fdp.remaining_bytes()); + dealer->dump(randString.c_str()); + }, + [&]() -> void { + size_t allocSize = fdp.ConsumeIntegralInRange<size_t>(0, kMaxAllocSize); + sp<IMemory> allocated = dealer->allocate(allocSize); + // If the allocation was successful, try to write to it + if (allocated != nullptr && allocated->unsecurePointer() != nullptr) { + memset(allocated->unsecurePointer(), 1, allocated->size()); + + // Clear the address from freelist since it has been allocated over again. + free_list.erase(allocated->offset()); + } + }, + })(); + } + + return 0; +} +} // namespace android diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp index c9500205df..5e3502aace 100644 --- a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp +++ b/libs/binder/tests/fuzzers/TextOutputFuzz.cpp @@ -16,7 +16,6 @@ #include <fuzzer/FuzzedDataProvider.h> -#include <binder/Debug.h> #include <binder/Parcel.h> #include <binder/TextOutput.h> #include "android-base/file.h" diff --git a/libs/binderdebug/Android.bp b/libs/binderdebug/Android.bp index 343246a324..3eeaf3e4f1 100644 --- a/libs/binderdebug/Android.bp +++ b/libs/binderdebug/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libbinderdebug", vendor_available: true, diff --git a/libs/binderdebug/tests/Android.bp b/libs/binderdebug/tests/Android.bp index 4c06b1d0d9..d141a05ca9 100644 --- a/libs/binderdebug/tests/Android.bp +++ b/libs/binderdebug/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libbinderdebug_test", test_suites: ["general-tests"], diff --git a/libs/binderthreadstate/1.0/Android.bp b/libs/binderthreadstate/1.0/Android.bp index ebdc932591..99477d8e26 100644 --- a/libs/binderthreadstate/1.0/Android.bp +++ b/libs/binderthreadstate/1.0/Android.bp @@ -1,5 +1,14 @@ // This file is autogenerated by hidl-gen -Landroidbp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + hidl_interface { name: "binderthreadstateutilstest@1.0", root: "binderthreadstateutilstest", diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp index 08c62df072..0a82463feb 100644 --- a/libs/binderthreadstate/Android.bp +++ b/libs/binderthreadstate/Android.bp @@ -14,6 +14,15 @@ // DO NOT ADD NEW USAGES OF THIS // See comments in header file. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libbinderthreadstateutils", double_loadable: true, diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp index bab267466c..c5d3a3207c 100644 --- a/libs/bufferqueueconverter/Android.bp +++ b/libs/bufferqueueconverter/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libbufferqueueconverter_headers", vendor_available: true, diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp index e3cd0859cb..570af71d9a 100644 --- a/libs/cputimeinstate/Android.bp +++ b/libs/cputimeinstate/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libtimeinstate", srcs: ["cputimeinstate.cpp"], @@ -35,4 +44,3 @@ cc_test { ], require_root: true, } - diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp index 4209dc5c6b..7e9bb7d468 100644 --- a/libs/cputimeinstate/cputimeinstate.cpp +++ b/libs/cputimeinstate/cputimeinstate.cpp @@ -56,6 +56,7 @@ static uint32_t gNCpus = 0; static std::vector<std::vector<uint32_t>> gPolicyFreqs; static std::vector<std::vector<uint32_t>> gPolicyCpus; static std::set<uint32_t> gAllFreqs; +static unique_fd gTisTotalMapFd; static unique_fd gTisMapFd; static unique_fd gConcurrentMapFd; static unique_fd gUidLastUpdateMapFd; @@ -98,7 +99,7 @@ static bool initGlobals() { struct dirent **dirlist; const char basepath[] = "/sys/devices/system/cpu/cpufreq"; int ret = scandir(basepath, &dirlist, isPolicyFile, comparePolicyFiles); - if (ret == -1) return false; + if (ret == -1 || ret == 0) return false; gNPolicies = ret; std::vector<std::string> policyFileNames; @@ -129,6 +130,10 @@ static bool initGlobals() { gPolicyCpus.emplace_back(*cpus); } + gTisTotalMapFd = + unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_total_time_in_state_map")}; + if (gTisTotalMapFd < 0) return false; + gTisMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_time_in_state_map")}; if (gTisMapFd < 0) return false; @@ -150,10 +155,14 @@ static bool initGlobals() { return true; } -static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) { +static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) { std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s", eventType.c_str(), eventName.c_str()); - int prog_fd = retrieveProgram(path.c_str()); + return retrieveProgram(path.c_str()); +} + +static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) { + int prog_fd = retrieveProgramFd(eventType, eventName); if (prog_fd < 0) return false; return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0; } @@ -169,6 +178,17 @@ static std::optional<uint32_t> getPolicyFreqIdx(uint32_t policy) { return {}; } +// Check if tracking is expected to work without activating it. +bool isTrackingUidTimesSupported() { + auto freqs = getCpuFreqs(); + if (!freqs || freqs->empty()) return false; + if (gTracking) return true; + if (retrieveProgramFd("sched", "sched_switch") < 0) return false; + if (retrieveProgramFd("power", "cpu_frequency") < 0) return false; + if (retrieveProgramFd("sched", "sched_process_free") < 0) return false; + return true; +} + // Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes. // Returns true on success, false otherwise. // Tracking is active only once a live process has successfully called this function; if the calling @@ -239,6 +259,31 @@ std::optional<std::vector<std::vector<uint32_t>>> getCpuFreqs() { return gPolicyFreqs; } +std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes() { + if (!gInitialized && !initGlobals()) return {}; + + std::vector<std::vector<uint64_t>> out; + uint32_t maxFreqCount = 0; + for (const auto &freqList : gPolicyFreqs) { + if (freqList.size() > maxFreqCount) maxFreqCount = freqList.size(); + out.emplace_back(freqList.size(), 0); + } + + std::vector<uint64_t> vals(gNCpus); + const uint32_t freqCount = maxFreqCount <= MAX_FREQS_FOR_TOTAL ? maxFreqCount : + MAX_FREQS_FOR_TOTAL; + for (uint32_t freqIdx = 0; freqIdx < freqCount; ++freqIdx) { + if (findMapEntry(gTisTotalMapFd, &freqIdx, vals.data())) return {}; + for (uint32_t policyIdx = 0; policyIdx < gNPolicies; ++policyIdx) { + if (freqIdx >= gPolicyFreqs[policyIdx].size()) continue; + for (const auto &cpu : gPolicyCpus[policyIdx]) { + out[policyIdx][freqIdx] += vals[cpu]; + } + } + } + + return out; +} // Retrieve the times in ns that uid spent running at each CPU frequency. // Return contains no value on error, otherwise it contains a vector of vectors using the format: // [[t0_0, t0_1, ...], diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h index 87a328a5a5..41453745a0 100644 --- a/libs/cputimeinstate/cputimeinstate.h +++ b/libs/cputimeinstate/cputimeinstate.h @@ -22,7 +22,9 @@ namespace android { namespace bpf { +bool isTrackingUidTimesSupported(); bool startTrackingUidTimes(); +std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes(); std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid); std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>> getUidsCpuFreqTimes(); diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp index 519689bb0c..2112b10ebc 100644 --- a/libs/cputimeinstate/testtimeinstate.cpp +++ b/libs/cputimeinstate/testtimeinstate.cpp @@ -40,6 +40,17 @@ static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365; using std::vector; +TEST(TimeInStateTest, IsTrackingSupported) { + isTrackingUidTimesSupported(); + SUCCEED(); +} + +TEST(TimeInStateTest, TotalTimeInState) { + auto times = getTotalCpuFreqTimes(); + ASSERT_TRUE(times.has_value()); + EXPECT_FALSE(times->empty()); +} + TEST(TimeInStateTest, SingleUidTimeInState) { auto times = getUidCpuFreqTimes(0); ASSERT_TRUE(times.has_value()); @@ -186,6 +197,31 @@ TEST(TimeInStateTest, AllUidUpdatedTimeInState) { } } +TEST(TimeInStateTest, TotalAndAllUidTimeInStateConsistent) { + auto allUid = getUidsCpuFreqTimes(); + auto total = getTotalCpuFreqTimes(); + + ASSERT_TRUE(allUid.has_value() && total.has_value()); + + // Check the number of policies. + ASSERT_EQ(allUid->at(0).size(), total->size()); + + for (uint32_t policyIdx = 0; policyIdx < total->size(); ++policyIdx) { + std::vector<uint64_t> totalTimes = total->at(policyIdx); + uint32_t totalFreqsCount = totalTimes.size(); + std::vector<uint64_t> allUidTimes(totalFreqsCount, 0); + for (auto const &[uid, uidTimes]: *allUid) { + for (uint32_t freqIdx = 0; freqIdx < uidTimes[policyIdx].size(); ++freqIdx) { + allUidTimes[std::min(freqIdx, totalFreqsCount - 1)] += uidTimes[policyIdx][freqIdx]; + } + } + + for (uint32_t freqIdx = 0; freqIdx < totalFreqsCount; ++freqIdx) { + ASSERT_LE(allUidTimes[freqIdx], totalTimes[freqIdx]); + } + } +} + TEST(TimeInStateTest, SingleAndAllUidTimeInStateConsistent) { uint64_t zero = 0; auto maps = {getUidsCpuFreqTimes(), getUidsUpdatedCpuFreqTimes(&zero)}; @@ -292,6 +328,22 @@ void TestCheckDelta(uint64_t before, uint64_t after) { ASSERT_LE(after - before, NSEC_PER_SEC * 2 * get_nprocs_conf()); } +TEST(TimeInStateTest, TotalTimeInStateMonotonic) { + auto before = getTotalCpuFreqTimes(); + ASSERT_TRUE(before.has_value()); + sleep(1); + auto after = getTotalCpuFreqTimes(); + ASSERT_TRUE(after.has_value()); + + for (uint32_t policyIdx = 0; policyIdx < after->size(); ++policyIdx) { + auto timesBefore = before->at(policyIdx); + auto timesAfter = after->at(policyIdx); + for (uint32_t freqIdx = 0; freqIdx < timesAfter.size(); ++freqIdx) { + ASSERT_NO_FATAL_FAILURE(TestCheckDelta(timesBefore[freqIdx], timesAfter[freqIdx])); + } + } +} + TEST(TimeInStateTest, AllUidTimeInStateMonotonic) { auto map1 = getUidsCpuFreqTimes(); ASSERT_TRUE(map1.has_value()); diff --git a/libs/diskusage/Android.bp b/libs/diskusage/Android.bp index a8263069de..86840613e6 100644 --- a/libs/diskusage/Android.bp +++ b/libs/diskusage/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libdiskusage", srcs: ["dirsize.c"], diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp index e403d36da1..acda402993 100644 --- a/libs/dumputils/Android.bp +++ b/libs/dumputils/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libdumputils", diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index 3faf792b1f..8b3c3ad8b5 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -52,7 +52,6 @@ static const char* debuggable_native_processes_to_dump[] = { /* list of hal interface to dump containing process during native dumps */ static const char* hal_interfaces_to_dump[] { - "android.hardware.audio@2.0::IDevicesFactory", "android.hardware.audio@4.0::IDevicesFactory", "android.hardware.audio@5.0::IDevicesFactory", "android.hardware.audio@6.0::IDevicesFactory", diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp index 76518c1286..47c0657bbd 100644 --- a/libs/fakeservicemanager/Android.bp +++ b/libs/fakeservicemanager/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "fakeservicemanager_defaults", host_supported: true, diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp index 243d7f119b..a0032aecb9 100644 --- a/libs/gralloc/types/Android.bp +++ b/libs/gralloc/types/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libgralloctypes", defaults: ["libbinder_ndk_host_user"], @@ -43,14 +52,14 @@ cc_library { ], shared_libs: [ - "android.hardware.graphics.common-unstable-ndk_platform", + "android.hardware.graphics.common-V2-ndk_platform", "android.hardware.graphics.mapper@4.0", "libhidlbase", "liblog", ], export_shared_lib_headers: [ - "android.hardware.graphics.common-unstable-ndk_platform", + "android.hardware.graphics.common-V2-ndk_platform", "android.hardware.graphics.mapper@4.0", "libhidlbase", ], diff --git a/libs/gralloc/types/fuzzer/Android.bp b/libs/gralloc/types/fuzzer/Android.bp index 8933dc323f..6689771a24 100644 --- a/libs/gralloc/types/fuzzer/Android.bp +++ b/libs/gralloc/types/fuzzer/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_fuzz { name: "libgralloctypes_fuzzer", defaults: ["libbinder_ndk_host_user"], diff --git a/libs/gralloc/types/tests/Android.bp b/libs/gralloc/types/tests/Android.bp index b939c1db59..66eb0aa2fe 100644 --- a/libs/gralloc/types/tests/Android.bp +++ b/libs/gralloc/types/tests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "GrallocTypes_test", shared_libs: [ diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp index 642c5f2cc0..a96a07a9b8 100644 --- a/libs/graphicsenv/Android.bp +++ b/libs/graphicsenv/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libgraphicsenv", diff --git a/libs/graphicsenv/OWNERS b/libs/graphicsenv/OWNERS index c0bb75f982..8c284647f2 100644 --- a/libs/graphicsenv/OWNERS +++ b/libs/graphicsenv/OWNERS @@ -1,6 +1,4 @@ chrisforbes@google.com cnorthrop@google.com -courtneygo@google.com lpy@google.com timvp@google.com -zzyiwei@google.com diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 18ade37ec6..83987940d6 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -11,6 +11,15 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libgui_headers", vendor_available: true, @@ -123,7 +132,16 @@ cc_library_shared { aidl: { export_aidl_headers: true, - } + }, + + pgo: { + sampling: true, + profile_file: "libgui/libgui.profdata", + }, + + lto: { + thin: true, + }, } // Used by media codec services exclusively as a static lib for diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS index 1667fb02cd..45c958ebe4 100644 --- a/libs/gui/OWNERS +++ b/libs/gui/OWNERS @@ -1,5 +1,4 @@ adyabr@google.com -akrulec@google.com alecmouri@google.com chaviw@google.com chrisforbes@google.com @@ -7,7 +6,6 @@ jessehall@google.com lpy@google.com mathias@google.com racarr@google.com -stoza@google.com vishnun@google.com per-file EndToEndNativeInputTest.cpp = svv@google.com diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp index 64b1eacaa2..bddb0ac5ee 100644 --- a/libs/gui/sysprop/Android.bp +++ b/libs/gui/sysprop/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + sysprop_library { name: "LibGuiProperties", srcs: ["*.sysprop"], diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index a6bcd107af..6077b4e59f 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -2,6 +2,15 @@ // Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE) // to integrate with auto-test framework. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libgui_test", test_suites: ["device-tests"], diff --git a/libs/incidentcompanion/Android.bp b/libs/incidentcompanion/Android.bp index 63411b9698..ef7f52318b 100644 --- a/libs/incidentcompanion/Android.bp +++ b/libs/incidentcompanion/Android.bp @@ -14,6 +14,15 @@ * limitations under the License. */ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + filegroup { name: "incidentcompanion_aidl", srcs: [ @@ -49,4 +58,3 @@ cc_library_static { "-Wunused-parameter", ], } - diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 6a5d434515..393c0f6c15 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -14,6 +14,15 @@ // libinput is partially built for the host (used by build time keymap validation tool) +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libinput", host_supported: true, diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index 3b57146461..cacce923af 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -1,4 +1,13 @@ // Build the unit tests. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libinput_tests", srcs: [ diff --git a/libs/math/Android.bp b/libs/math/Android.bp index 3b1edcb43a..55955870e3 100644 --- a/libs/math/Android.bp +++ b/libs/math/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_native_libs_math_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_math_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_static { name: "libmath", host_supported: true, diff --git a/libs/math/OWNERS b/libs/math/OWNERS index 6fb149a89c..72d33bc09e 100644 --- a/libs/math/OWNERS +++ b/libs/math/OWNERS @@ -1,6 +1,3 @@ -jaesoo@google.com -jiyong@google.com mathias@google.com -pawin@google.com randolphs@google.com romainguy@google.com diff --git a/libs/math/tests/Android.bp b/libs/math/tests/Android.bp index 0184f56dc4..4a7c4dd8a4 100644 --- a/libs/math/tests/Android.bp +++ b/libs/math/tests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_libs_math_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_libs_math_license"], +} + cc_test { name: "vec_test", srcs: ["vec_test.cpp"], diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp index 8399e8ce0a..1a4729c610 100644 --- a/libs/nativebase/Android.bp +++ b/libs/nativebase/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_native_libs_nativebase_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_nativebase_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_headers { name: "libnativebase_headers", vendor_available: true, diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index b431cbb6c0..62a4d7f208 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -21,7 +21,7 @@ #include <gui/DisplayEventDispatcher.h> #include <gui/ISurfaceComposer.h> #include <gui/SurfaceComposerClient.h> -#include <nativehelper/JNIHelp.h> +#include <jni.h> #include <private/android/choreographer.h> #include <utils/Looper.h> #include <utils/Timers.h> diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp index f56b3a2178..6e9c9990ec 100644 --- a/libs/nativedisplay/Android.bp +++ b/libs/nativedisplay/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_native_libs_nativedisplay_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_nativedisplay_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_headers { name: "libnativedisplay_headers", export_include_dirs: ["include",], @@ -53,15 +72,12 @@ cc_library_shared { "libcutils", "libEGL", "libGLESv2", - "libnativehelper", - ], - - export_shared_lib_headers: [ - "libnativehelper", ], header_libs: [ "libnativedisplay_headers", + "libnativehelper_header_only", ], + export_header_lib_headers: ["libnativehelper_header_only"], } diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h index 21649304bf..c00ce4ee9c 100644 --- a/libs/nativedisplay/include-private/private/android/choreographer.h +++ b/libs/nativedisplay/include-private/private/android/choreographer.h @@ -18,7 +18,7 @@ #include <apex/choreographer.h> #include <inttypes.h> -#include <nativehelper/JNIHelp.h> +#include <jni.h> namespace android { diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h index f3716674c5..85fe42f6fd 100644 --- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h +++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h @@ -19,7 +19,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> -#include <nativehelper/JNIHelp.h> +#include <jni.h> #include <system/graphics.h> // This file provides a facade API on top of SurfaceTexture, which avoids using diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp index ebe4484873..c214ab7718 100644 --- a/libs/nativedisplay/surfacetexture/surface_texture.cpp +++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp @@ -29,8 +29,7 @@ #include <mutex> #include <jni.h> -#include <nativehelper/JNIHelp.h> -#include <nativehelper/ScopedLocalRef.h> +#include <nativehelper/scoped_local_ref.h> struct ASurfaceTexture { android::sp<android::SurfaceTexture> consumer; diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp index 07e5d860d7..8675439938 100644 --- a/libs/nativewindow/Android.bp +++ b/libs/nativewindow/Android.bp @@ -12,6 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: [ + "frameworks_native_libs_nativewindow_license", + ], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_nativewindow_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + ndk_headers { name: "libnativewindow_ndk_headers", from: "include/android", @@ -28,6 +47,7 @@ cc_library_headers { // TODO(b/153609531): remove when no longer needed. native_bridge_supported: true, min_sdk_version: "29", + host_supported: true, } ndk_library { diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h index ae5e47ba97..dcb05b5536 100644 --- a/libs/nativewindow/include/android/hardware_buffer.h +++ b/libs/nativewindow/include/android/hardware_buffer.h @@ -332,8 +332,6 @@ typedef struct AHardwareBuffer_Planes { */ typedef struct AHardwareBuffer AHardwareBuffer; -#if __ANDROID_API__ >= 26 - /** * Allocates a buffer that matches the passed AHardwareBuffer_Desc. * @@ -501,10 +499,6 @@ int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int so */ int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26); -#endif // __ANDROID_API__ >= 26 - -#if __ANDROID_API__ >= 29 - /** * Test whether the given format and usage flag combination is * allocatable. @@ -540,7 +534,6 @@ int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_I int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage, int32_t fence, const ARect* rect, void** outVirtualAddress, int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29); -#endif // __ANDROID_API__ >= 29 __END_DECLS diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h index 36aad2eced..a3a45e3705 100644 --- a/libs/nativewindow/include/android/native_window.h +++ b/libs/nativewindow/include/android/native_window.h @@ -185,8 +185,6 @@ int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffe */ int32_t ANativeWindow_unlockAndPost(ANativeWindow* window); -#if __ANDROID_API__ >= 26 - /** * Set a transform that will be applied to future buffers posted to the window. * @@ -197,10 +195,6 @@ int32_t ANativeWindow_unlockAndPost(ANativeWindow* window); */ int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26); -#endif // __ANDROID_API__ >= 26 - -#if __ANDROID_API__ >= 28 - /** * All buffers queued after this call will be associated with the dataSpace * parameter specified. @@ -229,10 +223,6 @@ int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpa */ int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28); -#endif // __ANDROID_API__ >= 28 - -#if __ANDROID_API__ >= 30 - /** Compatibility value for ANativeWindow_setFrameRate. */ enum ANativeWindow_FrameRateCompatibility { /** @@ -301,8 +291,6 @@ int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_ */ void ANativeWindow_tryAllocateBuffers(ANativeWindow* window); -#endif // __ANDROID_API__ >= 30 - #ifdef __cplusplus }; #endif diff --git a/libs/nativewindow/tests/Android.bp b/libs/nativewindow/tests/Android.bp index cdb3d2054f..27444584d8 100644 --- a/libs/nativewindow/tests/Android.bp +++ b/libs/nativewindow/tests/Android.bp @@ -14,6 +14,17 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_libs_nativewindow_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: [ + "frameworks_native_libs_nativewindow_license", + ], +} + cc_test { name: "libnativewindow_test", test_suites: [ diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index eb6080fc21..aae1e3157c 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "renderengine_defaults", cflags: [ diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS index b44456b705..c4785060cb 100644 --- a/libs/renderengine/OWNERS +++ b/libs/renderengine/OWNERS @@ -1,4 +1,5 @@ alecmouri@google.com +djsollen@google.com jreck@google.com lpy@google.com -stoza@google.com +scroggo@google.com diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp index e98babc30c..fdb3a6f8d0 100644 --- a/libs/renderengine/tests/Android.bp +++ b/libs/renderengine/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "librenderengine_test", defaults: ["surfaceflinger_defaults"], diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp index e8154a6931..497c33c386 100644 --- a/libs/sensor/Android.bp +++ b/libs/sensor/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libsensor", diff --git a/libs/sensor/tests/Android.bp b/libs/sensor/tests/Android.bp index c9a7668563..8fdb003a5d 100644 --- a/libs/sensor/tests/Android.bp +++ b/libs/sensor/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libsensor_test", diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp index 4a606ffec2..00514c4417 100644 --- a/libs/sensorprivacy/Android.bp +++ b/libs/sensorprivacy/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libsensorprivacy", diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 47eb59fb0a..07760ab765 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -12,6 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + default_applicable_licenses: ["frameworks_native_libs_ui_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "frameworks_native_libs_ui_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + ], + license_text: [ + "NOTICE", + ], +} + cc_library_shared { name: "libui", vendor_available: true, @@ -72,7 +89,7 @@ cc_library_shared { "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.allocator@4.0", - "android.hardware.graphics.common-unstable-ndk_platform", + "android.hardware.graphics.common-V2-ndk_platform", "android.hardware.graphics.common@1.2", "android.hardware.graphics.mapper@2.0", "android.hardware.graphics.mapper@2.1", @@ -89,7 +106,7 @@ cc_library_shared { export_shared_lib_headers: [ "android.hardware.graphics.common@1.2", - "android.hardware.graphics.common-unstable-ndk_platform", + "android.hardware.graphics.common-V2-ndk_platform", "android.hardware.graphics.mapper@4.0", "libgralloctypes", ], diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS index b1317b169e..a0b5fe7119 100644 --- a/libs/ui/OWNERS +++ b/libs/ui/OWNERS @@ -1,7 +1,7 @@ +adyabr@google.com alecmouri@google.com chrisforbes@google.com jreck@google.com lpy@google.com mathias@google.com romainguy@google.com -stoza@google.com diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index b53342cb79..bc53346274 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_libs_ui_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_libs_ui_license"], +} + cc_test { name: "Region_test", shared_libs: ["libui"], diff --git a/libs/ui/tools/Android.bp b/libs/ui/tools/Android.bp index fb46c2b20c..c28c303c0c 100644 --- a/libs/ui/tools/Android.bp +++ b/libs/ui/tools/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_libs_ui_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_libs_ui_license"], +} + cc_defaults { name: "libui_tools_default", clang_cflags: [ diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp index 33ab8bab51..11b09bdced 100644 --- a/libs/vibrator/Android.bp +++ b/libs/vibrator/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libvibrator", diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp index 802015180e..f2a313cb8a 100644 --- a/libs/vibrator/fuzzer/Android.bp +++ b/libs/vibrator/fuzzer/Android.bp @@ -17,6 +17,15 @@ ***************************************************************************** */ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_fuzz { name: "vibrator_fuzzer", diff --git a/libs/vr/Android.bp b/libs/vr/Android.bp index e8176cf6b6..b308895faf 100644 --- a/libs/vr/Android.bp +++ b/libs/vr/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-BSD + // legacy_notice + default_applicable_licenses: ["frameworks_native_license"], +} + subdirs = [ "*", ] diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp index 13af470a26..2eb2f9f149 100644 --- a/libs/vr/libbroadcastring/Android.bp +++ b/libs/vr/libbroadcastring/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libbroadcastring", clang: true, diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp index 37c19d43f7..45bdd35519 100644 --- a/libs/vr/libbufferhub/Android.bp +++ b/libs/vr/libbufferhub/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libbufferhub_headers", export_include_dirs: ["include"], diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp index 77c79112de..f372bd79c2 100644 --- a/libs/vr/libbufferhubqueue/Android.bp +++ b/libs/vr/libbufferhubqueue/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + sourceFiles = [ "buffer_hub_queue_client.cpp", "buffer_hub_queue_parcelable.cpp", diff --git a/libs/vr/libbufferhubqueue/benchmarks/Android.bp b/libs/vr/libbufferhubqueue/benchmarks/Android.bp index ef1eed6d0a..fc1f376a73 100644 --- a/libs/vr/libbufferhubqueue/benchmarks/Android.bp +++ b/libs/vr/libbufferhubqueue/benchmarks/Android.bp @@ -1,4 +1,15 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_benchmark { srcs: ["buffer_transport_benchmark.cpp"], shared_libs: [ diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp index a33792177b..e883916f1a 100644 --- a/libs/vr/libbufferhubqueue/tests/Android.bp +++ b/libs/vr/libbufferhubqueue/tests/Android.bp @@ -1,4 +1,15 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + header_libraries = [ "libdvr_headers", ] diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp index 8c354fbc18..365a676bc4 100644 --- a/libs/vr/libdisplay/Android.bp +++ b/libs/vr/libdisplay/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + sourceFiles = [ "display_client.cpp", "display_manager_client.cpp", diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp index d5a19d3e6c..83c30d7010 100644 --- a/libs/vr/libdvr/Android.bp +++ b/libs/vr/libdvr/Android.bp @@ -13,6 +13,17 @@ // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libdvr_headers", export_include_dirs: ["include"], diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp index 3260447390..4ed80a4929 100644 --- a/libs/vr/libdvr/tests/Android.bp +++ b/libs/vr/libdvr/tests/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { srcs: [ "dvr_display_manager-test.cpp", diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp index e75176846e..9e1e516724 100644 --- a/libs/vr/libdvrcommon/Android.bp +++ b/libs/vr/libdvrcommon/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + localIncludeFiles = [ "include", ] diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp index 24ba83048d..c1f6da3b10 100644 --- a/libs/vr/libpdx/Android.bp +++ b/libs/vr/libpdx/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libpdx_headers", export_include_dirs: ["private"], diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp index b36e0deea0..cc32b1822b 100644 --- a/libs/vr/libpdx/fuzz/Android.bp +++ b/libs/vr/libpdx/fuzz/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_fuzz { name: "libpdx_service_dispatcher_fuzzer", clang: true, diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp index b3534de101..ea73d7a9db 100644 --- a/libs/vr/libpdx_default_transport/Android.bp +++ b/libs/vr/libpdx_default_transport/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "pdx_default_transport_compiler_defaults", clang: true, @@ -75,4 +86,3 @@ cc_binary { "libpdx_default_transport", ], } - diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp index 1d6eea29a6..532d1a767c 100644 --- a/libs/vr/libpdx_uds/Android.bp +++ b/libs/vr/libpdx_uds/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libpdx_uds", clang: true, diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp index 35d3dea9de..5beee359b5 100644 --- a/libs/vr/libperformance/Android.bp +++ b/libs/vr/libperformance/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + sourceFiles = [ "performance_client.cpp", "performance_rpc.cpp", diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp index 2cd6a28e2f..6f2ada4633 100644 --- a/libs/vr/libvr_manager/Android.bp +++ b/libs/vr/libvr_manager/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libvr_manager", srcs: [ diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp index abc64bde5a..8aca9a5adc 100644 --- a/libs/vr/libvrflinger/Android.bp +++ b/libs/vr/libvrflinger/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + sourceFiles = [ "acquired_buffer.cpp", "epoll_event_dispatcher.cpp", diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp index 7fafd3bf50..dafd35454f 100644 --- a/libs/vr/libvrflinger/tests/Android.bp +++ b/libs/vr/libvrflinger/tests/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + shared_libs = [ "android.hardware.configstore-utils", "android.hardware.configstore@1.0", diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp index 85427906f1..8f566a0a20 100644 --- a/libs/vr/libvrsensor/Android.bp +++ b/libs/vr/libvrsensor/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + sourceFiles = [ "pose_client.cpp", "latency_model.cpp", @@ -52,4 +63,3 @@ cc_library { header_libs: ["libdvr_headers"], name: "libvrsensor", } - diff --git a/opengl/Android.bp b/opengl/Android.bp index 48abdce712..748f7953c9 100644 --- a/opengl/Android.bp +++ b/opengl/Android.bp @@ -12,6 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-BSD + // SPDX-license-identifier-MIT + // legacy_notice + default_applicable_licenses: ["frameworks_native_license"], +} + ndk_headers { name: "libEGL_headers", from: "include", diff --git a/opengl/OWNERS b/opengl/OWNERS index b505712eb5..a9bd4bb2e2 100644 --- a/opengl/OWNERS +++ b/opengl/OWNERS @@ -1,7 +1,6 @@ chrisforbes@google.com cnorthrop@google.com -courtneygo@google.com ianelliott@google.com jessehall@google.com lpy@google.com -zzyiwei@google.com +timvp@google.com diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp index ed2ed831c9..3ee0fafdb1 100644 --- a/opengl/libs/Android.bp +++ b/opengl/libs/Android.bp @@ -1,4 +1,13 @@ // Build the ETC1 library +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library { name: "libETC1", srcs: ["ETC1/etc1.cpp"], diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp index f82c2a4ee7..4f85eff93d 100644 --- a/opengl/libs/EGL/egl_angle_platform.cpp +++ b/opengl/libs/EGL/egl_angle_platform.cpp @@ -24,16 +24,16 @@ #include <EGL/Platform.h> #pragma GCC diagnostic pop +#include <android-base/properties.h> #include <android/dlext.h> #include <dlfcn.h> #include <graphicsenv/GraphicsEnv.h> -#include <time.h> #include <log/log.h> +#include <time.h> #include <vndksupport/linker.h> namespace angle { -constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so"; constexpr int kAngleDlFlags = RTLD_LOCAL | RTLD_NOW; static GetDisplayPlatformFunc angleGetDisplayPlatform = nullptr; @@ -107,18 +107,36 @@ bool initializeAnglePlatform(EGLDisplay dpy) { android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace(); void* so = nullptr; if (ns) { + // Loading from an APK, so hard-code the suffix to "_angle". + constexpr char kAngleEs2Lib[] = "libGLESv2_angle.so"; const android_dlextinfo dlextinfo = { .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = ns, }; so = android_dlopen_ext(kAngleEs2Lib, kAngleDlFlags, &dlextinfo); + if (so) { + ALOGD("dlopen_ext from APK (%s) success at %p", kAngleEs2Lib, so); + } else { + ALOGE("dlopen_ext(\"%s\") failed: %s", kAngleEs2Lib, dlerror()); + return false; + } } else { // If we are here, ANGLE is loaded as built-in gl driver in the sphal. - so = android_load_sphal_library(kAngleEs2Lib, kAngleDlFlags); - } - if (!so) { - ALOGE("%s failed to dlopen %s!", __FUNCTION__, kAngleEs2Lib); - return false; + // Get the specified ANGLE library filename suffix. + std::string angleEs2LibSuffix = android::base::GetProperty("ro.hardware.egl", ""); + if (angleEs2LibSuffix.empty()) { + ALOGE("%s failed to get valid ANGLE library filename suffix!", __FUNCTION__); + return false; + } + + std::string angleEs2LibName = "libGLESv2_" + angleEs2LibSuffix + ".so"; + so = android_load_sphal_library(angleEs2LibName.c_str(), kAngleDlFlags); + if (so) { + ALOGD("dlopen (%s) success at %p", angleEs2LibName.c_str(), so); + } else { + ALOGE("%s failed to dlopen %s!", __FUNCTION__, angleEs2LibName.c_str()); + return false; + } } angleGetDisplayPlatform = @@ -130,8 +148,7 @@ bool initializeAnglePlatform(EGLDisplay dpy) { } angleResetDisplayPlatform = - reinterpret_cast<ResetDisplayPlatformFunc>( - eglGetProcAddress("ANGLEResetDisplayPlatform")); + reinterpret_cast<ResetDisplayPlatformFunc>(dlsym(so, "ANGLEResetDisplayPlatform")); PlatformMethods* platformMethods = nullptr; if (!((angleGetDisplayPlatform)(dpy, g_PlatformMethodNames, diff --git a/opengl/tests/Android.bp b/opengl/tests/Android.bp index 639f351c69..da717bddf8 100644 --- a/opengl/tests/Android.bp +++ b/opengl/tests/Android.bp @@ -1,4 +1,16 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-BSD + // SPDX-license-identifier-MIT + // legacy_notice + default_applicable_licenses: ["frameworks_native_license"], +} + subdirs = [ "angeles", "configdump", @@ -16,4 +28,3 @@ subdirs = [ "hwc", "lib", ] - diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp index e3912a84e6..51c937614f 100644 --- a/opengl/tests/EGLTest/Android.bp +++ b/opengl/tests/EGLTest/Android.bp @@ -1,4 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "EGL_test", diff --git a/opengl/tests/angeles/Android.bp b/opengl/tests/angeles/Android.bp index 5c398a6323..5b81501241 100644 --- a/opengl/tests/angeles/Android.bp +++ b/opengl/tests/angeles/Android.bp @@ -1,5 +1,50 @@ // Copyright 2006 The Android Open Source Project +package { + default_applicable_licenses: [ + "frameworks_native_opengl_tests_angeles_license", + ], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// +// large-scale-change included anything that looked like it might be a license +// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc. +// +// Please consider removing redundant or irrelevant files from 'license_text:'. +// +// large-scale-change filtered out the below license kinds as false-positives: +// SPDX-license-identifier-LGPL +// SPDX-license-identifier-LGPL-2.1 +// SPDX-license-identifier-LGPL-3.0 +// See: http://go/android-license-faq +license { + name: "frameworks_native_opengl_tests_angeles_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-BSD", + "SPDX-license-identifier-MIT", + "legacy_notice", + ], + license_text: [ + "license-BSD.txt", + "license-LGPL.txt", + "license.txt", + ], +} + cc_test { name: "angeles", diff --git a/opengl/tests/configdump/Android.bp b/opengl/tests/configdump/Android.bp index ee96797030..ffb0c1f0c4 100644 --- a/opengl/tests/configdump/Android.bp +++ b/opengl/tests/configdump/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-configdump", diff --git a/opengl/tests/fillrate/Android.bp b/opengl/tests/fillrate/Android.bp index 689cee42d5..e4bff014fc 100644 --- a/opengl/tests/fillrate/Android.bp +++ b/opengl/tests/fillrate/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-fillrate", diff --git a/opengl/tests/filter/Android.bp b/opengl/tests/filter/Android.bp index 23241e1116..3b92b37634 100644 --- a/opengl/tests/filter/Android.bp +++ b/opengl/tests/filter/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-filter", diff --git a/opengl/tests/finish/Android.bp b/opengl/tests/finish/Android.bp index be20851e8f..c2dfbc35b9 100644 --- a/opengl/tests/finish/Android.bp +++ b/opengl/tests/finish/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-finish", diff --git a/opengl/tests/gl2_basic/Android.bp b/opengl/tests/gl2_basic/Android.bp index f4538adb54..c54bdf335d 100644 --- a/opengl/tests/gl2_basic/Android.bp +++ b/opengl/tests/gl2_basic/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gl2_basic", diff --git a/opengl/tests/gl2_cameraeye/Android.bp b/opengl/tests/gl2_cameraeye/Android.bp index 00e00dfc91..6b8ee85d9c 100644 --- a/opengl/tests/gl2_cameraeye/Android.bp +++ b/opengl/tests/gl2_cameraeye/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "GL2CameraEye", // Only compile source java files in this apk. diff --git a/opengl/tests/gl2_copyTexImage/Android.bp b/opengl/tests/gl2_copyTexImage/Android.bp index 87fa7ea37d..0a84d254a5 100644 --- a/opengl/tests/gl2_copyTexImage/Android.bp +++ b/opengl/tests/gl2_copyTexImage/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gl2_copyTexImage", diff --git a/opengl/tests/gl2_java/Android.bp b/opengl/tests/gl2_java/Android.bp index a8e5d7d70b..a33075e3b7 100644 --- a/opengl/tests/gl2_java/Android.bp +++ b/opengl/tests/gl2_java/Android.bp @@ -1,6 +1,15 @@ //######################################################################## // OpenGL ES 2.0 Java sample //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "GL2Java", srcs: ["**/*.java"], diff --git a/opengl/tests/gl2_jni/Android.bp b/opengl/tests/gl2_jni/Android.bp index 8d4323f9ca..79773cb05f 100644 --- a/opengl/tests/gl2_jni/Android.bp +++ b/opengl/tests/gl2_jni/Android.bp @@ -3,6 +3,15 @@ // This makefile builds both an activity and a shared library. //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "GL2JNI", srcs: ["**/*.java"], diff --git a/opengl/tests/gl2_yuvtex/Android.bp b/opengl/tests/gl2_yuvtex/Android.bp index b64d94d320..fadf0e8fc5 100644 --- a/opengl/tests/gl2_yuvtex/Android.bp +++ b/opengl/tests/gl2_yuvtex/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gl2_yuvtex", diff --git a/opengl/tests/gl_basic/Android.bp b/opengl/tests/gl_basic/Android.bp index 5eed17e876..f777401b6f 100644 --- a/opengl/tests/gl_basic/Android.bp +++ b/opengl/tests/gl_basic/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gl_basic", diff --git a/opengl/tests/gl_jni/Android.bp b/opengl/tests/gl_jni/Android.bp index 0cb129a117..dc46483551 100644 --- a/opengl/tests/gl_jni/Android.bp +++ b/opengl/tests/gl_jni/Android.bp @@ -4,6 +4,15 @@ //######################################################################## // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "GLJNI", srcs: ["**/*.java"], diff --git a/opengl/tests/gl_perf/Android.bp b/opengl/tests/gl_perf/Android.bp index 25a317c3e3..ca0f7e8e33 100644 --- a/opengl/tests/gl_perf/Android.bp +++ b/opengl/tests/gl_perf/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gl2_perf", diff --git a/opengl/tests/gl_perfapp/Android.bp b/opengl/tests/gl_perfapp/Android.bp index 66afb6a82c..2f623462cf 100644 --- a/opengl/tests/gl_perfapp/Android.bp +++ b/opengl/tests/gl_perfapp/Android.bp @@ -2,6 +2,15 @@ // OpenGL ES Perf App // This makefile builds both an activity and a shared library. //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "GLPerf", srcs: ["**/*.java"], diff --git a/opengl/tests/gl_yuvtex/Android.bp b/opengl/tests/gl_yuvtex/Android.bp index 9b4924ab82..784418679c 100644 --- a/opengl/tests/gl_yuvtex/Android.bp +++ b/opengl/tests/gl_yuvtex/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gl_yuvtex", diff --git a/opengl/tests/gldual/Android.bp b/opengl/tests/gldual/Android.bp index 1006d44e47..3d6e677f0d 100644 --- a/opengl/tests/gldual/Android.bp +++ b/opengl/tests/gldual/Android.bp @@ -4,6 +4,15 @@ //######################################################################## // Build activity +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "GLDual", srcs: ["**/*.java"], diff --git a/opengl/tests/gralloc/Android.bp b/opengl/tests/gralloc/Android.bp index 33c3dbaa17..5fb4556697 100644 --- a/opengl/tests/gralloc/Android.bp +++ b/opengl/tests/gralloc/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "test-opengl-gralloc", diff --git a/opengl/tests/hwc/Android.bp b/opengl/tests/hwc/Android.bp index 55f058f922..719eb114a1 100644 --- a/opengl/tests/hwc/Android.bp +++ b/opengl/tests/hwc/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "hwc_tests_defaults", diff --git a/opengl/tests/lib/Android.bp b/opengl/tests/lib/Android.bp index 2f6095d8e7..05c9397dfa 100644 --- a/opengl/tests/lib/Android.bp +++ b/opengl/tests/lib/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libglTest", diff --git a/opengl/tests/lighting1709/Android.bp b/opengl/tests/lighting1709/Android.bp index e734dd1d2c..79daa26096 100644 --- a/opengl/tests/lighting1709/Android.bp +++ b/opengl/tests/lighting1709/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_test { name: "LightingTest", srcs: ["**/*.java"], diff --git a/opengl/tests/linetex/Android.bp b/opengl/tests/linetex/Android.bp index dbc2cdbd44..61976e599f 100644 --- a/opengl/tests/linetex/Android.bp +++ b/opengl/tests/linetex/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-opengl-linetex", srcs: ["linetex.cpp"], diff --git a/opengl/tests/swapinterval/Android.bp b/opengl/tests/swapinterval/Android.bp index eed4dff3a5..a76f4cfb9a 100644 --- a/opengl/tests/swapinterval/Android.bp +++ b/opengl/tests/swapinterval/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-opengl-swapinterval", srcs: ["swapinterval.cpp"], diff --git a/opengl/tests/testFramerate/Android.bp b/opengl/tests/testFramerate/Android.bp index 5aa83b0753..4334d88749 100644 --- a/opengl/tests/testFramerate/Android.bp +++ b/opengl/tests/testFramerate/Android.bp @@ -2,6 +2,15 @@ // Test framerate and look for hiccups //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "TestFramerate", srcs: ["**/*.java"], diff --git a/opengl/tests/testLatency/Android.bp b/opengl/tests/testLatency/Android.bp index c516dc3d17..473cb426cf 100644 --- a/opengl/tests/testLatency/Android.bp +++ b/opengl/tests/testLatency/Android.bp @@ -1,6 +1,15 @@ //######################################################################## // Test end-to-end latency. //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "TestLatency", sdk_version: "8", diff --git a/opengl/tests/testPauseResume/Android.bp b/opengl/tests/testPauseResume/Android.bp index 810e895ce2..8171e1fc8e 100644 --- a/opengl/tests/testPauseResume/Android.bp +++ b/opengl/tests/testPauseResume/Android.bp @@ -1,4 +1,13 @@ // OpenGL ES JNI sample +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "TestEGL", srcs: ["**/*.java"], diff --git a/opengl/tests/testViewport/Android.bp b/opengl/tests/testViewport/Android.bp index 629b573a2a..13ce3ad481 100644 --- a/opengl/tests/testViewport/Android.bp +++ b/opengl/tests/testViewport/Android.bp @@ -2,6 +2,15 @@ // OpenGL ES JNI sample // This makefile builds both an activity and a shared library. //######################################################################## +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + android_app { name: "TestViewport", srcs: ["**/*.java"], diff --git a/opengl/tests/textures/Android.bp b/opengl/tests/textures/Android.bp index 84adda2aa4..f113ff78d2 100644 --- a/opengl/tests/textures/Android.bp +++ b/opengl/tests/textures/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-opengl-textures", srcs: ["textures.cpp"], diff --git a/opengl/tests/tritex/Android.bp b/opengl/tests/tritex/Android.bp index 390397b9da..759582cab6 100644 --- a/opengl/tests/tritex/Android.bp +++ b/opengl/tests/tritex/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-opengl-tritex", srcs: ["tritex.cpp"], diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp index 12ad47e15a..e6fb2c3660 100644 --- a/services/audiomanager/Android.bp +++ b/services/audiomanager/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libaudiomanager", diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp index c3da216002..72bd29254d 100644 --- a/services/automotive/display/Android.bp +++ b/services/automotive/display/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "android.frameworks.automotive.display@1.0-service", defaults: ["hidl_defaults"], diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp index 66ee8ff55e..1e3799185e 100644 --- a/services/batteryservice/Android.bp +++ b/services/batteryservice/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libbatteryservice_headers", vendor_available: true, diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp index 4d2d87352b..8681784405 100644 --- a/services/displayservice/Android.bp +++ b/services/displayservice/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libdisplayservicehidl", diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp index 9a9bca1478..b9b6a19606 100644 --- a/services/gpuservice/Android.bp +++ b/services/gpuservice/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "gpuservice_defaults", cflags: [ diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS index 5d028393f6..ac300d009e 100644 --- a/services/gpuservice/OWNERS +++ b/services/gpuservice/OWNERS @@ -1,3 +1,2 @@ chrisforbes@google.com lpy@google.com -zzyiwei@google.com diff --git a/services/gpuservice/bpfprogs/Android.bp b/services/gpuservice/bpfprogs/Android.bp index b8758146cc..9842ed7c3c 100644 --- a/services/gpuservice/bpfprogs/Android.bp +++ b/services/gpuservice/bpfprogs/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + bpf { name: "gpu_mem.o", srcs: ["gpu_mem.c"], diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp index b2230b6c01..830e53d534 100644 --- a/services/gpuservice/gpumem/Android.bp +++ b/services/gpuservice/gpumem/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libgpumem", srcs: [ diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp index f52602ab78..54291ad6c6 100644 --- a/services/gpuservice/gpustats/Android.bp +++ b/services/gpuservice/gpustats/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libgfxstats", srcs: [ diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp index 940a26b3f5..6d87c45921 100644 --- a/services/gpuservice/tests/unittests/Android.bp +++ b/services/gpuservice/tests/unittests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "gpuservice_unittest", test_suites: ["device-tests"], @@ -20,6 +29,7 @@ cc_test { }, srcs: [ "GpuMemTest.cpp", + "GpuMemTracerTest.cpp", "GpuStatsTest.cpp", ], shared_libs: [ @@ -29,14 +39,19 @@ cc_test { "libcutils", "libgfxstats", "libgpumem", + "libgpumemtracer", "libgraphicsenv", "liblog", + "libprotobuf-cpp-lite", + "libprotoutil", "libstatslog", "libstatspull", "libutils", ], static_libs: [ "libgmock", + "libperfetto_client_experimental", + "perfetto_trace_protos", ], require_root: true, } diff --git a/services/gpuservice/tests/unittests/GpuMemTest.cpp b/services/gpuservice/tests/unittests/GpuMemTest.cpp index c5f8859e45..e916221c2e 100644 --- a/services/gpuservice/tests/unittests/GpuMemTest.cpp +++ b/services/gpuservice/tests/unittests/GpuMemTest.cpp @@ -59,7 +59,6 @@ public: } void SetUp() override { - SKIP_IF_BPF_NOT_SUPPORTED; bpf::setrlimitForTest(); mGpuMem = std::make_unique<GpuMem>(); @@ -87,8 +86,6 @@ public: }; TEST_F(GpuMemTest, validGpuMemTotalBpfPaths) { - SKIP_IF_BPF_NOT_SUPPORTED; - EXPECT_EQ(mTestableGpuMem.getGpuMemTraceGroup(), "gpu_mem"); EXPECT_EQ(mTestableGpuMem.getGpuMemTotalTracepoint(), "gpu_mem_total"); EXPECT_EQ(mTestableGpuMem.getGpuMemTotalProgPath(), @@ -97,20 +94,16 @@ TEST_F(GpuMemTest, validGpuMemTotalBpfPaths) { } TEST_F(GpuMemTest, bpfInitializationFailed) { - SKIP_IF_BPF_NOT_SUPPORTED; - EXPECT_EQ(dumpsys(), "Failed to initialize GPU memory eBPF\n"); } TEST_F(GpuMemTest, gpuMemTotalMapEmpty) { - SKIP_IF_BPF_NOT_SUPPORTED; mTestableGpuMem.setGpuMemTotalMap(mTestMap); EXPECT_EQ(dumpsys(), "GPU memory total usage map is empty\n"); } TEST_F(GpuMemTest, globalMemTotal) { - SKIP_IF_BPF_NOT_SUPPORTED; ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY)); mTestableGpuMem.setGpuMemTotalMap(mTestMap); @@ -118,7 +111,6 @@ TEST_F(GpuMemTest, globalMemTotal) { } TEST_F(GpuMemTest, missingGlobalMemTotal) { - SKIP_IF_BPF_NOT_SUPPORTED; ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY)); mTestableGpuMem.setGpuMemTotalMap(mTestMap); @@ -126,7 +118,6 @@ TEST_F(GpuMemTest, missingGlobalMemTotal) { } TEST_F(GpuMemTest, procMemTotal) { - SKIP_IF_BPF_NOT_SUPPORTED; ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY)); ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY)); mTestableGpuMem.setGpuMemTotalMap(mTestMap); @@ -146,7 +137,6 @@ TEST_F(GpuMemTest, procMemTotal) { } TEST_F(GpuMemTest, traverseGpuMemTotals) { - SKIP_IF_BPF_NOT_SUPPORTED; ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY)); ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY)); ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY)); diff --git a/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp b/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp new file mode 100644 index 0000000000..d76f039a6d --- /dev/null +++ b/services/gpuservice/tests/unittests/GpuMemTracerTest.cpp @@ -0,0 +1,196 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "gpuservice_unittest" + +#include <bpf/BpfMap.h> +#include <gpumem/GpuMem.h> +#include <gtest/gtest.h> +#include <perfetto/trace/trace.pb.h> +#include <tracing/GpuMemTracer.h> + +#include "TestableGpuMem.h" + +namespace android { + +constexpr uint32_t TEST_MAP_SIZE = 10; +constexpr uint64_t TEST_GLOBAL_KEY = 0; +constexpr uint32_t TEST_GLOBAL_PID = 0; +constexpr uint64_t TEST_GLOBAL_VAL = 123; +constexpr uint32_t TEST_GLOBAL_GPU_ID = 0; +constexpr uint64_t TEST_PROC_KEY_1 = 1; +constexpr uint32_t TEST_PROC_PID_1 = 1; +constexpr uint64_t TEST_PROC_VAL_1 = 234; +constexpr uint32_t TEST_PROC_1_GPU_ID = 0; +constexpr uint64_t TEST_PROC_KEY_2 = 4294967298; // (1 << 32) + 2 +constexpr uint32_t TEST_PROC_PID_2 = 2; +constexpr uint64_t TEST_PROC_VAL_2 = 345; +constexpr uint32_t TEST_PROC_2_GPU_ID = 1; + +class GpuMemTracerTest : public testing::Test { +public: + GpuMemTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + ~GpuMemTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + void SetUp() override { + bpf::setrlimitForTest(); + + mGpuMem = std::make_shared<GpuMem>(); + mGpuMemTracer = std::make_unique<GpuMemTracer>(); + mGpuMemTracer->initializeForTest(mGpuMem); + mTestableGpuMem = TestableGpuMem(mGpuMem.get()); + + errno = 0; + mTestMap = bpf::BpfMap<uint64_t, uint64_t>(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, + BPF_F_NO_PREALLOC); + + EXPECT_EQ(0, errno); + EXPECT_LE(0, mTestMap.getMap().get()); + EXPECT_TRUE(mTestMap.isValid()); + } + + int getTracerThreadCount() { return mGpuMemTracer->tracerThreadCount; } + + std::vector<perfetto::protos::TracePacket> readGpuMemTotalPacketsBlocking( + perfetto::TracingSession* tracingSession) { + std::vector<char> raw_trace = tracingSession->ReadTraceBlocking(); + perfetto::protos::Trace trace; + trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())); + + std::vector<perfetto::protos::TracePacket> packets; + for (const auto& packet : trace.packet()) { + if (!packet.has_gpu_mem_total_event()) { + continue; + } + packets.emplace_back(packet); + } + return packets; + } + + std::shared_ptr<GpuMem> mGpuMem; + TestableGpuMem mTestableGpuMem; + std::unique_ptr<GpuMemTracer> mGpuMemTracer; + bpf::BpfMap<uint64_t, uint64_t> mTestMap; +}; + +static constexpr uint64_t getSizeForPid(uint32_t pid) { + switch (pid) { + case TEST_GLOBAL_PID: + return TEST_GLOBAL_VAL; + case TEST_PROC_PID_1: + return TEST_PROC_VAL_1; + case TEST_PROC_PID_2: + return TEST_PROC_VAL_2; + } + return 0; +} + +static constexpr uint32_t getGpuIdForPid(uint32_t pid) { + switch (pid) { + case TEST_GLOBAL_PID: + return TEST_GLOBAL_GPU_ID; + case TEST_PROC_PID_1: + return TEST_PROC_1_GPU_ID; + case TEST_PROC_PID_2: + return TEST_PROC_2_GPU_ID; + } + return 0; +} + +TEST_F(GpuMemTracerTest, traceInitialCountersAfterGpuMemInitialize) { + ASSERT_RESULT_OK(mTestMap.writeValue(TEST_GLOBAL_KEY, TEST_GLOBAL_VAL, BPF_ANY)); + ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_1, TEST_PROC_VAL_1, BPF_ANY)); + ASSERT_RESULT_OK(mTestMap.writeValue(TEST_PROC_KEY_2, TEST_PROC_VAL_2, BPF_ANY)); + mTestableGpuMem.setGpuMemTotalMap(mTestMap); + mTestableGpuMem.setInitialized(); + + // Only 1 tracer thread should be existing for test. + EXPECT_EQ(getTracerThreadCount(), 1); + auto tracingSession = mGpuMemTracer->getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Sleep for a short time to let the tracer thread finish its work + sleep(1); + tracingSession->StopBlocking(); + + // The test tracer thread should have finished its execution by now. + EXPECT_EQ(getTracerThreadCount(), 0); + + auto packets = readGpuMemTotalPacketsBlocking(tracingSession.get()); + EXPECT_EQ(packets.size(), 3); + + const auto& packet0 = packets[0]; + ASSERT_TRUE(packet0.has_timestamp()); + ASSERT_TRUE(packet0.has_gpu_mem_total_event()); + const auto& gpuMemEvent0 = packet0.gpu_mem_total_event(); + ASSERT_TRUE(gpuMemEvent0.has_pid()); + const auto& pid0 = gpuMemEvent0.pid(); + ASSERT_TRUE(gpuMemEvent0.has_size()); + EXPECT_EQ(gpuMemEvent0.size(), getSizeForPid(pid0)); + ASSERT_TRUE(gpuMemEvent0.has_gpu_id()); + EXPECT_EQ(gpuMemEvent0.gpu_id(), getGpuIdForPid(pid0)); + + const auto& packet1 = packets[1]; + ASSERT_TRUE(packet1.has_timestamp()); + ASSERT_TRUE(packet1.has_gpu_mem_total_event()); + const auto& gpuMemEvent1 = packet1.gpu_mem_total_event(); + ASSERT_TRUE(gpuMemEvent1.has_pid()); + const auto& pid1 = gpuMemEvent1.pid(); + ASSERT_TRUE(gpuMemEvent1.has_size()); + EXPECT_EQ(gpuMemEvent1.size(), getSizeForPid(pid1)); + ASSERT_TRUE(gpuMemEvent1.has_gpu_id()); + EXPECT_EQ(gpuMemEvent1.gpu_id(), getGpuIdForPid(pid1)); + + const auto& packet2 = packets[2]; + ASSERT_TRUE(packet2.has_timestamp()); + ASSERT_TRUE(packet2.has_gpu_mem_total_event()); + const auto& gpuMemEvent2 = packet2.gpu_mem_total_event(); + ASSERT_TRUE(gpuMemEvent2.has_pid()); + const auto& pid2 = gpuMemEvent2.pid(); + ASSERT_TRUE(gpuMemEvent2.has_size()); + EXPECT_EQ(gpuMemEvent2.size(), getSizeForPid(pid2)); + ASSERT_TRUE(gpuMemEvent2.has_gpu_id()); + EXPECT_EQ(gpuMemEvent2.gpu_id(), getGpuIdForPid(pid2)); +} + +TEST_F(GpuMemTracerTest, noTracingWithoutGpuMemInitialize) { + // Only 1 tracer thread should be existing for test. + EXPECT_EQ(getTracerThreadCount(), 1); + + auto tracingSession = mGpuMemTracer->getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Sleep for a short time to let the tracer thread finish its work + sleep(1); + tracingSession->StopBlocking(); + + // The test tracer thread should have finished its execution by now. + EXPECT_EQ(getTracerThreadCount(), 0); + + auto packets = readGpuMemTotalPacketsBlocking(tracingSession.get()); + EXPECT_EQ(packets.size(), 0); +} +} // namespace android diff --git a/services/gpuservice/tracing/Android.bp b/services/gpuservice/tracing/Android.bp index 919fed3cec..a1bc1edad8 100644 --- a/services/gpuservice/tracing/Android.bp +++ b/services/gpuservice/tracing/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libgpumemtracer", srcs: [ diff --git a/services/gpuservice/tracing/GpuMemTracer.cpp b/services/gpuservice/tracing/GpuMemTracer.cpp index 6366e1d8e2..44a30eae13 100644 --- a/services/gpuservice/tracing/GpuMemTracer.cpp +++ b/services/gpuservice/tracing/GpuMemTracer.cpp @@ -44,9 +44,35 @@ void GpuMemTracer::initialize(std::shared_ptr<GpuMem> gpuMem) { args.backends = perfetto::kSystemBackend; perfetto::Tracing::Initialize(args); registerDataSource(); - std::thread tracerThread(&GpuMemTracer::threadLoop, this); + std::thread tracerThread(&GpuMemTracer::threadLoop, this, true); pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThread"); tracerThread.detach(); + tracerThreadCount++; +} + +void GpuMemTracer::initializeForTest(std::shared_ptr<GpuMem> gpuMem) { + mGpuMem = gpuMem; + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + registerDataSource(); + std::thread tracerThread(&GpuMemTracer::threadLoop, this, false); + pthread_setname_np(tracerThread.native_handle(), "GpuMemTracerThreadForTest"); + tracerThread.detach(); + tracerThreadCount++; +} + +// Each tracing session can be used for a single block of Start -> Stop. +std::unique_ptr<perfetto::TracingSession> GpuMemTracer::getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(500); + cfg.add_buffers()->set_size_kb(1024); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name(GpuMemTracer::kGpuMemDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; } void GpuMemTracer::registerDataSource() { @@ -55,8 +81,8 @@ void GpuMemTracer::registerDataSource() { GpuMemDataSource::Register(dsd); } -void GpuMemTracer::threadLoop() { - while (true) { +void GpuMemTracer::threadLoop(bool infiniteLoop) { + do { { std::unique_lock<std::mutex> lock(GpuMemTracer::sTraceMutex); while (!sTraceStarted) { @@ -68,7 +94,11 @@ void GpuMemTracer::threadLoop() { std::lock_guard<std::mutex> lock(GpuMemTracer::sTraceMutex); sTraceStarted = false; } - } + } while (infiniteLoop); + + // Thread loop is exiting. Reduce the tracerThreadCount to reflect the number of active threads + // in the wait loop. + tracerThreadCount--; } void GpuMemTracer::traceInitialCounters() { diff --git a/services/gpuservice/tracing/include/tracing/GpuMemTracer.h b/services/gpuservice/tracing/include/tracing/GpuMemTracer.h index 40deb4c212..ae871f11cb 100644 --- a/services/gpuservice/tracing/include/tracing/GpuMemTracer.h +++ b/services/gpuservice/tracing/include/tracing/GpuMemTracer.h @@ -20,6 +20,10 @@ #include <mutex> +namespace perfetto::protos { +class TracePacket; +} + namespace android { class GpuMem; @@ -45,16 +49,37 @@ public: // perfetto::kInProcessBackend in tests. void registerDataSource(); + // TODO(b/175904796): Refactor gpuservice lib to include perfetto lib and move the test + // functions into the unittests. + // Functions only used for testing with in-process backend. These functions require the static + // perfetto lib to be linked. If the tests have a perfetto linked, while libgpumemtracer.so also + // has one linked, they will both use different static states maintained in perfetto. Since the + // static perfetto states are not shared, tracing sessions created in the unit test are not + // recognized by GpuMemTracer. As a result, we cannot use any of the perfetto functions from + // this class, which defeats the purpose of the unit test. To solve this, we restrict all + // tracing functionality to this class, while the unit test validates the data. + // Sets up the perfetto in-process backend and calls into registerDataSource. + void initializeForTest(std::shared_ptr<GpuMem>); + // Creates a tracing session with in process backend, for testing. + std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest(); + // Read and filter the gpu memory packets from the created trace. + std::vector<perfetto::protos::TracePacket> readGpuMemTotalPacketsForTestBlocking( + perfetto::TracingSession* tracingSession); + static constexpr char kGpuMemDataSource[] = "android.gpu.memory"; static std::condition_variable sCondition; static std::mutex sTraceMutex; static bool sTraceStarted; private: - void traceInitialCounters(); - void threadLoop(); + // Friend class for testing + friend class GpuMemTracerTest; + void threadLoop(bool infiniteLoop); + void traceInitialCounters(); std::shared_ptr<GpuMem> mGpuMem; + // Count of how many tracer threads are currently active. Useful for testing. + std::atomic<int32_t> tracerThreadCount = 0; }; } // namespace android diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index f67c9d006b..8610737240 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // Default flags to be used throughout all libraries in inputflinger. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "inputflinger_defaults", cflags: [ diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp index 066a816069..67d85d669e 100644 --- a/services/inputflinger/benchmarks/Android.bp +++ b/services/inputflinger/benchmarks/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_benchmark { name: "inputflinger_benchmarks", srcs: [ diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp index 390c6b8506..40c24094ff 100644 --- a/services/inputflinger/dispatcher/Android.bp +++ b/services/inputflinger/dispatcher/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libinputdispatcher_headers", export_include_dirs: [ diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp index b56f356dfd..f0151c96d1 100644 --- a/services/inputflinger/host/Android.bp +++ b/services/inputflinger/host/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libinputflingerhost", diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index 83a610f768..dadbd0ea83 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libinputreader_headers", export_include_dirs: [ diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 4b19e5e353..3347ba6ad7 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -84,12 +84,13 @@ void InputDevice::setEnabled(bool enabled, nsecs_t when) { bumpGeneration(); } -void InputDevice::dump(std::string& dump) { +void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) { InputDeviceInfo deviceInfo; getDeviceInfo(&deviceInfo); dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(), deviceInfo.getDisplayName().c_str()); + dump += StringPrintf(INDENT "%s", eventHubDevStr.c_str()); dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration); dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal)); dump += StringPrintf(INDENT2 "AssociatedDisplayPort: "); @@ -101,6 +102,7 @@ void InputDevice::dump(std::string& dump) { dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic)); dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources()); dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType()); + dump += StringPrintf(INDENT2 "ControllerNum: %d\n", deviceInfo.getControllerNumber()); const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges(); if (!ranges.empty()) { @@ -200,6 +202,8 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { // insert the context into the devices set mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))}); + // Must change generation to flag this device as changed + bumpGeneration(); } void InputDevice::removeEventHubDevice(int32_t eventHubId) { diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index 06e374353c..dff830ca7f 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -206,6 +206,14 @@ void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) { } mDevices.emplace(eventHubId, device); + // Add device to device to EventHub ids map. + const auto mapIt = mDeviceToEventHubIdsMap.find(device); + if (mapIt == mDeviceToEventHubIdsMap.end()) { + std::vector<int32_t> ids = {eventHubId}; + mDeviceToEventHubIdsMap.emplace(device, ids); + } else { + mapIt->second.push_back(eventHubId); + } bumpGenerationLocked(); if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) { @@ -222,6 +230,17 @@ void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) { std::shared_ptr<InputDevice> device = std::move(deviceIt->second); mDevices.erase(deviceIt); + // Erase device from device to EventHub ids map. + auto mapIt = mDeviceToEventHubIdsMap.find(device); + if (mapIt != mDeviceToEventHubIdsMap.end()) { + std::vector<int32_t>& eventHubIds = mapIt->second; + eventHubIds.erase(std::remove_if(eventHubIds.begin(), eventHubIds.end(), + [eventHubId](int32_t eId) { return eId == eventHubId; }), + eventHubIds.end()); + if (eventHubIds.size() == 0) { + mDeviceToEventHubIdsMap.erase(mapIt); + } + } bumpGenerationLocked(); if (device->isIgnored()) { @@ -450,8 +469,7 @@ void InputReader::getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) { outInputDevices.clear(); - for (auto& devicePair : mDevices) { - std::shared_ptr<InputDevice>& device = devicePair.second; + for (const auto& [device, eventHubIds] : mDeviceToEventHubIdsMap) { if (!device->isIgnored()) { InputDeviceInfo info; device->getDeviceInfo(&info); @@ -622,11 +640,17 @@ void InputReader::dump(std::string& dump) { mEventHub->dump(dump); dump += "\n"; - dump += "Input Reader State:\n"; + dump += StringPrintf("Input Reader State (Nums of device: %zu):\n", + mDeviceToEventHubIdsMap.size()); - for (const auto& devicePair : mDevices) { - const std::shared_ptr<InputDevice>& device = devicePair.second; - device->dump(dump); + for (const auto& devicePair : mDeviceToEventHubIdsMap) { + const std::shared_ptr<InputDevice>& device = devicePair.first; + std::string eventHubDevStr = INDENT "EventHub Devices: [ "; + for (const auto& eId : devicePair.second) { + eventHubDevStr += StringPrintf("%d ", eId); + } + eventHubDevStr += "] \n"; + device->dump(dump, eventHubDevStr); } dump += INDENT "Configuration:\n"; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 7c17102826..d2bb4f4b4c 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -66,7 +66,7 @@ public: bool isEnabled(); void setEnabled(bool enabled, nsecs_t when); - void dump(std::string& dump); + void dump(std::string& dump, const std::string& eventHubDevStr); void addEventHubDevice(int32_t eventHubId, bool populateMappers = true); void removeEventHubDevice(int32_t eventHubId); void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes); diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 108b9c236c..2773f709eb 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -143,6 +143,11 @@ private: // to lookup the input device instance from the EventHub device id. std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices; + // An input device contains one or more eventHubId, this map provides a way to lookup the + // EventHubIds contained in the input device from the input device instance. + std::unordered_map<std::shared_ptr<InputDevice>, std::vector<int32_t> /*eventHubId*/> + mDeviceToEventHubIdsMap; + // low-level input event decoding and device management void processEventsLocked(const RawEvent* rawEvents, size_t count); diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 0b541fb94f..cbdb1d02f7 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -3673,6 +3673,9 @@ void TouchInputMapper::rotateAndScale(float& x, float& y) { const float xScaled = float(x - mRawPointerAxes.x.minValue) * mXScale; const float yScaled = float(y - mRawPointerAxes.y.minValue) * mYScale; + const float xScaledMax = float(mRawPointerAxes.x.maxValue - x) * mXScale; + const float yScaledMax = float(mRawPointerAxes.y.maxValue - y) * mYScale; + // Rotate to surface coordinate. // 0 - no swap and reverse. // 90 - swap x/y and reverse y. @@ -3684,16 +3687,16 @@ void TouchInputMapper::rotateAndScale(float& x, float& y) { y = yScaled + mYTranslate; break; case DISPLAY_ORIENTATION_90: - y = mSurfaceRight - xScaled; + y = xScaledMax - (mRawSurfaceWidth - mSurfaceRight); x = yScaled + mYTranslate; break; case DISPLAY_ORIENTATION_180: - x = mSurfaceRight - xScaled; - y = mSurfaceBottom - yScaled; + x = xScaledMax - (mRawSurfaceWidth - mSurfaceRight); + y = yScaledMax - (mRawSurfaceHeight - mSurfaceBottom); break; case DISPLAY_ORIENTATION_270: y = xScaled + mXTranslate; - x = mSurfaceBottom - yScaled; + x = yScaledMax - (mRawSurfaceHeight - mSurfaceBottom); break; default: assert(false); diff --git a/services/inputflinger/reporter/Android.bp b/services/inputflinger/reporter/Android.bp index fbc51dadc0..74307310c5 100644 --- a/services/inputflinger/reporter/Android.bp +++ b/services/inputflinger/reporter/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "libinputreporter_headers", export_include_dirs: ["."], @@ -46,4 +55,3 @@ cc_library_shared { "libinputreporter_headers", ], } - diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index a0d2f4f172..86ed60dbcc 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "inputflinger_tests", defaults: [ diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 58f83b518d..e9bb169d64 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -7449,8 +7449,8 @@ protected: configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); } - void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xInside, int32_t yInside, - int32_t xOutside, int32_t yOutside, int32_t xExpected, + void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xOutside, int32_t yOutside, + int32_t xInside, int32_t yInside, int32_t xExpected, int32_t yExpected) { // touch on outside area should not work. processPosition(mapper, toRawX(xOutside), toRawY(yOutside)); @@ -7532,6 +7532,34 @@ TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) { processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected); } +TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_Corner) { + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareDisplay(DISPLAY_ORIENTATION_0); + prepareAxes(POSITION); + MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>(); + + const int32_t x = 0; + const int32_t y = 0; + + const int32_t xExpected = x; + const int32_t yExpected = y; + processPositionAndVerify(mapper, x - 1, y, x, y, xExpected, yExpected); + + clearViewports(); + prepareDisplay(DISPLAY_ORIENTATION_90); + // expect x/y = swap x/y then reverse y. + const int32_t xExpected90 = y; + const int32_t yExpected90 = DISPLAY_WIDTH - 1; + processPositionAndVerify(mapper, x - 1, y, x, y, xExpected90, yExpected90); + + clearViewports(); + prepareDisplay(DISPLAY_ORIENTATION_270); + // expect x/y = swap x/y then reverse x. + const int32_t xExpected270 = DISPLAY_HEIGHT - 1; + const int32_t yExpected270 = x; + processPositionAndVerify(mapper, x - 1, y, x, y, xExpected270, yExpected270); +} + TEST_F(MultiTouchInputMapperTest, Process_TouchpadCapture) { // we need a pointer controller for mouse mode of touchpad (start pointer at 0,0) std::shared_ptr<FakePointerController> fakePointerController = diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp new file mode 100644 index 0000000000..2a90a08543 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/Android.bp @@ -0,0 +1,121 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + +cc_defaults { + name: "inputflinger_fuzz_defaults", + defaults: [ + "inputflinger_defaults", + ], + include_dirs: [ + "frameworks/native/services/inputflinger", + ], + shared_libs: [ + "android.hardware.input.classifier@1.0", + "libbase", + "libbinder", + "libcutils", + "liblog", + "libutils", + "libui", + "libinput", + "libinputflinger", + "libinputreader", + "libinputflinger_base", + "libstatslog", + ], + header_libs: [ + "libinputreader_headers", + ], +} + +cc_fuzz { + name: "inputflinger_cursor_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "CursorInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_keyboard_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "KeyboardInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_multitouch_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "MultiTouchInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_switch_input_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "SwitchInputFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_input_reader_device_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "InputReaderDeviceFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_blocking_queue_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "BlockingQueueFuzzer.cpp", + ], +} + +cc_fuzz { + name: "inputflinger_input_classifier_fuzzer", + defaults: [ + "inputflinger_fuzz_defaults", + ], + srcs: [ + "InputClassifierFuzzer.cpp", + ], +} diff --git a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp new file mode 100644 index 0000000000..6a136cfc99 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fuzzer/FuzzedDataProvider.h> +#include <thread> +#include "BlockingQueue.h" + +// Chosen to be a number large enough for variation in fuzzer runs, but not consume too much memory. +static constexpr size_t MAX_CAPACITY = 1024; + +namespace android { + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + size_t capacity = fdp.ConsumeIntegralInRange<size_t>(1, MAX_CAPACITY); + size_t filled = 0; + BlockingQueue<int32_t> queue(capacity); + + while (fdp.remaining_bytes() > 0) { + fdp.PickValueInArray<std::function<void()>>({ + [&]() -> void { + size_t numPushes = fdp.ConsumeIntegralInRange<size_t>(0, capacity + 1); + for (size_t i = 0; i < numPushes; i++) { + queue.push(fdp.ConsumeIntegral<int32_t>()); + } + filled = std::min(capacity, filled + numPushes); + }, + [&]() -> void { + // Pops blocks if it is empty, so only pop up to num elements inserted. + size_t numPops = fdp.ConsumeIntegralInRange<size_t>(0, filled); + for (size_t i = 0; i < numPops; i++) { + queue.pop(); + } + filled > numPops ? filled -= numPops : filled = 0; + }, + [&]() -> void { + queue.clear(); + filled = 0; + }, + [&]() -> void { + int32_t eraseElement = fdp.ConsumeIntegral<int32_t>(); + queue.erase([&](int32_t element) { + if (element == eraseElement) { + filled--; + return true; + } + return false; + }); + }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp new file mode 100644 index 0000000000..8aa74342f3 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/CursorInputFuzzer.cpp @@ -0,0 +1,90 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <CursorInputMapper.h> +#include <FuzzContainer.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) { + // Pick a random property to set for the mapper to have set. + fdp->PickValueInArray<std::function<void()>>( + {[&]() -> void { fuzzer.addProperty(String8("cursor.mode"), String8("pointer")); }, + [&]() -> void { fuzzer.addProperty(String8("cursor.mode"), String8("navigation")); }, + [&]() -> void { + fuzzer.addProperty(String8("cursor.mode"), + String8(fdp->ConsumeRandomLengthString(100).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("cursor.orientationAware"), + String8(fdp->ConsumeRandomLengthString(100).data())); + }})(); +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer = FuzzContainer(fdp); + + CursorInputMapper& mapper = fuzzer.getMapper<CursorInputMapper>(); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { addProperty(fuzzer, fdp); }, + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + // Need to reconfigure with 0 or you risk a NPE. + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + InputDeviceInfo info; + mapper.populateDeviceInfo(&info); + }, + [&]() -> void { + // Need to reconfigure with 0 or you risk a NPE. + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + // Need to reconfigure with 0 or you risk a NPE. + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, 0); + mapper.getAssociatedDisplayId(); + }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/FuzzContainer.h b/services/inputflinger/tests/fuzzers/FuzzContainer.h new file mode 100644 index 0000000000..84f05663d2 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/FuzzContainer.h @@ -0,0 +1,84 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <InputDevice.h> +#include <InputMapper.h> +#include <InputReader.h> +#include <MapperHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +class FuzzContainer { + int32_t meventID; + std::shared_ptr<FuzzEventHub> mFuzzEventHub; + sp<FuzzInputReaderPolicy> mFuzzPolicy; + sp<FuzzInputListener> mFuzzListener; + std::unique_ptr<FuzzInputReaderContext> mFuzzContext; + std::unique_ptr<InputDevice> mFuzzDevice; + InputReaderConfiguration mPolicyConfig; + std::shared_ptr<FuzzedDataProvider> fdp; + +public: + FuzzContainer(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) { + // Setup parameters. + std::string deviceName = fdp->ConsumeRandomLengthString(16); + std::string deviceLocation = fdp->ConsumeRandomLengthString(12); + int32_t deviceID = fdp->ConsumeIntegralInRange<int32_t>(0, 5); + int32_t deviceGeneration = fdp->ConsumeIntegralInRange<int32_t>(0, 5); + meventID = fdp->ConsumeIntegral<int32_t>(); + + // Create mocked objects. + mFuzzEventHub = std::make_shared<FuzzEventHub>(fdp); + mFuzzPolicy = new FuzzInputReaderPolicy(fdp); + mFuzzListener = new FuzzInputListener(); + mFuzzContext = std::make_unique<FuzzInputReaderContext>(mFuzzEventHub, mFuzzPolicy, + mFuzzListener, fdp); + + InputDeviceIdentifier identifier; + identifier.name = deviceName; + identifier.location = deviceLocation; + mFuzzDevice = std::make_unique<InputDevice>(mFuzzContext.get(), deviceID, deviceGeneration, + identifier); + mFuzzPolicy->getReaderConfiguration(&mPolicyConfig); + } + + ~FuzzContainer() {} + + void configureDevice() { + nsecs_t arbitraryTime = fdp->ConsumeIntegral<nsecs_t>(); + mFuzzDevice->configure(arbitraryTime, &mPolicyConfig, 0); + mFuzzDevice->reset(arbitraryTime); + } + + void addProperty(const String8& key, const String8& value) { + mFuzzEventHub->addProperty(key, value); + configureDevice(); + } + + InputReaderConfiguration& getPolicyConfig() { return mPolicyConfig; } + + template <class T, typename... Args> + T& getMapper(Args... args) { + T& mapper = mFuzzDevice->addMapper<T>(fdp->ConsumeIntegral<int32_t>(), args...); + configureDevice(); + return mapper; + } +}; + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp new file mode 100644 index 0000000000..7f9100098e --- /dev/null +++ b/services/inputflinger/tests/fuzzers/InputClassifierFuzzer.cpp @@ -0,0 +1,120 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <MapperHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> +#include "InputClassifier.h" +#include "InputClassifierConverter.h" + +namespace android { + +static constexpr int32_t MAX_AXES = 64; + +// Used by two fuzz operations and a bit lengthy, so pulled out into a function. +NotifyMotionArgs generateFuzzedMotionArgs(FuzzedDataProvider &fdp) { + // Create a basic motion event for testing + PointerProperties properties; + properties.id = 0; + properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; + PointerCoords coords; + coords.clear(); + for (int32_t i = 0; i < fdp.ConsumeIntegralInRange<int32_t>(0, MAX_AXES); i++) { + coords.setAxisValue(fdp.ConsumeIntegral<int32_t>(), fdp.ConsumeFloatingPoint<float>()); + } + + nsecs_t downTime = 2; + NotifyMotionArgs motionArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + downTime /*eventTime*/, fdp.ConsumeIntegral<int32_t>() /*deviceId*/, + AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, + fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/, + AMOTION_EVENT_ACTION_DOWN, + fdp.ConsumeIntegral<int32_t>() /*actionButton*/, + fdp.ConsumeIntegral<int32_t>() /*flags*/, AMETA_NONE, + fdp.ConsumeIntegral<int32_t>() /*buttonState*/, + MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, + 1 /*pointerCount*/, &properties, &coords, + fdp.ConsumeFloatingPoint<float>() /*xPrecision*/, + fdp.ConsumeFloatingPoint<float>() /*yPrecision*/, + AMOTION_EVENT_INVALID_CURSOR_POSITION, + AMOTION_EVENT_INVALID_CURSOR_POSITION, downTime, + {} /*videoFrames*/); + return motionArgs; +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + FuzzedDataProvider fdp(data, size); + + sp<FuzzInputListener> mFuzzListener = new FuzzInputListener(); + sp<InputClassifierInterface> mClassifier = new InputClassifier(mFuzzListener); + + while (fdp.remaining_bytes() > 0) { + fdp.PickValueInArray<std::function<void()>>({ + [&]() -> void { + // SendToNextStage_NotifyConfigurationChangedArgs + NotifyConfigurationChangedArgs + args(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/); + mClassifier->notifyConfigurationChanged(&args); + }, + [&]() -> void { + // SendToNextStage_NotifyKeyArgs + NotifyKeyArgs keyArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/, + fdp.ConsumeIntegral<int32_t>() /*deviceId*/, + AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_DEFAULT, + fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/, + AKEY_EVENT_ACTION_DOWN, + fdp.ConsumeIntegral<int32_t>() /*flags*/, AKEYCODE_HOME, + fdp.ConsumeIntegral<int32_t>() /*scanCode*/, AMETA_NONE, + fdp.ConsumeIntegral<nsecs_t>() /*downTime*/); + + mClassifier->notifyKey(&keyArgs); + }, + [&]() -> void { + // SendToNextStage_NotifyMotionArgs + NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp); + mClassifier->notifyMotion(&motionArgs); + }, + [&]() -> void { + // SendToNextStage_NotifySwitchArgs + NotifySwitchArgs switchArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/, + fdp.ConsumeIntegral<uint32_t>() /*policyFlags*/, + fdp.ConsumeIntegral<uint32_t>() /*switchValues*/, + fdp.ConsumeIntegral<uint32_t>() /*switchMask*/); + + mClassifier->notifySwitch(&switchArgs); + }, + [&]() -> void { + // SendToNextStage_NotifyDeviceResetArgs + NotifyDeviceResetArgs resetArgs(fdp.ConsumeIntegral<uint32_t>() /*sequenceNum*/, + fdp.ConsumeIntegral<nsecs_t>() /*eventTime*/, + fdp.ConsumeIntegral<int32_t>() /*deviceId*/); + + mClassifier->notifyDeviceReset(&resetArgs); + }, + [&]() -> void { + // InputClassifierConverterTest + const NotifyMotionArgs motionArgs = generateFuzzedMotionArgs(fdp); + hardware::input::common::V1_0::MotionEvent motionEvent = + notifyMotionArgsToHalMotionEvent(motionArgs); + }, + })(); + } + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp new file mode 100644 index 0000000000..919489139a --- /dev/null +++ b/services/inputflinger/tests/fuzzers/InputReaderDeviceFuzzer.cpp @@ -0,0 +1,103 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <InputReader.h> +#include <MapperHelpers.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <chrono> +#include <thread> + +namespace android { + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + + sp<FuzzInputListener> fuzzListener = new FuzzInputListener(); + sp<FuzzInputReaderPolicy> fuzzPolicy = new FuzzInputReaderPolicy(fdp); + std::shared_ptr<FuzzEventHub> fuzzEventHub = std::make_shared<FuzzEventHub>(fdp); + std::unique_ptr<InputReader> reader = + std::make_unique<InputReader>(fuzzEventHub, fuzzPolicy, fuzzListener); + + fuzzEventHub->addEvents(fdp); + reader->start(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { + std::string dump; + reader->dump(dump); + }, + [&]() -> void { reader->monitor(); }, + [&]() -> void { fuzzEventHub->addEvents(fdp); }, + [&]() -> void { + std::vector<InputDeviceInfo> inputDevices; + reader->getInputDevices(inputDevices); + }, + [&]() -> void { reader->isInputDeviceEnabled(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { + reader->getScanCodeState(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->getKeyCodeState(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->getSwitchState(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { reader->toggleCapsLockState(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { + size_t count = fdp->ConsumeIntegralInRange<size_t>(1, 1024); + uint8_t* outFlags = new uint8_t[count]; + reader->hasKeys(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<uint32_t>(), count, nullptr, outFlags); + delete[] outFlags; + }, + [&]() -> void { + reader->requestRefreshConfiguration(fdp->ConsumeIntegral<uint32_t>()); + }, + [&]() -> void { + // 260 is slightly higher than the maximum intended size of 256. + size_t count = fdp->ConsumeIntegralInRange<size_t>(0, 260); + nsecs_t pattern[count]; + + for (size_t i = 0; i < count; i++) pattern[i] = fdp->ConsumeIntegral<nsecs_t>(); + + reader->vibrate(fdp->ConsumeIntegral<int32_t>(), pattern, count, + fdp->ConsumeIntegral<ssize_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->cancelVibrate(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + reader->canDispatchToDisplay(fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + })(); + } + + reader->stop(); + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp new file mode 100644 index 0000000000..854e2fd366 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/KeyboardInputFuzzer.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <FuzzContainer.h> +#include <KeyboardInputMapper.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) { + // Pick a random property to set for the mapper to have set. + fdp->PickValueInArray<std::function<void()>>( + {[&]() -> void { + fuzzer.addProperty(String8("keyboard.orientationAware"), String8("1")); + }, + [&]() -> void { + fuzzer.addProperty(String8("keyboard.orientationAware"), + String8(fdp->ConsumeRandomLengthString(100).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("keyboard.doNotWakeByDefault"), + String8(fdp->ConsumeRandomLengthString(100).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("keyboard.handlesKeyRepeat"), + String8(fdp->ConsumeRandomLengthString(100).data())); + }})(); +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer = FuzzContainer(fdp); + + KeyboardInputMapper& mapper = + fuzzer.getMapper<KeyboardInputMapper>(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { addProperty(fuzzer, fdp); }, + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { + InputDeviceInfo info; + mapper.populateDeviceInfo(&info); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, + fdp->ConsumeIntegral<uint32_t>()); + }, + [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { + mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<size_t>(), nullptr, nullptr); + }, + [&]() -> void { mapper.getMetaState(); }, + [&]() -> void { mapper.updateMetaState(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { mapper.getAssociatedDisplayId(); }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h new file mode 100644 index 0000000000..edfb68d1e6 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -0,0 +1,224 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <InputDevice.h> +#include <InputMapper.h> +#include <InputReader.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +class FuzzEventHub : public EventHubInterface { + InputDeviceIdentifier mIdentifier; + std::vector<TouchVideoFrame> mVideoFrames; + PropertyMap mFuzzConfig; + std::mutex mEventLock; + size_t mCount = 0; + RawEvent mBuf[256]; + std::shared_ptr<FuzzedDataProvider> fdp; + +public: + FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {} + ~FuzzEventHub() {} + void addProperty(const String8& key, const String8 value) { + mFuzzConfig.addProperty(key, value); + } + void addEvents(std::shared_ptr<FuzzedDataProvider> fdp) { + std::lock_guard<std::mutex> guard(mEventLock); + mCount = fdp->ConsumeIntegralInRange<size_t>(0, 256); + + for (size_t i = 0; i < mCount; i++) + mBuf[i] = {fdp->ConsumeIntegral<nsecs_t>(), fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + } + uint32_t getDeviceClasses(int32_t deviceId) const override { + return fdp->ConsumeIntegral<uint32_t>(); + } + InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override { + return mIdentifier; + } + int32_t getDeviceControllerNumber(int32_t deviceId) const override { + return fdp->ConsumeIntegral<int32_t>(); + } + void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override { + *outConfiguration = mFuzzConfig; + } + status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, + RawAbsoluteAxisInfo* outAxisInfo) const override { + return fdp->ConsumeIntegral<status_t>(); + } + bool hasRelativeAxis(int32_t deviceId, int axis) const override { return fdp->ConsumeBool(); } + bool hasInputProperty(int32_t deviceId, int property) const override { + return fdp->ConsumeBool(); + } + status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, + int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override { + return fdp->ConsumeIntegral<status_t>(); + } + status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override { + return fdp->ConsumeIntegral<status_t>(); + } + void setExcludedDevices(const std::vector<std::string>& devices) override {} + size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override { + std::lock_guard<std::mutex> guard(mEventLock); + for (size_t i = 0; i < mCount; i++) buffer[i] = mBuf[i]; + + return mCount; + } + std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; } + int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override { + return fdp->ConsumeIntegral<int32_t>(); + } + int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override { + return fdp->ConsumeIntegral<int32_t>(); + } + int32_t getSwitchState(int32_t deviceId, int32_t sw) const override { + return fdp->ConsumeIntegral<int32_t>(); + } + status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, + int32_t* outValue) const override { + return fdp->ConsumeIntegral<status_t>(); + } + bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, + uint8_t* outFlags) const override { + return fdp->ConsumeBool(); + } + bool hasScanCode(int32_t deviceId, int32_t scanCode) const override { + return fdp->ConsumeBool(); + } + bool hasLed(int32_t deviceId, int32_t led) const override { return fdp->ConsumeBool(); } + void setLedState(int32_t deviceId, int32_t led, bool on) override {} + void getVirtualKeyDefinitions( + int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {} + sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override { return nullptr; } + bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) override { + return fdp->ConsumeBool(); + } + void vibrate(int32_t deviceId, nsecs_t duration) override {} + void cancelVibrate(int32_t deviceId) override {} + void requestReopenDevices() override {} + void wake() override {} + void dump(std::string& dump) override {} + void monitor() override {} + bool isDeviceEnabled(int32_t deviceId) override { return fdp->ConsumeBool(); } + status_t enableDevice(int32_t deviceId) override { return fdp->ConsumeIntegral<status_t>(); } + status_t disableDevice(int32_t deviceId) override { return fdp->ConsumeIntegral<status_t>(); } +}; + +class FuzzPointerController : public PointerControllerInterface { + std::shared_ptr<FuzzedDataProvider> fdp; + +public: + FuzzPointerController(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) {} + ~FuzzPointerController() {} + bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override { + return fdp->ConsumeBool(); + } + void move(float deltaX, float deltaY) override {} + void setButtonState(int32_t buttonState) override {} + int32_t getButtonState() const override { return fdp->ConsumeIntegral<int32_t>(); } + void setPosition(float x, float y) override {} + void getPosition(float* outX, float* outY) const override {} + void fade(Transition transition) override {} + void unfade(Transition transition) override {} + void setPresentation(Presentation presentation) override {} + void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, + BitSet32 spotIdBits, int32_t displayId) override {} + void clearSpots() override {} + int32_t getDisplayId() const override { return fdp->ConsumeIntegral<int32_t>(); } + void setDisplayViewport(const DisplayViewport& displayViewport) override {} +}; + +class FuzzInputReaderPolicy : public InputReaderPolicyInterface { + TouchAffineTransformation mTransform; + std::shared_ptr<FuzzPointerController> mPointerController; + std::shared_ptr<FuzzedDataProvider> fdp; + +protected: + ~FuzzInputReaderPolicy() {} + +public: + FuzzInputReaderPolicy(std::shared_ptr<FuzzedDataProvider> fdp) : fdp(fdp) { + mPointerController = std::make_shared<FuzzPointerController>(fdp); + } + void getReaderConfiguration(InputReaderConfiguration* outConfig) override {} + std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override { + return mPointerController; + } + void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {} + sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) override { + return nullptr; + } + std::string getDeviceAlias(const InputDeviceIdentifier& identifier) { + return fdp->ConsumeRandomLengthString(32); + } + TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor, + int32_t surfaceRotation) override { + return mTransform; + } + void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; } +}; + +class FuzzInputListener : public virtual InputListenerInterface { +protected: + ~FuzzInputListener() {} + +public: + FuzzInputListener() {} + void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override {} + void notifyKey(const NotifyKeyArgs* args) override {} + void notifyMotion(const NotifyMotionArgs* args) override {} + void notifySwitch(const NotifySwitchArgs* args) override {} + void notifyDeviceReset(const NotifyDeviceResetArgs* args) override {} +}; + +class FuzzInputReaderContext : public InputReaderContext { + std::shared_ptr<EventHubInterface> mEventHub; + sp<InputReaderPolicyInterface> mPolicy; + sp<InputListenerInterface> mListener; + std::shared_ptr<FuzzedDataProvider> fdp; + +public: + FuzzInputReaderContext(std::shared_ptr<EventHubInterface> eventHub, + const sp<InputReaderPolicyInterface>& policy, + const sp<InputListenerInterface>& listener, + std::shared_ptr<FuzzedDataProvider> fdp) + : mEventHub(eventHub), mPolicy(policy), mListener(listener), fdp(fdp) {} + ~FuzzInputReaderContext() {} + void updateGlobalMetaState() override {} + int32_t getGlobalMetaState() { return fdp->ConsumeIntegral<int32_t>(); } + void disableVirtualKeysUntil(nsecs_t time) override {} + bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override { + return fdp->ConsumeBool(); + } + void fadePointer() override {} + std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override { + return mPolicy->obtainPointerController(0); + } + void requestTimeoutAtTime(nsecs_t when) override {} + int32_t bumpGeneration() override { return fdp->ConsumeIntegral<int32_t>(); } + void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {} + void dispatchExternalStylusState(const StylusState& outState) override {} + InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); } + InputListenerInterface* getListener() override { return mListener.get(); } + EventHubInterface* getEventHub() override { return mEventHub.get(); } + int32_t getNextId() override { return fdp->ConsumeIntegral<int32_t>(); } +}; + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp new file mode 100644 index 0000000000..336ecb6409 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/MultiTouchInputFuzzer.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <FuzzContainer.h> +#include <MultiTouchInputMapper.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +void addProperty(FuzzContainer& fuzzer, std::shared_ptr<FuzzedDataProvider> fdp) { + // Pick a random property to set for the mapper to have set. + fdp->PickValueInArray<std::function<void()>>( + {[&]() -> void { + fuzzer.addProperty(String8("touch.deviceType"), String8("touchScreen")); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.deviceType"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.size.scale"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.size.bias"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.size.isSummed"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.size.calibration"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.pressure.scale"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.size.calibration"), + fdp->ConsumeBool() ? String8("diameter") : String8("area")); + }, + [&]() -> void { + fuzzer.addProperty(String8("touch.pressure.calibration"), + String8(fdp->ConsumeRandomLengthString(8).data())); + }})(); +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer = FuzzContainer(fdp); + + MultiTouchInputMapper& mapper = fuzzer.getMapper<MultiTouchInputMapper>(); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { addProperty(fuzzer, fdp); }, + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { + InputDeviceInfo info; + mapper.populateDeviceInfo(&info); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + mapper.configure(fdp->ConsumeIntegral<nsecs_t>(), &policyConfig, + fdp->ConsumeIntegral<uint32_t>()); + }, + [&]() -> void { mapper.reset(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { + mapper.getKeyCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + mapper.getScanCodeState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + [&]() -> void { + mapper.markSupportedKeyCodes(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<size_t>(), nullptr, nullptr); + }, + [&]() -> void { mapper.cancelTouch(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { mapper.timeoutExpired(fdp->ConsumeIntegral<nsecs_t>()); }, + [&]() -> void { + StylusState state{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeFloatingPoint<float>(), + fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + mapper.updateExternalStylusState(state); + }, + [&]() -> void { mapper.getAssociatedDisplayId(); }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp new file mode 100644 index 0000000000..ae7429c939 --- /dev/null +++ b/services/inputflinger/tests/fuzzers/SwitchInputFuzzer.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <FuzzContainer.h> +#include <SwitchInputMapper.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android { + +extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { + std::shared_ptr<FuzzedDataProvider> fdp = std::make_shared<FuzzedDataProvider>(data, size); + FuzzContainer fuzzer = FuzzContainer(fdp); + + SwitchInputMapper& mapper = fuzzer.getMapper<SwitchInputMapper>(); + auto policyConfig = fuzzer.getPolicyConfig(); + + // Loop through mapper operations until randomness is exhausted. + while (fdp->remaining_bytes() > 0) { + fdp->PickValueInArray<std::function<void()>>({ + [&]() -> void { + std::string dump; + mapper.dump(dump); + }, + [&]() -> void { mapper.getSources(); }, + [&]() -> void { + RawEvent rawEvent{fdp->ConsumeIntegral<nsecs_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>(), + fdp->ConsumeIntegral<int32_t>()}; + mapper.process(&rawEvent); + }, + [&]() -> void { + mapper.getSwitchState(fdp->ConsumeIntegral<uint32_t>(), + fdp->ConsumeIntegral<int32_t>()); + }, + })(); + } + + return 0; +} + +} // namespace android diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp index b0d3e3bde0..19b6a0f576 100644 --- a/services/powermanager/Android.bp +++ b/services/powermanager/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libpowermanager", diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp index 73802dbc9f..4ef72d0c83 100644 --- a/services/schedulerservice/Android.bp +++ b/services/schedulerservice/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libschedulerservicehidl", srcs: [ diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp index 532a2e5a13..ca9ff7c8c3 100644 --- a/services/sensorservice/Android.bp +++ b/services/sensorservice/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + subdirs = [ "hidl" ] diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp index 0e1af595f0..9bafb3cf95 100644 --- a/services/sensorservice/hidl/Android.bp +++ b/services/sensorservice/hidl/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libsensorservicehidl", srcs: [ diff --git a/services/sensorservice/tests/Android.bp b/services/sensorservice/tests/Android.bp index d33c0ca59d..ddc03a17e1 100644 --- a/services/sensorservice/tests/Android.bp +++ b/services/sensorservice/tests/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-sensorservice", srcs: ["sensorservicetest.cpp"], diff --git a/services/stats/Android.bp b/services/stats/Android.bp index 1ce0524299..58e59938fd 100644 --- a/services/stats/Android.bp +++ b/services/stats/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libstatshidl", srcs: [ diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index bdd04dbcb0..6b3bf8d865 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "surfaceflinger_defaults", cflags: [ @@ -20,7 +29,6 @@ cc_defaults { "-DEGL_EGLEXT_PROTOTYPES", ], shared_libs: [ - "android.frameworks.vr.composer@2.0", "android.hardware.configstore-utils", "android.hardware.configstore@1.0", "android.hardware.configstore@1.1", @@ -33,7 +41,7 @@ cc_defaults { "android.hardware.graphics.composer@2.4", "android.hardware.power@1.0", "android.hardware.power@1.3", - "android.hardware.power-cpp", + "android.hardware.power-V1-cpp", "libbase", "libbinder", "libbufferhubqueue", @@ -58,21 +66,12 @@ cc_defaults { "libutils", "libSurfaceFlingerProp", ], - // VrComposer is not used when building surfaceflinger for vendors - target: { - vendor: { - exclude_shared_libs: [ - "android.frameworks.vr.composer@2.0", - ], - }, - }, static_libs: [ "libcompositionengine", "libperfetto_client_experimental", "librenderengine", "libserviceutils", "libtrace_proto", - "libvrflinger", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", @@ -113,6 +112,10 @@ cc_defaults { thin: true, }, whole_program_vtables: true, // Requires ThinLTO + pgo: { + sampling: true, + profile_file: "surfaceflinger/surfaceflinger.profdata", + }, // TODO(b/131771163): Fix broken fuzzer support with LTO. sanitize: { fuzzer: false, @@ -198,17 +201,6 @@ cc_library_shared { // can be easily replaced. "SurfaceFlingerFactory.cpp", ], - cflags: [ - "-DUSE_VR_COMPOSER=1", - ], - // VrComposer is not used when building surfaceflinger for vendors - target: { - vendor: { - cflags: [ - "-DUSE_VR_COMPOSER=0", - ], - }, - }, logtags: ["EventLog/EventLogTags.logtags"], } diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f0b0200bc5..df26a3db70 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -176,7 +176,14 @@ std::optional<compositionengine::LayerFE::LayerSettings> BufferLayer::prepareCli if (!holes.isEmpty()) { targetSettings.clearRegion.orSelf(holes); } - return std::nullopt; + + if (mSidebandStream != nullptr) { + // For surfaceview of tv sideband, there is no activeBuffer + // in bufferqueue, we need return LayerSettings. + return result; + } else { + return std::nullopt; + } } bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index b37ca33d34..3f639510d6 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "libcompositionengine_defaults", defaults: ["surfaceflinger_defaults"], @@ -6,7 +15,6 @@ cc_defaults { "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", ], shared_libs: [ - "android.frameworks.vr.composer@2.0", "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index b4ed92f965..77400eb42b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -130,16 +130,6 @@ struct LayerFECompositionState { Rect geomContentCrop; Rect geomCrop; - /* - * Extra metadata - */ - - // The type for this layer - int type{0}; - - // The appId for this layer - int appId{0}; - GenericLayerMetadataMap metadata; /* diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index 02e3a45acd..1338538861 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -75,10 +75,6 @@ void LayerFECompositionState::dump(std::string& out) const { dumpVal(out, "alpha", alpha); dumpVal(out, "backgroundBlurRadius", backgroundBlurRadius); - out.append("\n "); - dumpVal(out, "type", type); - dumpVal(out, "appId", appId); - if (!metadata.empty()) { out.append("\n metadata {"); for (const auto& [key, entry] : metadata) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 1faf775ed3..3aed7f5519 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -402,13 +402,6 @@ void OutputLayer::writeOutputIndependentGeometryStateToHWC( outputIndependentState.alpha, to_string(error).c_str(), static_cast<int32_t>(error)); } - if (auto error = hwcLayer->setInfo(static_cast<uint32_t>(outputIndependentState.type), - static_cast<uint32_t>(outputIndependentState.appId)); - error != hal::Error::NONE) { - ALOGE("[%s] Failed to set info %s (%d)", getLayerFE().getDebugName(), - to_string(error).c_str(), static_cast<int32_t>(error)); - } - for (const auto& [name, entry] : outputIndependentState.metadata) { if (auto error = hwcLayer->setLayerGenericMetadata(name, entry.mandatory, entry.value); error != hal::Error::NONE) { diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h index d21b97e05e..87911ccacf 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h @@ -66,7 +66,6 @@ public: MOCK_METHOD1(setTransform, Error(hal::Transform)); MOCK_METHOD1(setVisibleRegion, Error(const android::Region&)); MOCK_METHOD1(setZOrder, Error(uint32_t)); - MOCK_METHOD2(setInfo, Error(uint32_t, uint32_t)); MOCK_METHOD1(setColorTransform, Error(const android::mat4&)); MOCK_METHOD3(setLayerGenericMetadata, diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 020f93a607..c32ef11a89 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -676,8 +676,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static constexpr Hwc2::IComposerClient::BlendMode kBlendMode = static_cast<Hwc2::IComposerClient::BlendMode>(41); static constexpr float kAlpha = 51.f; - static constexpr uint32_t kType = 61u; - static constexpr uint32_t kAppId = 62u; static constexpr ui::Dataspace kDataspace = static_cast<ui::Dataspace>(71); static constexpr int kSupportedPerFrameMetadata = 101; static constexpr int kExpectedHwcSlot = 0; @@ -711,8 +709,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { mLayerFEState.blendMode = kBlendMode; mLayerFEState.alpha = kAlpha; - mLayerFEState.type = kType; - mLayerFEState.appId = kAppId; mLayerFEState.colorTransform = kColorTransform; mLayerFEState.color = kColor; mLayerFEState.surfaceDamage = kSurfaceDamage; @@ -746,7 +742,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { EXPECT_CALL(*mHwcLayer, setBlendMode(kBlendMode)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setPlaneAlpha(kAlpha)).WillOnce(Return(kError)); - EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError)); } void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) { diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index a3f1b52378..1bf43dacdf 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -117,63 +117,7 @@ Error unwrapRet(Return<Error>& ret) namespace impl { -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER -Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize) - : CommandWriterBase(initialMaxSize) {} - -Composer::CommandWriter::~CommandWriter() -{ -} - -void Composer::CommandWriter::setLayerInfo(uint32_t type, uint32_t appId) -{ - constexpr uint16_t kSetLayerInfoLength = 2; - beginCommand(static_cast<V2_1::IComposerClient::Command>( - IVrComposerClient::VrCommand::SET_LAYER_INFO), - kSetLayerInfoLength); - write(type); - write(appId); - endCommand(); -} - -void Composer::CommandWriter::setClientTargetMetadata( - const IVrComposerClient::BufferMetadata& metadata) -{ - constexpr uint16_t kSetClientTargetMetadataLength = 7; - beginCommand(static_cast<V2_1::IComposerClient::Command>( - IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA), - kSetClientTargetMetadataLength); - writeBufferMetadata(metadata); - endCommand(); -} - -void Composer::CommandWriter::setLayerBufferMetadata( - const IVrComposerClient::BufferMetadata& metadata) -{ - constexpr uint16_t kSetLayerBufferMetadataLength = 7; - beginCommand(static_cast<V2_1::IComposerClient::Command>( - IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA), - kSetLayerBufferMetadataLength); - writeBufferMetadata(metadata); - endCommand(); -} - -void Composer::CommandWriter::writeBufferMetadata( - const IVrComposerClient::BufferMetadata& metadata) -{ - write(metadata.width); - write(metadata.height); - write(metadata.stride); - write(metadata.layerCount); - writeSigned(static_cast<int32_t>(metadata.format)); - write64(metadata.usage); -} -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - -Composer::Composer(const std::string& serviceName) - : mWriter(kWriterInitialSize), - mIsUsingVrComposer(serviceName == std::string("vr")) -{ +Composer::Composer(const std::string& serviceName) : mWriter(kWriterInitialSize) { mComposer = V2_1::IComposer::getService(serviceName); if (mComposer == nullptr) { @@ -215,15 +159,6 @@ Composer::Composer(const std::string& serviceName) if (mClient == nullptr) { LOG_ALWAYS_FATAL("failed to create composer client"); } - -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - if (mIsUsingVrComposer) { - sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient); - if (vrClient == nullptr) { - LOG_ALWAYS_FATAL("failed to create vr composer client"); - } - } -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER } Composer::~Composer() = default; @@ -262,10 +197,6 @@ void Composer::registerCallback(const sp<IComposerCallback>& callback) } } -bool Composer::isRemote() { - return mClient->isRemote(); -} - void Composer::resetCommands() { mWriter.reset(); } @@ -587,20 +518,6 @@ Error Composer::setClientTarget(Display display, uint32_t slot, { mWriter.selectDisplay(display); -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - if (mIsUsingVrComposer && target.get()) { - IVrComposerClient::BufferMetadata metadata = { - .width = target->getWidth(), - .height = target->getHeight(), - .stride = target->getStride(), - .layerCount = target->getLayerCount(), - .format = static_cast<types::V1_2::PixelFormat>(target->getPixelFormat()), - .usage = target->getUsage(), - }; - mWriter.setClientTargetMetadata(metadata); - } -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - const native_handle_t* handle = nullptr; if (target.get()) { handle = target->getNativeBuffer()->handle; @@ -720,20 +637,6 @@ Error Composer::setLayerBuffer(Display display, Layer layer, mWriter.selectDisplay(display); mWriter.selectLayer(layer); -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - if (mIsUsingVrComposer && buffer.get()) { - IVrComposerClient::BufferMetadata metadata = { - .width = buffer->getWidth(), - .height = buffer->getHeight(), - .stride = buffer->getStride(), - .layerCount = buffer->getLayerCount(), - .format = static_cast<types::V1_2::PixelFormat>(buffer->getPixelFormat()), - .usage = buffer->getUsage(), - }; - mWriter.setLayerBufferMetadata(metadata); - } -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - const native_handle_t* handle = nullptr; if (buffer.get()) { handle = buffer->getNativeBuffer()->handle; @@ -850,27 +753,6 @@ Error Composer::setLayerZOrder(Display display, Layer layer, uint32_t z) return Error::NONE; } -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER -Error Composer::setLayerInfo(Display display, Layer layer, uint32_t type, - uint32_t appId) -{ - if (mIsUsingVrComposer) { - mWriter.selectDisplay(display); - mWriter.selectLayer(layer); - mWriter.setLayerInfo(type, appId); - } - return Error::NONE; -} -#else -Error Composer::setLayerInfo(Display display, Layer layer, uint32_t, uint32_t) { - if (mIsUsingVrComposer) { - mWriter.selectDisplay(display); - mWriter.selectLayer(layer); - } - return Error::NONE; -} -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - Error Composer::execute() { // prepare input command queue diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 00ef782ef7..5b66809d53 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -27,9 +27,6 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER -#include <android/frameworks/vr/composer/2.0/IVrComposerClient.h> -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER #include <android/hardware/graphics/common/1.1/types.h> #include <android/hardware/graphics/composer/2.4/IComposer.h> #include <android/hardware/graphics/composer/2.4/IComposerClient.h> @@ -47,10 +44,6 @@ namespace android { namespace Hwc2 { -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER -using frameworks::vr::composer::V2_0::IVrComposerClient; -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - namespace types = hardware::graphics::common; namespace V2_1 = hardware::graphics::composer::V2_1; @@ -91,11 +84,6 @@ public: virtual void registerCallback(const sp<IComposerCallback>& callback) = 0; - // Returns true if the connected composer service is running in a remote - // process, false otherwise. This will return false if the service is - // configured in passthrough mode, for example. - virtual bool isRemote() = 0; - // Reset all pending commands in the command buffer. Useful if you want to // skip a frame but have already queued some commands. virtual void resetCommands() = 0; @@ -104,7 +92,6 @@ public: virtual Error executeCommands() = 0; virtual uint32_t getMaxVirtualDisplayCount() = 0; - virtual bool isUsingVrComposer() const = 0; virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, Display* outDisplay) = 0; virtual Error destroyVirtualDisplay(Display display) = 0; @@ -188,7 +175,6 @@ public: virtual Error setLayerVisibleRegion(Display display, Layer layer, const std::vector<IComposerClient::Rect>& visible) = 0; virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0; - virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0; // Composer HAL 2.2 virtual Error setLayerPerFrameMetadata( @@ -344,11 +330,6 @@ public: void registerCallback(const sp<IComposerCallback>& callback) override; - // Returns true if the connected composer service is running in a remote - // process, false otherwise. This will return false if the service is - // configured in passthrough mode, for example. - bool isRemote() override; - // Reset all pending commands in the command buffer. Useful if you want to // skip a frame but have already queued some commands. void resetCommands() override; @@ -357,7 +338,6 @@ public: Error executeCommands() override; uint32_t getMaxVirtualDisplayCount() override; - bool isUsingVrComposer() const override { return mIsUsingVrComposer; } Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, Display* outDisplay) override; Error destroyVirtualDisplay(Display display) override; @@ -436,7 +416,6 @@ public: Error setLayerVisibleRegion(Display display, Layer layer, const std::vector<IComposerClient::Rect>& visible) override; Error setLayerZOrder(Display display, Layer layer, uint32_t z) override; - Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override; // Composer HAL 2.2 Error setLayerPerFrameMetadata( @@ -490,29 +469,11 @@ public: IComposerClient::ClientTargetProperty* outClientTargetProperty) override; private: -#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER - class CommandWriter : public CommandWriterBase { - public: - explicit CommandWriter(uint32_t initialMaxSize); - ~CommandWriter() override; - - void setLayerInfo(uint32_t type, uint32_t appId); - void setClientTargetMetadata( - const IVrComposerClient::BufferMetadata& metadata); - void setLayerBufferMetadata( - const IVrComposerClient::BufferMetadata& metadata); - - private: - void writeBufferMetadata( - const IVrComposerClient::BufferMetadata& metadata); - }; -#else class CommandWriter : public CommandWriterBase { public: explicit CommandWriter(uint32_t initialMaxSize) : CommandWriterBase(initialMaxSize) {} ~CommandWriter() override {} }; -#endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER // Many public functions above simply write a command into the command // queue to batch the calls. validateDisplay and presentDisplay will call @@ -531,10 +492,6 @@ private: 64 * 1024 / sizeof(uint32_t) - 16; CommandWriter mWriter; CommandReader mReader; - - // When true, the we attach to the vr_hwcomposer service instead of the - // hwcomposer. This allows us to redirect surfaces to 3d surfaces in vr. - const bool mIsUsingVrComposer; }; } // namespace impl diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 08559bd939..e6bff04601 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -977,12 +977,6 @@ Error Layer::setZOrder(uint32_t z) return static_cast<Error>(intError); } -Error Layer::setInfo(uint32_t type, uint32_t appId) -{ - auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId); - return static_cast<Error>(intError); -} - // Composer HAL 2.3 Error Layer::setColorTransform(const android::mat4& matrix) { if (matrix == mColorMatrix) { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 6819ff43d2..8bd6ea8c03 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -380,7 +380,6 @@ public: [[clang::warn_unused_result]] virtual hal::Error setVisibleRegion( const android::Region& region) = 0; [[clang::warn_unused_result]] virtual hal::Error setZOrder(uint32_t z) = 0; - [[clang::warn_unused_result]] virtual hal::Error setInfo(uint32_t type, uint32_t appId) = 0; // Composer HAL 2.3 [[clang::warn_unused_result]] virtual hal::Error setColorTransform( @@ -422,7 +421,6 @@ public: hal::Error setTransform(hal::Transform transform) override; hal::Error setVisibleRegion(const android::Region& region) override; hal::Error setZOrder(uint32_t z) override; - hal::Error setInfo(uint32_t type, uint32_t appId) override; // Composer HAL 2.3 hal::Error setColorTransform(const android::mat4& matrix) override; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7a2f0f34ee..7db9359f03 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -815,10 +815,6 @@ std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, floa }); } -bool HWComposer::isUsingVrComposer() const { - return getComposer()->isUsingVrComposer(); -} - status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on); @@ -883,11 +879,6 @@ std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId disp bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId, bool hasDisplayIdentificationData) const { - if (isUsingVrComposer() && mInternalHwcDisplayId) { - ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); - return true; - } - if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) { ALOGE("Ignoring connection of display %" PRIu64 " without identification data", hwcDisplayId); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index c355ebd4a6..e05e41a7a1 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -195,8 +195,6 @@ public: virtual status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode, ui::RenderIntent renderIntent) = 0; - virtual bool isUsingVrComposer() const = 0; - // Composer 2.4 virtual DisplayConnectionType getDisplayConnectionType(DisplayId) const = 0; virtual bool isVsyncPeriodSwitchSupported(DisplayId displayId) const = 0; @@ -336,8 +334,6 @@ public: status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode, ui::RenderIntent renderIntent) override; - bool isUsingVrComposer() const override; - // Composer 2.4 DisplayConnectionType getDisplayConnectionType(DisplayId) const override; bool isVsyncPeriodSwitchSupported(DisplayId displayId) const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 55af849b7f..3282a5a4c6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -492,9 +492,6 @@ void Layer::prepareGeometryCompositionState() { compositionState->geomUsesSourceCrop = usesSourceCrop(); compositionState->isSecure = isSecure(); - compositionState->type = type; - compositionState->appId = appId; - compositionState->metadata.clear(); const auto& supportedMetadata = mFlinger->getHwComposer().getSupportedLayerGenericMetadata(); for (const auto& [key, mandatory] : supportedMetadata) { diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS index f273725518..43a6e55a09 100644 --- a/services/surfaceflinger/OWNERS +++ b/services/surfaceflinger/OWNERS @@ -1,8 +1,6 @@ adyabr@google.com -akrulec@google.com alecmouri@google.com chaviw@google.com lpy@google.com racarr@google.com -stoza@google.com vishnun@google.com diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index 61f3fbbdf1..708a5b87be 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -78,8 +78,12 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { if (!validate(timestamp)) { // VSR could elect to ignore the incongruent timestamp or resetModel(). If ts is ignored, - // don't insert this ts into mTimestamps ringbuffer. - if (!mTimestamps.empty()) { + // don't insert this ts into mTimestamps ringbuffer. If we are still + // in the learning phase we should just clear all timestamps and start + // over. + if (mTimestamps.size() < kMinimumSamplesForPrediction) { + clearTimestamps(); + } else if (!mTimestamps.empty()) { mKnownTimestamp = std::max(timestamp, *std::max_element(mTimestamps.begin(), mTimestamps.end())); } else { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 02b5324e9c..4698ac6199 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -46,7 +46,6 @@ #include <cutils/compiler.h> #include <cutils/properties.h> #include <dlfcn.h> -#include <dvr/vr_flinger.h> #include <errno.h> #include <gui/BufferQueue.h> #include <gui/DebugEGLImageTracker.h> @@ -267,7 +266,6 @@ int64_t SurfaceFlinger::dispSyncPresentTimeOffset; bool SurfaceFlinger::useHwcForRgbToYuv; uint64_t SurfaceFlinger::maxVirtualDisplaySize; bool SurfaceFlinger::hasSyncFramework; -bool SurfaceFlinger::useVrFlinger; int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers; uint32_t SurfaceFlinger::maxGraphicsWidth; uint32_t SurfaceFlinger::maxGraphicsHeight; @@ -332,9 +330,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI maxVirtualDisplaySize = max_virtual_display_dimension(0); - // Vr flinger is only enabled on Daydream ready devices. - useVrFlinger = use_vr_flinger(false); - maxFrameBufferAcquiredBuffers = max_frame_buffer_acquired_buffers(2); maxGraphicsWidth = std::max(max_graphics_width(0), 0); @@ -601,17 +596,6 @@ void SurfaceFlinger::bootFinished() if (mWindowManager != 0) { mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this)); } - sp<IBinder> input(defaultServiceManager()->getService( - String16("inputflinger"))); - if (input == nullptr) { - ALOGE("Failed to link to input service"); - } else { - mInputFlinger = interface_cast<IInputFlinger>(input); - } - - if (mVrFlinger) { - mVrFlinger->OnBootFinished(); - } // stop boot animation // formerly we would just kill the process, but we now ask it to exit so it @@ -622,7 +606,15 @@ void SurfaceFlinger::bootFinished() LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); - static_cast<void>(schedule([this] { + sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger"))); + + static_cast<void>(schedule([=] { + if (input == nullptr) { + ALOGE("Failed to link to input service"); + } else { + mInputFlinger = interface_cast<IInputFlinger>(input); + } + readPersistentProperties(); mPowerAdvisor.onBootFinished(); mBootStage = BootStage::FINISHED; @@ -688,9 +680,6 @@ void SurfaceFlinger::init() { : renderengine::RenderEngine::ContextPriority::MEDIUM) .build())); mCompositionEngine->setTimeStats(mTimeStats); - - LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, - "Starting with vr flinger active is not currently supported."); mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName)); mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId); // Process any initial hotplug and resulting display changes. @@ -700,30 +689,6 @@ void SurfaceFlinger::init() { LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()), "Internal display is disconnected."); - if (useVrFlinger) { - auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) { - // This callback is called from the vr flinger dispatch thread. We - // need to call signalTransaction(), which requires holding - // mStateLock when we're not on the main thread. Acquiring - // mStateLock from the vr flinger dispatch thread might trigger a - // deadlock in surface flinger (see b/66916578), so post a message - // to be handled on the main thread instead. - static_cast<void>(schedule([=] { - ALOGI("VR request display mode: requestDisplay=%d", requestDisplay); - mVrFlingerRequestsDisplay = requestDisplay; - signalTransaction(); - })); - }; - mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(), - getHwComposer() - .fromPhysicalDisplayId(*display->getId()) - .value_or(0), - vrFlingerRequestDisplayCallback); - if (!mVrFlinger) { - ALOGE("Failed to start vrflinger"); - } - } - // initialize our drawing state mDrawingState = mCurrentState; @@ -1700,98 +1665,6 @@ void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) { } } -void SurfaceFlinger::resetDisplayState() { - mScheduler->disableHardwareVsync(true); - // Clear the drawing state so that the logic inside of - // handleTransactionLocked will fire. It will determine the delta between - // mCurrentState and mDrawingState and re-apply all changes when we make the - // transition. - mDrawingState.displays.clear(); - mDisplays.clear(); -} - -void SurfaceFlinger::updateVrFlinger() { - ATRACE_CALL(); - if (!mVrFlinger) - return; - bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay; - if (vrFlingerRequestsDisplay == getHwComposer().isUsingVrComposer()) { - return; - } - - if (vrFlingerRequestsDisplay && !getHwComposer().getComposer()->isRemote()) { - ALOGE("Vr flinger is only supported for remote hardware composer" - " service connections. Ignoring request to transition to vr" - " flinger."); - mVrFlingerRequestsDisplay = false; - return; - } - - Mutex::Autolock _l(mStateLock); - - sp<DisplayDevice> display = getDefaultDisplayDeviceLocked(); - LOG_ALWAYS_FATAL_IF(!display); - - const hal::PowerMode currentDisplayPowerMode = display->getPowerMode(); - - // Clear out all the output layers from the composition engine for all - // displays before destroying the hardware composer interface. This ensures - // any HWC layers are destroyed through that interface before it becomes - // invalid. - for (const auto& [token, displayDevice] : mDisplays) { - displayDevice->getCompositionDisplay()->clearOutputLayers(); - } - - // This DisplayDevice will no longer be relevant once resetDisplayState() is - // called below. Clear the reference now so we don't accidentally use it - // later. - display.clear(); - - if (!vrFlingerRequestsDisplay) { - mVrFlinger->SeizeDisplayOwnership(); - } - - resetDisplayState(); - // Delete the current instance before creating the new one - mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>()); - mCompositionEngine->setHwComposer(getFactory().createHWComposer( - vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName)); - mCompositionEngine->getHwComposer().setConfiguration(this, ++getBE().mComposerSequenceId); - - LOG_ALWAYS_FATAL_IF(!getHwComposer().getComposer()->isRemote(), - "Switched to non-remote hardware composer"); - - if (vrFlingerRequestsDisplay) { - mVrFlinger->GrantDisplayOwnership(); - } - - mVisibleRegionsDirty = true; - invalidateHwcGeometry(); - - // Re-enable default display. - display = getDefaultDisplayDeviceLocked(); - LOG_ALWAYS_FATAL_IF(!display); - setPowerModeInternal(display, currentDisplayPowerMode); - - // Reset the timing values to account for the period of the swapped in HWC - const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); - mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod); - - // The present fences returned from vr_hwc are not an accurate - // representation of vsync times. - mScheduler->setIgnorePresentFences(getHwComposer().isUsingVrComposer() || !hasSyncFramework); - - // Use phase of 0 since phase is not known. - // Use latency of 0, which will snap to the ideal latency. - DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod}; - setCompositorTimingSnapped(stats, 0); - - mScheduler->resyncToHardwareVsync(false, vsyncPeriod); - - mRepaintEverything = true; - setTransactionFlags(eDisplayTransactionNeeded); -} - sp<Fence> SurfaceFlinger::previousFrameFence() { // We are storing the last 2 present fences. If sf's phase offset is to be // woken up before the actual vsync but targeting the next vsync, we need to check @@ -1853,8 +1726,14 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { // calculate the expected present time once and use the cached // value throughout this frame to make sure all layers are // seeing this same value. - const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load(); - mExpectedPresentTime = expectedVSyncTime; + if (expectedVSyncTime >= frameStart) { + mExpectedPresentTime = expectedVSyncTime; + } else { + mExpectedPresentTime = mScheduler->getDispSyncExpectedPresentTime(frameStart); + } + + const nsecs_t lastScheduledPresentTime = mScheduledPresentTime; + mScheduledPresentTime = expectedVSyncTime; // When Backpressure propagation is enabled we want to give a small grace period // for the present fence to fire instead of just giving up on this frame to handle cases @@ -1884,7 +1763,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed", framePending || (previousPresentTime >= 0 && - (lastExpectedPresentTime < + (lastScheduledPresentTime < previousPresentTime - frameMissedSlop))}; const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed", mHadDeviceComposition && frameMissed}; @@ -1960,11 +1839,6 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { } } - // Now that we're going to make it to the handleMessageTransaction() - // call below it's safe to call updateVrFlinger(), which will - // potentially trigger a display handoff. - updateVrFlinger(); - if (mTracingEnabledChanged) { mTracingEnabled = mTracing.isEnabled(); mTracingEnabledChanged = false; @@ -2611,7 +2485,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, builder.setIsSecure(state.isSecure); builder.setLayerStackId(state.layerStack); builder.setPowerAdvisor(&mPowerAdvisor); - builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()); + builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays); builder.setName(state.displayName); const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); @@ -4832,15 +4706,6 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); alloc.dump(result); - /* - * Dump VrFlinger state if in use. - */ - if (mVrFlingerRequestsDisplay && mVrFlinger) { - result.append("VrFlinger state:\n"); - result.append(mVrFlinger->Dump()); - result.append("\n"); - } - result.append(mTimeStats->miniDump()); result.append("\n"); } @@ -5223,11 +5088,8 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } return NO_ERROR; } - // Is VrFlinger active? - case 1028: { - Mutex::Autolock _l(mStateLock); - reply->writeBool(getHwComposer().isUsingVrComposer()); - return NO_ERROR; + case 1028: { // Unused. + return NAME_NOT_FOUND; } // Set buffer size for SF tracing (value in KB) case 1029: { @@ -6206,9 +6068,6 @@ const std::unordered_map<std::string, uint32_t>& SurfaceFlinger::getGenericLayer // on the work to remove the table in that bug rather than adding more to // it. static const std::unordered_map<std::string, uint32_t> genericLayerMetadataKeyMap{ - // Note: METADATA_OWNER_UID and METADATA_WINDOW_TYPE are officially - // supported, and exposed via the - // IVrComposerClient::VrCommand::SET_LAYER_INFO command. {"org.chromium.arc.V1_0.TaskId", METADATA_TASK_ID}, {"org.chromium.arc.V1_0.CursorInfo", METADATA_MOUSE_CURSOR}, }; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c727574780..90ac856277 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -109,10 +109,6 @@ namespace renderengine { class RenderEngine; } // namespace renderengine -namespace dvr { -class VrFlinger; -} // namespace dvr - enum { eTransactionNeeded = 0x01, eTraversalNeeded = 0x02, @@ -798,8 +794,7 @@ private: // The following thread safety rules apply when accessing mHwc, either // directly or via getHwComposer(): // - // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc - // only when switching into and out of vr. Recreating mHwc must only be + // 1. When recreating mHwc, acquire mStateLock. Recreating mHwc must only be // done on the main thread. // // 2. When accessing mHwc on the main thread, it's not necessary to acquire @@ -983,14 +978,6 @@ private: void onFrameRateFlexibilityTokenReleased(); - /* ------------------------------------------------------------------------ - * VrFlinger - */ - void resetDisplayState() REQUIRES(mStateLock); - - // Check to see if we should handoff to vr flinger. - void updateVrFlinger(); - void updateColorMatrixLocked(); /* ------------------------------------------------------------------------ @@ -1175,9 +1162,6 @@ private: // to mWindowManager or mInputFlinger std::atomic<bool> mBootFinished = false; - std::unique_ptr<dvr::VrFlinger> mVrFlinger; - std::atomic<bool> mVrFlingerRequestsDisplay = false; - static bool useVrFlinger; std::thread::id mMainThreadId = std::this_thread::get_id(); DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::kEnhanced; @@ -1215,6 +1199,7 @@ private: std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats; std::atomic<nsecs_t> mExpectedPresentTime = 0; + nsecs_t mScheduledPresentTime = 0; hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE; /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp index 39017575b7..d6d0cb8174 100644 --- a/services/surfaceflinger/TimeStats/Android.bp +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libtimestats", srcs: [ diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS index 1441f91489..ded3ebbe05 100644 --- a/services/surfaceflinger/TimeStats/OWNERS +++ b/services/surfaceflinger/TimeStats/OWNERS @@ -1,2 +1 @@ alecmouri@google.com -zzyiwei@google.com diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp index b937f418b2..474309898d 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp +++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libtimestats_proto", export_include_dirs: ["include"], diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index d03cb7b22a..7f8da5a691 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "liblayers_proto", export_include_dirs: ["include"], diff --git a/services/surfaceflinger/sysprop/Android.bp b/services/surfaceflinger/sysprop/Android.bp index 7721d7d2b7..f5791195db 100644 --- a/services/surfaceflinger/sysprop/Android.bp +++ b/services/surfaceflinger/sysprop/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + sysprop_library { name: "SurfaceFlingerProperties", srcs: ["*.sysprop"], diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 1532855089..15744a1609 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "SurfaceFlinger_test", defaults: ["surfaceflinger_defaults"], @@ -44,7 +53,7 @@ cc_test { "libtrace_proto", ], shared_libs: [ - "android.hardware.graphics.common-unstable-ndk_platform", + "android.hardware.graphics.common-V2-ndk_platform", "android.hardware.graphics.common@1.2", "android.hardware.graphics.composer@2.1", "libandroid", diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 3535fbb1b4..2551a19b71 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "sffakehwc_test", defaults: ["surfaceflinger_defaults"], diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 1bbc3f8b41..e00c3da2b3 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "libsurfaceflinger_unittest", defaults: ["libsurfaceflinger_defaults"], diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 32d722e9c9..faa619e309 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -577,8 +577,6 @@ struct BaseLayerProperties { .Times(1); // TODO: Coverage of other values EXPECT_CALL(*test->mComposer, setLayerZOrder(HWC_DISPLAY, HWC_LAYER, 0u)).Times(1); - // TODO: Coverage of other values - EXPECT_CALL(*test->mComposer, setLayerInfo(HWC_DISPLAY, HWC_LAYER, 0u, 0u)).Times(1); // These expectations retire on saturation as the code path these // expectations are for appears to make an extra call to them. diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 06bdcdc666..0323778979 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -1298,55 +1298,6 @@ TEST_F(DisplayTransactionTest, destroyDisplayHandlesUnknownDisplay) { } /* ------------------------------------------------------------------------ - * SurfaceFlinger::resetDisplayState - */ - -TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { - using Case = NonHwcVirtualDisplayCase; - - // -------------------------------------------------------------------- - // Preconditions - - // vsync is enabled and available - mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled() = true; - mFlinger.scheduler()->mutableHWVsyncAvailable() = true; - - // A display exists - auto existing = Case::Display::makeFakeExistingDisplayInjector(this); - existing.inject(); - - // -------------------------------------------------------------------- - // Call Expectations - - // The call disable vsyncs - EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1); - - // The call ends any display resyncs - EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1); - - // -------------------------------------------------------------------- - // Invocation - - mFlinger.resetDisplayState(); - - // -------------------------------------------------------------------- - // Postconditions - - // vsyncs should be off and not available. - EXPECT_FALSE(mFlinger.scheduler()->mutablePrimaryHWVsyncEnabled()); - EXPECT_FALSE(mFlinger.scheduler()->mutableHWVsyncAvailable()); - - // The display should have been removed from the display map. - EXPECT_FALSE(hasDisplayDevice(existing.token())); - - // The display should still exist in the current state - EXPECT_TRUE(hasCurrentDisplayState(existing.token())); - - // The display should have been removed from the drawing state - EXPECT_FALSE(hasDrawingDisplayState(existing.token())); -} - -/* ------------------------------------------------------------------------ * DisplayDevice::GetBestColorMode */ class GetBestColorModeTest : public DisplayTransactionTest { @@ -2019,8 +1970,6 @@ void HandleTransactionLockedTest::processesHotplugConnectCommon() { // -------------------------------------------------------------------- // Call Expectations - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillOnce(Return(false)); - setupCommonCallExpectationsForConnectProcessing<Case>(); // -------------------------------------------------------------------- @@ -2082,7 +2031,6 @@ void HandleTransactionLockedTest::processesHotplugDisconnectCommon() { // -------------------------------------------------------------------- // Call Expectations - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false)); EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _)) .Times(0); @@ -2139,20 +2087,9 @@ TEST_F(HandleTransactionLockedTest, ignoresHotplugConnectIfPrimaryAndExternalAlr SetArgPointee<2>(TertiaryDisplay::GET_IDENTIFICATION_DATA()), Return(Error::NONE))); - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false)); - ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>(); } -TEST_F(HandleTransactionLockedTest, ignoresHotplugConnectIfExternalForVrComposer) { - // Inject a primary display. - PrimaryDisplayVariant::injectHwcDisplay(this); - - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(true)); - - ignoresHotplugConnectCommon<SimpleExternalDisplayCase>(); -} - TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) { processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>(); } @@ -2177,8 +2114,6 @@ TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary // -------------------------------------------------------------------- // Call Expectations - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false)); - setupCommonCallExpectationsForConnectProcessing<Case>(); setupCommonCallExpectationsForDisconnectProcessing<Case>(); @@ -2225,8 +2160,6 @@ TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary // -------------------------------------------------------------------- // Call Expectations - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false)); - setupCommonCallExpectationsForConnectProcessing<Case>(); setupCommonCallExpectationsForDisconnectProcessing<Case>(); @@ -2385,11 +2318,6 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) { mFlinger.mutableCurrentState().displays.removeItem(existing.token()); // -------------------------------------------------------------------- - // Call Expectations - - EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false)); - - // -------------------------------------------------------------------- // Invocation mFlinger.handleTransactionLocked(eDisplayTransactionNeeded); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index cbf264de53..cd2a482e42 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -289,8 +289,6 @@ public: return mFlinger->destroyDisplay(displayToken); } - auto resetDisplayState() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->resetDisplayState(); } - auto setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index d4cd11dbe1..5e5d51c994 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -450,6 +450,20 @@ TEST_F(VSyncPredictorTest, aPhoneThatHasBeenAroundAWhileCanStillComputePeriod) { EXPECT_THAT(intercept, Eq(0)); } +TEST_F(VSyncPredictorTest, InconsistentVsyncValueIsFlushedEventually) { + EXPECT_TRUE(tracker.addVsyncTimestamp(600)); + EXPECT_TRUE(tracker.needsMoreSamples()); + + EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod)); + + for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) { + EXPECT_TRUE(tracker.needsMoreSamples()); + EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod)); + } + + EXPECT_FALSE(tracker.needsMoreSamples()); +} + } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index c2c5072b24..cd9b87a60e 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -52,11 +52,9 @@ public: MOCK_METHOD0(getCapabilities, std::vector<IComposer::Capability>()); MOCK_METHOD0(dumpDebugInfo, std::string()); MOCK_METHOD1(registerCallback, void(const sp<IComposerCallback>&)); - MOCK_METHOD0(isRemote, bool()); MOCK_METHOD0(resetCommands, void()); MOCK_METHOD0(executeCommands, Error()); MOCK_METHOD0(getMaxVirtualDisplayCount, uint32_t()); - MOCK_CONST_METHOD0(isUsingVrComposer, bool()); MOCK_METHOD4(createVirtualDisplay, Error(uint32_t, uint32_t, PixelFormat*, Display*)); MOCK_METHOD1(destroyVirtualDisplay, Error(Display)); MOCK_METHOD1(acceptDisplayChanges, Error(Display)); @@ -110,7 +108,6 @@ public: MOCK_METHOD3(setLayerVisibleRegion, Error(Display, Layer, const std::vector<IComposerClient::Rect>&)); MOCK_METHOD3(setLayerZOrder, Error(Display, Layer, uint32_t)); - MOCK_METHOD4(setLayerInfo, Error(Display, Layer, uint32_t, uint32_t)); MOCK_METHOD3(getRenderIntents, Error(Display, ColorMode, std::vector<RenderIntent>*)); MOCK_METHOD3(setLayerColorTransform, Error(Display, Layer, const float*)); MOCK_METHOD4(getDisplayedContentSamplingAttributes, diff --git a/services/surfaceflinger/tests/vsync/Android.bp b/services/surfaceflinger/tests/vsync/Android.bp index 6a89945a92..bae9796598 100644 --- a/services/surfaceflinger/tests/vsync/Android.bp +++ b/services/surfaceflinger/tests/vsync/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-vsync-events", defaults: ["surfaceflinger_defaults"], diff --git a/services/surfaceflinger/tests/waitforvsync/Android.bp b/services/surfaceflinger/tests/waitforvsync/Android.bp index cb6d0fde0d..ffed4d77c7 100644 --- a/services/surfaceflinger/tests/waitforvsync/Android.bp +++ b/services/surfaceflinger/tests/waitforvsync/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_binary { name: "test-waitforvsync", cflags: [ diff --git a/services/utils/Android.bp b/services/utils/Android.bp index f3d2bc9766..81e1232e2c 100644 --- a/services/utils/Android.bp +++ b/services/utils/Android.bp @@ -15,6 +15,15 @@ // // Static library used in testing and executables // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libserviceutils", diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp index f21254cd7d..54cf5b7404 100644 --- a/services/utils/tests/Android.bp +++ b/services/utils/tests/Android.bp @@ -14,6 +14,15 @@ // Build unit tests. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_test { name: "prioritydumper_test", test_suites: ["device-tests"], diff --git a/services/vr/Android.bp b/services/vr/Android.bp index 80df479e8d..980dcf4616 100644 --- a/services/vr/Android.bp +++ b/services/vr/Android.bp @@ -1,3 +1,13 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + default_applicable_licenses: ["frameworks_native_license"], +} + subdirs = [ "*", ] diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp index 7097e7a8cc..8523bb205f 100644 --- a/services/vr/bufferhubd/Android.bp +++ b/services/vr/bufferhubd/Android.bp @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + sharedLibraries = [ "libbase", "libcutils", diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp index 372873149d..866007e188 100644 --- a/services/vr/hardware_composer/Android.bp +++ b/services/vr/hardware_composer/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libvr_hwc-hal", diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp index a1d5392071..98afdec517 100644 --- a/services/vr/hardware_composer/aidl/Android.bp +++ b/services/vr/hardware_composer/aidl/Android.bp @@ -1,3 +1,14 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + // SPDX-license-identifier-Unicode-DFS + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_static { name: "libvr_hwc-binder", srcs: [ diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp index 0ef8cc4762..5eca88b1f9 100644 --- a/services/vr/performanced/Android.bp +++ b/services/vr/performanced/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-MIT + default_applicable_licenses: ["frameworks_native_license"], +} + cc_defaults { name: "performanced_defaults", static_libs: [ diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp index 9cf4905b68..f2ec5a42b1 100644 --- a/services/vr/virtual_touchpad/Android.bp +++ b/services/vr/virtual_touchpad/Android.bp @@ -2,6 +2,15 @@ // Touchpad implementation. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + src = [ "EvdevInjector.cpp", "VirtualTouchpadEvdev.cpp", diff --git a/vulkan/Android.bp b/vulkan/Android.bp index 4934970aaa..33599ea35b 100644 --- a/vulkan/Android.bp +++ b/vulkan/Android.bp @@ -14,6 +14,16 @@ // This module makes the Vulkan libhardware HAL headers available, for // the loader and for HAL/driver implementations. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + // SPDX-license-identifier-MIT + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_headers { name: "hwvulkan_headers", vendor_available: true, diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp index 1d29bab355..67cd8754a3 100644 --- a/vulkan/libvulkan/Android.bp +++ b/vulkan/libvulkan/Android.bp @@ -13,6 +13,15 @@ // limitations under the License. // Headers module is in external/vulkan-headers/Android.bp. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + ndk_library { name: "libvulkan", symbol_file: "libvulkan.map.txt", diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index 5b9affd03a..9aaac5f1d6 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -33,6 +33,7 @@ #include <unordered_set> #include <utility> +#include <android-base/properties.h> #include <android-base/strings.h> #include <cutils/properties.h> #include <log/log.h> @@ -134,7 +135,7 @@ class OverrideLayerNames { // If no layers specified via Settings, check legacy properties if (implicit_layers_.count <= 0) { ParseDebugVulkanLayers(); - property_list(ParseDebugVulkanLayer, this); + ParseDebugVulkanLayer(); // sort by priorities auto& arr = implicit_layers_; @@ -181,30 +182,39 @@ class OverrideLayerNames { AddImplicitLayer(prio, p, strlen(p)); } - static void ParseDebugVulkanLayer(const char* key, - const char* val, - void* user_data) { + void ParseDebugVulkanLayer() { + // Checks for consecutive debug.vulkan.layer.<priority> system + // properties after always checking an initial fixed range. static const char prefix[] = "debug.vulkan.layer."; - const size_t prefix_len = sizeof(prefix) - 1; - - if (strncmp(key, prefix, prefix_len) || val[0] == '\0') - return; - key += prefix_len; - - // debug.vulkan.layer.<priority> - int priority = -1; - if (key[0] >= '0' && key[0] <= '9') - priority = atoi(key); + static constexpr int kFixedRangeBeginInclusive = 0; + static constexpr int kFixedRangeEndInclusive = 9; + + bool logged = false; + + int priority = kFixedRangeBeginInclusive; + while (true) { + const std::string prop_key = + std::string(prefix) + std::to_string(priority); + const std::string prop_val = + android::base::GetProperty(prop_key, ""); + + if (!prop_val.empty()) { + if (!logged) { + ALOGI( + "Detected Vulkan layers configured with " + "debug.vulkan.layer.<priority>. Checking for " + "debug.vulkan.layer.<priority> in the range [%d, %d] " + "followed by a consecutive scan.", + kFixedRangeBeginInclusive, kFixedRangeEndInclusive); + logged = true; + } + AddImplicitLayer(priority, prop_val.c_str(), prop_val.length()); + } else if (priority >= kFixedRangeEndInclusive) { + return; + } - if (priority < 0) { - ALOGW("Ignored implicit layer %s with invalid priority %s", val, - key); - return; + ++priority; } - - OverrideLayerNames& override_layers = - *reinterpret_cast<OverrideLayerNames*>(user_data); - override_layers.AddImplicitLayer(priority, val, strlen(val)); } void AddImplicitLayer(int priority, const char* name, size_t len) { diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 55d80fb7d9..5d4717200d 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -149,8 +149,8 @@ class CreateInfoWrapper { Hal Hal::hal_; const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{ - "ro.hardware.vulkan", - "ro.board.platform", + "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID, + "ro.board.platform" }}; constexpr int LIB_DL_FLAGS = RTLD_LOCAL | RTLD_NOW; @@ -184,8 +184,9 @@ int LoadDriver(android_namespace_t* library_namespace, if (so) break; } - if (!so) + if (!so) { return -ENOENT; + } auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR)); if (!hmi) { @@ -230,7 +231,6 @@ int LoadUpdatedDriver(const hwvulkan_module_t** module) { bool Hal::Open() { ATRACE_CALL(); - const nsecs_t openTime = systemTime(); ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once"); @@ -248,16 +248,16 @@ bool Hal::Open() { if (result != 0) { android::GraphicsEnv::getInstance().setDriverLoaded( android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime); - ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result); return true; } - hwvulkan_device_t* device; ATRACE_BEGIN("hwvulkan module open"); result = module->common.methods->open(&module->common, HWVULKAN_DEVICE_0, reinterpret_cast<hw_device_t**>(&device)); + + ATRACE_END(); if (result != 0) { android::GraphicsEnv::getInstance().setDriverLoaded( diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 6b51817caa..4b69bec743 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -606,44 +606,9 @@ void DestroySurfaceKHR(VkInstance instance, VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/, uint32_t /*queue_family*/, - VkSurfaceKHR surface_handle, + VkSurfaceKHR /*surface_handle*/, VkBool32* supported) { - ATRACE_CALL(); - - const Surface* surface = SurfaceFromHandle(surface_handle); - if (!surface) { - return VK_ERROR_SURFACE_LOST_KHR; - } - const ANativeWindow* window = surface->window.get(); - - int query_value; - int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value); - if (err != android::OK || query_value < 0) { - ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d", - strerror(-err), err, query_value); - return VK_ERROR_SURFACE_LOST_KHR; - } - - android_pixel_format native_format = - static_cast<android_pixel_format>(query_value); - - bool format_supported = false; - switch (native_format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - case HAL_PIXEL_FORMAT_RGB_565: - case HAL_PIXEL_FORMAT_RGBA_FP16: - case HAL_PIXEL_FORMAT_RGBA_1010102: - format_supported = true; - break; - default: - break; - } - - *supported = static_cast<VkBool32>( - format_supported || (surface->consumer_usage & - (AHARDWAREBUFFER_USAGE_CPU_READ_MASK | - AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0); - + *supported = VK_TRUE; return VK_SUCCESS; } @@ -1130,13 +1095,6 @@ VkResult CreateSwapchainKHR(VkDevice device, return VK_ERROR_SURFACE_LOST_KHR; } - err = native_window_set_buffer_count(window, 0); - if (err != android::OK) { - ALOGE("native_window_set_buffer_count(0) failed: %s (%d)", - strerror(-err), err); - return VK_ERROR_SURFACE_LOST_KHR; - } - int swap_interval = create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1; err = window->setSwapInterval(window, swap_interval); @@ -1744,7 +1702,7 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { if (err != android::OK) { ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err); swapchain_result = WorstPresentResult( - swapchain_result, VK_ERROR_OUT_OF_DATE_KHR); + swapchain_result, VK_ERROR_SURFACE_LOST_KHR); } else { if (img.dequeue_fence >= 0) { close(img.dequeue_fence); diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp index ba025046fa..0daad9c634 100644 --- a/vulkan/nulldrv/Android.bp +++ b/vulkan/nulldrv/Android.bp @@ -12,6 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { // Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM) name: "vulkan.default", diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp index 8528898f3d..fa0258bc06 100644 --- a/vulkan/vkjson/Android.bp +++ b/vulkan/vkjson/Android.bp @@ -1,3 +1,12 @@ +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + cc_library_shared { name: "libvkjson", srcs: [ diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc index bfc240e4dd..a513239061 100644 --- a/vulkan/vkjson/vkjson.cc +++ b/vulkan/vkjson/vkjson.cc @@ -1196,10 +1196,10 @@ template <typename T> bool VkTypeFromJson(const std::string& json, std::string* errors) { *t = T(); Json::Value object(Json::objectValue); - Json::Reader reader; - reader.parse(json, object, false); - if (!object) { - if (errors) errors->assign(reader.getFormatedErrorMessages()); + Json::CharReaderBuilder builder; + builder["collectComments"] = false; + std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); + if (!reader->parse(json.data(), json.data() + json.size(), &object, errors)) { return false; } return AsValue(&object, t); diff --git a/vulkan/vkjson/vkjson_info.cc b/vulkan/vkjson/vkjson_info.cc deleted file mode 100644 index 3c4b08b16f..0000000000 --- a/vulkan/vkjson/vkjson_info.cc +++ /dev/null @@ -1,184 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015-2016 The Khronos Group Inc. -// Copyright (c) 2015-2016 Valve Corporation -// Copyright (c) 2015-2016 LunarG, Inc. -// Copyright (c) 2015-2016 Google, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VK_PROTOTYPES -#define VK_PROTOTYPES -#endif - -#include "vkjson.h" - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#include <iostream> -#include <vector> - -const uint32_t unsignedNegOne = (uint32_t)(-1); - -struct Options { - bool instance = false; - uint32_t device_index = unsignedNegOne; - std::string device_name; - std::string output_file; -}; - -bool ParseOptions(int argc, char* argv[], Options* options) { - for (int i = 1; i < argc; ++i) { - std::string arg(argv[i]); - if (arg == "--instance" || arg == "-i") { - options->instance = true; - } else if (arg == "--first" || arg == "-f") { - options->device_index = 0; - } else { - ++i; - if (i >= argc) { - std::cerr << "Missing parameter after: " << arg << std::endl; - return false; - } - std::string arg2(argv[i]); - if (arg == "--device-index" || arg == "-d") { - int result = sscanf(arg2.c_str(), "%u", &options->device_index); - if (result != 1) { - options->device_index = static_cast<uint32_t>(-1); - std::cerr << "Unable to parse index: " << arg2 << std::endl; - return false; - } - } else if (arg == "--device-name" || arg == "-n") { - options->device_name = arg2; - } else if (arg == "--output" || arg == "-o") { - options->output_file = arg2; - } else { - std::cerr << "Unknown argument: " << arg << std::endl; - return false; - } - } - } - if (options->instance && (options->device_index != unsignedNegOne || - !options->device_name.empty())) { - std::cerr << "Specifying a specific device is incompatible with dumping " - "the whole instance." << std::endl; - return false; - } - if (options->device_index != unsignedNegOne && !options->device_name.empty()) { - std::cerr << "Must specify only one of device index and device name." - << std::endl; - return false; - } - if (options->instance && options->output_file.empty()) { - std::cerr << "Must specify an output file when dumping the whole instance." - << std::endl; - return false; - } - if (!options->output_file.empty() && !options->instance && - options->device_index == unsignedNegOne && options->device_name.empty()) { - std::cerr << "Must specify instance, device index, or device name when " - "specifying " - "output file." << std::endl; - return false; - } - return true; -} - -bool Dump(const VkJsonInstance& instance, const Options& options) { - const VkJsonDevice* out_device = nullptr; - if (options.device_index != unsignedNegOne) { - if (static_cast<uint32_t>(options.device_index) >= - instance.devices.size()) { - std::cerr << "Error: device " << options.device_index - << " requested but only " << instance.devices.size() - << " devices found." << std::endl; - return false; - } - out_device = &instance.devices[options.device_index]; - } else if (!options.device_name.empty()) { - for (const auto& device : instance.devices) { - if (device.properties.deviceName == options.device_name) { - out_device = &device; - } - } - if (!out_device) { - std::cerr << "Error: device '" << options.device_name - << "' requested but not found." << std::endl; - return false; - } - } - - std::string output_file; - if (options.output_file.empty()) { - assert(out_device); -#if defined(ANDROID) - output_file.assign("/sdcard/Android/" + std::string(out_device->properties.deviceName)); -#else - output_file.assign(out_device->properties.deviceName); -#endif - output_file.append(".json"); - } else { - output_file = options.output_file; - } - FILE* file = nullptr; - if (output_file == "-") { - file = stdout; - } else { - file = fopen(output_file.c_str(), "w"); - if (!file) { - std::cerr << "Unable to open file " << output_file << "." << std::endl; - return false; - } - } - - std::string json = out_device ? VkJsonDeviceToJson(*out_device) - : VkJsonInstanceToJson(instance); - fwrite(json.data(), 1, json.size(), file); - fputc('\n', file); - - if (output_file != "-") { - fclose(file); - std::cout << "Wrote file " << output_file; - if (out_device) - std::cout << " for device " << out_device->properties.deviceName; - std::cout << "." << std::endl; - } - return true; -} - -int main(int argc, char* argv[]) { -#if defined(ANDROID) - int vulkanSupport = InitVulkan(); - if (vulkanSupport == 0) - return 1; -#endif - Options options; - if (!ParseOptions(argc, argv, &options)) - return 1; - - VkJsonInstance instance = VkJsonGetInstance(); - if (options.instance || options.device_index != unsignedNegOne || - !options.device_name.empty()) { - Dump(instance, options); - } else { - for (uint32_t i = 0, n = static_cast<uint32_t>(instance.devices.size()); i < n; i++) { - options.device_index = i; - Dump(instance, options); - } - } - - return 0; -} diff --git a/vulkan/vkjson/vkjson_unittest.cc b/vulkan/vkjson/vkjson_unittest.cc deleted file mode 100644 index de765cdd73..0000000000 --- a/vulkan/vkjson/vkjson_unittest.cc +++ /dev/null @@ -1,101 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// Copyright (c) 2015-2016 The Khronos Group Inc. -// Copyright (c) 2015-2016 Valve Corporation -// Copyright (c) 2015-2016 LunarG, Inc. -// Copyright (c) 2015-2016 Google, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -/////////////////////////////////////////////////////////////////////////////// - -#include "vkjson.h" - -#include <stdlib.h> -#include <string.h> - -#include <iostream> - -#define EXPECT(X) if (!(X)) \ - ReportFailure(__FILE__, __LINE__, #X); - -#define ASSERT(X) if (!(X)) { \ - ReportFailure(__FILE__, __LINE__, #X); \ - return 2; \ -} - -int g_failures; - -void ReportFailure(const char* file, int line, const char* assertion) { - std::cout << file << ":" << line << ": \"" << assertion << "\" failed." - << std::endl; - ++g_failures; -} - -int main(int argc, char* argv[]) { - std::string errors; - bool result = false; - - VkJsonInstance instance; - instance.devices.resize(1); - VkJsonDevice& device = instance.devices[0]; - - const char name[] = "Test device"; - memcpy(device.properties.deviceName, name, sizeof(name)); - device.properties.limits.maxImageDimension1D = 3; - device.properties.limits.maxSamplerLodBias = 3.5f; - device.properties.limits.bufferImageGranularity = 0x1ffffffffull; - device.properties.limits.maxViewportDimensions[0] = 1; - device.properties.limits.maxViewportDimensions[1] = 2; - VkFormatProperties format_props = { - VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT, - VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT, - VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT}; - device.formats.insert(std::make_pair(VK_FORMAT_R8_UNORM, format_props)); - device.formats.insert(std::make_pair(VK_FORMAT_R8G8_UNORM, format_props)); - - std::string json = VkJsonInstanceToJson(instance); - std::cout << json << std::endl; - - VkJsonInstance instance2; - result = VkJsonInstanceFromJson(json, &instance2, &errors); - EXPECT(result); - if (!result) - std::cout << "Error: " << errors << std::endl; - const VkJsonDevice& device2 = instance2.devices.at(0); - - EXPECT(!memcmp(&device.properties, &device2.properties, - sizeof(device.properties))); - for (auto& kv : device.formats) { - auto it = device2.formats.find(kv.first); - EXPECT(it != device2.formats.end()); - EXPECT(!memcmp(&kv.second, &it->second, sizeof(kv.second))); - } - - VkImageFormatProperties props = {}; - json = VkJsonImageFormatPropertiesToJson(props); - VkImageFormatProperties props2 = {}; - result = VkJsonImageFormatPropertiesFromJson(json, &props2, &errors); - EXPECT(result); - if (!result) - std::cout << "Error: " << errors << std::endl; - - EXPECT(!memcmp(&props, &props2, sizeof(props))); - - if (g_failures) { - std::cout << g_failures << " failures." << std::endl; - return 1; - } else { - std::cout << "Success." << std::endl; - return 0; - } -} |