summaryrefslogtreecommitdiff
path: root/dexopt_chroot_setup
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2024-08-23 15:15:12 +0100
committer Jiakai Zhang <jiakaiz@google.com> 2024-08-29 11:54:30 +0000
commitdd06f773e8c9f2a54191d38f8fbc7b6925335380 (patch)
treed5178336ed9ad3f4a2d876bee06bce429830858c /dexopt_chroot_setup
parent3394ab00a058f4bb5ec227b8aacbb6cc98c36dae (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.cc31
-rw-r--r--dexopt_chroot_setup/dexopt_chroot_setup.h6
-rw-r--r--dexopt_chroot_setup/dexopt_chroot_setup_test.cc33
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.