diff options
| author | 2022-11-29 08:40:11 +0000 | |
|---|---|---|
| committer | 2022-11-29 08:40:11 +0000 | |
| commit | 2e295314894a759f9562f662aa3a4dd8dbf6027b (patch) | |
| tree | f3b977b8a199a74b5717440b32195b7c973e08b2 | |
| parent | 39f3eae9dc3dd71638fe0f772a7ac6382e81742b (diff) | |
| parent | a8fc0153456d0579e7ae0a58ca8bfc3ff73ddfcc (diff) | |
Merge "Enforce the overlayable mechanism for self-targeting"
7 files changed, 425 insertions, 19 deletions
diff --git a/cmds/idmap2/self_targeting/SelfTargeting.cpp b/cmds/idmap2/self_targeting/SelfTargeting.cpp index 20aa7d32a3c2..a8aa03309b16 100644 --- a/cmds/idmap2/self_targeting/SelfTargeting.cpp +++ b/cmds/idmap2/self_targeting/SelfTargeting.cpp @@ -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()); diff --git a/core/java/com/android/internal/content/om/OverlayManagerImpl.java b/core/java/com/android/internal/content/om/OverlayManagerImpl.java index 76e068d11d74..e56c06e318a8 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 @@ 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( diff --git a/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp b/core/jni/com_android_internal_content_om_OverlayManagerImpl.cpp index df55e424f2ed..bba1760bc45c 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 @@ 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)}, diff --git a/core/tests/overlaytests/device_self_targeting/Android.bp b/core/tests/overlaytests/device_self_targeting/Android.bp index 82998dbdae27..063c5694ab5b 100644 --- a/core/tests/overlaytests/device_self_targeting/Android.bp +++ b/core/tests/overlaytests/device_self_targeting/Android.bp @@ -29,6 +29,7 @@ android_test { "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 000000000000..5cc214d859d2 --- /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 f0b4a6fe8969..d82de9717717 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 ca584106a910..8a9ab5b7a902 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 @@ 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); + } } |