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
This commit is contained in:
felkachang
2022-09-22 20:00:34 +08:00
parent 3170042b18
commit a8fc015345
7 changed files with 425 additions and 19 deletions

View File

@@ -38,9 +38,10 @@ namespace android::self_targeting {
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 @@ CreateFrroFile(std::string& out_err_result, std::string& packageName, std::strin
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 @@ CreateIdmapFile(std::string& out_err, const std::string& targetPath, const std::
}
// 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());

View File

@@ -170,6 +170,16 @@ public class OverlayManagerImpl {
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 @@ public class OverlayManagerImpl {
/**
* 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 @@ public class OverlayManagerImpl {
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 @@ public class OverlayManagerImpl {
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 @@ public class OverlayManagerImpl {
@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(

View File

@@ -123,8 +123,12 @@ public:
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 @@ private:
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 CreateFrroFile(JNIEnv* env, jclass /*clazz*/, jstring jsFrroFilePath
}
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 @@ static void CreateIdmapFile(JNIEnv* env, jclass /* clazz */, jstring jsTargetPat
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 @@ static const JNINativeMethod gOverlayManagerMethods[] = {
{"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)},

View File

@@ -29,6 +29,7 @@ android_test {
"androidx.test.rules",
"androidx.test.runner",
"androidx.test.ext.junit",
"mockito-target-minus-junit4",
"truth-prebuilt",
],

View File

@@ -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>

View File

@@ -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>

View File

@@ -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 @@ public class OverlayManagerImplTest {
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 class OverlayManagerImplTest {
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 @@ public class OverlayManagerImplTest {
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 @@ public class OverlayManagerImplTest {
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
SYSTEM_APP_OVERLAYABLE,
"android",
List.of(Pair.create("color/white", Pair.create(null, Color.BLACK))));
@@ -190,6 +241,7 @@ public class OverlayManagerImplTest {
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_COLOR_RES, Pair.create(null, Color.WHITE))));
@@ -215,6 +267,7 @@ public class OverlayManagerImplTest {
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_STRING_RES, Pair.create(null, "HELLO"))));
@@ -242,6 +295,7 @@ public class OverlayManagerImplTest {
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create(TARGET_DRAWABLE_RES,
Pair.create(null, parcelFileDescriptor))));
@@ -268,6 +322,7 @@ public class OverlayManagerImplTest {
FabricatedOverlayInternal overlayInternal =
createOverlayWithName(
mOverlayName,
SIGNATURE_OVERLAYABLE,
mContext.getPackageName(),
List.of(Pair.create("color/not_existed", Pair.create(null, "HELLO"))));
@@ -301,6 +356,7 @@ public class OverlayManagerImplTest {
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 @@ public class OverlayManagerImplTest {
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 @@ public class OverlayManagerImplTest {
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 @@ public class OverlayManagerImplTest {
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 @@ public class OverlayManagerImplTest {
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);
}
}