Snap for 13210474 from 292962bf29c33406dad4358c2c9e93035a5351c0 to 25Q2-release

Change-Id: I349a23b4086e3b0805006731f90866b5f2c4d203
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index d1c3bf2..b10be76 100644
--- a/aosp/dynamic_partition_control_android.cc
+++ b/aosp/dynamic_partition_control_android.cc
@@ -226,7 +226,7 @@
     // One exception is when /metadata is not mounted. Fallback to
     // CreateLogicalPartition as snapshots are not created in the first place.
     params.timeout_ms = kMapSnapshotTimeout;
-    success = snapshot_->MapUpdateSnapshot(params, path);
+    success = GetSnapshotManager()->MapUpdateSnapshot(params, path);
   } else {
     params.timeout_ms = kMapTimeout;
     success = CreateLogicalPartition(params, path);
@@ -311,7 +311,7 @@
     // a paused update. Clean up any underlying devices.
     if (ExpectMetadataMounted() &&
         !device_name.ends_with(kRWSourcePartitionSuffix)) {
-      success &= snapshot_->UnmapUpdateSnapshot(device_name);
+      success &= GetSnapshotManager()->UnmapUpdateSnapshot(device_name);
     } else {
       LOG(INFO) << "Skip UnmapUpdateSnapshot(" << device_name << ")";
     }
@@ -328,7 +328,7 @@
 }
 
 bool DynamicPartitionControlAndroid::UnmapAllPartitions() {
-  snapshot_->UnmapAllSnapshots();
+  GetSnapshotManager()->UnmapAllSnapshots();
   if (mapped_devices_.empty()) {
     return false;
   }
@@ -358,12 +358,9 @@
   LOG(INFO) << "UnmapAllPartitions done";
   metadata_device_.reset();
   if (GetVirtualAbFeatureFlag().IsEnabled()) {
-    snapshot_ = SnapshotManager::New();
-  } else {
-    snapshot_ = SnapshotManagerStub::New();
+    // Release ISnapshotManager instance so GSID can be gracefully shutdown
+    snapshot_ = nullptr;
   }
-  CHECK(snapshot_ != nullptr) << "Cannot initialize SnapshotManager.";
-  LOG(INFO) << "SnapshotManager initialized.";
 }
 
 bool DynamicPartitionControlAndroid::DeviceExists(const std::string& path) {
@@ -585,7 +582,7 @@
     // should not proceed because during next boot, snapshots will overlay on
     // the devices incorrectly.
     if (ExpectMetadataMounted()) {
-      TEST_AND_RETURN_FALSE(snapshot_->CancelUpdate());
+      TEST_AND_RETURN_FALSE(GetSnapshotManager()->CancelUpdate());
     } else {
       LOG(INFO) << "Skip canceling previous update because metadata is not "
                 << "mounted";
@@ -996,6 +993,20 @@
   return true;
 }
 
+android::snapshot::ISnapshotManager*
+DynamicPartitionControlAndroid::GetSnapshotManager() {
+  if (snapshot_ == nullptr) {
+    if (GetVirtualAbFeatureFlag().IsEnabled()) {
+      snapshot_ = SnapshotManager::New();
+    } else {
+      snapshot_ = SnapshotManagerStub::New();
+    }
+  }
+  CHECK(snapshot_ != nullptr) << "Cannot initialize SnapshotManager.";
+  LOG(INFO) << "SnapshotManager initialized.";
+  return snapshot_.get();
+}
+
 bool DynamicPartitionControlAndroid::PrepareSnapshotPartitionsForUpdate(
     uint32_t source_slot,
     uint32_t target_slot,
@@ -1018,11 +1029,11 @@
   TEST_AND_RETURN_FALSE(
       CheckSuperPartitionAllocatableSpace(builder.get(), manifest, true));
 
-  if (!snapshot_->BeginUpdate()) {
+  if (!GetSnapshotManager()->BeginUpdate()) {
     LOG(ERROR) << "Cannot begin new update.";
     return false;
   }
-  auto ret = snapshot_->CreateUpdateSnapshots(manifest);
+  auto ret = GetSnapshotManager()->CreateUpdateSnapshots(manifest);
   if (!ret) {
     LOG(ERROR) << "Cannot create update snapshots: " << ret.string();
     if (required_size != nullptr &&
@@ -1124,9 +1135,9 @@
 
 bool DynamicPartitionControlAndroid::FinishUpdate(bool powerwash_required) {
   if (ExpectMetadataMounted()) {
-    if (snapshot_->GetUpdateState() == UpdateState::Initiated) {
+    if (GetSnapshotManager()->GetUpdateState() == UpdateState::Initiated) {
       LOG(INFO) << "Snapshot writes are done.";
-      return snapshot_->FinishedSnapshotWrites(powerwash_required);
+      return GetSnapshotManager()->FinishedSnapshotWrites(powerwash_required);
     }
   } else {
     LOG(INFO) << "Skip FinishedSnapshotWrites() because /metadata is not "
@@ -1350,7 +1361,7 @@
     return std::make_unique<NoOpAction>();
   }
   return std::make_unique<CleanupPreviousUpdateAction>(
-      prefs, boot_control, snapshot_.get(), delegate);
+      prefs, boot_control, GetSnapshotManager(), delegate);
 }
 
 bool DynamicPartitionControlAndroid::ResetUpdate(PrefsInterface* prefs) {
@@ -1372,7 +1383,7 @@
       prefs, false /* quick */, false /* skip dynamic partitions metadata */));
 
   if (ExpectMetadataMounted()) {
-    TEST_AND_RETURN_FALSE(snapshot_->CancelUpdate());
+    TEST_AND_RETURN_FALSE(GetSnapshotManager()->CancelUpdate());
   } else {
     LOG(INFO) << "Skip cancelling update in ResetUpdate because /metadata is "
               << "not mounted";
@@ -1473,7 +1484,7 @@
   }
 
   if (metadata_device_ == nullptr) {
-    metadata_device_ = snapshot_->EnsureMetadataMounted();
+    metadata_device_ = GetSnapshotManager()->EnsureMetadataMounted();
   }
   return metadata_device_ != nullptr;
 }
@@ -1497,7 +1508,7 @@
       .timeout_ms = kMapSnapshotTimeout};
   // TODO(zhangkelvin) Open an APPEND mode CowWriter once there's an API to do
   // it.
-  return snapshot_->OpenSnapshotWriter(params, label);
+  return GetSnapshotManager()->OpenSnapshotWriter(params, label);
 }  // namespace chromeos_update_engine
 
 std::unique_ptr<FileDescriptor> DynamicPartitionControlAndroid::OpenCowFd(
@@ -1531,7 +1542,13 @@
 }
 
 bool DynamicPartitionControlAndroid::MapAllPartitions() {
-  return snapshot_->MapAllSnapshots(kMapSnapshotTimeout);
+  // This flag tells us if VAB is enabled. In the case it's not (e.g. for
+  // secondary payloads) we are falling back on A/B and MapAllPartitions should
+  // just be a no-op
+  if (!target_supports_snapshot_) {
+    return true;
+  }
+  return GetSnapshotManager()->MapAllSnapshots(kMapSnapshotTimeout);
 }
 
 bool DynamicPartitionControlAndroid::IsDynamicPartition(
@@ -1555,7 +1572,7 @@
 
 bool DynamicPartitionControlAndroid::UpdateUsesSnapshotCompression() {
   return GetVirtualAbFeatureFlag().IsEnabled() &&
-         snapshot_->UpdateUsesCompression();
+         GetSnapshotManager()->UpdateUsesCompression();
 }
 
 FeatureFlag
diff --git a/aosp/dynamic_partition_control_android.h b/aosp/dynamic_partition_control_android.h
index 1f70184..e5ba86a 100644
--- a/aosp/dynamic_partition_control_android.h
+++ b/aosp/dynamic_partition_control_android.h
@@ -339,6 +339,7 @@
   bool SetTargetBuildVars(const DeltaArchiveManifest& manifest);
 
   std::string GetDeviceName(std::string partition_name, uint32_t slot) const;
+  android::snapshot::ISnapshotManager* GetSnapshotManager();
 
   std::set<std::string> mapped_devices_;
   const FeatureFlag dynamic_partitions_;
diff --git a/aosp/update_attempter_android.cc b/aosp/update_attempter_android.cc
index b46f584..461cece 100644
--- a/aosp/update_attempter_android.cc
+++ b/aosp/update_attempter_android.cc
@@ -875,6 +875,8 @@
     return;
   }
 
+  boot_control_->GetDynamicPartitionControl()->Cleanup();
+
   if (status_ == UpdateStatus::CLEANUP_PREVIOUS_UPDATE) {
     ClearUpdateCompletedMarker();
     LOG(INFO) << "Terminating cleanup previous update.";
@@ -884,8 +886,6 @@
     return;
   }
 
-  boot_control_->GetDynamicPartitionControl()->Cleanup();
-
   for (auto observer : daemon_state_->service_observers())
     observer->SendPayloadApplicationComplete(error_code);
 
diff --git a/liburing_cpp/Android.bp b/liburing_cpp/Android.bp
index e17f080..8566bc2 100644
--- a/liburing_cpp/Android.bp
+++ b/liburing_cpp/Android.bp
@@ -1,4 +1,3 @@
-
 package {
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
@@ -9,31 +8,32 @@
 }
 
 cc_library {
-	name: "liburing_cpp",
-	host_supported: true,
-	recovery_available: true,
-	srcs: [
-		"src/IoUring.cpp",
-		"src/IoUringSQE.cpp",
-	],
-	static_libs: [
-		"liburing",
-	],
-	export_include_dirs: [
-		"include",
-	],
+    name: "liburing_cpp",
+    host_supported: true,
+    recovery_available: true,
+    ramdisk_available: true,
+    vendor_ramdisk_available: true,
+    srcs: [
+        "src/IoUring.cpp",
+        "src/IoUringSQE.cpp",
+    ],
+    static_libs: [
+        "liburing",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
 }
 
-
 cc_test_host {
-	name: "liburing_cpp_tests",
-	srcs: [
-		"tests/BasicTests.cpp",
-		"tests/main.cpp",
-	],
-	static_libs: [
-		"libgtest",
-		"liburing",
-		"liburing_cpp",
-	],
+    name: "liburing_cpp_tests",
+    srcs: [
+        "tests/BasicTests.cpp",
+        "tests/main.cpp",
+    ],
+    static_libs: [
+        "libgtest",
+        "liburing",
+        "liburing_cpp",
+    ],
 }
diff --git a/liburing_cpp/include/liburing_cpp/IoUring.h b/liburing_cpp/include/liburing_cpp/IoUring.h
index 09ed5cc..b382630 100644
--- a/liburing_cpp/include/liburing_cpp/IoUring.h
+++ b/liburing_cpp/include/liburing_cpp/IoUring.h
@@ -53,6 +53,12 @@
   // Register a set of file descriptors to kernel.
   virtual Errno RegisterFiles(const int* files, size_t files_size) = 0;
   virtual Errno UnregisterFiles() = 0;
+
+  // Prepare read to a registered buffer. This does not submit the operation
+  // to the kernel. For that, call |IoUringInterface::Submit()|
+  virtual IoUringSQE PrepReadFixed(
+      int fd, void* buf, unsigned nbytes, uint64_t offset, int buf_index) = 0;
+
   // Append a submission entry into this io_uring. This does not submit the
   // operation to the kernel. For that, call |IoUringInterface::Submit()|
   virtual IoUringSQE PrepRead(int fd, void *buf, unsigned nbytes,
diff --git a/liburing_cpp/src/IoUring.cpp b/liburing_cpp/src/IoUring.cpp
index cf10272..8589220 100644
--- a/liburing_cpp/src/IoUring.cpp
+++ b/liburing_cpp/src/IoUring.cpp
@@ -82,6 +82,19 @@
     return ret;
   }
 
+  IoUringSQE PrepReadFixed(int fd,
+                           void* buf,
+                           unsigned nbytes,
+                           uint64_t offset,
+                           int buf_index) override {
+    auto sqe = io_uring_get_sqe(&ring);
+    if (sqe == nullptr) {
+      return IoUringSQE{nullptr};
+    }
+    io_uring_prep_read_fixed(sqe, fd, buf, nbytes, offset, buf_index);
+    return IoUringSQE{static_cast<void*>(sqe)};
+  }
+
   IoUringSQE PrepRead(int fd, void* buf, unsigned nbytes,
                       uint64_t offset) override {
     auto sqe = io_uring_get_sqe(&ring);
diff --git a/liburing_cpp/tests/BasicTests.cpp b/liburing_cpp/tests/BasicTests.cpp
index 81288f6..680fb64 100644
--- a/liburing_cpp/tests/BasicTests.cpp
+++ b/liburing_cpp/tests/BasicTests.cpp
@@ -191,4 +191,51 @@
   for (int i = 0; i < data.size(); ++i) {
     ASSERT_EQ(data[i], i % 256);
   }
-}
\ No newline at end of file
+}
+
+TEST_F(IoUringTest, ExtentReadFixedBuffers) {
+  const int fd = fileno(fp);
+  ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 3, kBlockSize));
+  ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 5, kBlockSize));
+  ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 8, kBlockSize));
+  ASSERT_NO_FATAL_FAILURE(WriteTestData(fd, kBlockSize * 13, kBlockSize));
+  fsync(fd);
+
+  std::vector<unsigned char> data;
+  data.resize(kBlockSize * 4);
+  std::unique_ptr<struct iovec[]> vecs = std::make_unique<struct iovec[]>(4);
+  for (int i = 0; i < 4; i++) {
+    vecs[i].iov_base = data.data() + i * kBlockSize;
+    vecs[i].iov_len = kBlockSize;
+  }
+
+  ASSERT_TRUE(ring->RegisterBuffers(vecs.get(), 4).IsOk());
+
+  ASSERT_TRUE(
+      ring->PrepReadFixed(fd, data.data(), kBlockSize, 3 * kBlockSize, 0)
+          .IsOk());
+  ASSERT_TRUE(
+      ring->PrepReadFixed(
+              fd, data.data() + kBlockSize, kBlockSize, 5 * kBlockSize, 1)
+          .IsOk());
+  ASSERT_TRUE(
+      ring->PrepReadFixed(
+              fd, data.data() + kBlockSize * 2, kBlockSize, 8 * kBlockSize, 2)
+          .IsOk());
+  ASSERT_TRUE(
+      ring->PrepReadFixed(
+              fd, data.data() + kBlockSize * 3, kBlockSize, 13 * kBlockSize, 3)
+          .IsOk());
+  ring->SubmitAndWait(4);
+  const auto cqes = ring->PopCQE(4);
+  if (cqes.IsErr()) {
+    FAIL() << cqes.GetError().ErrMsg();
+    return;
+  }
+  for (const auto& cqe : cqes.GetResult()) {
+    ASSERT_GT(cqe.res, 0);
+  }
+  for (int i = 0; i < data.size(); ++i) {
+    ASSERT_EQ(data[i], i % 256);
+  }
+}