From b3a4e01448a32b2dc53cad8a981ed7c75d12d2cc Mon Sep 17 00:00:00 2001 From: Victor Hsieh Date: Mon, 14 Jun 2021 12:48:10 -0700 Subject: odrefresh: Support option to run dex2oat in PVM pvm_exec is an executable to run a command remotely, assuming the code is also in the VM. Since the input files may not be available in the VM, pvm_exec internally takes over the FDs and becomes a file server. In the remote execution setup, dex2oat receives the same FD numbers, and relies on "authfs", a FUSE client that talkes to the file server, to translate the read/write. By wrapping dex2oat with pvm_exec, this change makes it possible run dex2oat remotely, though not necessarily securely. For example, a command is not a secure interface since it allows unlimited numbers of combination of input paramters (or even allow manipulating the compilation, e.g. by adjusting Java property). We'll need to change the interface later. But in the meantime, this change will allow us to iterate more easily. Bug: 187346876 Test: 1. Start a PVM with ART and CompOS apex mounted 2. /apex/com.android.art/bin/odrefresh --use-compos=$CID \ --force-compile # odrefresh returns successfully (though much slower right now) Change-Id: I722e5290246e180a89f6d42d9a6bc10c79dc0d1a --- odrefresh/odr_config.h | 4 ++++ odrefresh/odrefresh.cc | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/odrefresh/odr_config.h b/odrefresh/odr_config.h index 41619442c6..89ca8c735a 100644 --- a/odrefresh/odr_config.h +++ b/odrefresh/odr_config.h @@ -54,6 +54,7 @@ class OdrConfig final { std::string system_server_classpath_; std::string updatable_bcp_packages_file_; ZygoteKind zygote_kind_; + std::string compilation_os_address_; public: explicit OdrConfig(const char* program_name) @@ -117,6 +118,8 @@ class OdrConfig final { bool GetDryRun() const { return dry_run_; } const std::string& GetSystemServerClasspath() const { return system_server_classpath_; } const std::string& GetUpdatableBcpPackagesFile() const { return updatable_bcp_packages_file_; } + bool UseCompilationOs() const { return !compilation_os_address_.empty(); } + std::string GetCompilationOsAddress() const { return compilation_os_address_; } void SetApexInfoListFile(const std::string& file_path) { apex_info_list_file_ = file_path; } void SetArtBinDir(const std::string& art_bin_dir) { art_bin_dir_ = art_bin_dir; } @@ -127,6 +130,7 @@ class OdrConfig final { void SetDryRun() { dry_run_ = true; } void SetIsa(const InstructionSet isa) { isa_ = isa; } + void SetCompilationOsAddress(const std::string& address) { compilation_os_address_ = address; } void SetSystemServerClasspath(const std::string& classpath) { system_server_classpath_ = classpath; diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc index 8acaf2266f..aa5b72f38c 100644 --- a/odrefresh/odrefresh.cc +++ b/odrefresh/odrefresh.cc @@ -1011,6 +1011,20 @@ class OnDeviceRefresh final { return Concatenate({staging_dir, "/", android::base::Basename(path)}); } + std::string JoinFilesAsFDs(const std::vector>& files, char delimiter) const { + std::stringstream output; + bool is_first = true; + for (const auto& f : files) { + output << std::to_string(f->Fd()); + if (is_first) { + is_first = false; + } else { + output << delimiter; + } + } + return output.str(); + } + WARN_UNUSED bool CompileBootExtensionArtifacts(const InstructionSet isa, const std::string& staging_dir, OdrMetrics& metrics, @@ -1100,6 +1114,17 @@ class OnDeviceRefresh final { return false; } + if (config_.UseCompilationOs()) { + std::vector prefix_args = { + "/apex/com.android.compos/bin/pvm_exec", + "--cid=" + config_.GetCompilationOsAddress(), + "--in-fd=" + JoinFilesAsFDs(readonly_files_raii, ','), + "--out-fd=" + JoinFilesAsFDs(staging_files, ','), + "--", + }; + args.insert(args.begin(), prefix_args.begin(), prefix_args.end()); + } + const time_t timeout = GetSubprocessTimeout(); const std::string cmd_line = android::base::Join(args, ' '); LOG(INFO) << "Compiling boot extensions (" << isa << "): " << cmd_line @@ -1234,6 +1259,17 @@ class OnDeviceRefresh final { const std::string extension_image = GetBootImageExtensionImage(/*on_system=*/false); args.emplace_back(Concatenate({"--boot-image=", GetBootImage(), ":", extension_image})); + if (config_.UseCompilationOs()) { + std::vector prefix_args = { + "/apex/com.android.compos/bin/pvm_exec", + "--cid=" + config_.GetCompilationOsAddress(), + "--in-fd=" + JoinFilesAsFDs(readonly_files_raii, ','), + "--out-fd=" + JoinFilesAsFDs(staging_files, ','), + "--", + }; + args.insert(args.begin(), prefix_args.begin(), prefix_args.end()); + } + const time_t timeout = GetSubprocessTimeout(); const std::string cmd_line = android::base::Join(args, ' '); LOG(INFO) << "Compiling " << jar << ": " << cmd_line << " [timeout " << timeout << "s]"; @@ -1470,8 +1506,12 @@ class OnDeviceRefresh final { int n = 1; for (; n < argc - 1; ++n) { - if (!InitializeCommonConfig(argv[n], config)) { - UsageError("Unrecognized argument: '%s'", argv[n]); + const char* arg = argv[n]; + std::string value; + if (ArgumentMatches(arg, "--use-compilation-os=", &value)) { + config->SetCompilationOsAddress(value); + } else if (!InitializeCommonConfig(arg, config)) { + UsageError("Unrecognized argument: '%s'", arg); } } return n; -- cgit v1.2.3-59-g8ed1b