summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2023-02-20 16:40:47 +0000
committer Jiakai Zhang <jiakaiz@google.com> 2023-02-27 12:04:26 +0000
commitc66398d182443208e73133705da1a25a3794fc8e (patch)
tree015bd6bcf8e3aef7c87f3439ab013a0cf44d7f67
parent3b17ccb6deb7015fa3859319d3711c5ff11aecbb (diff)
Add the mainline framework boot image extension to the default.
This change makes the runtime and dex2oat pick up the mainline framework boot image extension built by the build system. Bug: 269230245 Test: atest art_standalone_dexpreopt_tests Test: - 1. boot without aosp/2434294. 2. See the process map showing that the boot images are successfully loaded. Test: - 1. boot with aosp/2434294. 2. See the process map showing that the boot images are successfully loaded. 3. See "zygote64: Verified 0 classes from mainline modules in 46.718us" in the logs. Change-Id: I3fe88c48526516196ef8745d976fd2d17c96a9d0
-rw-r--r--dexoptanalyzer/dexoptanalyzer.cc11
-rw-r--r--libartbase/base/file_utils.cc119
-rw-r--r--libartbase/base/file_utils.h10
-rw-r--r--test/dexpreopt/dexpreopt_test.cc10
4 files changed, 116 insertions, 34 deletions
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index ef4315739b..b182f68a7f 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -239,11 +239,16 @@ class DexoptAnalyzer final {
// If we don't receive the image, try to use the default one.
// Tests may specify a different image (e.g. core image).
std::string error_msg;
- image_ = GetDefaultBootImageLocation(&error_msg);
-
+ std::string android_root = GetAndroidRootSafe(&error_msg);
+ if (android_root.empty()) {
+ LOG(ERROR) << error_msg;
+ Usage("--image unspecified and ANDROID_ROOT not set.");
+ }
+ image_ = GetDefaultBootImageLocationSafe(
+ android_root, /*deny_art_apex_data_files=*/false, &error_msg);
if (image_.empty()) {
LOG(ERROR) << error_msg;
- Usage("--image unspecified and ANDROID_ROOT not set or image file does not exist.");
+ Usage("--image unspecified and failed to get default boot image location.");
}
}
}
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index 239628978e..bf0422a954 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -40,6 +40,7 @@
#include <memory>
#include <sstream>
+#include <vector>
#include "android-base/file.h"
#include "android-base/logging.h"
@@ -50,6 +51,7 @@
#include "base/os.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#if defined(__APPLE__)
#include <crt_externs.h>
@@ -78,6 +80,7 @@ static constexpr const char* kAndroidConscryptRootEnvVar = "ANDROID_CONSCRYPT_RO
static constexpr const char* kAndroidI18nRootEnvVar = "ANDROID_I18N_ROOT";
static constexpr const char* kApexDefaultPath = "/apex/";
static constexpr const char* kArtApexDataEnvVar = "ART_APEX_DATA";
+static constexpr const char* kBootImageStem = "boot";
// Get the "root" directory containing the "lib" directory where this instance
// of the libartbase library (which contains `GetRootContainingLibartbase`) is
@@ -298,10 +301,73 @@ std::string GetPrebuiltPrimaryBootImageDir() {
return GetPrebuiltPrimaryBootImageDir(android_root);
}
-std::string GetDefaultBootImageLocation(const std::string& android_root,
- bool deny_art_apex_data_files) {
+static std::string GetFirstMainlineFrameworkLibraryName(std::string* error_msg) {
+ const char* env_bcp = getenv("BOOTCLASSPATH");
+ const char* env_dex2oat_bcp = getenv("DEX2OATBOOTCLASSPATH");
+ if (env_bcp == nullptr || env_dex2oat_bcp == nullptr) {
+ *error_msg = "BOOTCLASSPATH and DEX2OATBOOTCLASSPATH must not be empty";
+ return "";
+ }
+
+ // DEX2OATBOOTCLASSPATH contains core libraries and framework libraries. We used to only compile
+ // those libraries. Now we compile mainline framework libraries as well, and we have repurposed
+ // DEX2OATBOOTCLASSPATH to indicate the separation between mainline framework libraries and other
+ // libraries.
+ std::string_view mainline_bcp(env_bcp);
+ if (!android::base::ConsumePrefix(&mainline_bcp, env_dex2oat_bcp)) {
+ *error_msg = "DEX2OATBOOTCLASSPATH must be a prefix of BOOTCLASSPATH";
+ return "";
+ }
+
+ std::vector<std::string_view> mainline_bcp_jars;
+ Split(mainline_bcp, ':', &mainline_bcp_jars);
+ if (mainline_bcp_jars.empty()) {
+ *error_msg = "No mainline framework library found";
+ return "";
+ }
+
+ std::string jar_name = android::base::Basename(mainline_bcp_jars[0]);
+
+ std::string_view library_name(jar_name);
+ if (!android::base::ConsumeSuffix(&library_name, ".jar")) {
+ *error_msg = "Invalid mainline framework jar: " + jar_name;
+ return "";
+ }
+
+ return std::string(library_name);
+}
+
+// Returns true when no error occurs, even if the extension doesn't exist.
+static bool MaybeAppendBootImageMainlineExtension(const std::string& android_root,
+ /*inout*/ std::string* location,
+ /*out*/ std::string* error_msg) {
+ if (!kIsTargetAndroid) {
+ return true;
+ }
+ // Due to how the runtime determines the mapping between boot images and bootclasspath jars, the
+ // name of the boot image extension must be in the format of
+ // `<primary-boot-image-stem>-<first-library-name>.art`.
+ std::string library_name = GetFirstMainlineFrameworkLibraryName(error_msg);
+ if (library_name.empty()) {
+ return false;
+ }
+ std::string mainline_extension_location = StringPrintf(
+ "%s/framework/%s-%s.art", android_root.c_str(), kBootImageStem, library_name.c_str());
+ std::string mainline_extension_path =
+ GetSystemImageFilename(mainline_extension_location.c_str(), kRuntimeISA);
+ if (!OS::FileExists(mainline_extension_path.c_str(), /*check_file_type=*/true)) {
+ // This is expected when the ART module is preloaded on an old source tree that doesn't
+ // dexpreopt mainline BCP jars, so it shouldn't be considered as an error.
+ return true;
+ }
+ *location += ":" + mainline_extension_location;
+ return true;
+}
+
+std::string GetDefaultBootImageLocationSafe(const std::string& android_root,
+ bool deny_art_apex_data_files,
+ std::string* error_msg) {
constexpr static const char* kEtcBootImageProf = "etc/boot-image.prof";
- constexpr static const char* kBootImageStem = "boot";
constexpr static const char* kMinimalBootImageStem = "boot_minimal";
// If an update for the ART module has been been installed, a single boot image for the entire
@@ -347,28 +413,37 @@ std::string GetDefaultBootImageLocation(const std::string& android_root,
PLOG(ERROR) << "Minimal boot image check failed, could not stat: " << boot_image_filename;
}
}
- // Boot image consists of two parts:
+
+ // Boot image consists of three parts:
// - the primary boot image (contains the Core Libraries)
- // - the boot image extensions (contains framework libraries)
- // Typically "/apex/com.android.art/javalib/boot.art!/apex/com.android.art/etc/boot-image.prof:
- // /system/framework/boot-framework.art!/system/etc/boot-image.prof".
- return StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s",
- GetPrebuiltPrimaryBootImageDir(android_root).c_str(),
- kBootImageStem,
- kAndroidArtApexDefaultPath,
- kEtcBootImageProf,
- android_root.c_str(),
- kBootImageStem,
- android_root.c_str(),
- kEtcBootImageProf);
-}
-
-std::string GetDefaultBootImageLocation(std::string* error_msg) {
- std::string android_root = GetAndroidRootSafe(error_msg);
- if (android_root.empty()) {
+ // - the boot image framework extension (contains framework libraries)
+ // - the boot image mainline extension (contains mainline framework libraries)
+ // Typically "/system/framework/boot.art!/apex/com.android.art/etc/boot-image.prof:
+ // /system/framework/boot-framework.art!/system/etc/boot-image.prof:
+ // /system/framework/boot-framework-adservices.art".
+
+ std::string location = StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s",
+ GetPrebuiltPrimaryBootImageDir(android_root).c_str(),
+ kBootImageStem,
+ kAndroidArtApexDefaultPath,
+ kEtcBootImageProf,
+ android_root.c_str(),
+ kBootImageStem,
+ android_root.c_str(),
+ kEtcBootImageProf);
+ if (!MaybeAppendBootImageMainlineExtension(android_root, &location, error_msg)) {
return "";
}
- return GetDefaultBootImageLocation(android_root, /*deny_art_apex_data_files=*/false);
+ return location;
+}
+
+std::string GetDefaultBootImageLocation(const std::string& android_root,
+ bool deny_art_apex_data_files) {
+ std::string error_msg;
+ std::string location =
+ GetDefaultBootImageLocationSafe(android_root, deny_art_apex_data_files, &error_msg);
+ CHECK(!location.empty()) << error_msg;
+ return location;
}
std::string GetJitZygoteBootImageLocation() {
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index f539f5fd55..a8fb0064a9 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -78,11 +78,13 @@ std::string GetArtApexData();
// generated at build time).
std::string GetPrebuiltPrimaryBootImageDir();
-// Returns the default boot image location (ANDROID_ROOT/framework/boot.art).
-// Returns an empty string if ANDROID_ROOT is not set.
-std::string GetDefaultBootImageLocation(std::string* error_msg);
-
// Returns the default boot image location, based on the passed `android_root`.
+// Returns an empty string if an error occurs.
+std::string GetDefaultBootImageLocationSafe(const std::string& android_root,
+ bool deny_art_apex_data_files,
+ std::string* error_msg);
+
+// Same as above, but fails if an error occurs.
std::string GetDefaultBootImageLocation(const std::string& android_root,
bool deny_art_apex_data_files);
diff --git a/test/dexpreopt/dexpreopt_test.cc b/test/dexpreopt/dexpreopt_test.cc
index 55593eae66..3fb2730cc1 100644
--- a/test/dexpreopt/dexpreopt_test.cc
+++ b/test/dexpreopt/dexpreopt_test.cc
@@ -46,7 +46,7 @@
namespace art {
-using ::testing::IsSubsetOf;
+using ::testing::IsSupersetOf;
constexpr const char* kZygote32 = "zygote";
constexpr const char* kZygote64 = "zygote64";
@@ -95,9 +95,9 @@ android::base::Result<std::vector<std::pair<std::string, InstructionSet>>> GetZy
}
android::base::Result<std::vector<std::string>> GetZygoteExpectedArtifacts(InstructionSet isa) {
- std::vector<std::string> jars = GetListFromEnv("DEX2OATBOOTCLASSPATH");
+ std::vector<std::string> jars = GetListFromEnv("BOOTCLASSPATH");
if (jars.empty()) {
- return Errorf("Environment variable `DEX2OATBOOTCLASSPATH` is not defined or empty");
+ return Errorf("Environment variable `BOOTCLASSPATH` is not defined or empty");
}
std::string art_root = GetArtRoot();
std::string android_root = GetAndroidRoot();
@@ -218,7 +218,7 @@ TEST(DexpreoptTest, ForZygote) {
GetZygoteMappedOatFiles(zygote_name);
ASSERT_RESULT_OK(mapped_oat_files);
- EXPECT_THAT(expected_artifacts.value(), IsSubsetOf(mapped_oat_files.value()));
+ EXPECT_THAT(mapped_oat_files.value(), IsSupersetOf(expected_artifacts.value()));
}
}
@@ -236,7 +236,7 @@ TEST(DexpreoptTest, ForSystemServer) {
GetSystemServerArtifactsMappedOdexes();
ASSERT_RESULT_OK(mapped_odexes);
- EXPECT_THAT(expected_artifacts.value(), IsSubsetOf(mapped_odexes.value()));
+ EXPECT_THAT(mapped_odexes.value(), IsSupersetOf(expected_artifacts.value()));
}
} // namespace art