diff options
author | 2024-08-23 15:15:12 +0100 | |
---|---|---|
committer | 2024-08-29 11:54:30 +0000 | |
commit | dd06f773e8c9f2a54191d38f8fbc7b6925335380 (patch) | |
tree | d5178336ed9ad3f4a2d876bee06bce429830858c /dexopt_chroot_setup | |
parent | 3394ab00a058f4bb5ec227b8aacbb6cc98c36dae (diff) |
Support configuring additional partitions for Pre-reboot Dexopt.
This CL adds a system property
"dalvik.vm.pr_dexopt_additional_system_partitions" for this purpose.
Bug: 356966116
Test: atest art_standalone_dexopt_chroot_setup_tests
Change-Id: Ifa362173d8280bde162199138def8b0b46152281
Diffstat (limited to 'dexopt_chroot_setup')
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup.cc | 31 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup.h | 6 | ||||
-rw-r--r-- | dexopt_chroot_setup/dexopt_chroot_setup_test.cc | 33 |
3 files changed, 56 insertions, 14 deletions
diff --git a/dexopt_chroot_setup/dexopt_chroot_setup.cc b/dexopt_chroot_setup/dexopt_chroot_setup.cc index 46858127c3..7a1467a149 100644 --- a/dexopt_chroot_setup/dexopt_chroot_setup.cc +++ b/dexopt_chroot_setup/dexopt_chroot_setup.cc @@ -34,6 +34,7 @@ #include <string> #include <string_view> #include <system_error> +#include <tuple> #include <vector> #include "aidl/com/android/server/art/BnDexoptChrootSetup.h" @@ -66,6 +67,7 @@ namespace { using ::android::base::ConsumePrefix; using ::android::base::Error; +using ::android::base::GetProperty; using ::android::base::Join; using ::android::base::make_scope_guard; using ::android::base::NoDestructor; @@ -530,12 +532,25 @@ Result<void> DexoptChrootSetup::SetUpChroot(const std::optional<std::string>& ot OR_RETURN(CreateDir(CHROOT_DIR)); LOG(INFO) << ART_FORMAT("Created '{}'", CHROOT_DIR); - std::vector<std::string> additional_system_partitions = { - "system_ext", - "vendor", - "product", + std::vector<std::tuple<std::string, std::string>> additional_system_partitions = { + {"system_ext", "/system_ext"}, + {"vendor", "/vendor"}, + {"product", "/product"}, }; + std::string partitions_from_sysprop = + GetProperty(kAdditionalPartitionsSysprop, /*default_value=*/""); + std::vector<std::string_view> partitions_from_sysprop_entries; + art::Split(partitions_from_sysprop, ',', &partitions_from_sysprop_entries); + for (std::string_view entry : partitions_from_sysprop_entries) { + std::vector<std::string_view> pair; + art::Split(entry, ':', &pair); + if (pair.size() != 2 || pair[0].empty() || pair[1].empty() || !pair[1].starts_with('/')) { + return Errorf("Malformed entry in '{}': '{}'", kAdditionalPartitionsSysprop, entry); + } + additional_system_partitions.emplace_back(std::string(pair[0]), std::string(pair[1])); + } + if (!IsOtaUpdate(ota_slot)) { // Mainline update OR_RETURN(BindMount("/", CHROOT_DIR)); // Normally, we don't need to bind-mount "/system" because it's a part of the image mounted at @@ -543,11 +558,11 @@ Result<void> DexoptChrootSetup::SetUpChroot(const std::optional<std::string>& ot // "/system", so we need to bind-mount "/system" to handle this case. On devices where readonly // partitions are not remounted, bind-mounting "/system" doesn't hurt. OR_RETURN(BindMount("/system", PathInChroot("/system"))); - for (const std::string& partition : additional_system_partitions) { + for (const auto& [partition, mount_point] : additional_system_partitions) { // Some additional partitions are optional, but that's okay. The root filesystem (mounted at // `/`) has empty directories for additional partitions. If additional partitions don't exist, // we'll just be bind-mounting empty directories. - OR_RETURN(BindMount("/" + partition, PathInChroot("/" + partition))); + OR_RETURN(BindMount(mount_point, PathInChroot(mount_point))); } } else { CHECK(ota_slot.value() == "_a" || ota_slot.value() == "_b"); @@ -577,9 +592,9 @@ Result<void> DexoptChrootSetup::SetUpChroot(const std::optional<std::string>& ot OR_RETURN(BindMount("/postinstall", CHROOT_DIR)); } - for (const std::string& partition : additional_system_partitions) { + for (const auto& [partition, mount_point] : additional_system_partitions) { OR_RETURN(Mount(GetBlockDeviceName(partition, ota_slot.value()), - PathInChroot("/" + partition), + PathInChroot(mount_point), /*is_optional=*/true)); } } diff --git a/dexopt_chroot_setup/dexopt_chroot_setup.h b/dexopt_chroot_setup/dexopt_chroot_setup.h index f362e057a6..a80b1f7a16 100644 --- a/dexopt_chroot_setup/dexopt_chroot_setup.h +++ b/dexopt_chroot_setup/dexopt_chroot_setup.h @@ -27,6 +27,12 @@ namespace art { namespace dexopt_chroot_setup { +// A comma-separated list, where each entry is a colon-separated pair of a partition name in the +// super image and a mount point. E.g., +// some_partition_1:/some_mount_point_1,some_partition_2:/some_mount_point_2 +constexpr const char* kAdditionalPartitionsSysprop = + "dalvik.vm.pr_dexopt_additional_system_partitions"; + // A service that sets up the chroot environment for Pre-reboot Dexopt. class DexoptChrootSetup : public aidl::com::android::server::art::BnDexoptChrootSetup { public: diff --git a/dexopt_chroot_setup/dexopt_chroot_setup_test.cc b/dexopt_chroot_setup/dexopt_chroot_setup_test.cc index 51a41ebd6d..bbe0da352c 100644 --- a/dexopt_chroot_setup/dexopt_chroot_setup_test.cc +++ b/dexopt_chroot_setup/dexopt_chroot_setup_test.cc @@ -22,8 +22,10 @@ #include <filesystem> #include <string> #include <string_view> +#include <utility> #include "aidl/com/android/server/art/BnDexoptChrootSetup.h" +#include "android-base/file.h" #include "android-base/properties.h" #include "android-base/result-gmock.h" #include "android-base/scopeguard.h" @@ -41,7 +43,9 @@ namespace art { namespace dexopt_chroot_setup { namespace { +using ::android::base::GetProperty; using ::android::base::ScopeGuard; +using ::android::base::SetProperty; using ::android::base::WaitForProperty; using ::android::base::testing::HasError; using ::android::base::testing::HasValue; @@ -78,20 +82,29 @@ class DexoptChrootSetupTest : public CommonArtTest { GTEST_SKIP() << "A real Pre-reboot Dexopt is running"; } - ASSERT_TRUE(WaitForProperty("dev.bootcomplete", "1", /*relative_timeout=*/std::chrono::minutes(3))); + ASSERT_TRUE( + WaitForProperty("dev.bootcomplete", "1", /*relative_timeout=*/std::chrono::minutes(3))); - test_skipped = false; + test_skipped_ = false; scratch_dir_ = std::make_unique<ScratchDir>(); scratch_path_ = scratch_dir_->GetPath(); // Remove the trailing '/'; scratch_path_.resize(scratch_path_.length() - 1); + + partitions_sysprop_value_ = GetProperty(kAdditionalPartitionsSysprop, /*default_value=*/""); + ASSERT_TRUE(SetProperty(kAdditionalPartitionsSysprop, "odm:/odm,system_dlkm:/system_dlkm")); + partitions_sysprop_set_ = true; } void TearDown() override { - if (test_skipped) { + if (test_skipped_) { return; } + if (partitions_sysprop_set_ && + !SetProperty(kAdditionalPartitionsSysprop, partitions_sysprop_value_)) { + LOG(ERROR) << ART_FORMAT("Failed to recover sysprop '{}'", kAdditionalPartitionsSysprop); + } scratch_dir_.reset(); dexopt_chroot_setup_->tearDown(/*in_allowConcurrent=*/false); CommonArtTest::TearDown(); @@ -100,7 +113,9 @@ class DexoptChrootSetupTest : public CommonArtTest { std::shared_ptr<DexoptChrootSetup> dexopt_chroot_setup_; std::unique_ptr<ScratchDir> scratch_dir_; std::string scratch_path_; - bool test_skipped = true; + bool test_skipped_ = true; + std::string partitions_sysprop_value_; + bool partitions_sysprop_set_ = false; }; TEST_F(DexoptChrootSetupTest, Run) { @@ -110,6 +125,9 @@ TEST_F(DexoptChrootSetupTest, Run) { dexopt_chroot_setup_->setUp(/*in_otaSlot=*/std::nullopt, /*in_mapSnapshotsForOta=*/false)); ASSERT_STATUS_OK(dexopt_chroot_setup_->init()); + std::string mounts; + ASSERT_TRUE(android::base::ReadFileToString("/proc/mounts", &mounts, /*follow_symlinks=*/true)); + // Some important dirs that should be the same as outside. std::vector<const char*> same_dirs = { "/", @@ -127,6 +145,8 @@ TEST_F(DexoptChrootSetupTest, Run) { "/sys/fs/cgroup", "/sys/fs/selinux", "/metadata", + "/odm", + "/system_dlkm", }; for (const std::string& dir : same_dirs) { @@ -134,8 +154,9 @@ TEST_F(DexoptChrootSetupTest, Run) { ASSERT_EQ(stat(dir.c_str(), &st_outside), 0); struct stat st_inside; ASSERT_EQ(stat(PathInChroot(dir).c_str(), &st_inside), 0); - EXPECT_EQ(st_outside.st_dev, st_inside.st_dev); - EXPECT_EQ(st_outside.st_ino, st_inside.st_ino); + EXPECT_EQ(std::make_pair(st_outside.st_dev, st_outside.st_ino), + std::make_pair(st_inside.st_dev, st_inside.st_ino)) + << ART_FORMAT("Unexpected different directory in chroot: '{}'\n", dir) << mounts; } // Some important dirs that are expected to be writable. |