Merge "Add trusty_rkp_set_uds_cert for UdsCert provisioning" into main
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index d402bf1..d476d36 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -499,7 +499,7 @@
}
// Canonical list of supported primary reboot reasons.
-const std::vector<const std::string> knownReasons = {
+const std::vector<std::string> knownReasons = {
// clang-format off
// kernel
"watchdog",
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index af1bb81..632f6f1 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -138,7 +138,7 @@
auto remaining = end - std::chrono::steady_clock::now();
if (remaining < decltype(remaining)::zero()) {
- log_error(output_fd, 0, "timeout expired");
+ log_error(output_fd, 0, "timeout expired (update_timeout)");
return false;
}
@@ -254,7 +254,7 @@
if (timeout_ms <= 0) {
remaining_ms = -1;
} else if (remaining_ms < 0) {
- log_error(output_fd, 0, "timeout expired");
+ log_error(output_fd, 0, "timeout expired before poll");
return false;
}
@@ -271,7 +271,7 @@
return false;
}
} else if (rc == 0) {
- log_error(output_fd, 0, "timeout expired");
+ log_error(output_fd, 0, "poll timeout expired");
return false;
}
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 32e8b88..192232d 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -34,6 +34,9 @@
],
"kernel-presubmit": [
{
+ "name": "adb-remount-sh"
+ },
+ {
"name": "libdm_test"
},
{
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index bd0fcfd..b63b9e7 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -74,7 +74,7 @@
return android::gsi::IsGsiRunning();
}
-std::vector<const std::string> OverlayMountPoints() {
+std::vector<std::string> OverlayMountPoints() {
// Never fallback to legacy cache mount point if within a DSU system,
// because running a DSU system implies the device supports dynamic
// partitions, which means legacy cache mustn't be used.
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.h b/fs_mgr/fs_mgr_overlayfs_mount.h
index 98b9007..f941ab1 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.h
+++ b/fs_mgr/fs_mgr_overlayfs_mount.h
@@ -54,7 +54,7 @@
bool OverlayfsSetupAllowed(bool verbose = false);
bool MountScratch(const std::string& device_path, bool readonly = false);
bool fs_mgr_overlayfs_umount_scratch();
-std::vector<const std::string> OverlayMountPoints();
+std::vector<std::string> OverlayMountPoints();
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
diff --git a/fs_mgr/fs_mgr_vendor_overlay.cpp b/fs_mgr/fs_mgr_vendor_overlay.cpp
index 6b742e5..6687283 100644
--- a/fs_mgr/fs_mgr_vendor_overlay.cpp
+++ b/fs_mgr/fs_mgr_vendor_overlay.cpp
@@ -36,7 +36,7 @@
// The order of the list means the priority to show the files in the directory.
// The last one has the highest priority.
-const std::vector<const std::string> kVendorOverlaySourceDirs = {
+const std::vector<std::string> kVendorOverlaySourceDirs = {
"/system/vendor_overlay/",
"/product/vendor_overlay/",
};
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index f00e0dc..21d2e2e 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -520,6 +520,24 @@
} // namespace
+// Return the path to the recovery fstab file. There may be multiple fstab files;
+// the one that is returned will be the first that exists of recovery.fstab.<fstab_suffix>,
+// recovery.fstab.<hardware>, and recovery.fstab.<hardware.platform>.
+std::string GetRecoveryFstabPath() {
+ for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
+ std::string suffix;
+
+ if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
+
+ std::string fstab_path = "/etc/recovery.fstab." + suffix;
+ if (access(fstab_path.c_str(), F_OK) == 0) {
+ return fstab_path;
+ }
+ }
+
+ return "/etc/recovery.fstab";
+}
+
// Return the path to the fstab file. There may be multiple fstab files; the
// one that is returned will be the first that exists of fstab.<fstab_suffix>,
// fstab.<hardware>, and fstab.<hardware.platform>. The fstab is searched for
@@ -529,7 +547,7 @@
// the system/etc directory is supported too and is the preferred location.
std::string GetFstabPath() {
if (InRecovery()) {
- return "/etc/recovery.fstab";
+ return GetRecoveryFstabPath();
}
for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
std::string suffix;
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index 2e948dd..62f9901 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -229,6 +229,10 @@
// Enable direct reads from source device
bool o_direct = 12;
+
+ // Number of cow operations to be merged at once
+ uint32 cow_op_merge_size = 13;
+
}
// Next: 10
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 1ec8634..4a3ec1d 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -831,6 +831,8 @@
// Check if direct reads are enabled for the source image
bool UpdateUsesODirect(LockedFile* lock);
+ // Get value of maximum cow op merge size
+ uint32_t GetUpdateCowOpMergeSize(LockedFile* lock);
// Wrapper around libdm, with diagnostics.
bool DeleteDeviceIfExists(const std::string& name,
const std::chrono::milliseconds& timeout_ms = {});
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index 90813fe..0afd8bd 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -30,6 +30,8 @@
#include <storage_literals/storage_literals.h>
#include <update_engine/update_metadata.pb.h>
+#include "utility.h"
+
namespace android {
namespace snapshot {
@@ -234,5 +236,21 @@
#define RETURN_IF_NON_VIRTUAL_AB() RETURN_IF_NON_VIRTUAL_AB_MSG("")
+#define SKIP_IF_VENDOR_ON_ANDROID_S() \
+ do { \
+ if (IsVendorFromAndroid12()) \
+ GTEST_SKIP() << "Skip test as Vendor partition is on Android S"; \
+ } while (0)
+
+#define RETURN_IF_VENDOR_ON_ANDROID_S_MSG(msg) \
+ do { \
+ if (IsVendorFromAndroid12()) { \
+ std::cerr << (msg); \
+ return; \
+ } \
+ } while (0)
+
+#define RETURN_IF_VENDOR_ON_ANDROID_S() RETURN_IF_VENDOR_ON_ANDROID_S_MSG("")
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 3a474d7..265445b 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -20,7 +20,9 @@
#include <sys/file.h>
#include <sys/types.h>
#include <sys/unistd.h>
+#include <sys/xattr.h>
+#include <chrono>
#include <filesystem>
#include <optional>
#include <thread>
@@ -90,6 +92,8 @@
static constexpr char kRollbackIndicatorPath[] = "/metadata/ota/rollback-indicator";
static constexpr char kSnapuserdFromSystem[] = "/metadata/ota/snapuserd-from-system";
static constexpr auto kUpdateStateCheckInterval = 2s;
+static constexpr char kOtaFileContext[] = "u:object_r:ota_metadata_file:s0";
+
/*
* The readahead size is set to 32kb so that
* there is no significant memory pressure (/proc/pressure/memory) during boot.
@@ -1705,6 +1709,10 @@
if (UpdateUsesODirect(lock.get())) {
snapuserd_argv->emplace_back("-o_direct");
}
+ uint cow_op_merge_size = GetUpdateCowOpMergeSize(lock.get());
+ if (cow_op_merge_size != 0) {
+ snapuserd_argv->emplace_back("-cow_op_merge_size=" + std::to_string(cow_op_merge_size));
+ }
}
size_t num_cows = 0;
@@ -2127,6 +2135,11 @@
return update_status.o_direct();
}
+uint32_t SnapshotManager::GetUpdateCowOpMergeSize(LockedFile* lock) {
+ SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
+ return update_status.cow_op_merge_size();
+}
+
bool SnapshotManager::MarkSnapuserdFromSystem() {
auto path = GetSnapuserdFromSystemPath();
@@ -2134,6 +2147,24 @@
PLOG(ERROR) << "Unable to write to vendor update path: " << path;
return false;
}
+
+ unique_fd fd(open(path.c_str(), O_PATH));
+ if (fd < 0) {
+ PLOG(ERROR) << "Failed to open file: " << path;
+ return false;
+ }
+
+ /*
+ * This function is invoked by first stage init and hence we need to
+ * explicitly set the correct selinux label for this file as update_engine
+ * will try to remove this file later on once the snapshot merge is
+ * complete.
+ */
+ if (fsetxattr(fd.get(), XATTR_NAME_SELINUX, kOtaFileContext, strlen(kOtaFileContext) + 1, 0) <
+ 0) {
+ PLOG(ERROR) << "fsetxattr for the path: " << path << " failed";
+ }
+
return true;
}
@@ -2184,18 +2215,24 @@
*
*/
bool SnapshotManager::IsLegacySnapuserdPostReboot() {
- if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
- auto slot = GetCurrentSlot();
- if (slot == Slot::Target) {
- // If this marker is present, then daemon can handle userspace
- // snapshots; also, it indicates that the vendor partition was
- // updated from Android 12.
- if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
- return false;
- }
+ auto slot = GetCurrentSlot();
+ if (slot == Slot::Target) {
+ /*
+ If this marker is present, the daemon can handle userspace snapshots.
+ During post-OTA reboot, this implies that the vendor partition is
+ Android 13 or higher. If the snapshots were created on an
+ Android 12 vendor, this means the vendor partition has been updated.
+ */
+ if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
+ is_snapshot_userspace_ = true;
+ return false;
+ }
+ // If the marker isn't present and if the vendor is still in Android 12
+ if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
return true;
}
}
+
return false;
}
@@ -2865,10 +2902,12 @@
}
bool SnapshotManager::UnmapAllSnapshots(LockedFile* lock) {
+ LOG(INFO) << "Lock acquired for " << __FUNCTION__;
std::vector<std::string> snapshots;
if (!ListSnapshots(lock, &snapshots)) {
return false;
}
+ LOG(INFO) << "Found " << snapshots.size() << " partitions with snapshots";
for (const auto& snapshot : snapshots) {
if (!UnmapPartitionWithSnapshot(lock, snapshot)) {
@@ -2876,6 +2915,7 @@
return false;
}
}
+ LOG(INFO) << "Unmapped " << snapshots.size() << " partitions with snapshots";
// Terminate the daemon and release the snapuserd_client_ object.
// If we need to re-connect with the daemon, EnsureSnapuserdConnected()
@@ -2891,6 +2931,7 @@
auto SnapshotManager::OpenFile(const std::string& file,
int lock_flags) -> std::unique_ptr<LockedFile> {
+ const auto start = std::chrono::system_clock::now();
unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (fd < 0) {
PLOG(ERROR) << "Open failed: " << file;
@@ -2903,6 +2944,11 @@
// For simplicity, we want to CHECK that lock_mode == LOCK_EX, in some
// calls, so strip extra flags.
int lock_mode = lock_flags & (LOCK_EX | LOCK_SH);
+ const auto end = std::chrono::system_clock::now();
+ const auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+ if (duration_ms >= 1000ms) {
+ LOG(INFO) << "Taking lock on " << file << " took " << duration_ms.count() << "ms";
+ }
return std::make_unique<LockedFile>(file, std::move(fd), lock_mode);
}
@@ -3055,6 +3101,7 @@
status.set_io_uring_enabled(old_status.io_uring_enabled());
status.set_legacy_snapuserd(old_status.legacy_snapuserd());
status.set_o_direct(old_status.o_direct());
+ status.set_cow_op_merge_size(old_status.cow_op_merge_size());
}
return WriteSnapshotUpdateStatus(lock, status);
}
@@ -3437,6 +3484,8 @@
status.set_legacy_snapuserd(true);
LOG(INFO) << "Setting legacy_snapuserd to true";
}
+ status.set_cow_op_merge_size(
+ android::base::GetUintProperty<uint32_t>("ro.virtual_ab.cow_op_merge_size", 0));
} else if (legacy_compression) {
LOG(INFO) << "Virtual A/B using legacy snapuserd";
} else {
@@ -3872,6 +3921,7 @@
ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
ss << "Using o_direct: " << update_status.o_direct() << std::endl;
+ ss << "Cow op merge size (0 for uncapped): " << update_status.cow_op_merge_size() << std::endl;
ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl;
ss << "Current slot: " << device_->GetSlotSuffix() << std::endl;
ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 3299ec5..b2e36d4 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -122,6 +122,7 @@
LOG(INFO) << "Starting test: " << test_name_;
SKIP_IF_NON_VIRTUAL_AB();
+ SKIP_IF_VENDOR_ON_ANDROID_S();
SetupProperties();
if (!DeviceSupportsMode()) {
@@ -168,6 +169,7 @@
void TearDown() override {
RETURN_IF_NON_VIRTUAL_AB();
+ RETURN_IF_VENDOR_ON_ANDROID_S();
LOG(INFO) << "Tearing down SnapshotTest test: " << test_name_;
@@ -1015,6 +1017,7 @@
public:
void SetUp() override {
SKIP_IF_NON_VIRTUAL_AB();
+ SKIP_IF_VENDOR_ON_ANDROID_S();
SnapshotTest::SetUp();
if (!image_manager_) {
@@ -1097,6 +1100,7 @@
}
void TearDown() override {
RETURN_IF_NON_VIRTUAL_AB();
+ RETURN_IF_VENDOR_ON_ANDROID_S();
LOG(INFO) << "Tearing down SnapshotUpdateTest test: " << test_name_;
@@ -1978,6 +1982,8 @@
}
TEST_F(MetadataMountedTest, Recovery) {
+ GTEST_SKIP() << "b/350715463";
+
test_device->set_recovery(true);
metadata_dir_ = test_device->GetMetadataDir();
@@ -2659,6 +2665,7 @@
status.set_o_direct(true);
status.set_io_uring_enabled(true);
status.set_userspace_snapshots(true);
+ status.set_cow_op_merge_size(16);
sm->WriteSnapshotUpdateStatus(lock_.get(), status);
// Ensure a connection to the second-stage daemon, but use the first-stage
@@ -2680,6 +2687,8 @@
snapuserd_argv.end());
ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-user_snapshot") !=
snapuserd_argv.end());
+ ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-cow_op_merge_size=16") !=
+ snapuserd_argv.end());
}
class FlashAfterUpdateTest : public SnapshotUpdateTest,
@@ -2831,6 +2840,7 @@
// that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
// suites.
RETURN_IF_NON_VIRTUAL_AB_MSG("Virtual A/B is not enabled, skipping global setup.\n");
+ RETURN_IF_VENDOR_ON_ANDROID_S_MSG("Test not enabled for Vendor on Android S.\n");
std::vector<std::string> paths = {
// clang-format off
@@ -2885,6 +2895,8 @@
void SnapshotTestEnvironment::TearDown() {
RETURN_IF_NON_VIRTUAL_AB();
+ RETURN_IF_VENDOR_ON_ANDROID_S();
+
if (super_images_ != nullptr) {
DeleteBackingImage(super_images_.get(), "fake-super");
}
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index d83524a..b3a7e8c 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -166,6 +166,7 @@
],
ramdisk_available: false,
vendor_ramdisk_available: true,
+ recovery_available: true,
}
// This target will install to /system/bin/snapuserd_ramdisk
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index 67e9e52..dd2dd56 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -30,6 +30,7 @@
DEFINE_bool(user_snapshot, false, "If true, user-space snapshots are used");
DEFINE_bool(io_uring, false, "If true, io_uring feature is enabled");
DEFINE_bool(o_direct, false, "If true, enable direct reads on source device");
+DEFINE_int32(cow_op_merge_size, 0, "number of operations to be processed at once");
namespace android {
namespace snapshot {
@@ -106,7 +107,6 @@
}
return user_server_.Run();
}
-
for (int i = arg_start; i < argc; i++) {
auto parts = android::base::Split(argv[i], ",");
@@ -114,8 +114,8 @@
LOG(ERROR) << "Malformed message, expected at least four sub-arguments.";
return false;
}
- auto handler =
- user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3], FLAGS_o_direct);
+ auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3],
+ FLAGS_o_direct, FLAGS_cow_op_merge_size);
if (!handler || !user_server_.StartHandler(parts[0])) {
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
index c85331b..ef4ba93 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
@@ -41,7 +41,7 @@
bool Extractor::Init() {
auto opener = factory_.CreateTestOpener(control_name_);
handler_ = std::make_shared<SnapshotHandler>(control_name_, cow_path_, base_path_, base_path_,
- opener, 1, false, false, false);
+ opener, 1, false, false, false, 0);
if (!handler_->InitCowDevice()) {
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
index ea11f0e..fdd9cce 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -53,10 +53,10 @@
const std::string& misc_name, const std::string& cow_device_path,
const std::string& backing_device, const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
- bool o_direct) {
+ bool o_direct, uint32_t cow_op_merge_size) {
auto snapuserd = std::make_shared<SnapshotHandler>(
misc_name, cow_device_path, backing_device, base_path_merge, opener, num_worker_threads,
- use_iouring, perform_verification_, o_direct);
+ use_iouring, perform_verification_, o_direct, cow_op_merge_size);
if (!snapuserd->InitCowDevice()) {
LOG(ERROR) << "Failed to initialize Snapuserd";
return nullptr;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
index f23f07e..ecf5d5c 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
@@ -52,13 +52,11 @@
virtual ~ISnapshotHandlerManager() {}
// Add a new snapshot handler but do not start serving requests yet.
- virtual std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
- const std::string& cow_device_path,
- const std::string& backing_device,
- const std::string& base_path_merge,
- std::shared_ptr<IBlockServerOpener> opener,
- int num_worker_threads, bool use_iouring,
- bool o_direct) = 0;
+ virtual std::shared_ptr<HandlerThread> AddHandler(
+ const std::string& misc_name, const std::string& cow_device_path,
+ const std::string& backing_device, const std::string& base_path_merge,
+ std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
+ bool o_direct, uint32_t cow_op_merge_size) = 0;
// Start serving requests on a snapshot handler.
virtual bool StartHandler(const std::string& misc_name) = 0;
@@ -98,7 +96,7 @@
const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener,
int num_worker_threads, bool use_iouring,
- bool o_direct) override;
+ bool o_direct, uint32_t cow_op_merge_size) override;
bool StartHandler(const std::string& misc_name) override;
bool DeleteHandler(const std::string& misc_name) override;
bool InitiateMerge(const std::string& misc_name) override;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
index e6a9a29..e2c5874 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
@@ -32,12 +32,18 @@
MergeWorker::MergeWorker(const std::string& cow_device, const std::string& misc_name,
const std::string& base_path_merge,
- std::shared_ptr<SnapshotHandler> snapuserd)
- : Worker(cow_device, misc_name, base_path_merge, snapuserd) {}
+ std::shared_ptr<SnapshotHandler> snapuserd, uint32_t cow_op_merge_size)
+ : Worker(cow_device, misc_name, base_path_merge, snapuserd),
+ cow_op_merge_size_(cow_op_merge_size) {}
int MergeWorker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
std::vector<const CowOperation*>* replace_zero_vec) {
int num_ops = *pending_ops;
+ // 0 indicates ro.virtual_ab.cow_op_merge_size was not set in the build
+ if (cow_op_merge_size_ != 0) {
+ num_ops = std::min(cow_op_merge_size_, static_cast<uint32_t>(*pending_ops));
+ }
+
int nr_consecutive = 0;
bool checkOrderedOp = (replace_zero_vec == nullptr);
size_t num_blocks = 1;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h
index 478d4c8..a19352d 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h
@@ -23,7 +23,8 @@
class MergeWorker : public Worker {
public:
MergeWorker(const std::string& cow_device, const std::string& misc_name,
- const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd);
+ const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd,
+ uint32_t cow_op_merge_size);
bool Run();
private:
@@ -53,6 +54,7 @@
// syscalls and fallback to synchronous I/O, we
// don't want huge queue depth
int queue_depth_ = 8;
+ uint32_t cow_op_merge_size_ = 0;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
index 05ba047..7c9a64e 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -36,7 +36,8 @@
SnapshotHandler::SnapshotHandler(std::string misc_name, std::string cow_device,
std::string backing_device, std::string base_path_merge,
std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads,
- bool use_iouring, bool perform_verification, bool o_direct) {
+ bool use_iouring, bool perform_verification, bool o_direct,
+ uint32_t cow_op_merge_size) {
misc_name_ = std::move(misc_name);
cow_device_ = std::move(cow_device);
backing_store_device_ = std::move(backing_device);
@@ -46,6 +47,7 @@
is_io_uring_enabled_ = use_iouring;
perform_verification_ = perform_verification;
o_direct_ = o_direct;
+ cow_op_merge_size_ = cow_op_merge_size;
}
bool SnapshotHandler::InitializeWorkers() {
@@ -60,12 +62,11 @@
worker_threads_.push_back(std::move(wt));
}
-
merge_thread_ = std::make_unique<MergeWorker>(cow_device_, misc_name_, base_path_merge_,
- GetSharedPtr());
+ GetSharedPtr(), cow_op_merge_size_);
read_ahead_thread_ = std::make_unique<ReadAhead>(cow_device_, backing_store_device_, misc_name_,
- GetSharedPtr());
+ GetSharedPtr(), cow_op_merge_size_);
update_verify_ = std::make_unique<UpdateVerify>(misc_name_);
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index 9b7238a..c7de995 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -104,7 +104,8 @@
public:
SnapshotHandler(std::string misc_name, std::string cow_device, std::string backing_device,
std::string base_path_merge, std::shared_ptr<IBlockServerOpener> opener,
- int num_workers, bool use_iouring, bool perform_verification, bool o_direct);
+ int num_workers, bool use_iouring, bool perform_verification, bool o_direct,
+ uint32_t cow_op_merge_size);
bool InitCowDevice();
bool Start();
@@ -247,7 +248,7 @@
bool resume_merge_ = false;
bool merge_complete_ = false;
bool o_direct_ = false;
-
+ uint32_t cow_op_merge_size_ = 0;
std::unique_ptr<UpdateVerify> update_verify_;
std::shared_ptr<IBlockServerOpener> block_server_opener_;
};
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
index 2baf20d..6b1ed0c 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
@@ -18,6 +18,7 @@
#include <pthread.h>
+#include "android-base/properties.h"
#include "snapuserd_core.h"
#include "utility.h"
@@ -29,11 +30,13 @@
using android::base::unique_fd;
ReadAhead::ReadAhead(const std::string& cow_device, const std::string& backing_device,
- const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd) {
+ const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd,
+ uint32_t cow_op_merge_size) {
cow_device_ = cow_device;
backing_store_device_ = backing_device;
misc_name_ = misc_name;
snapuserd_ = snapuserd;
+ cow_op_merge_size_ = cow_op_merge_size;
}
void ReadAhead::CheckOverlap(const CowOperation* cow_op) {
@@ -62,8 +65,11 @@
std::vector<uint64_t>& blocks,
std::vector<const CowOperation*>& xor_op_vec) {
int num_ops = *pending_ops;
- int nr_consecutive = 0;
+ if (cow_op_merge_size_ != 0) {
+ num_ops = std::min(static_cast<int>(cow_op_merge_size_), *pending_ops);
+ }
+ int nr_consecutive = 0;
bool is_ops_present = (!RAIterDone() && num_ops);
if (!is_ops_present) {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
index d3ba126..4885c96 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
@@ -35,7 +35,8 @@
class ReadAhead {
public:
ReadAhead(const std::string& cow_device, const std::string& backing_device,
- const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd);
+ const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd,
+ uint32_t cow_op_merge_size);
bool RunThread();
private:
@@ -106,6 +107,7 @@
// syscalls and fallback to synchronous I/O, we
// don't want huge queue depth
int queue_depth_ = 8;
+ uint32_t cow_op_merge_size_;
std::unique_ptr<struct io_uring> ring_;
};
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index 0b881b6..c0af5c5 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -347,7 +347,8 @@
const std::string& cow_device_path,
const std::string& backing_device,
const std::string& base_path_merge,
- const bool o_direct) {
+ const bool o_direct,
+ uint32_t cow_op_merge_size) {
// We will need multiple worker threads only during
// device boot after OTA. For all other purposes,
// one thread is sufficient. We don't want to consume
@@ -369,7 +370,8 @@
auto opener = block_server_factory_->CreateOpener(misc_name);
return handlers_->AddHandler(misc_name, cow_device_path, backing_device, base_path_merge,
- opener, num_worker_threads, io_uring_enabled_, o_direct);
+ opener, num_worker_threads, io_uring_enabled_, o_direct,
+ cow_op_merge_size);
}
bool UserSnapshotServer::WaitForSocket() {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
index d9cf97f..ceea36a 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
@@ -87,7 +87,8 @@
const std::string& cow_device_path,
const std::string& backing_device,
const std::string& base_path_merge,
- bool o_direct = false);
+ bool o_direct = false,
+ uint32_t cow_op_merge_size = 0);
bool StartHandler(const std::string& misc_name);
void SetTerminating() { terminating_ = true; }
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index 56f7b59..9042f2b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -67,6 +67,7 @@
std::string compression;
int block_size;
int num_threads;
+ uint32_t cow_op_merge_size;
};
class SnapuserdTestBase : public ::testing::TestWithParam<TestParam> {
@@ -79,6 +80,8 @@
std::unique_ptr<ICowWriter> CreateCowDeviceInternal();
std::unique_ptr<ICowWriter> CreateV3Cow();
+ unique_fd GetCowFd() { return unique_fd{dup(cow_system_->fd)}; }
+
std::unique_ptr<ITestHarness> harness_;
size_t size_ = 10_MiB;
int total_base_size_ = 0;
@@ -101,7 +104,9 @@
#endif
}
-void SnapuserdTestBase::TearDown() {}
+void SnapuserdTestBase::TearDown() {
+ cow_system_ = nullptr;
+}
void SnapuserdTestBase::CreateBaseDevice() {
total_base_size_ = (size_ * 5);
@@ -132,10 +137,7 @@
CowOptions options;
options.compression = "gz";
- unique_fd fd(cow_system_->fd);
- cow_system_->fd = -1;
-
- return CreateCowWriter(2, options, std::move(fd));
+ return CreateCowWriter(2, options, GetCowFd());
}
std::unique_ptr<ICowWriter> SnapuserdTestBase::CreateV3Cow() {
@@ -151,10 +153,7 @@
std::string path = android::base::GetExecutableDirectory();
cow_system_ = std::make_unique<TemporaryFile>(path);
- unique_fd fd(cow_system_->fd);
- cow_system_->fd = -1;
-
- return CreateCowWriter(3, options, std::move(fd));
+ return CreateCowWriter(3, options, GetCowFd());
}
void SnapuserdTestBase::CreateCowDevice() {
@@ -710,9 +709,9 @@
auto opener = factory->CreateOpener(system_device_ctrl_name_);
handlers_->DisableVerification();
const TestParam params = GetParam();
- auto handler = handlers_->AddHandler(system_device_ctrl_name_, cow_system_->path,
- base_dev_->GetPath(), base_dev_->GetPath(), opener, 1,
- params.io_uring, params.o_direct);
+ auto handler = handlers_->AddHandler(
+ system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(), base_dev_->GetPath(),
+ opener, 1, params.io_uring, params.o_direct, params.cow_op_merge_size);
ASSERT_NE(handler, nullptr);
ASSERT_NE(handler->snapuserd(), nullptr);
#ifdef __ANDROID__
@@ -1229,9 +1228,9 @@
ASSERT_NE(opener_, nullptr);
const TestParam params = GetParam();
- handler_ = std::make_shared<SnapshotHandler>(system_device_ctrl_name_, cow_system_->path,
- base_dev_->GetPath(), base_dev_->GetPath(),
- opener_, 1, false, false, params.o_direct);
+ handler_ = std::make_shared<SnapshotHandler>(
+ system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(), base_dev_->GetPath(),
+ opener_, 1, false, false, params.o_direct, params.cow_op_merge_size);
ASSERT_TRUE(handler_->InitCowDevice());
ASSERT_TRUE(handler_->InitializeWorkers());
@@ -1509,6 +1508,7 @@
param.num_threads = thread;
param.io_uring = io_uring;
param.o_direct = false;
+ param.cow_op_merge_size = 0;
testParams.push_back(std::move(param));
}
}
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 26af13b..54b469b 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -306,8 +306,8 @@
if (!batt_anim_.run || now < next_screen_transition_) return;
- // If battery level is not ready, keep checking in the defined time
- if (health_info_.battery_level == 0 && health_info_.battery_status == BatteryStatus::UNKNOWN) {
+ // If battery status is not ready, keep checking in the defined time
+ if (health_info_.battery_status == BatteryStatus::UNKNOWN) {
if (wait_batt_level_timestamp_ == 0) {
// Set max delay time and skip drawing screen
wait_batt_level_timestamp_ = now + MAX_BATT_LEVEL_WAIT_TIME;
@@ -317,7 +317,7 @@
// Do nothing, keep waiting
return;
}
- // If timeout and battery level is still not ready, draw unknown battery
+ // If timeout and battery status is still not ready, draw unknown battery
}
if (healthd_draw_ == nullptr) return;
diff --git a/init/Android.bp b/init/Android.bp
index 7b7a856..ffb6380 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -330,7 +330,7 @@
static_libs: ["libinit.microdroid"],
cflags: ["-DMICRODROID=1"],
no_full_install: true,
- visibility: ["//packages/modules/Virtualization/microdroid"],
+ visibility: ["//packages/modules/Virtualization/build/microdroid"],
}
soong_config_module_type {
@@ -338,7 +338,7 @@
module_type: "cc_defaults",
config_namespace: "ANDROID",
bool_variables: ["BOARD_USES_RECOVERY_AS_BOOT"],
- properties: ["installable"],
+ properties: ["no_full_install"],
}
// Do not install init_first_stage even with mma if we're system-as-root.
@@ -347,7 +347,7 @@
name: "init_first_stage_defaults",
soong_config_variables: {
BOARD_USES_RECOVERY_AS_BOOT: {
- installable: false,
+ no_full_install: true,
},
},
diff --git a/init/README.md b/init/README.md
index 11c4e1c..0bb26e8 100644
--- a/init/README.md
+++ b/init/README.md
@@ -499,9 +499,11 @@
4. `late-fs` - Mount partitions marked as latemounted.
5. `post-fs-data` - Mount and configure `/data`; set up encryption. `/metadata` is
reformatted here if it couldn't mount in first-stage init.
- 6. `zygote-start` - Start the zygote.
- 7. `early-boot` - After zygote has started.
- 8. `boot` - After `early-boot` actions have completed.
+ 6. `post-fs-data-checkpointed` - Triggered when vold has completed committing a checkpoint
+ after an OTA update. Not triggered if checkpointing is not needed or supported.
+ 7. `zygote-start` - Start the zygote.
+ 8. `early-boot` - After zygote has started.
+ 9. `boot` - After `early-boot` actions have completed.
Commands
--------
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index a686d05..8f52158 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -139,6 +139,10 @@
return InitDevice("/sys/devices/platform", dev_name);
}
+bool BlockDevInitializer::InitHvcDevice(const std::string& dev_name) {
+ return InitDevice("/sys/devices/virtual/tty", dev_name);
+}
+
bool BlockDevInitializer::InitDevice(const std::string& syspath, const std::string& device_name) {
bool found = false;
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index d5b1f60..cb1d365 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -34,6 +34,7 @@
bool InitDevices(std::set<std::string> devices);
bool InitDmDevice(const std::string& device);
bool InitPlatformDevice(const std::string& device);
+ bool InitHvcDevice(const std::string& device);
private:
ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices);
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 39cae1b..3c3eeb6 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -155,23 +155,18 @@
"fs_config.cpp",
],
},
- not_windows: {
- srcs: libcutils_nonwindows_sources + [
- "ashmem-host.cpp",
- "trace-host.cpp",
- ],
- },
- windows: {
- host_ldlibs: ["-lws2_32"],
-
+ host: {
srcs: [
"trace-host.cpp",
+ "ashmem-host.cpp",
],
-
+ },
+ not_windows: {
+ srcs: libcutils_nonwindows_sources,
+ },
+ windows: {
enabled: true,
- cflags: [
- "-D_GNU_SOURCE",
- ],
+ host_ldlibs: ["-lws2_32"],
},
android: {
sanitize: {
@@ -240,6 +235,7 @@
cc_defaults {
name: "libcutils_test_default",
srcs: [
+ "ashmem_base_test.cpp",
"native_handle_test.cpp",
"properties_test.cpp",
"sockets_test.cpp",
@@ -298,20 +294,26 @@
cc_defaults {
name: "libcutils_test_static_defaults",
defaults: ["libcutils_test_default"],
- static_libs: [
- "libc",
- "libcgrouprc_format",
- ] + test_libraries + always_static_test_libraries,
stl: "libc++_static",
require_root: true,
target: {
android: {
static_executable: true,
+ static_libs: [
+ "libcgrouprc_format",
+ ] + test_libraries + always_static_test_libraries,
+ },
+ not_windows: {
+ static_libs: test_libraries + always_static_test_libraries,
},
windows: {
+ static_libs: [
+ "libbase",
+ "libcutils",
+ "libcutils_sockets",
+ ],
host_ldlibs: ["-lws2_32"],
-
enabled: true,
},
},
@@ -319,6 +321,7 @@
cc_test {
name: "libcutils_test_static",
+ host_supported: true,
test_suites: ["device-tests"],
defaults: ["libcutils_test_static_defaults"],
}
diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp
index 2ba1eb0..9003b76 100644
--- a/libcutils/ashmem-host.cpp
+++ b/libcutils/ashmem-host.cpp
@@ -17,10 +17,13 @@
#include <cutils/ashmem.h>
/*
- * Implementation of the user-space ashmem API for the simulator, which lacks
- * an ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version.
+ * Implementation of the user-space ashmem API for the simulator, which lacks an
+ * ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version. A
+ * disk-backed temp file is the best option that is consistently supported
+ * across all host platforms.
*/
+#include <android-base/unique_fd.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -31,8 +34,10 @@
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
-
#include <utils/Compat.h>
+#include <memory>
+
+using android::base::unique_fd;
static bool ashmem_validate_stat(int fd, struct stat* buf) {
int result = fstat(fd, buf);
@@ -40,15 +45,20 @@
return false;
}
- /*
- * Check if this is an "ashmem" region.
- * TODO: This is very hacky, and can easily break.
- * We need some reliable indicator.
- */
- if (!(buf->st_nlink == 0 && S_ISREG(buf->st_mode))) {
+ // Check if this is an ashmem region. Since there's no such thing on the host,
+ // we can't actually implement that. Check that it's at least a regular file.
+ if (!S_ISREG(buf->st_mode)) {
errno = ENOTTY;
return false;
}
+ // In Win32, unlike Unix, the temp file is not unlinked immediately after
+ // creation.
+#if !defined(_WIN32)
+ if (buf->st_nlink != 0) {
+ errno = ENOTTY;
+ return false;
+ }
+#endif
return true;
}
@@ -58,19 +68,24 @@
}
int ashmem_create_region(const char* /*ignored*/, size_t size) {
- char pattern[PATH_MAX];
- snprintf(pattern, sizeof(pattern), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid());
- int fd = mkstemp(pattern);
- if (fd == -1) return -1;
+ // Files returned by tmpfile are automatically removed.
+ std::unique_ptr<FILE, decltype(&fclose)> tmp(tmpfile(), &fclose);
- unlink(pattern);
-
- if (TEMP_FAILURE_RETRY(ftruncate(fd, size)) == -1) {
- close(fd);
- return -1;
+ if (!tmp) {
+ return -1;
}
-
- return fd;
+ int fd = fileno(tmp.get());
+ if (fd == -1) {
+ return -1;
+ }
+ unique_fd dupfd = unique_fd(dup(fd));
+ if (dupfd == -1) {
+ return -1;
+ }
+ if (TEMP_FAILURE_RETRY(ftruncate(dupfd, size)) == -1) {
+ return -1;
+ }
+ return dupfd.release();
}
int ashmem_set_prot_region(int /*fd*/, int /*prot*/) {
diff --git a/libcutils/ashmem_base_test.cpp b/libcutils/ashmem_base_test.cpp
new file mode 100644
index 0000000..c9b14e5
--- /dev/null
+++ b/libcutils/ashmem_base_test.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <unistd.h>
+
+#include <android-base/mapped_file.h>
+#include <android-base/unique_fd.h>
+#include <cutils/ashmem.h>
+
+/*
+ * Tests in AshmemBaseTest are designed to run on Android as well as host
+ * platforms (Linux, Mac, Windows).
+ */
+
+#if defined(_WIN32)
+static inline size_t getpagesize() {
+ return 4096;
+}
+#endif
+
+using android::base::unique_fd;
+
+TEST(AshmemBaseTest, BasicTest) {
+ const size_t size = getpagesize();
+ std::vector<uint8_t> data(size);
+ std::generate(data.begin(), data.end(), [n = 0]() mutable { return n++ & 0xFF; });
+
+ unique_fd fd = unique_fd(ashmem_create_region(nullptr, size));
+ ASSERT_TRUE(fd >= 0);
+ ASSERT_TRUE(ashmem_valid(fd));
+ ASSERT_EQ(size, static_cast<size_t>(ashmem_get_size_region(fd)));
+
+ std::unique_ptr<android::base::MappedFile> mapped =
+ android::base::MappedFile::FromFd(fd, 0, size, PROT_READ | PROT_WRITE);
+ EXPECT_TRUE(mapped.get() != nullptr);
+ void* region1 = mapped->data();
+ EXPECT_TRUE(region1 != nullptr);
+
+ memcpy(region1, data.data(), size);
+ ASSERT_EQ(0, memcmp(region1, data.data(), size));
+
+ std::unique_ptr<android::base::MappedFile> mapped2 =
+ android::base::MappedFile::FromFd(fd, 0, size, PROT_READ | PROT_WRITE);
+ EXPECT_TRUE(mapped2.get() != nullptr);
+ void* region2 = mapped2->data();
+ EXPECT_TRUE(region2 != nullptr);
+ ASSERT_EQ(0, memcmp(region2, data.data(), size));
+}
diff --git a/libcutils/ashmem_test.cpp b/libcutils/ashmem_test.cpp
index 571b410..ccbb8c9 100644
--- a/libcutils/ashmem_test.cpp
+++ b/libcutils/ashmem_test.cpp
@@ -69,28 +69,6 @@
}
}
-TEST(AshmemTest, BasicTest) {
- const size_t size = getpagesize();
- std::vector<uint8_t> data(size);
- FillData(data);
-
- unique_fd fd;
- ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE));
-
- void* region1 = nullptr;
- ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, ®ion1));
-
- memcpy(region1, data.data(), size);
- ASSERT_EQ(0, memcmp(region1, data.data(), size));
-
- EXPECT_EQ(0, munmap(region1, size));
-
- void *region2;
- ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, ®ion2));
- ASSERT_EQ(0, memcmp(region2, data.data(), size));
- EXPECT_EQ(0, munmap(region2, size));
-}
-
TEST(AshmemTest, ForkTest) {
const size_t size = getpagesize();
std::vector<uint8_t> data(size);
diff --git a/libcutils/sockets_test.cpp b/libcutils/sockets_test.cpp
index 1fa40bc..f6f9c36 100644
--- a/libcutils/sockets_test.cpp
+++ b/libcutils/sockets_test.cpp
@@ -19,8 +19,6 @@
// should be the case for loopback communication, but is not guaranteed.
#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
#include <time.h>
#include <cutils/sockets.h>
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index 94945ec..3bc6dc3 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -49,17 +49,17 @@
constexpr uint32_t kSeqNoNotInit = static_cast<uint32_t>(-1);
-atomic_bool atrace_is_ready = ATOMIC_VAR_INIT(false);
+atomic_bool atrace_is_ready = false;
int atrace_marker_fd = -1;
uint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY;
-static atomic_bool atrace_is_enabled = ATOMIC_VAR_INIT(true);
+static atomic_bool atrace_is_enabled = true;
static pthread_mutex_t atrace_tags_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Sequence number of debug.atrace.tags.enableflags the last time the enabled
* tags were reloaded.
**/
-static _Atomic(uint32_t) last_sequence_number = ATOMIC_VAR_INIT(kSeqNoNotInit);
+static _Atomic(uint32_t) last_sequence_number = kSeqNoNotInit;
#if defined(__BIONIC__)
// All zero prop_info that has a sequence number of 0. This is easier than
diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp
index 2bf57eb..c45d067 100644
--- a/libcutils/trace-host.cpp
+++ b/libcutils/trace-host.cpp
@@ -16,7 +16,7 @@
#include <cutils/trace.h>
-atomic_bool atrace_is_ready = ATOMIC_VAR_INIT(true);
+atomic_bool atrace_is_ready = true;
int atrace_marker_fd = -1;
uint64_t atrace_enabled_tags = 0;
diff --git a/mini_keyctl/OWNERS b/mini_keyctl/OWNERS
index f9e7b25..1f2485a 100644
--- a/mini_keyctl/OWNERS
+++ b/mini_keyctl/OWNERS
@@ -1,4 +1,3 @@
-alanstokes@google.com
ebiggers@google.com
jeffv@google.com
jiyong@google.com
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index e8f7627..7105ed5 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -114,10 +114,23 @@
sub_dir: "init",
}
+prebuilt_etc {
+ name: "asan.options",
+ src: "asan.options",
+}
+
+sh_binary {
+ name: "asan_extract",
+ src: "asan_extract.sh",
+ init_rc: ["asan_extract.rc"],
+ // We need bzip2 on device for extraction.
+ required: ["bzip2"],
+}
+
llndk_libraries_txt {
name: "llndk.libraries.txt",
}
sanitizer_libraries_txt {
name: "sanitizer.libraries.txt",
-}
\ No newline at end of file
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 4c1f2e4..e6ccda7 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -3,39 +3,12 @@
$(eval $(call declare-1p-copy-files,system/core/rootdir,))
#######################################
-# asan.options
ifneq ($(filter address,$(SANITIZE_TARGET)),)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := asan.options
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_PATH := $(TARGET_OUT)
-
-include $(BUILD_PREBUILT)
-
-# ASAN extration.
ASAN_EXTRACT_FILES :=
ifeq ($(SANITIZE_TARGET_SYSTEM),true)
-include $(CLEAR_VARS)
-LOCAL_MODULE:= asan_extract
-LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS:= notice
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES := asan_extract.sh
-LOCAL_INIT_RC := asan_extract.rc
-# We need bzip2 on device for extraction.
-LOCAL_REQUIRED_MODULES := bzip2
-include $(BUILD_PREBUILT)
ASAN_EXTRACT_FILES := asan_extract
endif
-
endif
-
#######################################
# init.environ.rc
diff --git a/rootdir/avb/Android.bp b/rootdir/avb/Android.bp
new file mode 100644
index 0000000..a584e3e
--- /dev/null
+++ b/rootdir/avb/Android.bp
@@ -0,0 +1,71 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+soong_config_module_type {
+ name: "avb_keys_prebuilt_avb",
+ module_type: "prebuilt_avb",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT",
+ ],
+ properties: [
+ "ramdisk",
+ "vendor_ramdisk",
+ ],
+}
+
+avb_keys_prebuilt_avb {
+ name: "q-developer-gsi.avbpubkey",
+ src: "q-developer-gsi.avbpubkey",
+ soong_config_variables: {
+ BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT: {
+ ramdisk: false,
+ vendor_ramdisk: true,
+ conditions_default: {
+ ramdisk: true,
+ vendor_ramdisk: false,
+ },
+ },
+ },
+}
+
+avb_keys_prebuilt_avb {
+ name: "r-developer-gsi.avbpubkey",
+ src: "r-developer-gsi.avbpubkey",
+ soong_config_variables: {
+ BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT: {
+ ramdisk: false,
+ vendor_ramdisk: true,
+ conditions_default: {
+ ramdisk: true,
+ vendor_ramdisk: false,
+ },
+ },
+ },
+}
+
+avb_keys_prebuilt_avb {
+ name: "s-developer-gsi.avbpubkey",
+ src: "s-developer-gsi.avbpubkey",
+ soong_config_variables: {
+ BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT: {
+ ramdisk: false,
+ vendor_ramdisk: true,
+ conditions_default: {
+ ramdisk: true,
+ vendor_ramdisk: false,
+ },
+ },
+ },
+}
diff --git a/rootdir/avb/Android.mk b/rootdir/avb/Android.mk
deleted file mode 100644
index 8cf3172..0000000
--- a/rootdir/avb/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-ifeq ($(BOARD_MOVE_GSI_AVB_KEYS_TO_VENDOR_BOOT),true) # AVB keys are installed to vendor ramdisk
- ifeq ($(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT),true) # no dedicated recovery partition
- my_gsi_avb_keys_path := $(TARGET_VENDOR_RAMDISK_OUT)/first_stage_ramdisk/avb
- else # device has a dedicated recovery partition
- my_gsi_avb_keys_path := $(TARGET_VENDOR_RAMDISK_OUT)/avb
- endif
-else
- ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true) # no dedicated recovery partition
- my_gsi_avb_keys_path := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
- else # device has a dedicated recovery partition
- my_gsi_avb_keys_path := $(TARGET_RAMDISK_OUT)/avb
- endif
-endif
-
-#######################################
-# q-developer-gsi.avbpubkey
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := q-developer-gsi.avbpubkey
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_PATH := $(my_gsi_avb_keys_path)
-
-include $(BUILD_PREBUILT)
-
-#######################################
-# r-developer-gsi.avbpubkey
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := r-developer-gsi.avbpubkey
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_PATH := $(my_gsi_avb_keys_path)
-
-include $(BUILD_PREBUILT)
-
-#######################################
-# s-developer-gsi.avbpubkey
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := s-developer-gsi.avbpubkey
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_PATH := $(my_gsi_avb_keys_path)
-
-include $(BUILD_PREBUILT)
-
-my_gsi_avb_keys_path :=
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 2443b7c..b804c1b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1087,6 +1087,9 @@
# Update dm-verity state and set partition.*.verified properties.
verity_update_state
+on property:vold.checkpoint_committed=1
+ trigger post-fs-data-checkpointed
+
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index 6d0c616..ca39f6a 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -55,7 +55,7 @@
static struct storage_mapping_node* storage_mapping_head;
/*
- * Property set to 1 after we have opened a file under ssdir_name. The backing
+ * Properties set to 1 after we have opened a file under ssdir_name. The backing
* files for both TD and TDP are currently located under /data/vendor/ss and can
* only be opened once userdata is mounted. This storageproxyd service is
* restarted when userdata is available, which causes the Trusty storage service
@@ -64,11 +64,16 @@
* ports will be available (although they may block if still being initialized),
* and connections will not be reset after this point (assuming the
* storageproxyd service stays running).
+ *
+ * fs_ready - secure storage is read-only (due to checkpointing after upgrade)
+ * fs_ready_rw - secure storage is readable and writable
*/
#define FS_READY_PROPERTY "ro.vendor.trusty.storage.fs_ready"
+#define FS_READY_RW_PROPERTY "ro.vendor.trusty.storage.fs_ready_rw"
/* has FS_READY_PROPERTY been set? */
-static bool fs_ready_initialized = false;
+static bool fs_ready_set = false;
+static bool fs_ready_rw_set = false;
static enum sync_state fs_state;
static enum sync_state fd_state[FD_TBL_SIZE];
@@ -80,6 +85,17 @@
uint8_t data[MAX_READ_SIZE];
} read_rsp;
+static bool property_set_helper(const char* prop) {
+ int rc = property_set(prop, "1");
+ if (rc == 0) {
+ ALOGI("Set property %s\n", prop);
+ } else {
+ ALOGE("Could not set property %s, rc: %d\n", prop, rc);
+ }
+
+ return rc == 0;
+}
+
static uint32_t insert_fd(int open_flags, int fd, struct storage_mapping_node* node) {
uint32_t handle = fd;
@@ -520,12 +536,20 @@
path = NULL;
/* a backing file has been opened, notify any waiting init steps */
- if (!fs_ready_initialized) {
- rc = property_set(FS_READY_PROPERTY, "1");
- if (rc == 0) {
- fs_ready_initialized = true;
+ if (!fs_ready_set || !fs_ready_rw_set) {
+ bool is_checkpoint_active = false;
+
+ rc = is_data_checkpoint_active(&is_checkpoint_active);
+ if (rc != 0) {
+ ALOGE("is_data_checkpoint_active() failed (%d)\n", rc);
} else {
- ALOGE("Could not set property %s, rc: %d\n", FS_READY_PROPERTY, rc);
+ if (!fs_ready_rw_set && !is_checkpoint_active) {
+ fs_ready_rw_set = property_set_helper(FS_READY_RW_PROPERTY);
+ }
+
+ if (!fs_ready_set) {
+ fs_ready_set = property_set_helper(FS_READY_PROPERTY);
+ }
}
}