Add support for DynamicRefTable when serializing/deserializing proto

Test: make aapt2_tests
Bug: 239390219
Bug: 237783271
Change-Id: I768f9167117c3a85c4dcabf2ece8a31e277c1e98
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 2a450ba..1d7fd1d 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -46,6 +46,13 @@
   string version = 2;
 }
 
+// References to non local resources
+message DynamicRefTable {
+  PackageId package_id = 1;
+  string package_name = 2;
+}
+
+
 // Top level message representing a resource table.
 message ResourceTable {
   // The string pool containing source paths referenced throughout the resource table. This does
@@ -60,6 +67,8 @@
 
   // The version fingerprints of the tools that built the resource table.
   repeated ToolFingerprint tool_fingerprint = 4;
+
+  repeated DynamicRefTable dynamic_ref_table = 5;
 }
 
 // A package ID in the range [0x00, 0xff].
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 6a1e8c1..e39f327 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -562,6 +562,11 @@
     }
   }
 
+  for (const pb::DynamicRefTable& dynamic_ref : pb_table.dynamic_ref_table()) {
+    out_table->included_packages_.insert(
+        {dynamic_ref.package_id().id(), dynamic_ref.package_name()});
+  }
+
   // Deserialize the overlayable groups of the table
   std::vector<std::shared_ptr<Overlayable>> overlayables;
   for (const pb::Overlayable& pb_overlayable : pb_table.overlayable()) {
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 163a60a..a6d58fd 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -345,7 +345,11 @@
   pb::ToolFingerprint* pb_fingerprint = out_table->add_tool_fingerprint();
   pb_fingerprint->set_tool(util::GetToolName());
   pb_fingerprint->set_version(util::GetToolFingerprint());
-
+  for (auto it = table.included_packages_.begin(); it != table.included_packages_.end(); ++it) {
+    pb::DynamicRefTable* pb_dynamic_ref = out_table->add_dynamic_ref_table();
+    pb_dynamic_ref->mutable_package_id()->set_id(it->first);
+    pb_dynamic_ref->set_package_name(it->second);
+  }
   std::vector<Overlayable*> overlayables;
   auto table_view = table.GetPartitionedView();
   for (const auto& package : table_view.packages) {
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index 692fa42..5adc5e6 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -1024,4 +1024,28 @@
   EXPECT_THAT(*(custom_layout->path), Eq("res/layout/bar.xml"));
 }
 
+TEST(ProtoSerializeTest, SerializeDynamicRef) {
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x7f).Build();
+  std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder().Build();
+  table->included_packages_.insert({20, "foobar"});
+  table->included_packages_.insert({30, "barfoo"});
+
+  ResourceTable new_table;
+  pb::ResourceTable pb_table;
+  MockFileCollection files;
+  std::string error;
+  SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
+  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
+  EXPECT_THAT(error, IsEmpty());
+
+  int result = new_table.included_packages_.size();
+  EXPECT_THAT(result, Eq(2));
+  auto it = new_table.included_packages_.begin();
+  EXPECT_THAT(it->first, Eq(20));
+  EXPECT_THAT(it->second, Eq("foobar"));
+  it++;
+  EXPECT_THAT(it->first, Eq(30));
+  EXPECT_THAT(it->second, Eq("barfoo"));
+}
 }  // namespace aapt