Merge "Enforce the overlayable mechanism for self-targeting"
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);
+ }
}