Allow odrefresh to write elsewhere than dalvik-cache
For CompOS we want to be able to generate artifacts in different
subdirectories, e.g. /data/misc/apexdata/com.android.art/pending
rather than /data/misc/apexdata/com.android.art/dalvik-cache.
Add a command line flag to enable this.
Bug: 200020887
Test: atest art_standalone_libartbase_tests
Test: manual: odrefresh --dalvik-cache=foo --force-compile
Change-Id: Id10c9bcc8cb9f810c48727abc1858f5b16b360d2
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index 0780fe0..0cbc77b 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -370,11 +370,18 @@
}
}
+static /*constinit*/ std::string_view dalvik_cache_sub_dir = "dalvik-cache";
+
+void OverrideDalvikCacheSubDirectory(std::string sub_dir) {
+ static std::string overridden_dalvik_cache_sub_dir;
+ overridden_dalvik_cache_sub_dir = std::move(sub_dir);
+ dalvik_cache_sub_dir = overridden_dalvik_cache_sub_dir;
+}
+
static std::string GetDalvikCacheDirectory(std::string_view root_directory,
std::string_view sub_directory = {}) {
- static constexpr std::string_view kDalvikCache = "dalvik-cache";
std::stringstream oss;
- oss << root_directory << '/' << kDalvikCache;
+ oss << root_directory << '/' << dalvik_cache_sub_dir;
if (!sub_directory.empty()) {
oss << '/' << sub_directory;
}
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index 6fc1caa..33ea2e9 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -80,6 +80,10 @@
// Returns the boot image path of the provided jar, on /system or /data.
std::string GetBootImagePath(bool on_system, const std::string& jar_path);
+// Allows the name to be used for the dalvik cache directory (normally "dalvik-cache") to be
+// overridden with a new value.
+void OverrideDalvikCacheSubDirectory(std::string sub_dir);
+
// Return true if we found the dalvik cache and stored it in the dalvik_cache argument.
// `have_android_data` will be set to true if we have an ANDROID_DATA that exists,
// `dalvik_cache_exists` will be true if there is a dalvik-cache directory that is present.
diff --git a/libartbase/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index a0b3325..7678df4 100644
--- a/libartbase/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
@@ -29,6 +29,21 @@
static constexpr const char kAndroidWifiApexDefaultPath[] = "/apex/com.android.wifi";
+namespace {
+class ScopedOverrideDalvikCacheSubDirectory {
+ public:
+ explicit ScopedOverrideDalvikCacheSubDirectory(const char* override) {
+ OverrideDalvikCacheSubDirectory(override);
+ }
+
+ ~ScopedOverrideDalvikCacheSubDirectory() {
+ OverrideDalvikCacheSubDirectory("dalvik-cache");
+ }
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedOverrideDalvikCacheSubDirectory);
+};
+} // namespace
+
class FileUtilsTest : public CommonArtTest {};
TEST_F(FileUtilsTest, GetDalvikCacheFilename) {
@@ -271,6 +286,33 @@
CHECK_EQ(vdex_filename, ReplaceFileExtension(art_filename, "vdex"));
}
+TEST_F(FileUtilsTest, OverrideDalvikCacheSubDirectory) {
+ ScopedUnsetEnvironmentVariable android_root("ANDROID_ROOT");
+ ScopedUnsetEnvironmentVariable i18n_root("ANDROID_I18N_ROOT");
+ ScopedUnsetEnvironmentVariable art_apex_data("ART_APEX_DATA");
+
+ ScopedOverrideDalvikCacheSubDirectory dalvik_cache("overridden-cache");
+
+ EXPECT_EQ(GetArtApexData() + "/overridden-cache/arm/boot-beep.oat",
+ GetApexDataOatFilename("/product/javalib/beep.jar", InstructionSet::kArm));
+
+ EXPECT_EQ(GetArtApexData() + "/overridden-cache/arm/data@some@code.odex",
+ GetApexDataOdexFilename("/data/some/code.dex", InstructionSet::kArm));
+
+ const std::string system_jar = "/system/framework/disk.jar";
+ const std::string boot_image = GetApexDataBootImage(system_jar.c_str());
+ EXPECT_EQ(GetArtApexData() + "/overridden-cache/boot-disk.art", boot_image);
+
+ EXPECT_EQ(
+ GetArtApexData() + "/overridden-cache/apex@com.android.wifi@lib@javalib@bar.jar@classes.art",
+ GetApexDataImage(std::string {kAndroidWifiApexDefaultPath} + "/lib/javalib/bar.jar"));
+
+ const std::string apex_jar = std::string {kAndroidWifiApexDefaultPath} + "/lib/javalib/bar.jar";
+ EXPECT_EQ(GetArtApexData() +
+ "/overridden-cache/x86_64/apex@com.android.wifi@lib@javalib@bar.jar@classes.art",
+ GetApexDataDalvikCacheFilename(apex_jar, InstructionSet::kX86_64, "art"));
+}
+
TEST_F(FileUtilsTest, GetSystemOdexFilenameForApex) {
ScopedUnsetEnvironmentVariable android_root("ANDROID_ROOT");
diff --git a/odrefresh/include/odrefresh/odrefresh.h b/odrefresh/include/odrefresh/odrefresh.h
index 1fe2382..f1c18ac 100644
--- a/odrefresh/include/odrefresh/odrefresh.h
+++ b/odrefresh/include/odrefresh/odrefresh.h
@@ -22,6 +22,8 @@
namespace art {
namespace odrefresh {
+// Default directory to which artifacts are written. (Overridable via the --dalvik-cache command
+// line argument.)
static constexpr const char* kOdrefreshArtifactDirectory =
"/data/misc/apexdata/com.android.art/dalvik-cache";
diff --git a/odrefresh/odr_config.h b/odrefresh/odr_config.h
index 253bd49..402955c 100644
--- a/odrefresh/odr_config.h
+++ b/odrefresh/odr_config.h
@@ -24,6 +24,7 @@
#include "arch/instruction_set.h"
#include "base/globals.h"
#include "log/log.h"
+#include "odrefresh/odrefresh.h"
namespace art {
namespace odrefresh {
@@ -55,6 +56,7 @@
ZygoteKind zygote_kind_;
int compilation_os_address_ = 0;
std::string boot_classpath_;
+ std::string artifact_dir_;
// Staging directory for artifacts. The directory must exist and will be automatically removed
// after compilation. If empty, use the default directory.
@@ -64,7 +66,8 @@
explicit OdrConfig(const char* program_name)
: dry_run_(false),
isa_(InstructionSet::kNone),
- program_name_(android::base::Basename(program_name)) {
+ program_name_(android::base::Basename(program_name)),
+ artifact_dir_(kOdrefreshArtifactDirectory) {
}
const std::string& GetApexInfoListFile() const { return apex_info_list_file_; }
@@ -96,6 +99,8 @@
const std::string& GetDex2oatBootClasspath() const { return dex2oat_boot_classpath_; }
+ const std::string& GetArtifactDirectory() const { return artifact_dir_; }
+
std::string GetDex2Oat() const {
const char* prefix = UseDebugBinaries() ? "dex2oatd" : "dex2oat";
const char* suffix = "";
@@ -136,6 +141,10 @@
dex2oat_boot_classpath_ = classpath;
}
+ void SetArtifactDirectory(const std::string& artifact_dir) {
+ artifact_dir_ = artifact_dir;
+ }
+
void SetDryRun() { dry_run_ = true; }
void SetIsa(const InstructionSet isa) { isa_ = isa; }
void SetCompilationOsAddress(int address) { compilation_os_address_ = address; }
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index 4e4c800..be58702 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -472,7 +472,7 @@
OnDeviceRefresh::OnDeviceRefresh(const OdrConfig& config)
: OnDeviceRefresh(config,
- Concatenate({kOdrefreshArtifactDirectory, "/", kCacheInfoFile}),
+ Concatenate({config.GetArtifactDirectory(), "/", kCacheInfoFile}),
std::make_unique<ExecUtils>(),
std::move(OdrDexopt::Create(config, std::make_unique<ExecUtils>()))) {}
@@ -700,11 +700,11 @@
WARN_UNUSED bool OnDeviceRefresh::RemoveArtifactsDirectory() const {
if (config_.GetDryRun()) {
- LOG(INFO) << "Directory " << QuotePath(kOdrefreshArtifactDirectory)
+ LOG(INFO) << "Directory " << QuotePath(config_.GetArtifactDirectory())
<< " and contents would be removed (dry-run).";
return true;
}
- return RemoveDirectory(kOdrefreshArtifactDirectory);
+ return RemoveDirectory(config_.GetArtifactDirectory());
}
WARN_UNUSED bool OnDeviceRefresh::BootExtensionArtifactsExist(
diff --git a/odrefresh/odrefresh_main.cc b/odrefresh/odrefresh_main.cc
index 2135224..7359df5 100644
--- a/odrefresh/odrefresh_main.cc
+++ b/odrefresh/odrefresh_main.cc
@@ -71,25 +71,6 @@
exit(EX_USAGE);
}
-NO_RETURN void UsageHelp(const char* argv0) {
- std::string name(android::base::Basename(argv0));
- UsageError("Usage: %s ACTION", name.c_str());
- UsageError("On-device refresh tool for boot class path extensions and system server");
- UsageError("following an update of the ART APEX.");
- UsageError("");
- UsageError("Valid ACTION choices are:");
- UsageError("");
- UsageError(
- "--check Check compilation artifacts are up-to-date based on metadata (fast).");
- UsageError("--compile Compile boot class path extensions and system_server jars");
- UsageError(" when necessary.");
- UsageError("--force-compile Unconditionally compile the boot class path extensions and");
- UsageError(" system_server jars.");
- UsageError("--verify Verify artifacts are up-to-date with dexoptanalyzer (slow).");
- UsageError("--help Display this help information.");
- exit(EX_USAGE);
-}
-
bool ParseZygoteKind(const char* input, ZygoteKind* zygote_kind) {
std::string_view z(input);
if (z == "zygote32") {
@@ -135,6 +116,10 @@
return false;
}
+void CommonOptionsHelp() {
+ UsageError("--dry-run");
+}
+
int InitializeHostConfig(int argc, char** argv, OdrConfig* config) {
__android_log_set_logger(__android_log_stderr_logger);
@@ -181,6 +166,17 @@
return n;
}
+void HostOptionsHelp() {
+ UsageError("--android-root");
+ UsageError("--android-art-root");
+ UsageError("--apex-info-list");
+ UsageError("--art-apex-data");
+ UsageError("--dex2oat-bootclasspath");
+ UsageError("--isa-root");
+ UsageError("--system-server-classpath");
+ UsageError("--zygote-arch");
+}
+
int InitializeTargetConfig(int argc, char** argv, OdrConfig* config) {
config->SetApexInfoListFile("/apex/apex-info-list.xml");
config->SetArtBinDir(art::GetArtBinDir());
@@ -206,6 +202,10 @@
ArgumentError("Failed to parse CID: %s", value.c_str());
}
config->SetCompilationOsAddress(cid);
+ } else if (ArgumentMatches(arg, "--dalvik-cache=", &value)) {
+ art::OverrideDalvikCacheSubDirectory(value);
+ config->SetArtifactDirectory(Concatenate(
+ {android::base::Dirname(art::odrefresh::kOdrefreshArtifactDirectory), "/", value}));
} else if (!InitializeCommonConfig(arg, config)) {
UsageError("Unrecognized argument: '%s'", arg);
}
@@ -213,6 +213,13 @@
return n;
}
+void TargetOptionsHelp() {
+ UsageError("--use-compilation-os=<CID> Run compilation in the VM with the given CID.");
+ UsageError(" (0 = do not use VM, -1 = use composd's VM)");
+ UsageError(
+ "--dalvik-cache=<DIR> Write artifacts to .../<DIR> rather than .../dalvik-cache");
+}
+
int InitializeConfig(int argc, char** argv, OdrConfig* config) {
if (art::kIsTargetBuild) {
return InitializeTargetConfig(argc, argv, config);
@@ -221,6 +228,35 @@
}
}
+NO_RETURN void UsageHelp(const char* argv0) {
+ std::string name(android::base::Basename(argv0));
+ UsageError("Usage: %s [OPTION...] ACTION", name.c_str());
+ UsageError("On-device refresh tool for boot class path extensions and system server");
+ UsageError("following an update of the ART APEX.");
+ UsageError("");
+ UsageError("Valid ACTION choices are:");
+ UsageError("");
+ UsageError(
+ "--check Check compilation artifacts are up-to-date based on metadata (fast).");
+ UsageError("--compile Compile boot class path extensions and system_server jars");
+ UsageError(" when necessary.");
+ UsageError("--force-compile Unconditionally compile the boot class path extensions and");
+ UsageError(" system_server jars.");
+ UsageError("--verify Verify artifacts are up-to-date with dexoptanalyzer (slow).");
+ UsageError("--help Display this help information.");
+ UsageError("");
+ UsageError("Available OPTIONs are:");
+ UsageError("");
+ CommonOptionsHelp();
+ if (art::kIsTargetBuild) {
+ TargetOptionsHelp();
+ } else {
+ HostOptionsHelp();
+ }
+
+ exit(EX_USAGE);
+}
+
} // namespace
int main(int argc, char** argv) {
@@ -240,7 +276,7 @@
UsageError("Expected 1 argument, but have %d.", argc);
}
- OdrMetrics metrics(art::odrefresh::kOdrefreshArtifactDirectory);
+ OdrMetrics metrics(config.GetArtifactDirectory());
OnDeviceRefresh odr(config);
for (int i = 0; i < argc; ++i) {
std::string_view action(argv[i]);