summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiakai Zhang <jiakaiz@google.com>2023-06-09 11:34:59 +0100
committerTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2023-06-12 09:43:51 +0000
commitfff86f6dc8dff440ff8cf56cf87fad288a1b06f2 (patch)
treead827e5c596a303165b5c6fbf4bbb96392e8895c
parentbacf884bb31a67489a6fba24b1b2e98587707102 (diff)
downloadart-fff86f6dc8dff440ff8cf56cf87fad288a1b06f2.tar.gz
Pass the cache-info fd from odrefresh to dex2oat.
This allows dex2oat in CompOS to read the cache-info file. Otherwise, CompOS will generate invalid artifacts that put the device into JIT Zygote. Bug: 286422732 Test: atest art_standalone_odrefresh_tests Test: (on udc-dev) - 1. adb shell device_config set_sync_disabled_for_tests persistent 2. adb shell device_config put runtime_native_boot enable_uffd_gc true 3. atest odsign_e2e_tests_full:CompOsSigningHostTest Change-Id: I4c6c5fb13a93b58ce53f46cd8d6d9c1e05ecd720 Merged-In: I4c6c5fb13a93b58ce53f46cd8d6d9c1e05ecd720 (cherry picked from commit d609d0762b9d8c473da4fa8de1122733b2a7a50c)
-rw-r--r--dex2oat/dex2oat_options.cc5
-rw-r--r--odrefresh/odrefresh.cc19
-rw-r--r--odrefresh/odrefresh_test.cc22
-rw-r--r--runtime/gc/collector/mark_compact.cc61
4 files changed, 94 insertions, 13 deletions
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index cf600087a3..4da219897b 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -462,7 +462,10 @@ Parser CreateDex2oatArgumentParser() {
.Define("--force-palette-compilation-hooks")
.WithHelp("Force PaletteNotify{Start,End}Dex2oatCompilation calls.")
.IntoKey(M::ForcePaletteCompilationHooks)
- .Ignore({"--comments=_"});
+ .Ignore({
+ "--comments=_",
+ "--cache-info-fd=_", // Handled in mark_compact.cc.
+ });
// clang-format on
AddCompilerOptionsArgumentParserOptions<Dex2oatArgumentMap>(*parser_builder);
diff --git a/odrefresh/odrefresh.cc b/odrefresh/odrefresh.cc
index cdec0a35af..7bbc922a8c 100644
--- a/odrefresh/odrefresh.cc
+++ b/odrefresh/odrefresh.cc
@@ -496,6 +496,19 @@ Result<void> AddBootClasspathFds(/*inout*/ std::vector<std::string>& args,
return {};
}
+Result<void> AddCacheInfoFd(/*inout*/ std::vector<std::string>& args,
+ /*inout*/ std::vector<std::unique_ptr<File>>& readonly_files_raii,
+ const std::string& cache_info_filename) {
+ std::unique_ptr<File> cache_info_file(OS::OpenFileForReading(cache_info_filename.c_str()));
+ if (cache_info_file == nullptr) {
+ return ErrnoErrorf("Failed to open a cache info file '{}'", cache_info_file);
+ }
+
+ args.emplace_back("--cache-info-fd=" + std::to_string(cache_info_file->Fd()));
+ readonly_files_raii.push_back(std::move(cache_info_file));
+ return {};
+}
+
std::string GetBootImageComponentBasename(const std::string& jar_path, bool is_first_jar) {
if (is_first_jar) {
return kFirstBootImageBasename;
@@ -1653,6 +1666,12 @@ WARN_UNUSED CompilationResult OnDeviceRefresh::RunDex2oat(
return CompilationResult::Error(OdrMetrics::Status::kUnknown, result.error().message());
}
+ // dex2oat reads some system properties from cache-info.xml generated by odrefresh.
+ result = AddCacheInfoFd(args, readonly_files_raii, cache_info_filename_);
+ if (!result.ok()) {
+ return CompilationResult::Error(OdrMetrics::Status::kUnknown, result.error().message());
+ }
+
for (const std::string& dex_file : dex_files) {
std::string actual_path = RewriteParentDirectoryIfNeeded(dex_file);
args.emplace_back("--dex-file=" + dex_file);
diff --git a/odrefresh/odrefresh_test.cc b/odrefresh/odrefresh_test.cc
index 6c99cdda40..8ebeeab6bb 100644
--- a/odrefresh/odrefresh_test.cc
+++ b/odrefresh/odrefresh_test.cc
@@ -236,8 +236,9 @@ class OdRefreshTest : public CommonArtTest {
mock_exec_utils_ = mock_exec_utils.get();
metrics_ = std::make_unique<OdrMetrics>(dalvik_cache_dir_);
+ cache_info_xml_ = dalvik_cache_dir_ + "/cache-info.xml";
odrefresh_ = std::make_unique<OnDeviceRefresh>(
- config_, dalvik_cache_dir_ + "/cache-info.xml", std::move(mock_exec_utils));
+ config_, cache_info_xml_, std::move(mock_exec_utils));
}
void TearDown() override {
@@ -273,6 +274,7 @@ class OdRefreshTest : public CommonArtTest {
std::string services_jar_profile_;
std::string dirty_image_objects_file_;
std::string preloaded_classes_file_;
+ std::string cache_info_xml_;
};
TEST_F(OdRefreshTest, PrimaryBootImage) {
@@ -291,7 +293,8 @@ TEST_F(OdRefreshTest, PrimaryBootImage) {
ElementsAre(FdOf(core_oj_jar_), FdOf(framework_jar_)))),
Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot.oat")),
Contains(Flag("--base=", _)),
- Not(Contains(Flag("--boot-image=", _))))))
+ Not(Contains(Flag("--boot-image=", _))),
+ Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
.WillOnce(Return(0));
// Ignore the invocation for the mainline extension.
@@ -330,7 +333,8 @@ TEST_F(OdRefreshTest, BootImageMainlineExtension) {
FdOf(framework_wifi_jar_)))),
Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot-conscrypt.oat")),
Not(Contains(Flag("--base=", _))),
- Contains(Flag("--boot-image=", _)))))
+ Contains(Flag("--boot-image=", _)),
+ Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
.WillOnce(Return(0));
EXPECT_EQ(odrefresh_->Compile(
@@ -429,14 +433,16 @@ TEST_F(OdRefreshTest, AllSystemServerJars) {
EXPECT_CALL(*mock_exec_utils_,
DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)),
Contains("--class-loader-context=PCL[]"),
- Not(Contains(Flag("--class-loader-context-fds=", _))))))
+ Not(Contains(Flag("--class-loader-context-fds=", _))),
+ Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
.WillOnce(Return(0));
EXPECT_CALL(
*mock_exec_utils_,
DoExecAndReturnCode(
AllOf(Contains(Flag("--dex-file=", services_jar_)),
Contains(Flag("--class-loader-context=", "PCL[{}]"_format(location_provider_jar_))),
- Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))))))
+ Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))),
+ Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
.WillOnce(Return(0));
EXPECT_CALL(
*mock_exec_utils_,
@@ -445,7 +451,8 @@ TEST_F(OdRefreshTest, AllSystemServerJars) {
Contains(Flag("--class-loader-context=",
"PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))),
Contains(ListFlag("--class-loader-context-fds=",
- ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))))))
+ ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))),
+ Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
.WillOnce(Return(0));
EXPECT_CALL(
*mock_exec_utils_,
@@ -454,7 +461,8 @@ TEST_F(OdRefreshTest, AllSystemServerJars) {
Contains(Flag("--class-loader-context=",
"PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))),
Contains(ListFlag("--class-loader-context-fds=",
- ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))))))
+ ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))),
+ Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
.WillOnce(Return(0));
EXPECT_EQ(
diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc
index 82cd13e0da..bb34068fb1 100644
--- a/runtime/gc/collector/mark_compact.cc
+++ b/runtime/gc/collector/mark_compact.cc
@@ -29,10 +29,15 @@
#include <fstream>
#include <numeric>
+#include <string>
+#include <string_view>
+#include <vector>
#include "android-base/file.h"
#include "android-base/parsebool.h"
+#include "android-base/parseint.h"
#include "android-base/properties.h"
+#include "android-base/strings.h"
#include "base/file_utils.h"
#include "base/memfd.h"
#include "base/quasi_atomic.h"
@@ -162,18 +167,64 @@ static gc::CollectorType FetchCmdlineGcType() {
}
#ifdef ART_TARGET_ANDROID
+static int GetOverrideCacheInfoFd() {
+ std::string args_str;
+ if (!android::base::ReadFileToString("/proc/self/cmdline", &args_str)) {
+ LOG(WARNING) << "Failed to load /proc/self/cmdline";
+ return -1;
+ }
+ std::vector<std::string_view> args;
+ Split(std::string_view(args_str), /*separator=*/'\0', &args);
+ for (std::string_view arg : args) {
+ if (android::base::ConsumePrefix(&arg, "--cache-info-fd=")) { // This is a dex2oat flag.
+ int fd;
+ if (!android::base::ParseInt(std::string(arg), &fd)) {
+ LOG(ERROR) << "Failed to parse --cache-info-fd (value: '" << arg << "')";
+ return -1;
+ }
+ return fd;
+ }
+ }
+ return -1;
+}
+
static bool GetCachedBoolProperty(const std::string& key, bool default_value) {
- std::string path = GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + "/cache-info.xml";
- std::optional<com::android::art::CacheInfo> cache_info = com::android::art::read(path.c_str());
+ // For simplicity, we don't handle multiple calls because otherwise we would have to reset the fd.
+ static bool called = false;
+ CHECK(!called) << "GetCachedBoolProperty can be called only once";
+ called = true;
+
+ std::string cache_info_contents;
+ int fd = GetOverrideCacheInfoFd();
+ if (fd >= 0) {
+ if (!android::base::ReadFdToString(fd, &cache_info_contents)) {
+ PLOG(ERROR) << "Failed to read cache-info from fd " << fd;
+ return default_value;
+ }
+ } else {
+ std::string path = GetApexDataDalvikCacheDirectory(InstructionSet::kNone) + "/cache-info.xml";
+ if (!android::base::ReadFileToString(path, &cache_info_contents)) {
+ // If the file is not found, then we are in chroot or in a standalone runtime process (e.g.,
+ // IncidentHelper), or odsign/odrefresh failed to generate and sign the cache info. There's
+ // nothing we can do.
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Failed to read cache-info from the default path";
+ }
+ return default_value;
+ }
+ }
+
+ std::optional<com::android::art::CacheInfo> cache_info =
+ com::android::art::parse(cache_info_contents.c_str());
if (!cache_info.has_value()) {
- // We are in chroot or in a standalone runtime process (e.g., IncidentHelper), or
- // odsign/odrefresh failed to generate and sign the cache info. There's nothing we can do.
+ // This should never happen.
+ LOG(ERROR) << "Failed to parse cache-info";
return default_value;
}
const com::android::art::KeyValuePairList* list = cache_info->getFirstSystemProperties();
if (list == nullptr) {
// This should never happen.
- LOG(ERROR) << "Missing system properties from cache-info.";
+ LOG(ERROR) << "Missing system properties from cache-info";
return default_value;
}
const std::vector<com::android::art::KeyValuePair>& properties = list->getItem();