AAPT2: Support id reference chaining from AAPT

AAPT would allow for ids to be declared in the form:

<item name="name" type="id>@id/other</item>

@id/name should hold a reference to @id/other. When
getResources().getValue() is called on R.id.name with resolveRefs
enabled, the resuling reference should be R.id.other.

Bug: 69445910
Test: Created tests for correct parsing of id references and correct
resolving of deep references

Change-Id: Id1feb37b2565c213dc6a19b4c401906260d7fc14
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 3118009..f1cc569 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -386,6 +386,38 @@
   EXPECT_EQ(basic::R::array::integerArray1, last_ref);
 }
 
+TEST_F(AssetManager2Test, ResolveDeepIdReference) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({basic_assets_.get()});
+
+  // Set up the resource ids
+  const uint32_t high_ref = assetmanager
+      .GetResourceId("@id/high_ref", "values", "com.android.basic");
+  ASSERT_NE(high_ref, 0u);
+  const uint32_t middle_ref = assetmanager
+      .GetResourceId("@id/middle_ref", "values", "com.android.basic");
+  ASSERT_NE(middle_ref, 0u);
+  const uint32_t low_ref = assetmanager
+      .GetResourceId("@id/low_ref", "values", "com.android.basic");
+  ASSERT_NE(low_ref, 0u);
+
+  // Retrieve the most shallow resource
+  Res_value value;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = assetmanager.GetResource(high_ref, false /*may_be_bag*/,
+                                                    0 /*density_override*/,
+                                                    &value, &config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+  EXPECT_EQ(middle_ref, value.data);
+
+  // Check that resolving the reference resolves to the deepest id
+  uint32_t last_ref = high_ref;
+  assetmanager.ResolveReference(cookie, &value, &config, &flags, &last_ref);
+  EXPECT_EQ(last_ref, low_ref);
+}
+
 TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) {
   AssetManager2 assetmanager;
   assetmanager.SetApkAssets({basic_assets_.get()});