Merge "Enforce the overlayable mechanism for self-targeting"
This commit is contained in:
committed by
Android (Google) Code Review
commit
2e29531489
@@ -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());
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)},
|
||||
|
||||
@@ -29,6 +29,7 @@ android_test {
|
||||
"androidx.test.rules",
|
||||
"androidx.test.runner",
|
||||
"androidx.test.ext.junit",
|
||||
"mockito-target-minus-junit4",
|
||||
"truth-prebuilt",
|
||||
],
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user