Add art::GetAndroidRuntimeRootSafe and art::GetAndroidRuntimeRoot.
Test: m test-art-host-gtest-file_utils_test
Change-Id: Ib1f188e448b46891ae6fea713a5e92f5e160f060
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index af1d2e6..3f8bf4d 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -178,6 +178,15 @@
}
}
+std::string GetAndroidRuntimeRootSafe(std::string* error_msg) {
+ const char* android_dir =
+ GetAndroidDirSafe(kAndroidRuntimeRootEnvVar, kAndroidRuntimeApexDefaultPath, error_msg);
+ return (android_dir != nullptr) ? android_dir : "";
+}
+
+std::string GetAndroidRuntimeRoot() {
+ return GetAndroidDir(kAndroidRuntimeRootEnvVar, kAndroidRuntimeApexDefaultPath);
+}
const char* GetAndroidData() {
return GetAndroidDir(kAndroidDataEnvVar, kAndroidDataDefaultPath);
}
@@ -341,13 +350,10 @@
}
bool RuntimeModuleRootDistinctFromAndroidRoot() {
- std::string error_msg;
- std::string android_root = GetAndroidRootSafe(&error_msg);
- const char* runtime_root =
- GetAndroidDirSafe(kAndroidRuntimeRootEnvVar, kAndroidRuntimeApexDefaultPath, &error_msg);
- return !android_root.empty()
- && (runtime_root != nullptr)
- && (android_root != std::string_view(runtime_root));
+ std::string unused_error_msg;
+ std::string android_root = GetAndroidRootSafe(&unused_error_msg);
+ std::string runtime_root = GetAndroidRuntimeRootSafe(&unused_error_msg);
+ return !android_root.empty() && !runtime_root.empty() && (android_root != runtime_root);
}
int DupCloexec(int fd) {
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index 1594aee..d2a0839 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -34,6 +34,11 @@
// Find $ANDROID_ROOT, /system, or return an empty string.
std::string GetAndroidRootSafe(/*out*/ std::string* error_msg);
+// Find $ANDROID_RUNTIME_ROOT, /apex/com.android.runtime, or abort.
+std::string GetAndroidRuntimeRoot();
+// Find $ANDROID_RUNTIME_ROOT, /apex/com.android.runtime, or return an empty string.
+std::string GetAndroidRuntimeRootSafe(/*out*/ std::string* error_msg);
+
// Find $ANDROID_DATA, /data, or abort.
const char* GetAndroidData();
// Find $ANDROID_DATA, /data, or return null.
diff --git a/libartbase/base/file_utils_test.cc b/libartbase/base/file_utils_test.cc
index c917307..0a5a7a7 100644
--- a/libartbase/base/file_utils_test.cc
+++ b/libartbase/base/file_utils_test.cc
@@ -66,14 +66,14 @@
// CommonArtTest sets ANDROID_ROOT, so expect this to be the same.
std::string android_root = GetAndroidRootSafe(&error_msg);
std::string android_root_env = getenv("ANDROID_ROOT");
- EXPECT_EQ(android_root, android_root_env);
+ EXPECT_EQ(android_root, android_root_env) << error_msg;
// Set ANDROID_ROOT to something else (but the directory must exist). So use dirname.
UniqueCPtr<char> root_dup(strdup(android_root_env.c_str()));
char* dir = dirname(root_dup.get());
ASSERT_EQ(0, setenv("ANDROID_ROOT", dir, /* overwrite */ 1));
std::string android_root2 = GetAndroidRootSafe(&error_msg);
- EXPECT_STREQ(dir, android_root2.c_str());
+ EXPECT_STREQ(dir, android_root2.c_str()) << error_msg;
// Set a bogus value for ANDROID_ROOT. This should be an error.
ASSERT_EQ(0, setenv("ANDROID_ROOT", "/this/is/obviously/bogus", /* overwrite */ 1));
@@ -88,15 +88,40 @@
UniqueCPtr<char> real_root3(realpath(android_root3.c_str(), nullptr));
#if !defined(__BIONIC__ ) || defined(__ANDROID__)
UniqueCPtr<char> real_root(realpath(android_root.c_str(), nullptr));
- EXPECT_STREQ(real_root.get(), real_root3.get());
+ EXPECT_STREQ(real_root.get(), real_root3.get()) << error_msg;
#else
- EXPECT_STRNE(real_root3.get(), "");
+ EXPECT_STRNE(real_root3.get(), "") << error_msg;
#endif
// Reset ANDROID_ROOT, as other things may depend on it.
ASSERT_EQ(0, setenv("ANDROID_ROOT", android_root_env.c_str(), /* overwrite */ 1));
}
+TEST_F(FileUtilsTest, GetAndroidRuntimeRootSafe) {
+ std::string error_msg;
+
+ // We don't expect null returns for most cases, so don't check and let std::string crash.
+
+ // CommonArtTest sets ANDROID_RUNTIME_ROOT, so expect this to be the same.
+ std::string android_runtime_root = GetAndroidRuntimeRootSafe(&error_msg);
+ std::string android_runtime_root_env = getenv("ANDROID_RUNTIME_ROOT");
+ EXPECT_EQ(android_runtime_root, android_runtime_root_env) << error_msg;
+
+ // Set ANDROID_RUNTIME_ROOT to something else (but the directory must exist). So use dirname.
+ UniqueCPtr<char> root_dup(strdup(android_runtime_root_env.c_str()));
+ char* dir = dirname(root_dup.get());
+ ASSERT_EQ(0, setenv("ANDROID_RUNTIME_ROOT", dir, /* overwrite */ 1));
+ std::string android_runtime_root2 = GetAndroidRuntimeRootSafe(&error_msg);
+ EXPECT_STREQ(dir, android_runtime_root2.c_str()) << error_msg;
+
+ // Set a bogus value for ANDROID_RUNTIME_ROOT. This should be an error.
+ ASSERT_EQ(0, setenv("ANDROID_RUNTIME_ROOT", "/this/is/obviously/bogus", /* overwrite */ 1));
+ EXPECT_EQ(GetAndroidRuntimeRootSafe(&error_msg), "");
+
+ // Reset ANDROID_RUNTIME_ROOT, as other things may depend on it.
+ ASSERT_EQ(0, setenv("ANDROID_RUNTIME_ROOT", android_runtime_root_env.c_str(), /* overwrite */ 1));
+}
+
TEST_F(FileUtilsTest, ReplaceFileExtension) {
EXPECT_EQ("/directory/file.vdex", ReplaceFileExtension("/directory/file.oat", "vdex"));
EXPECT_EQ("/.directory/file.vdex", ReplaceFileExtension("/.directory/file.oat", "vdex"));