liblp: Add MetadataBuilder helpers for pruning unused groups.

These will help update_engine clear the target slot before applying an OTA.

Bug: 117182932
Test: liblp_test gtest
Change-Id: I6ad370e617f22f2098245a0028a93488f9ac8674
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index bbdec5b..4953655 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -47,6 +47,9 @@
     cppflags: [
         "-Wno-unused-parameter",
     ],
+    static_libs: [
+        "libgmock",
+    ],
     shared_libs: [
         "liblp",
         "libbase",
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 963e1b3..2c57a35 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -339,7 +339,7 @@
     return nullptr;
 }
 
-PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) const {
+PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
     for (const auto& group : groups_) {
         if (group->name() == group_name) {
             return group.get();
@@ -624,5 +624,36 @@
     return true;
 }
 
+std::vector<std::string> MetadataBuilder::ListGroups() const {
+    std::vector<std::string> names;
+    for (const auto& group : groups_) {
+        names.emplace_back(group->name());
+    }
+    return names;
+}
+
+void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) {
+    if (group_name == "default") {
+        // Cannot remove the default group.
+        return;
+    }
+    std::vector<std::string> partition_names;
+    for (const auto& partition : partitions_) {
+        if (partition->group_name() == group_name) {
+            partition_names.emplace_back(partition->name());
+        }
+    }
+
+    for (const auto& partition_name : partition_names) {
+        RemovePartition(partition_name);
+    }
+    for (auto iter = groups_.begin(); iter != groups_.end(); iter++) {
+        if ((*iter)->name() == group_name) {
+            groups_.erase(iter);
+            break;
+        }
+    }
+}
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index f72b8e1..27ad250 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
+#include <fs_mgr.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <liblp/builder.h>
-#include "fs_mgr.h"
+
 #include "utility.h"
 
 using namespace std;
 using namespace android::fs_mgr;
+using ::testing::ElementsAre;
 
 TEST(liblp, BuildBasic) {
     unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
@@ -542,3 +545,30 @@
     p = builder->AddPartition("vendor_a", "foo_a", 0);
     ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
 }
+
+TEST(liblp, ListGroups) {
+    BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+    unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+    ASSERT_NE(builder, nullptr);
+    ASSERT_TRUE(builder->AddGroup("example", 0));
+
+    std::vector<std::string> groups = builder->ListGroups();
+    ASSERT_THAT(groups, ElementsAre("default", "example"));
+}
+
+TEST(liblp, RemoveGroupAndPartitions) {
+    BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+    unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+    ASSERT_NE(builder, nullptr);
+    ASSERT_TRUE(builder->AddGroup("example", 0));
+    ASSERT_NE(builder->AddPartition("system", "default", 0), nullptr);
+    ASSERT_NE(builder->AddPartition("vendor", "example", 0), nullptr);
+
+    builder->RemoveGroupAndPartitions("example");
+    ASSERT_NE(builder->FindPartition("system"), nullptr);
+    ASSERT_EQ(builder->FindPartition("vendor"), nullptr);
+    ASSERT_THAT(builder->ListGroups(), ElementsAre("default"));
+
+    builder->RemoveGroupAndPartitions("default");
+    ASSERT_NE(builder->FindPartition("system"), nullptr);
+}
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 30dc300..7e07df4 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -199,6 +199,9 @@
     // Find a partition by name. If no partition is found, nullptr is returned.
     Partition* FindPartition(const std::string& name);
 
+    // Find a group by name. If no group is found, nullptr is returned.
+    PartitionGroup* FindGroup(const std::string& name);
+
     // Grow or shrink a partition to the requested size. This size will be
     // rounded UP to the nearest block (512 bytes).
     //
@@ -215,6 +218,12 @@
     uint64_t AllocatableSpace() const;
     uint64_t UsedSpace() const;
 
+    // Return a list of all group names.
+    std::vector<std::string> ListGroups() const;
+
+    // Remove all partitions belonging to a group, then remove the group.
+    void RemoveGroupAndPartitions(const std::string& group_name);
+
     bool GetBlockDeviceInfo(BlockDeviceInfo* info) const;
     bool UpdateBlockDeviceInfo(const BlockDeviceInfo& info);
 
@@ -229,7 +238,6 @@
     bool GrowPartition(Partition* partition, uint64_t aligned_size);
     void ShrinkPartition(Partition* partition, uint64_t aligned_size);
     uint64_t AlignSector(uint64_t sector) const;
-    PartitionGroup* FindGroup(const std::string& group_name) const;
     uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
 
     struct Interval {