Enforce overlayable API when defined

If a package defines overlayable resources, then do not allow resources
that are not defined as overlayable to be overlaid.

Bug:123600120
Test: idmap2_tests and cts-tradefed run cts -m CtsRROTestCases
Change-Id: I35120a97ccf4650e67c7ba65a60f4f3c51b0e627
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 803f83c..056add5 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -16,11 +16,11 @@
     name: "idmap2_defaults",
     tidy: true,
     tidy_checks: [
+        "modernize-*",
+        "-modernize-avoid-c-arrays",
         "android-*",
         "misc-*",
-        "modernize-*",
         "readability-*",
-        "-modernize-avoid-c-arrays",
     ],
     tidy_flags: [
         "-system-headers",
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 5d449e9..fa5ac8e 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -281,10 +281,10 @@
   if (overlayable_info == nullptr) {
     // If the resource does not have an overlayable definition, allow the resource to be overlaid.
     // Once overlayable enforcement is turned on, this check will return false.
-    return true;
+    return !target_package.DefinesOverlayable();
   }
 
-  if (!overlay_info.target_name.empty() && overlay_info.target_name != overlayable_info->name) {
+  if (overlay_info.target_name != overlayable_info->name) {
     // If the overlay supplies a target overlayable name, the resource must belong to the
     // overlayable defined with the specified name to be overlaid.
     return false;
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 45f84fe..8514e12 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -40,9 +40,14 @@
                                const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
   ASSERT_THAT(v, NotNull());
   ASSERT_EQ(v->size(), 6U);
-  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
-            std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target",
-                                   root + "/system-overlay", root + "/system-overlay-invalid"}));
+  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>({
+                                                             root + "/.",
+                                                             root + "/..",
+                                                             root + "/overlay",
+                                                             root + "/target",
+                                                             root + "/system-overlay",
+                                                             root + "/system-overlay-invalid",
+                                                         }));
 }
 
 TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
@@ -51,13 +56,15 @@
     return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
   });
   ASSERT_THAT(v, NotNull());
-  ASSERT_EQ(v->size(), 6U);
-  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
-            std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk",
-                                   root + "/overlay/overlay-static-1.apk",
-                                   root + "/overlay/overlay-static-2.apk",
-                                   root + "/system-overlay/system-overlay.apk",
-                                   root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
+  ASSERT_EQ(v->size(), 9U);
+  ASSERT_EQ(
+      std::set<std::string>(v->begin(), v->end()),
+      std::set<std::string>(
+          {root + "/target/target.apk", root + "/target/target-no-overlayable.apk",
+           root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk",
+           root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-static-1.apk",
+           root + "/overlay/overlay-static-2.apk", root + "/system-overlay/system-overlay.apk",
+           root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
 }
 
 TEST(FileUtilsTests, ReadFile) {
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index c550eaf..1216f9ec 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -163,8 +163,12 @@
 TEST_F(Idmap2BinaryTests, Scan) {
   SKIP_TEST_IF_CANT_EXEC_IDMAP2;
 
+  const std::string overlay_static_no_name_apk_path =
+      GetTestDataPath() + "/overlay/overlay-no-name-static.apk";
   const std::string overlay_static_1_apk_path = GetTestDataPath() + "/overlay/overlay-static-1.apk";
   const std::string overlay_static_2_apk_path = GetTestDataPath() + "/overlay/overlay-static-2.apk";
+  const std::string idmap_static_no_name_path =
+      Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_no_name_apk_path);
   const std::string idmap_static_1_path =
       Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_1_apk_path);
   const std::string idmap_static_2_path =
@@ -184,11 +188,18 @@
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
   std::stringstream expected;
+  expected << idmap_static_no_name_path << std::endl;
   expected << idmap_static_1_path << std::endl;
   expected << idmap_static_2_path << std::endl;
   ASSERT_EQ(result->stdout, expected.str());
 
   std::stringstream error;
+  auto idmap_static_no_name_raw_string = utils::ReadFile(idmap_static_no_name_path);
+  auto idmap_static_no_name_raw_stream = std::istringstream(*idmap_static_no_name_raw_string);
+  auto idmap_static_no_name = Idmap::FromBinaryStream(idmap_static_no_name_raw_stream, error);
+  ASSERT_THAT(idmap_static_no_name, NotNull());
+  ASSERT_IDMAP(*idmap_static_no_name, GetTargetApkPath(), overlay_static_no_name_apk_path);
+
   auto idmap_static_1_raw_string = utils::ReadFile(idmap_static_1_path);
   auto idmap_static_1_raw_stream = std::istringstream(*idmap_static_1_raw_string);
   auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream, error);
@@ -201,6 +212,7 @@
   ASSERT_THAT(idmap_static_2, NotNull());
   ASSERT_IDMAP(*idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path);
 
+  unlink(idmap_static_no_name_path.c_str());
   unlink(idmap_static_2_path.c_str());
   unlink(idmap_static_1_path.c_str());
 
@@ -218,6 +230,7 @@
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
   ASSERT_EQ(result->stdout, expected.str());
+  unlink(idmap_static_no_name_path.c_str());
   unlink(idmap_static_2_path.c_str());
   unlink(idmap_static_1_path.c_str());
 
@@ -236,6 +249,7 @@
   ASSERT_THAT(result, NotNull());
   ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
   ASSERT_EQ(result->stdout, expected.str());
+  unlink(idmap_static_no_name_path.c_str());
   unlink(idmap_static_2_path.c_str());
   unlink(idmap_static_1_path.c_str());
 
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index df28918..9e27ccd 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -224,7 +224,8 @@
   ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
 }
 
-TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
+// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
   const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
   std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
   ASSERT_THAT(target_apk, NotNull());
@@ -260,7 +261,8 @@
   ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_system_vendor
 }
 
-TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
+// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
   const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
   std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
   ASSERT_THAT(target_apk, NotNull());
@@ -290,17 +292,15 @@
 
   ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
   ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
-  ASSERT_EQ(types[0]->GetEntryCount(), 6U);
-  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
-  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);   // string/not_overlayable
-  ASSERT_EQ(types[0]->GetEntry(1), kNoEntry);  // string/other
-  ASSERT_EQ(types[0]->GetEntry(2), kNoEntry);  // string/policy_product
-  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);   // string/policy_public
-  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);   // string/policy_system
-  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);   // string/policy_system_vendor
+  ASSERT_EQ(types[0]->GetEntryCount(), 3U);
+  ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0003U);  // string/policy_public
+  ASSERT_EQ(types[0]->GetEntry(1), 0x0004U);  // string/policy_system
+  ASSERT_EQ(types[0]->GetEntry(2), 0x0005U);  // string/policy_system_vendor
 }
 
-TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
+// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
   const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
   std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
   ASSERT_THAT(target_apk, NotNull());
@@ -340,6 +340,91 @@
   ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system_vendor
 }
 
+// The resources of APKs that do not include an overlayable declaration should not restrict what
+// resources can be overlaid.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) {
+  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() +
+                                     "/system-overlay-invalid/system-overlay-invalid.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+  ASSERT_EQ(dataBlocks.size(), 1U);
+
+  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+  ASSERT_EQ(types.size(), 1U);
+
+  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+  ASSERT_EQ(types[0]->GetEntryCount(), 6U);
+  ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);  // string/not_overlayable
+  ASSERT_EQ(types[0]->GetEntry(1), 0x0001U);  // string/other
+  ASSERT_EQ(types[0]->GetEntry(2), 0x0002U);  // string/policy_product
+  ASSERT_EQ(types[0]->GetEntry(3), 0x0003U);  // string/policy_public
+  ASSERT_EQ(types[0]->GetEntry(4), 0x0004U);  // string/policy_system
+  ASSERT_EQ(types[0]->GetEntry(5), 0x0005U);  // string/policy_system_vendor
+}
+
+// The resources of APKs that do not include an overlayable declaration should not restrict what
+// resources can be overlaid.
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
+  const std::string target_apk_path(GetTestDataPath() + "/target/target-no-overlayable.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay-no-name.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+                           PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+  ASSERT_EQ(dataBlocks.size(), 1U);
+
+  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
+
+  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+  ASSERT_EQ(types.size(), 2U);
+
+  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
+  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+  ASSERT_EQ(types[0]->GetEntryCount(), 1U);
+  ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+
+  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
+  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
+  ASSERT_EQ(types[1]->GetEntryCount(), 4U);
+  ASSERT_EQ(types[1]->GetEntryOffset(), 9U);
+  ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
+  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
+  ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
+  ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
+}
+
 TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
   std::string target_apk_path(GetTestDataPath());
   for (int i = 0; i < 32; i++) {
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
index 9f89d31..a7767a6 100644
--- a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
@@ -17,5 +17,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="test.overlay">
     <overlay
-        android:targetPackage="test.target" />
+        android:targetPackage="test.target"
+        android:targetName="TestResources"/>
 </manifest>
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestNoName.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestNoName.xml
new file mode 100644
index 0000000..bc6b733
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifestNoName.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.overlay.no.name">
+    <overlay
+        android:targetPackage="test.target"/>
+</manifest>
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestNoNameStatic.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestNoNameStatic.xml
new file mode 100644
index 0000000..ed327ce
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifestNoNameStatic.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.overlay.no.name.static">
+    <overlay
+        android:targetPackage="test.target"
+        android:targetName="TestResources"
+        android:isStatic="true"
+        android:priority="1" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml
index 39336cc..1c4dae6 100644
--- a/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml
@@ -18,6 +18,7 @@
     package="test.overlay.static1">
     <overlay
         android:targetPackage="test.target"
+        android:targetName="TestResources"
         android:isStatic="true"
         android:priority="1" />
 </manifest>
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml
index e1cc175..70efc86 100644
--- a/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml
@@ -18,6 +18,7 @@
     package="test.overlay.static2">
     <overlay
         android:targetPackage="test.target"
+        android:targetName="TestResources"
         android:isStatic="true"
         android:priority="2" />
 </manifest>
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
index cba1086..e60da80 100644
--- a/cmds/idmap2/tests/data/overlay/build
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -26,6 +26,20 @@
 aapt2 link \
     --no-resource-removal \
     -I "$FRAMEWORK_RES_APK" \
+    --manifest AndroidManifestNoName.xml \
+    -o overlay-no-name.apk \
+    compiled.flata
+
+aapt2 link \
+    --no-resource-removal \
+    -I "$FRAMEWORK_RES_APK" \
+    --manifest AndroidManifestNoNameStatic.xml \
+    -o overlay-no-name-static.apk \
+    compiled.flata
+
+aapt2 link \
+    --no-resource-removal \
+    -I "$FRAMEWORK_RES_APK" \
     --manifest AndroidManifestStatic1.xml \
     -o overlay-static-1.apk \
     compiled.flata
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
new file mode 100644
index 0000000..18ee43d
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
new file mode 100644
index 0000000..7d23c09
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
index 9a0f487..642ab90 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
index 3fc31c7..2ec5602 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay.apk b/cmds/idmap2/tests/data/overlay/overlay.apk
index b4cd7cf..5842da4 100644
--- a/cmds/idmap2/tests/data/overlay/overlay.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
index 8af9064..5dacebd 100644
--- a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
+++ b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
@@ -14,8 +14,9 @@
      limitations under the License.
 -->
 <manifest
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        package="test.overlay.system">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.overlay.system">
     <overlay
-            android:targetPackage="test.target" />
+        android:targetPackage="test.target"
+        android:targetName="TestResources"/>
 </manifest>
diff --git a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
index 90f30eb..a0fba43 100644
--- a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
+++ b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/build b/cmds/idmap2/tests/data/target/build
index 8569c4f..137ddb5 100644
--- a/cmds/idmap2/tests/data/target/build
+++ b/cmds/idmap2/tests/data/target/build
@@ -15,3 +15,7 @@
 aapt2 compile --dir res -o compiled.flata
 aapt2 link --manifest AndroidManifest.xml -A assets -o target.apk compiled.flata
 rm compiled.flata
+
+aapt2 compile res/values/values.xml -o .
+aapt2 link --manifest AndroidManifest.xml -A assets -o target_no_overlayable.apk values_values.arsc.flat
+rm values_values.arsc.flat
\ No newline at end of file
diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
new file mode 100644
index 0000000..8676cbb
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
Binary files differ
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 70ce9bc..bdd4706 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -633,6 +633,7 @@
               overlayable_info.actor = actor;
               overlayable_info.policy_flags = policy_header->policy_flags;
               loaded_package->overlayable_infos_.push_back(std::make_pair(overlayable_info, ids));
+              loaded_package->defines_overlayable_ = true;
               break;
             }
 
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index be62f30..b5f4006 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -223,7 +223,7 @@
     }
   }
 
-  // Retrieve the overlayable properties of the specified resource. If the resource is not
+  // Retrieves the overlayable properties of the specified resource. If the resource is not
   // overlayable, this will return a null pointer.
   const OverlayableInfo* GetOverlayableInfo(uint32_t resid) const {
     for (const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>& overlayable_info_ids
@@ -235,6 +235,13 @@
     return nullptr;
   }
 
+  // Retrieves whether or not the package defines overlayable resources.
+  // TODO(123905379): Remove this when the enforcement of overlayable is turned on for all APK and
+  // not just those that defined overlayable resources.
+  bool DefinesOverlayable() const {
+    return defines_overlayable_;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
 
@@ -248,6 +255,7 @@
   bool dynamic_ = false;
   bool system_ = false;
   bool overlay_ = false;
+  bool defines_overlayable_ = false;
 
   ByteBucketArray<TypeSpecPtr> type_specs_;
   ByteBucketArray<uint32_t> resource_ids_;