Merge "Update to support new shared_ptr returns." into main
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index ac58ba0..a8a7716 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -420,6 +420,7 @@
     },
     data: [
         "tools/testdata/cow_v2",
+        "tools/testdata/incompressible_block",
     ],
     auto_gen_config: true,
     require_root: false,
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 91e0425..75467cb 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -94,11 +94,23 @@
 
 } __attribute__((packed));
 
+// Resume point structure used for resume buffer
+struct ResumePoint {
+    // monotonically increasing value used by update_engine
+    uint64_t label;
+    // Index of last CowOperation guaranteed to be resumable
+    uint32_t op_index;
+} __attribute__((packed));
+
+static constexpr uint8_t kNumResumePoints = 4;
+
 struct CowHeaderV3 : public CowHeader {
     // Location of sequence buffer in COW.
     uint64_t sequence_buffer_offset;
+    // number of currently written resume points
+    uint32_t resume_point_count;
     // Size, in bytes, of the CowResumePoint buffer.
-    uint32_t resume_buffer_size;
+    uint32_t resume_point_max;
     // Number of CowOperationV3 structs in the operation buffer, currently and total
     // region size.
     uint32_t op_count;
@@ -220,6 +232,19 @@
     return op.source_info & kCowOpSourceInfoDataMask;
 }
 
+static constexpr off_t GetOpOffset(uint32_t op_index, const CowHeaderV3 header) {
+    return header.prefix.header_size + header.buffer_size +
+           (header.resume_point_max * sizeof(ResumePoint)) + (op_index * sizeof(CowOperationV3));
+}
+static constexpr off_t GetDataOffset(const CowHeaderV3 header) {
+    return header.prefix.header_size + header.buffer_size +
+           (header.resume_point_max * sizeof(ResumePoint)) +
+           header.op_count_max * sizeof(CowOperation);
+}
+static constexpr off_t GetResumeOffset(const CowHeaderV3 header) {
+    return header.prefix.header_size + header.buffer_size;
+}
+
 struct CowFooter {
     CowFooterOperation op;
     uint8_t unused[64];
@@ -245,6 +270,8 @@
 
 std::ostream& operator<<(std::ostream& os, CowOperation const& arg);
 
+std::ostream& operator<<(std::ostream& os, ResumePoint const& arg);
+
 int64_t GetNextOpOffset(const CowOperationV2& op, uint32_t cluster_size);
 int64_t GetNextDataOffset(const CowOperationV2& op, uint32_t cluster_size);
 
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 1ab6ada..c87b32d 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -16,6 +16,7 @@
 
 #include <stdint.h>
 
+#include <deque>
 #include <functional>
 #include <memory>
 #include <optional>
@@ -192,6 +193,5 @@
 // The extra fields will just be filled as 0. V3 header is strictly a superset of v1/v2 header and
 // contains all of the latter's field
 bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header);
-
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
index b905291..937065d 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_format.cpp
@@ -100,6 +100,11 @@
     return os;
 }
 
+std::ostream& operator<<(std::ostream& os, ResumePoint const& resume_point) {
+    os << "ResumePoint(" << resume_point.label << " , " << resume_point.op_index << ")";
+    return os;
+}
+
 int64_t GetNextOpOffset(const CowOperationV2& op, uint32_t cluster_ops) {
     if (op.type == kCowClusterOp) {
         return op.source;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
index a8a63d8..52c6348 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
@@ -15,8 +15,10 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/strings.h>
 
 #include <libsnapshot/cow_format.h>
+#include <libsnapshot/cow_reader.h>
 
 namespace android {
 namespace snapshot {
@@ -36,6 +38,7 @@
         LOG(ERROR) << "Footer size isn't 0, read " << header_.footer_size;
         return false;
     }
+
     if (header_.op_size != sizeof(CowOperationV3)) {
         LOG(ERROR) << "Operation size unknown, read " << header_.op_size << ", expected "
                    << sizeof(CowOperationV3);
@@ -55,18 +58,48 @@
         return false;
     }
 
-    return ParseOps(fd, label);
+    std::optional<uint32_t> op_index = header_.op_count;
+    if (label) {
+        if (!ReadResumeBuffer(fd)) {
+            PLOG(ERROR) << "Failed to read resume buffer";
+            return false;
+        }
+        op_index = FindResumeOp(label.value());
+        if (op_index == std::nullopt) {
+            LOG(ERROR) << "failed to get op index from given label: " << label.value();
+            return false;
+        }
+    }
+
+    return ParseOps(fd, op_index.value());
 }
 
-off_t CowParserV3::GetDataOffset() const {
-    return sizeof(CowHeaderV3) + header_.buffer_size + header_.op_count_max * sizeof(CowOperation);
+bool CowParserV3::ReadResumeBuffer(borrowed_fd fd) {
+    resume_points_ = std::make_shared<std::vector<ResumePoint>>(header_.resume_point_count);
+
+    return android::base::ReadFullyAtOffset(fd, resume_points_->data(),
+                                            header_.resume_point_count * sizeof(ResumePoint),
+                                            header_.prefix.header_size + header_.buffer_size);
 }
 
-bool CowParserV3::ParseOps(borrowed_fd fd, std::optional<uint64_t> label) {
+std::optional<uint32_t> CowParserV3::FindResumeOp(const uint64_t label) {
+    for (auto& resume_point : *resume_points_) {
+        if (resume_point.label == label) {
+            return resume_point.op_index;
+        }
+    }
+    LOG(ERROR) << "failed to find label: " << label << "from following labels";
+    LOG(ERROR) << android::base::Join(*resume_points_, " ");
+
+    return std::nullopt;
+}
+
+bool CowParserV3::ParseOps(borrowed_fd fd, const uint32_t op_index) {
     ops_ = std::make_shared<std::vector<CowOperationV3>>();
-    ops_->resize(header_.op_count);
+    ops_->resize(op_index);
 
-    const off_t offset = header_.prefix.header_size + header_.buffer_size;
+    // read beginning of operation buffer -> so op_index = 0
+    const off_t offset = GetOpOffset(0, header_);
     if (!android::base::ReadFullyAtOffset(fd, ops_->data(), ops_->size() * sizeof(CowOperationV3),
                                           offset)) {
         PLOG(ERROR) << "read ops failed";
@@ -74,7 +107,7 @@
     }
 
     // fill out mapping of XOR op data location
-    uint64_t data_pos = GetDataOffset();
+    uint64_t data_pos = GetDataOffset(header_);
 
     xor_data_loc_ = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
 
@@ -87,7 +120,6 @@
     // :TODO: sequence buffer & resume buffer follow
     // Once we implement labels, we'll have to discard unused ops and adjust
     // the header as needed.
-    CHECK(!label);
 
     ops_->shrink_to_fit();
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
index e2663cc..afc01af 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
@@ -45,12 +45,15 @@
     bool Parse(android::base::borrowed_fd fd, const CowHeaderV3& header,
                std::optional<uint64_t> label = {}) override;
     bool Translate(TranslatedCowOps* out) override;
+    std::shared_ptr<std::vector<ResumePoint>> resume_points() const { return resume_points_; }
 
   private:
-    bool ParseOps(android::base::borrowed_fd fd, std::optional<uint64_t> label);
-    off_t GetDataOffset() const;
+    bool ParseOps(android::base::borrowed_fd fd, const uint32_t op_index);
+    std::optional<uint32_t> FindResumeOp(const uint64_t label);
     CowHeaderV3 header_ = {};
     std::shared_ptr<std::vector<CowOperationV3>> ops_;
+    bool ReadResumeBuffer(android::base::borrowed_fd fd);
+    std::shared_ptr<std::vector<ResumePoint>> resume_points_;
 };
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
index 35d74ba..2709059 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
@@ -1522,6 +1522,37 @@
     ASSERT_TRUE(reader.GetFooter(&footer));
 }
 
+TEST_F(CowTest, DecompressIncompressibleBlock) {
+    auto fd = OpenTestFile("incompressible_block", O_RDONLY);
+    ASSERT_GE(fd, 0);
+
+    std::string original;
+    ASSERT_TRUE(android::base::ReadFdToString(fd, &original)) << strerror(errno);
+    ASSERT_EQ(original.size(), 4096);
+
+    CowOptions options;
+    options.compression = "gz";
+    auto writer = CreateCowWriter(2, options, GetCowFd());
+    ASSERT_NE(writer, nullptr);
+    ASSERT_TRUE(writer->AddRawBlocks(0, original.data(), original.size()));
+    ASSERT_TRUE(writer->Finalize());
+
+    CowReader reader;
+    ASSERT_TRUE(reader.Parse(cow_->fd));
+
+    auto iter = reader.GetOpIter();
+    ASSERT_NE(iter, nullptr);
+    ASSERT_FALSE(iter->AtEnd());
+
+    std::string block(original.size(), '\0');
+    ASSERT_EQ(iter->Get()->data_length, 4096);
+    ASSERT_TRUE(ReadData(reader, iter->Get(), block.data(), block.size()));
+
+    for (size_t i = 0; i < block.size(); i++) {
+        ASSERT_EQ(block[i], original[i]) << "mismatch at byte " << i;
+    }
+}
+
 }  // namespace snapshot
 }  // namespace android
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
index d0af0f9..c41e07c 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
@@ -457,5 +457,30 @@
     iter->Next();
     ASSERT_TRUE(iter->AtEnd());
 }
+
+TEST_F(CowTestV3, ResumePointTest) {
+    CowOptions options;
+    options.op_count_max = 100;
+    auto writer = CreateCowWriter(3, options, GetCowFd());
+
+    ASSERT_TRUE(writer->AddZeroBlocks(0, 15));
+    ASSERT_TRUE(writer->AddLabel(0));
+    ASSERT_TRUE(writer->AddZeroBlocks(15, 15));
+    ASSERT_TRUE(writer->Finalize());
+
+    CowReader reader;
+    ASSERT_TRUE(reader.Parse(cow_->fd));
+
+    auto header = reader.header_v3();
+    ASSERT_EQ(header.op_count, 30);
+
+    CowWriterV3 second_writer(options, GetCowFd());
+    ASSERT_TRUE(second_writer.Initialize(0));
+    ASSERT_TRUE(second_writer.Finalize());
+
+    ASSERT_TRUE(reader.Parse(cow_->fd));
+    header = reader.header_v3();
+    ASSERT_EQ(header.op_count, 15);
+}
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 86dd9f7..6883c5e 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -34,6 +34,7 @@
 #include <zlib.h>
 
 #include <fcntl.h>
+#include <libsnapshot_cow/parser_v3.h>
 #include <linux/fs.h>
 #include <sys/ioctl.h>
 #include <unistd.h>
@@ -77,7 +78,8 @@
     // WIP: not quite sure how some of these are calculated yet, assuming buffer_size is determined
     // during COW size estimation
     header_.sequence_buffer_offset = 0;
-    header_.resume_buffer_size = 0;
+    header_.resume_point_count = 0;
+    header_.resume_point_max = kNumResumePoints;
     header_.op_count = 0;
     header_.op_count_max = 0;
     header_.compression_algorithm = kCowCompressNone;
@@ -120,11 +122,14 @@
     if (!InitFd() || !ParseOptions()) {
         return false;
     }
-
-    CHECK(!label.has_value());
-
-    if (!OpenForWrite()) {
-        return false;
+    if (!label) {
+        if (!OpenForWrite()) {
+            return false;
+        }
+    } else {
+        if (!OpenForAppend(*label)) {
+            return false;
+        }
     }
 
     return true;
@@ -159,13 +164,44 @@
         }
     }
     header_.op_count_max = options_.op_count_max;
+    resume_points_ = std::make_shared<std::vector<ResumePoint>>();
 
     if (!Sync()) {
         LOG(ERROR) << "Header sync failed";
         return false;
     }
-    next_data_pos_ =
-            sizeof(CowHeaderV3) + header_.buffer_size + header_.op_count_max * sizeof(CowOperation);
+    next_data_pos_ = GetDataOffset(header_);
+    return true;
+}
+
+bool CowWriterV3::OpenForAppend(uint64_t label) {
+    CowHeaderV3 header_v3;
+    if (!ReadCowHeader(fd_, &header_v3)) {
+        LOG(ERROR) << "Couldn't read Cow Header";
+        return false;
+    }
+
+    header_ = header_v3;
+
+    CHECK(label >= 0);
+    CowParserV3 parser;
+    if (!parser.Parse(fd_, header_, label)) {
+        PLOG(ERROR) << "unable to parse with given label: " << label;
+        return false;
+    }
+
+    resume_points_ = parser.resume_points();
+    options_.block_size = header_.block_size;
+    next_data_pos_ = GetDataOffset(header_);
+
+    TranslatedCowOps ops;
+    parser.Translate(&ops);
+    header_.op_count = ops.ops->size();
+
+    for (const auto& op : *ops.ops) {
+        next_data_pos_ += op.data_length;
+    }
+
     return true;
 }
 
@@ -249,9 +285,33 @@
 }
 
 bool CowWriterV3::EmitLabel(uint64_t label) {
-    LOG(ERROR) << __LINE__ << " " << __FILE__ << " <- function here should never be called";
-    if (label) return false;
-    return false;
+    // remove all labels greater than this current one. we want to avoid the situation of adding
+    // in
+    // duplicate labels with differing op values
+    auto remove_if_callback = [&](const auto& resume_point) -> bool {
+        if (resume_point.label >= label) return true;
+        return false;
+    };
+    resume_points_->erase(
+            std::remove_if(resume_points_->begin(), resume_points_->end(), remove_if_callback),
+            resume_points_->end());
+
+    resume_points_->push_back({label, header_.op_count});
+    header_.resume_point_count++;
+    // remove the oldest resume point if resume_buffer is full
+    while (resume_points_->size() > header_.resume_point_max) {
+        resume_points_->erase(resume_points_->begin());
+    }
+
+    CHECK_LE(resume_points_->size(), header_.resume_point_max);
+
+    if (!android::base::WriteFullyAtOffset(fd_, resume_points_->data(),
+                                           resume_points_->size() * sizeof(ResumePoint),
+                                           GetResumeOffset(header_))) {
+        PLOG(ERROR) << "writing resume buffer failed";
+        return false;
+    }
+    return Sync();
 }
 
 bool CowWriterV3::EmitSequenceData(size_t num_ops, const uint32_t* data) {
@@ -264,6 +324,7 @@
     if (IsEstimating()) {
         header_.op_count++;
         header_.op_count_max++;
+        next_data_pos_ += op.data_length;
         return true;
     }
 
@@ -272,7 +333,7 @@
         return false;
     }
 
-    const off_t offset = GetOpOffset(header_.op_count);
+    const off_t offset = GetOpOffset(header_.op_count, header_);
     if (!android::base::WriteFullyAtOffset(fd_, &op, sizeof(op), offset)) {
         PLOG(ERROR) << "write failed for " << op << " at " << offset;
         return false;
@@ -301,9 +362,7 @@
 }
 
 uint64_t CowWriterV3::GetCowSize() {
-    LOG(ERROR) << __LINE__ << " " << __FILE__
-               << " <- Get Cow Size function here should never be called";
-    return 0;
+    return next_data_pos_;
 }
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index 2347e91..3dfc33c 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -43,17 +43,12 @@
     void SetupHeaders();
     bool ParseOptions();
     bool OpenForWrite();
+    bool OpenForAppend(uint64_t label);
     bool WriteOperation(const CowOperationV3& op, const void* data = nullptr, size_t size = 0);
     bool EmitBlocks(uint64_t new_block_start, const void* data, size_t size, uint64_t old_block,
                     uint16_t offset, uint8_t type);
     bool CompressBlocks(size_t num_blocks, const void* data);
 
-    off_t GetOpOffset(uint32_t op_index) const {
-        CHECK_LT(op_index, header_.op_count_max);
-        return header_.prefix.header_size + header_.buffer_size +
-               (op_index * sizeof(CowOperationV3));
-    }
-
   private:
     CowHeaderV3 header_{};
     CowCompression compression_;
@@ -61,6 +56,8 @@
     // compressor
     std::unique_ptr<ICompressor> compressor_;
     std::vector<std::unique_ptr<CompressWorker>> compress_threads_;
+    // Resume points contain a laebl + cow_op_index.
+    std::shared_ptr<std::vector<ResumePoint>> resume_points_;
 
     uint64_t next_op_pos_ = 0;
     uint64_t next_data_pos_ = 0;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c639e43..e91e3b7 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -4339,32 +4339,30 @@
 }
 
 bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() {
-    auto slot = GetCurrentSlot();
-    if (slot == Slot::Target) {
-        // Merge in-progress
-        if (IsSnapuserdRequired()) {
+    // We cannot grab /metadata/ota lock here as this
+    // is in reboot path. See b/308900853
+    //
+    // Check if any of the partitions are mounted
+    // off dm-user block device. If so, then we are certain
+    // that OTA update in progress.
+    auto current_suffix = device_->GetSlotSuffix();
+    auto& dm = DeviceMapper::Instance();
+    auto dm_block_devices = dm.FindDmPartitions();
+    if (dm_block_devices.empty()) {
+        LOG(ERROR) << "No dm-enabled block device is found.";
+        return false;
+    }
+    for (auto& partition : dm_block_devices) {
+        std::string partition_name = partition.first + current_suffix;
+        DeviceMapper::TargetInfo snap_target;
+        if (!GetSingleTarget(partition_name, TableQuery::Status, &snap_target)) {
+            return false;
+        }
+        auto type = DeviceMapper::GetTargetType(snap_target.spec);
+        if (type == "user") {
             return true;
         }
     }
-
-    // Let's check more deeper to see if snapshots are mounted
-    auto lock = LockExclusive();
-    if (!lock) {
-        return false;
-    }
-
-    std::vector<std::string> snapshots;
-    if (!ListSnapshots(lock.get(), &snapshots)) {
-        return false;
-    }
-
-    for (const auto& snapshot : snapshots) {
-        // Active snapshot and daemon is alive
-        if (IsSnapshotDevice(snapshot) && EnsureSnapuserdConnected(2s)) {
-            return true;
-        }
-    }
-
     return false;
 }
 
diff --git a/fs_mgr/libsnapshot/tools/testdata/incompressible_block b/fs_mgr/libsnapshot/tools/testdata/incompressible_block
new file mode 100644
index 0000000..cc45cd0
--- /dev/null
+++ b/fs_mgr/libsnapshot/tools/testdata/incompressible_block
Binary files differ
diff --git a/init/service.cpp b/init/service.cpp
index 311a132..d351a8f 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -196,11 +196,12 @@
 }
 
 void Service::KillProcessGroup(int signal) {
-    // If we've already seen a successful result from killProcessGroup*(), then we have removed
-    // the cgroup already and calling these functions a second time will simply result in an error.
-    // This is true regardless of which signal was sent.
-    // These functions handle their own logging, so no additional logging is needed.
-    if (!process_cgroup_empty_) {
+    // Always attempt the process kill if process is still running.
+    // Cgroup clean up routines are idempotent. It's safe to call
+    // killProcessGroup repeatedly. During shutdown, `init` will
+    // call this function to send SIGTERM/SIGKILL to all processes.
+    // These signals must be sent for a successful shutdown.
+    if (!process_cgroup_empty_ || IsRunning()) {
         LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_
                   << ") process group...";
         int r;
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index e7c6e04..32057b4 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -196,14 +196,6 @@
   }
   if (setegid(old_egid) == -1) error(1, errno, "couldn't restore egid");
 
-  // Handle a multi-user data path
-  if (userId > 0) {
-    free(info.data_dir);
-    if (asprintf(&info.data_dir, "/data/user/%d/%s", userId, pkgname) == -1) {
-      error(1, errno, "asprintf failed");
-    }
-  }
-
   if (info.uid == 0) {
     error(1, 0, "unknown package: %s", pkgname);
   }
@@ -226,6 +218,12 @@
     error(1, 0, "package not debuggable: %s", pkgname);
   }
 
+  // Ensure we have the right data path for the specific user.
+  free(info.data_dir);
+  if (asprintf(&info.data_dir, "/data/user/%d/%s", userId, pkgname) == -1) {
+    error(1, errno, "asprintf failed");
+  }
+
   // Check that the data directory path is valid.
   check_data_path(pkgname, info.data_dir, userAppId);