Enforce the overlayable mechanism for self-targeting

The overlayable mechanism has defined which roles can overlay the
specified resources and which resources are overlayable.

In order to reduce the argument between platform and applications,
self-targeting applications should enforce the overlayable mechanism.
It makes the overlay range be defined in the overlayable list. It
also defines the limitation of what kind of package can overlay the
resources of the self-targeting application.

To fill the policy flag, OverlayManagerImpl.java gets the following
information and passes them as bool type to JNI OverlayManagerImpl.
* SYSTEM_PARTITION
* VENDOR_PARTITION
* PRODUCT_PARTITION
* ODM_PARTITION
* OEM_PARTITION
* SIGNATURE

Not support
* ACTOR_SIGNATURE
* CONFIG_SIGNATURE

JNI OverlayManagerImpl fills the policy flags according to the
information from the ApplicationInfo. 'enforce_overlayable'is true to
enforce checking overlayable before generating an idmap.

Fixes: 238061808
Bug: 205919743

Test: atest \
              OverlayHostTests \
              OverlayDeviceTests \
              SelfTargetingOverlayDeviceTests \
              OverlayRemountedTest \
              FrameworksServicesTests:com.android.server.om \
              CtsContentTestCases:android.content.om.cts \
              idmap2_tests

Change-Id: I749d1a90a00f0a91e7796bc0f9f668f9ecfdb8b0
diff --git a/cmds/idmap2/self_targeting/SelfTargeting.cpp b/cmds/idmap2/self_targeting/SelfTargeting.cpp
index 20aa7d3..a8aa033 100644
--- a/cmds/idmap2/self_targeting/SelfTargeting.cpp
+++ b/cmds/idmap2/self_targeting/SelfTargeting.cpp
@@ -38,9 +38,10 @@
 constexpr const mode_t kIdmapFilePermission = S_IRUSR | S_IWUSR;  // u=rw-, g=---, o=---
 
 extern "C" bool
-CreateFrroFile(std::string& out_err_result, std::string& packageName, std::string& overlayName,
-               std::string& targetPackageName, std::optional<std::string>& targetOverlayable,
-               std::vector<FabricatedOverlayEntryParameters>& entries_params,
+CreateFrroFile(std::string& out_err_result, const std::string& packageName,
+               const std::string& overlayName, const std::string& targetPackageName,
+               const std::optional<std::string>& targetOverlayable,
+               const std::vector<FabricatedOverlayEntryParameters>& entries_params,
                const std::string& frro_file_path) {
     android::idmap2::FabricatedOverlay::Builder builder(packageName, overlayName,
                                                         targetPackageName);
@@ -90,9 +91,46 @@
     return true;
 }
 
+static PolicyBitmask GetFulfilledPolicy(const bool isSystem, const bool isVendor,
+                                        const bool isProduct, const bool isTargetSignature,
+                                        const bool isOdm, const bool isOem) {
+    auto fulfilled_policy = static_cast<PolicyBitmask>(PolicyFlags::PUBLIC);
+
+    if (isSystem) {
+        fulfilled_policy |= PolicyFlags::SYSTEM_PARTITION;
+    }
+    if (isVendor) {
+        fulfilled_policy |= PolicyFlags::VENDOR_PARTITION;
+    }
+    if (isProduct) {
+        fulfilled_policy |= PolicyFlags::PRODUCT_PARTITION;
+    }
+    if (isOdm) {
+        fulfilled_policy |= PolicyFlags::ODM_PARTITION;
+    }
+    if (isOem) {
+        fulfilled_policy |= PolicyFlags::OEM_PARTITION;
+    }
+    if (isTargetSignature) {
+        fulfilled_policy |= PolicyFlags::SIGNATURE;
+    }
+
+    // Not support actor_signature and config_overlay_signature
+    fulfilled_policy &=
+            ~(PolicyFlags::ACTOR_SIGNATURE | PolicyFlags::CONFIG_SIGNATURE);
+
+    ALOGV(
+            "fulfilled_policy = 0x%08x, isSystem = %d, isVendor = %d, isProduct = %d,"
+            " isTargetSignature = %d, isOdm = %d, isOem = %d,",
+            fulfilled_policy, isSystem, isVendor, isProduct, isTargetSignature, isOdm, isOem);
+    return fulfilled_policy;
+}
+
 extern "C" bool
 CreateIdmapFile(std::string& out_err, const std::string& targetPath, const std::string& overlayPath,
-                const std::string& idmapPath, const std::string& overlayName) {
+                const std::string& idmapPath, const std::string& overlayName,
+                const bool isSystem, const bool isVendor, const bool isProduct,
+                const bool isTargetSignature, const bool isOdm, const bool isOem) {
     // idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap
     // guarantees that existing memory maps will continue to be valid and unaffected. The file must
     // be deleted before attempting to create the idmap, so that if idmap  creation fails, the
@@ -114,14 +152,11 @@
     }
 
     // Overlay self target process. Only allow self-targeting types.
-    const auto fulfilled_policies = static_cast<PolicyBitmask>(
-            PolicyFlags::PUBLIC | PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION |
-            PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE | PolicyFlags::ODM_PARTITION |
-            PolicyFlags::OEM_PARTITION | PolicyFlags::ACTOR_SIGNATURE |
-            PolicyFlags::CONFIG_SIGNATURE);
+    const auto fulfilled_policies = GetFulfilledPolicy(isSystem, isVendor, isProduct,
+                                                       isTargetSignature, isOdm, isOem);
 
     const auto idmap = Idmap::FromContainers(**target, **overlay, overlayName,
-                                             fulfilled_policies, false /* enforce_overlayable */);
+                                             fulfilled_policies, true /* enforce_overlayable */);
     if (!idmap) {
         out_err = base::StringPrintf("Failed to create idmap because of %s",
                                      idmap.GetErrorMessage().c_str());
diff --git a/core/java/com/android/internal/content/om/OverlayManagerImpl.java b/core/java/com/android/internal/content/om/OverlayManagerImpl.java
index 76e068d..e56c06e 100644
--- a/core/java/com/android/internal/content/om/OverlayManagerImpl.java
+++ b/core/java/com/android/internal/content/om/OverlayManagerImpl.java
@@ -170,6 +170,16 @@
         mBasePath = baseFile.toPath();
     }
 
+    private boolean isSameWithTargetSignature(final String targetPackage) {
+        final PackageManager packageManager = mContext.getPackageManager();
+        final String packageName = mContext.getPackageName();
+        if (TextUtils.equals(packageName, targetPackage)) {
+            return true;
+        }
+        return packageManager.checkSignatures(packageName, targetPackage)
+                == PackageManager.SIGNATURE_MATCH;
+    }
+
     /**
      * Check if the overlay name is valid or not.
      *
@@ -202,6 +212,9 @@
     /**
      * Save FabricatedOverlay instance as frro and idmap files.
      *
+     * <p>In order to fill the overlayable policy, it's necessary to collect the information from
+     * app. And then, the information is passed to native layer to fill the overlayable policy
+     *
      * @param overlayInternal the FabricatedOverlayInternal to be saved.
      */
     public void registerFabricatedOverlay(@NonNull FabricatedOverlayInternal overlayInternal)
@@ -214,6 +227,9 @@
         final String overlayName = checkOverlayNameValid(overlayInternal.overlayName);
         checkPackageName(overlayInternal.packageName);
         checkPackageName(overlayInternal.targetPackageName);
+        Preconditions.checkStringNotEmpty(
+                overlayInternal.targetOverlayable,
+                "Target overlayable should be neither null nor empty string.");
 
         final ApplicationInfo applicationInfo = mContext.getApplicationInfo();
         final String targetPackage = Preconditions.checkStringNotEmpty(
@@ -223,7 +239,17 @@
 
         createFrroFile(frroPath.toString(), overlayInternal);
         try {
-            createIdmapFile(targetPackage, frroPath.toString(), idmapPath.toString(), overlayName);
+            createIdmapFile(
+                    targetPackage,
+                    frroPath.toString(),
+                    idmapPath.toString(),
+                    overlayName,
+                    applicationInfo.isSystemApp() || applicationInfo.isSystemExt() /* isSystem */,
+                    applicationInfo.isVendor(),
+                    applicationInfo.isProduct(),
+                    isSameWithTargetSignature(overlayInternal.targetPackageName),
+                    applicationInfo.isOdm(),
+                    applicationInfo.isOem());
         } catch (IOException e) {
             if (!frroPath.toFile().delete()) {
                 Log.w(TAG, "Failed to delete file " + frroPath);
@@ -315,7 +341,13 @@
             @NonNull String targetPath,
             @NonNull String overlayPath,
             @NonNull String idmapPath,
-            @NonNull String overlayName)
+            @NonNull String overlayName,
+            boolean isSystem,
+            boolean isVendor,
+            boolean isProduct,
+            boolean isSameWithTargetSignature,
+            boolean isOdm,
+            boolean isOem)
             throws IOException;
 
     private static native FabricatedOverlayInfo getFabricatedOverlayInfo(
diff --git a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
index df55e42..bba1760 100644
--- a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
+++ b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp
@@ -123,8 +123,12 @@
 
     bool callCreateIdmapFile(std::string& out_error, const std::string& targetPath,
                              const std::string& overlayPath, const std::string& idmapPath,
-                             const std::string& overlayName) {
-        return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName);
+                             const std::string& overlayName, const bool isSystem,
+                             const bool isVendor, const bool isProduct,
+                             const bool isTargetSignature, const bool isOdm, const bool isOem) {
+        return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName,
+                                       isSystem, isVendor, isProduct, isTargetSignature, isOdm,
+                                       isOem);
     }
 
     bool callGetFabricatedOverlayInfo(std::string& out_error, const std::string& overlay_path,
@@ -158,7 +162,10 @@
     typedef bool (*CreateIdmapFileFunc)(std::string& out_error, const std::string& targetPath,
                                         const std::string& overlayPath,
                                         const std::string& idmapPath,
-                                        const std::string& overlayName);
+                                        const std::string& overlayName, const jboolean isSystem,
+                                        const jboolean isVendor, const jboolean isProduct,
+                                        const jboolean isSameWithTargetSignature,
+                                        const jboolean isOdm, const jboolean isOem);
 
     typedef bool (*GetFabricatedOverlayInfoFunc)(std::string& out_error,
                                                  const std::string& overlay_path,
@@ -295,7 +302,9 @@
 }
 
 static void CreateIdmapFile(JNIEnv* env, jclass /* clazz */, jstring jsTargetPath,
-                            jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName) {
+                            jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName,
+                            jboolean isSystem, jboolean isVendor, jboolean isProduct,
+                            jboolean isTargetSignature, jboolean isOdm, jboolean isOem) {
     DynamicLibraryLoader& dlLoader = EnsureDynamicLibraryLoader(env);
     if (!dlLoader) {
         jniThrowNullPointerException(env, "libidmap2 is not loaded");
@@ -327,7 +336,10 @@
 
     std::string err_result;
     if (!dlLoader.callCreateIdmapFile(err_result, targetPath.c_str(), overlayPath.c_str(),
-                                      idmapPath.c_str(), overlayName.c_str())) {
+                                      idmapPath.c_str(), overlayName.c_str(),
+                                      (isSystem == JNI_TRUE), (isVendor == JNI_TRUE),
+                                      (isProduct == JNI_TRUE), (isTargetSignature == JNI_TRUE),
+                                      (isOdm == JNI_TRUE), (isOem == JNI_TRUE))) {
         jniThrowException(env, kIOException, err_result.c_str());
         return;
     }
@@ -374,7 +386,7 @@
         {"createFrroFile", "(Ljava/lang/String;Landroid/os/FabricatedOverlayInternal;)V",
          reinterpret_cast<void*>(self_targeting::CreateFrroFile)},
         {"createIdmapFile",
-         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
+         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZZZZ)V",
          reinterpret_cast<void*>(self_targeting::CreateIdmapFile)},
         {"getFabricatedOverlayInfo", "(Ljava/lang/String;)Landroid/os/FabricatedOverlayInfo;",
          reinterpret_cast<void*>(self_targeting::GetFabricatedOverlayInfo)},
diff --git a/core/tests/overlaytests/device_self_targeting/Android.bp b/core/tests/overlaytests/device_self_targeting/Android.bp
index 82998db..063c569 100644
--- a/core/tests/overlaytests/device_self_targeting/Android.bp
+++ b/core/tests/overlaytests/device_self_targeting/Android.bp
@@ -29,6 +29,7 @@
         "androidx.test.rules",
         "androidx.test.runner",
         "androidx.test.ext.junit",
+        "mockito-target-minus-junit4",
         "truth-prebuilt",
     ],
 
diff --git a/core/tests/overlaytests/device_self_targeting/res/values/overlayable.xml b/core/tests/overlaytests/device_self_targeting/res/values/overlayable.xml
new file mode 100644
index 0000000..5cc214d
--- /dev/null
+++ b/core/tests/overlaytests/device_self_targeting/res/values/overlayable.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2022 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.
+  -->
+
+<resources>
+    <overlayable name="PublicOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="public">
+            <item type="color" name="public_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="SignatureOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="signature">
+            <item type="color" name="mycolor" />
+            <item type="color" name="signature_overlayable_color" />
+            <item type="string" name="mystring" />
+            <item type="drawable" name="mydrawable" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="SystemAppOverlayable" actor="overlay://theme">
+        <!-- The app in system partition can overlay the below resources -->
+        <policy type="system">
+            <item type="color" name="system_app_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="OdmOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="odm">
+            <item type="color" name="odm_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="OemOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="oem">
+            <item type="color" name="oem_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="VendorOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="vendor">
+            <item type="color" name="vendor_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="ProductOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="product">
+            <item type="color" name="product_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="ActorOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="actor">
+            <item type="color" name="actor_overlayable_color" />
+        </policy>
+    </overlayable>
+
+    <overlayable name="ConfigOverlayable" actor="overlay://theme">
+        <!-- The app with the same signature can overlay the below resources -->
+        <policy type="config_signature">
+            <item type="color" name="config_overlayable_color" />
+        </policy>
+    </overlayable>
+
+</resources>
diff --git a/core/tests/overlaytests/device_self_targeting/res/values/values.xml b/core/tests/overlaytests/device_self_targeting/res/values/values.xml
index f0b4a6f..d82de97 100644
--- a/core/tests/overlaytests/device_self_targeting/res/values/values.xml
+++ b/core/tests/overlaytests/device_self_targeting/res/values/values.xml
@@ -17,4 +17,14 @@
 <resources>
     <color name="mycolor">#ff112233</color>
     <string name="mystring">hello</string>
+
+    <color name="public_overlayable_color">#000</color>
+    <color name="signature_overlayable_color">#000</color>
+    <color name="system_app_overlayable_color">#000</color>
+    <color name="odm_overlayable_color">#000</color>
+    <color name="oem_overlayable_color">#000</color>
+    <color name="vendor_overlayable_color">#000</color>
+    <color name="product_overlayable_color">#000</color>
+    <color name="actor_overlayable_color">#000</color>
+    <color name="config_overlayable_color">#000</color>
 </resources>
diff --git a/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java b/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java
index ca58410..8a9ab5b 100644
--- a/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java
+++ b/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java
@@ -17,15 +17,22 @@
 package com.android.overlaytest;
 
 import static android.content.Context.MODE_PRIVATE;
+import static android.content.pm.PackageManager.SIGNATURE_NO_MATCH;
 
 import static com.android.internal.content.om.OverlayManagerImpl.SELF_TARGET;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.os.FabricatedOverlayInternal;
@@ -72,11 +79,23 @@
     private static final String TARGET_COLOR_RES = "color/mycolor";
     private static final String TARGET_STRING_RES = "string/mystring";
     private static final String TARGET_DRAWABLE_RES = "drawable/mydrawable";
+    private static final String PUBLIC_OVERLAYABLE = "PublicOverlayable";
+    private static final String SIGNATURE_OVERLAYABLE = "SignatureOverlayable";
+    private static final String SYSTEM_APP_OVERLAYABLE = "SystemAppOverlayable";
+    private static final String ODM_OVERLAYABLE = "OdmOverlayable";
+    private static final String OEM_OVERLAYABLE = "OemOverlayable";
+    private static final String VENDOR_OVERLAYABLE = "VendorOverlayable";
+    private static final String PRODUCT_OVERLAYABLE = "ProductOverlayable";
+    private static final String ACTOR_OVERLAYABLE = "ActorOverlayable";
+    private static final String CONFIG_OVERLAYABLE = "ConfigOverlayable";
 
     private Context mContext;
     private OverlayManagerImpl mOverlayManagerImpl;
     private String mOverlayName;
 
+    private PackageManager mMockPackageManager;
+    private ApplicationInfo mMockApplicationInfo;
+
     @Rule public TestName mTestName = new TestName();
 
     @Rule public Expect expect = Expect.create();
@@ -111,7 +130,36 @@
     public void setUp() throws IOException {
         clearDir();
         mOverlayName = mTestName.getMethodName();
-        mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+        mMockApplicationInfo = mock(ApplicationInfo.class);
+        when(mMockApplicationInfo.isSystemApp()).thenReturn(false);
+        when(mMockApplicationInfo.isSystemExt()).thenReturn(false);
+        when(mMockApplicationInfo.isOdm()).thenReturn(false);
+        when(mMockApplicationInfo.isOem()).thenReturn(false);
+        when(mMockApplicationInfo.isVendor()).thenReturn(false);
+        when(mMockApplicationInfo.isProduct()).thenReturn(false);
+        when(mMockApplicationInfo.getBaseCodePath()).thenReturn(
+                context.getApplicationInfo().getBaseCodePath());
+        mMockApplicationInfo.sourceDir = context.getApplicationInfo().sourceDir;
+
+        mMockPackageManager = mock(PackageManager.class);
+        when(mMockPackageManager.checkSignatures(anyString(), anyString()))
+                .thenReturn(SIGNATURE_NO_MATCH);
+
+        mContext =
+                new ContextWrapper(context) {
+                    @Override
+                    public ApplicationInfo getApplicationInfo() {
+                        return mMockApplicationInfo;
+                    }
+
+                    @Override
+                    public PackageManager getPackageManager() {
+                        return mMockPackageManager;
+                    }
+                };
+
         mOverlayManagerImpl = new OverlayManagerImpl(mContext);
     }
 
@@ -144,12 +192,14 @@
 
     private <T> FabricatedOverlayInternal createOverlayWithName(
             @NonNull String overlayName,
+            @NonNull String targetOverlayable,
             @NonNull String targetPackageName,
             @NonNull List<Pair<String, Pair<String, T>>> entryDefinitions) {
         final String packageName = mContext.getPackageName();
         FabricatedOverlayInternal overlayInternal = new FabricatedOverlayInternal();
         overlayInternal.overlayName = overlayName;
         overlayInternal.targetPackageName = targetPackageName;
+        overlayInternal.targetOverlayable = targetOverlayable;
         overlayInternal.packageName = packageName;
 
         addOverlayEntry(overlayInternal, entryDefinitions);
@@ -162,6 +212,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SYSTEM_APP_OVERLAYABLE,
                         "android",
                         List.of(Pair.create("color/white", Pair.create(null, Color.BLACK))));
 
@@ -190,6 +241,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
 
@@ -215,6 +267,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_STRING_RES, Pair.create(null, "HELLO"))));
 
@@ -242,6 +295,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_DRAWABLE_RES,
                                             Pair.create(null, parcelFileDescriptor))));
@@ -268,6 +322,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create("color/not_existed", Pair.create(null, "HELLO"))));
 
@@ -301,6 +356,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
         mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -309,6 +365,7 @@
         overlayInternal =
                 createOverlayWithName(
                         secondOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
         mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -341,6 +398,7 @@
         FabricatedOverlayInternal overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
         mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -349,6 +407,7 @@
         overlayInternal =
                 createOverlayWithName(
                         mOverlayName,
+                        SIGNATURE_OVERLAYABLE,
                         mContext.getPackageName(),
                         List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
         mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
@@ -408,4 +467,177 @@
 
         assertThrows(SecurityException.class, () -> new OverlayManagerImpl(fakeContext));
     }
+
+    FabricatedOverlayInternal prepareFabricatedOverlayInternal(
+            String targetOverlayableName, String targetEntryName) {
+        return createOverlayWithName(
+                mOverlayName,
+                targetOverlayableName,
+                mContext.getPackageName(),
+                List.of(
+                        Pair.create(
+                                targetEntryName,
+                                Pair.create(null, Color.WHITE))));
+    }
+
+    @Test
+    public void registerOverlayOnSystemOverlayable_selfIsNotSystemApp_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                SYSTEM_APP_OVERLAYABLE,
+                "color/system_app_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnOdmOverlayable_selfIsNotOdm_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                ODM_OVERLAYABLE,
+                "color/odm_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnOemOverlayable_selfIsNotOem_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                OEM_OVERLAYABLE,
+                "color/oem_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnVendorOverlayable_selfIsNotVendor_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                VENDOR_OVERLAYABLE,
+                "color/vendor_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnProductOverlayable_selfIsNotProduct_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                PRODUCT_OVERLAYABLE,
+                "color/product_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnActorOverlayable_notSupport_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                ACTOR_OVERLAYABLE,
+                "color/actor_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnConfigOverlayable_notSupport_shouldFail() {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                CONFIG_OVERLAYABLE,
+                "color/config_overlayable_color");
+
+        assertThrows(
+                IOException.class,
+                () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal));
+    }
+
+    @Test
+    public void registerOverlayOnPublicOverlayable_shouldAlwaysSucceed()
+            throws PackageManager.NameNotFoundException, IOException {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                PUBLIC_OVERLAYABLE,
+                "color/public_overlayable_color");
+
+        mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+        assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+                .isEqualTo(1);
+    }
+
+    @Test
+    public void registerOverlayOnSystemOverlayable_selfIsSystemApp_shouldSucceed()
+            throws PackageManager.NameNotFoundException, IOException {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                SYSTEM_APP_OVERLAYABLE,
+                "color/system_app_overlayable_color");
+        when(mMockApplicationInfo.isSystemApp()).thenReturn(true);
+        when(mMockApplicationInfo.isSystemExt()).thenReturn(true);
+
+        mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+        assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+                .isEqualTo(1);
+    }
+
+    @Test
+    public void registerOverlayOnOdmOverlayable_selfIsOdm_shouldSucceed()
+            throws PackageManager.NameNotFoundException, IOException {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                ODM_OVERLAYABLE,
+                "color/odm_overlayable_color");
+        when(mMockApplicationInfo.isOdm()).thenReturn(true);
+
+        mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+        assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+                .isEqualTo(1);
+    }
+
+    @Test
+    public void registerOverlayOnOemOverlayable_selfIsOem_shouldSucceed()
+            throws PackageManager.NameNotFoundException, IOException {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                OEM_OVERLAYABLE,
+                "color/oem_overlayable_color");
+        when(mMockApplicationInfo.isOem()).thenReturn(true);
+
+        mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+        assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+                .isEqualTo(1);
+    }
+
+    @Test
+    public void registerOverlayOnVendorOverlayable_selfIsVendor_shouldSucceed()
+            throws PackageManager.NameNotFoundException, IOException {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                VENDOR_OVERLAYABLE,
+                "color/vendor_overlayable_color");
+        when(mMockApplicationInfo.isVendor()).thenReturn(true);
+
+        mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+        assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+                .isEqualTo(1);
+    }
+
+    @Test
+    public void registerOverlayOnProductOverlayable_selfIsProduct_shouldSucceed()
+            throws PackageManager.NameNotFoundException, IOException {
+        final FabricatedOverlayInternal overlayInternal = prepareFabricatedOverlayInternal(
+                PRODUCT_OVERLAYABLE,
+                "color/product_overlayable_color");
+        when(mMockApplicationInfo.isProduct()).thenReturn(true);
+
+        mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal);
+
+        assertThat(mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName()).size())
+                .isEqualTo(1);
+    }
 }