diff options
10 files changed, 269 insertions, 168 deletions
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index f82c8f1af713..44acbcaf8ace 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -61,7 +61,8 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package, const ResourceId& target_resource) { static constexpr const PolicyBitmask sDefaultPolicies = PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION | - PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE; + PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE | + PolicyFlags::ACTOR_SIGNATURE; // If the resource does not have an overlayable definition, allow the resource to be overlaid if // the overlay is preinstalled or signed with the same signature as the target. diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index de039f440e33..5754eaf078a9 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -287,66 +287,26 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTarget R::overlay::string::str4, false /* rewrite */)); } -// Overlays that are neither pre-installed nor signed with the same signature as the target cannot -// overlay packages that have not defined overlayable resources. -TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) { - auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk", - "/overlay/overlay-no-name.apk", PolicyFlags::PUBLIC, - /* enforce_overlayable */ true); - - ASSERT_TRUE(resources) << resources.GetErrorMessage(); - ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U); -} -// Overlays that are pre-installed or are signed with the same signature as the target can overlay -// packages that have not defined overlayable resources. +// Overlays that are pre-installed or are signed with the same signature as the target/actor can +// overlay packages that have not defined overlayable resources. TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { - auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void { + constexpr PolicyBitmask kDefaultPolicies = + PolicyFlags::SIGNATURE | PolicyFlags::ACTOR_SIGNATURE | PolicyFlags::PRODUCT_PARTITION | + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION | PolicyFlags::ODM_PARTITION | + PolicyFlags::OEM_PARTITION; + + for (PolicyBitmask policy = 1U << (sizeof(PolicyBitmask) * 8 - 1); policy > 0; + policy = policy >> 1U) { auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk", "/system-overlay-invalid/system-overlay-invalid.apk", - fulfilled_policies, - /* enforce_overlayable */ true); - + policy, /* enforce_overlayable */ true); ASSERT_TRUE(resources) << resources.GetErrorMessage(); - auto& res = *resources; - ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U); - ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::not_overlayable, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::other, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_actor, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_odm, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_oem, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_product, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_public, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_signature, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system, - false /* rewrite */)); - ASSERT_RESULT(MappingExists( - res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */)); - }; - - CheckEntries(PolicyFlags::SIGNATURE); - CheckEntries(PolicyFlags::PRODUCT_PARTITION); - CheckEntries(PolicyFlags::SYSTEM_PARTITION); - CheckEntries(PolicyFlags::VENDOR_PARTITION); - CheckEntries(PolicyFlags::ODM_PARTITION); - CheckEntries(PolicyFlags::OEM_PARTITION); + + const size_t expected_overlaid = (policy & kDefaultPolicies) != 0 ? 10U : 0U; + ASSERT_EQ(expected_overlaid, resources->GetTargetToOverlayMap().size()) + << "Incorrect number of resources overlaid through policy " << policy; + } } } // namespace android::idmap2 diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 735d66983520..59735ebb24d2 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -29,18 +29,15 @@ import android.os.OverlayablePolicy; import android.os.SystemProperties; import android.util.Slog; -import com.android.internal.util.ArrayUtils; - import java.io.IOException; /** * Handle the creation and deletion of idmap files. * - * The actual work is performed by the idmap binary, launched through idmap2d. - * - * Note: this class is subclassed in the OMS unit tests, and hence not marked as final. + * The actual work is performed by idmap2d. + * @see IdmapDaemon */ -class IdmapManager { +final class IdmapManager { private static final boolean VENDOR_IS_Q_OR_LATER; static { final String value = SystemProperties.get("ro.vndk.version", "29"); @@ -57,14 +54,10 @@ class IdmapManager { private final IdmapDaemon mIdmapDaemon; private final OverlayableInfoCallback mOverlayableCallback; - private final String mOverlayableConfigurator; - private final String[] mOverlayableConfiguratorTargets; IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) { mOverlayableCallback = verifyCallback; mIdmapDaemon = idmapDaemon; - mOverlayableConfigurator = verifyCallback.getOverlayableConfigurator(); - mOverlayableConfiguratorTargets = verifyCallback.getOverlayableConfiguratorTargets() ; } /** @@ -72,7 +65,7 @@ class IdmapManager { * modified. */ boolean createIdmap(@NonNull final PackageInfo targetPackage, - @NonNull final PackageInfo overlayPackage, int userId) { + @NonNull final PackageInfo overlayPackage, int additionalPolicies, int userId) { if (DEBUG) { Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and " + overlayPackage.packageName); @@ -80,13 +73,14 @@ class IdmapManager { final String targetPath = targetPackage.applicationInfo.getBaseCodePath(); final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath(); try { - int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId); boolean enforce = enforceOverlayable(overlayPackage); + int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId) + | additionalPolicies; if (mIdmapDaemon.verifyIdmap(targetPath, overlayPath, policies, enforce, userId)) { return false; } - return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies, - enforce, userId) != null; + return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies, enforce, userId) + != null; } catch (Exception e) { Slog.w(TAG, "failed to generate idmap for " + targetPath + " and " + overlayPath + ": " + e.getMessage()); @@ -190,14 +184,6 @@ class IdmapManager { String targetOverlayableName = overlayPackage.targetOverlayableName; if (targetOverlayableName != null) { try { - if (!mOverlayableConfigurator.isEmpty() - && ArrayUtils.contains(mOverlayableConfiguratorTargets, - targetPackage.packageName) - && mOverlayableCallback.signaturesMatching(mOverlayableConfigurator, - overlayPackage.packageName, userId)) { - return true; - } - OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget( targetPackage.packageName, targetOverlayableName, userId); if (overlayableInfo != null && overlayableInfo.actor != null) { diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 086ab8183254..3c5e47625fa2 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -252,7 +252,8 @@ public final class OverlayManagerService extends SystemService { mSettings = new OverlayManagerSettings(); mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(), - new OverlayChangeListener()); + new OverlayChangeListener(), getOverlayableConfigurator(), + getOverlayableConfiguratorTargets()); mActorEnforcer = new OverlayActorEnforcer(mPackageManager); final IntentFilter packageFilter = new IntentFilter(); @@ -335,6 +336,28 @@ public final class OverlayManagerService extends SystemService { return defaultPackages.toArray(new String[defaultPackages.size()]); } + + /** + * Retrieves the package name that is recognized as an actor for the packages specified by + * {@link #getOverlayableConfiguratorTargets()}. + */ + @Nullable + private String getOverlayableConfigurator() { + return TextUtils.nullIfEmpty(Resources.getSystem() + .getString(R.string.config_overlayableConfigurator)); + } + + /** + * Retrieves the target packages that recognize the {@link #getOverlayableConfigurator} as an + * actor for itself. Overlays targeting one of the specified targets that are signed with the + * same signature as the overlayable configurator will be granted the "actor" policy. + */ + @Nullable + private String[] getOverlayableConfiguratorTargets() { + return Resources.getSystem().getStringArray( + R.array.config_overlayableConfiguratorTargets); + } + private final class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { @@ -1121,17 +1144,6 @@ public final class OverlayManagerService extends SystemService { } @Override - public String getOverlayableConfigurator() { - return Resources.getSystem().getString(R.string.config_overlayableConfigurator); - } - - @Override - public String[] getOverlayableConfiguratorTargets() { - return Resources.getSystem().getStringArray( - R.array.config_overlayableConfiguratorTargets); - } - - @Override public List<PackageInfo> getOverlayPackages(final int userId) { final List<PackageInfo> overlays = mPackageManagerInternal.getOverlayPackages(userId); for (final PackageInfo info : overlays) { diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 05a4a38feef1..879ad4fdf011 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -31,6 +31,7 @@ import android.annotation.Nullable; import android.content.om.OverlayInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.os.OverlayablePolicy; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -73,6 +74,9 @@ final class OverlayManagerServiceImpl { private final String[] mDefaultOverlays; private final OverlayChangeListener mListener; + private final String mOverlayableConfigurator; + private final String[] mOverlayableConfiguratorTargets; + /** * Helper method to merge the overlay manager's (as read from overlays.xml) * and package manager's (as parsed from AndroidManifest.xml files) views @@ -115,13 +119,17 @@ final class OverlayManagerServiceImpl { @NonNull final OverlayManagerSettings settings, @NonNull final OverlayConfig overlayConfig, @NonNull final String[] defaultOverlays, - @NonNull final OverlayChangeListener listener) { + @NonNull final OverlayChangeListener listener, + @Nullable final String overlayableConfigurator, + @Nullable final String[] overlayableConfiguratorTargets) { mPackageManager = packageManager; mIdmapManager = idmapManager; mSettings = settings; mOverlayConfig = overlayConfig; mDefaultOverlays = defaultOverlays; mListener = listener; + mOverlayableConfigurator = overlayableConfigurator; + mOverlayableConfiguratorTargets = overlayableConfiguratorTargets; } /** @@ -706,7 +714,25 @@ final class OverlayManagerServiceImpl { if (targetPackage != null && overlayPackage != null && !("android".equals(targetPackageName) && !isPackageConfiguredMutable(overlayPackageName))) { - modified |= mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); + + int additionalPolicies = 0; + if (TextUtils.nullIfEmpty(mOverlayableConfigurator) != null + && ArrayUtils.contains(mOverlayableConfiguratorTargets, targetPackageName) + && isPackageConfiguredMutable(overlayPackageName) + && mPackageManager.signaturesMatching(mOverlayableConfigurator, + overlayPackageName, userId)) { + // The overlay targets a package that has the overlayable configurator configured as + // its actor. The overlay and this actor are signed with the same signature, so + // the overlay fulfills the actor policy. + modified |= mSettings.setHasConfiguratorActorPolicy(overlayPackageName, userId, + true); + additionalPolicies |= OverlayablePolicy.ACTOR_SIGNATURE; + } else if (mSettings.hasConfiguratorActorPolicy(overlayPackageName, userId)) { + additionalPolicies |= OverlayablePolicy.ACTOR_SIGNATURE; + } + + modified |= mIdmapManager.createIdmap(targetPackage, overlayPackage, additionalPolicies, + userId); } if (overlayPackage != null) { diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index bdbaf78439a8..f8226faf1336 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -73,7 +73,7 @@ final class OverlayManagerSettings { remove(packageName, userId); insert(new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName, baseCodePath, OverlayInfo.STATE_UNKNOWN, isEnabled, isMutable, priority, - overlayCategory)); + overlayCategory, false /* hasConfiguratorActorPolicy */)); } /** @@ -160,6 +160,26 @@ final class OverlayManagerSettings { return mItems.get(idx).setState(state); } + boolean hasConfiguratorActorPolicy(@NonNull final String packageName, final int userId) { + final int idx = select(packageName, userId); + if (idx < 0) { + throw new BadKeyException(packageName, userId); + } + return mItems.get(idx).hasConfiguratorActorPolicy(); + } + + /** + * Returns true if the settings were modified, false if they remain the same. + */ + boolean setHasConfiguratorActorPolicy(@NonNull final String packageName, final int userId, + boolean hasPolicy) { + final int idx = select(packageName, userId); + if (idx < 0) { + throw new BadKeyException(packageName, userId); + } + return mItems.get(idx).setHasConfiguratorActorPolicy(hasPolicy); + } + List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName, final int userId) { // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be @@ -323,16 +343,17 @@ final class OverlayManagerSettings { pw.println(item.mPackageName + ":" + item.getUserId() + " {"); pw.increaseIndent(); - pw.println("mPackageName...........: " + item.mPackageName); - pw.println("mUserId................: " + item.getUserId()); - pw.println("mTargetPackageName.....: " + item.getTargetPackageName()); - pw.println("mTargetOverlayableName.: " + item.getTargetOverlayableName()); - pw.println("mBaseCodePath..........: " + item.getBaseCodePath()); - pw.println("mState.................: " + OverlayInfo.stateToString(item.getState())); - pw.println("mIsEnabled.............: " + item.isEnabled()); - pw.println("mIsMutable.............: " + item.isMutable()); - pw.println("mPriority..............: " + item.mPriority); - pw.println("mCategory..............: " + item.mCategory); + pw.println("mPackageName................: " + item.mPackageName); + pw.println("mUserId.....................: " + item.getUserId()); + pw.println("mTargetPackageName..........: " + item.getTargetPackageName()); + pw.println("mTargetOverlayableName......: " + item.getTargetOverlayableName()); + pw.println("mBaseCodePath...............: " + item.getBaseCodePath()); + pw.println("mState......................: " + OverlayInfo.stateToString(item.getState())); + pw.println("mIsEnabled..................: " + item.isEnabled()); + pw.println("mIsMutable..................: " + item.isMutable()); + pw.println("mPriority...................: " + item.mPriority); + pw.println("mCategory...................: " + item.mCategory); + pw.println("mHasConfiguratorActorPolicy.: " + item.hasConfiguratorActorPolicy()); pw.decreaseIndent(); pw.println("}"); @@ -371,6 +392,9 @@ final class OverlayManagerSettings { case "category": pw.println(item.mCategory); break; + case "hasconfiguratoractorpolicy": + pw.println(item.mHasConfiguratorActorPolicy); + break; } } @@ -398,9 +422,11 @@ final class OverlayManagerSettings { private static final String ATTR_CATEGORY = "category"; private static final String ATTR_USER_ID = "userId"; private static final String ATTR_VERSION = "version"; + private static final String ATTR_HAS_CONFIGURATOR_ACTOR_POLICY = + "hasConfiguratorActorPolicy"; @VisibleForTesting - static final int CURRENT_VERSION = 3; + static final int CURRENT_VERSION = 4; public static void restore(@NonNull final ArrayList<SettingsItem> table, @NonNull final InputStream is) throws IOException, XmlPullParserException { @@ -454,9 +480,12 @@ final class OverlayManagerSettings { final boolean isStatic = XmlUtils.readBooleanAttribute(parser, ATTR_IS_STATIC); final int priority = XmlUtils.readIntAttribute(parser, ATTR_PRIORITY); final String category = XmlUtils.readStringAttribute(parser, ATTR_CATEGORY); + final boolean hasConfiguratorActorPolicy = XmlUtils.readBooleanAttribute(parser, + ATTR_HAS_CONFIGURATOR_ACTOR_POLICY); return new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName, - baseCodePath, state, isEnabled, !isStatic, priority, category); + baseCodePath, state, isEnabled, !isStatic, priority, category, + hasConfiguratorActorPolicy); } public static void persist(@NonNull final ArrayList<SettingsItem> table, @@ -491,6 +520,8 @@ final class OverlayManagerSettings { XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, !item.mIsMutable); XmlUtils.writeIntAttribute(xml, ATTR_PRIORITY, item.mPriority); XmlUtils.writeStringAttribute(xml, ATTR_CATEGORY, item.mCategory); + XmlUtils.writeBooleanAttribute(xml, ATTR_HAS_CONFIGURATOR_ACTOR_POLICY, + item.mHasConfiguratorActorPolicy); xml.endTag(null, TAG_ITEM); } } @@ -507,12 +538,14 @@ final class OverlayManagerSettings { private boolean mIsMutable; private int mPriority; private String mCategory; + private boolean mHasConfiguratorActorPolicy; SettingsItem(@NonNull final String packageName, final int userId, @NonNull final String targetPackageName, @Nullable final String targetOverlayableName, @NonNull final String baseCodePath, final @OverlayInfo.State int state, final boolean isEnabled, - final boolean isMutable, final int priority, @Nullable String category) { + final boolean isMutable, final int priority, @Nullable String category, + final boolean hasConfiguratorActorPolicy) { mPackageName = packageName; mUserId = userId; mTargetPackageName = targetPackageName; @@ -524,6 +557,7 @@ final class OverlayManagerSettings { mCache = null; mIsMutable = isMutable; mPriority = priority; + mHasConfiguratorActorPolicy = hasConfiguratorActorPolicy; } private String getTargetPackageName() { @@ -614,6 +648,18 @@ final class OverlayManagerSettings { private int getPriority() { return mPriority; } + + private boolean hasConfiguratorActorPolicy() { + return mHasConfiguratorActorPolicy; + } + + private boolean setHasConfiguratorActorPolicy(boolean hasPolicy) { + if (mHasConfiguratorActorPolicy != hasPolicy) { + mHasConfiguratorActorPolicy = hasPolicy; + return true; + } + return false; + } } private int select(@NonNull final String packageName, final int userId) { diff --git a/services/core/java/com/android/server/om/OverlayableInfoCallback.java b/services/core/java/com/android/server/om/OverlayableInfoCallback.java index 41c341adf1bc..5066ecdd6316 100644 --- a/services/core/java/com/android/server/om/OverlayableInfoCallback.java +++ b/services/core/java/com/android/server/om/OverlayableInfoCallback.java @@ -80,24 +80,4 @@ public interface OverlayableInfoCallback { * in the system returns {@link PackageManager#SIGNATURE_MATCH} */ boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId); - - /** - * Retrieves the package name that is recognized as an actor for the packages specified by - * {@link #getOverlayableConfiguratorTargets()}. - */ - @NonNull - default String getOverlayableConfigurator() { - return ""; - } - - /** - * Retrieves the target packages that recognize the {@link #getOverlayableConfigurator} as an - * actor for its overlayable declarations. Overlays targeting one of the specified targets that - * are signed with the same signature as the overlayable configurator will be granted the - * "actor" policy. - */ - @NonNull - default String[] getOverlayableConfiguratorTargets() { - return new String[0]; - } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java index b25af0543829..8774ab020202 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -208,45 +208,134 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes @Test public void testConfigurator() { - final DummyPackageManagerHelper packageManager = getPackageManager(); - packageManager.overlayableConfigurator = "actor"; - packageManager.overlayableConfiguratorTargets = new String[]{TARGET}; + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; reinitializeImpl(); installNewPackage(target("actor").setCertificate("one"), USER); - installNewPackage(target(TARGET) - .addOverlayable("TestResources") - .setCertificate("two"), USER); + installNewPackage(target(TARGET).addOverlayable("TestResources").setCertificate("two"), + USER); - final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") .setCertificate("one"); installNewPackage(overlay, USER); - final DummyIdmapDaemon idmapDaemon = getIdmapDaemon(); - final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath); + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); assertNotNull(idmap); assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); } @Test + public void testConfiguratorWithoutOverlayable() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).setCertificate("two"), USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET).setCertificate("one"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, + idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorDifferentTargets() { + // The target package is not listed in the configurator target list, so the actor policy + // should not be granted. + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{"somethingElse"}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).setCertificate("two"), USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET).setCertificate("one"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test public void testConfiguratorDifferentSignatures() { - final DummyPackageManagerHelper packageManager = getPackageManager(); - packageManager.overlayableConfigurator = "actor"; - packageManager.overlayableConfiguratorTargets = new String[]{TARGET}; + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; reinitializeImpl(); installNewPackage(target("actor").setCertificate("one"), USER); - installNewPackage(target(TARGET) - .addOverlayable("TestResources") - .setCertificate("two"), USER); + installNewPackage(target(TARGET).addOverlayable("TestResources").setCertificate("two"), + USER); - final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") .setCertificate("two"); installNewPackage(overlay, USER); - final DummyIdmapDaemon idmapDaemon = getIdmapDaemon(); - final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath); + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorWithoutOverlayableDifferentSignatures() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).setCertificate("two"), USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET).setCertificate("two"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorChanges() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).addOverlayable("TestResources").setCertificate("two"), + USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") + .setCertificate("one"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, + idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + + // Change the configurator to a different package. The overlay should still be granted the + // actor policy. + mOverlayableConfigurator = "differentActor"; + OverlayManagerServiceImpl impl = reinitializeImpl(); + impl.updateOverlaysForUser(USER); + + idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, + idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + + // Reset the setting persisting that the overlay once fulfilled the actor policy implicitly + // through the configurator. The overlay should lose the actor policy. + impl = reinitializeImpl(); + getSettings().setHasConfiguratorActorPolicy(OVERLAY, USER, false); + impl.updateOverlaysForUser(USER); + + idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); assertNotNull(idmap); assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index ec6a48182a25..52a58907ea5a 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -42,7 +42,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */ @@ -53,6 +52,9 @@ class OverlayManagerServiceImplTestsBase { private DummyPackageManagerHelper mPackageManager; private DummyIdmapDaemon mIdmapDaemon; private OverlayConfig mOverlayConfig; + private OverlayManagerSettings mSettings; + String mOverlayableConfigurator; + String[] mOverlayableConfiguratorTargets; @Before public void setUp() { @@ -60,20 +62,26 @@ class OverlayManagerServiceImplTestsBase { mListener = new DummyListener(); mPackageManager = new DummyPackageManagerHelper(mState); mIdmapDaemon = new DummyIdmapDaemon(mState); + mSettings = new OverlayManagerSettings(); mOverlayConfig = mock(OverlayConfig.class); when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY); when(mOverlayConfig.isEnabled(any())).thenReturn(false); when(mOverlayConfig.isMutable(any())).thenReturn(true); + mOverlayableConfigurator = null; + mOverlayableConfiguratorTargets = null; reinitializeImpl(); } - void reinitializeImpl() { + OverlayManagerServiceImpl reinitializeImpl() { mImpl = new OverlayManagerServiceImpl(mPackageManager, new IdmapManager(mIdmapDaemon, mPackageManager), - new OverlayManagerSettings(), + mSettings, mOverlayConfig, new String[0], - mListener); + mListener, + mOverlayableConfigurator, + mOverlayableConfiguratorTargets); + return mImpl; } OverlayManagerServiceImpl getImpl() { @@ -84,14 +92,14 @@ class OverlayManagerServiceImplTestsBase { return mListener; } - DummyPackageManagerHelper getPackageManager() { - return mPackageManager; - } - DummyIdmapDaemon getIdmapDaemon() { return mIdmapDaemon; } + OverlayManagerSettings getSettings() { + return mSettings; + } + void assertState(@State int expected, final String overlayPackageName, int userId) { final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId); if (info == null) { @@ -314,8 +322,6 @@ class OverlayManagerServiceImplTestsBase { static final class DummyPackageManagerHelper implements PackageManagerHelper, OverlayableInfoCallback { private final DummyDeviceState mState; - String[] overlayableConfiguratorTargets = new String[0]; - String overlayableConfigurator = ""; private DummyPackageManagerHelper(DummyDeviceState state) { mState = state; @@ -387,16 +393,6 @@ class OverlayManagerServiceImplTestsBase { public void enforcePermission(String permission, String message) throws SecurityException { throw new UnsupportedOperationException(); } - - @Override - public String[] getOverlayableConfiguratorTargets() { - return overlayableConfiguratorTargets; - } - - @Override - public String getOverlayableConfigurator() { - return overlayableConfigurator; - } } static class DummyIdmapDaemon extends IdmapDaemon { @@ -433,7 +429,8 @@ class OverlayManagerServiceImplTestsBase { if (idmap == null) { return false; } - return idmap.isUpToDate(getCrc(targetPath), getCrc(overlayPath), targetPath); + return idmap.isUpToDate(getCrc(targetPath), getCrc(overlayPath), targetPath, policies, + enforce); } @Override @@ -462,9 +459,11 @@ class OverlayManagerServiceImplTestsBase { } private boolean isUpToDate(int expectedTargetCrc, int expectedOverlayCrc, - String expectedTargetPath) { + String expectedTargetPath, int expectedPolicies, + boolean expectedEnforceOverlayable) { return expectedTargetCrc == targetCrc && expectedOverlayCrc == overlayCrc - && expectedTargetPath.equals(targetPath); + && expectedTargetPath.equals(targetPath) && expectedPolicies == policies + && expectedEnforceOverlayable == enforceOverlayable; } } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java index 146f60aff724..e2cedb5e1a62 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java @@ -367,7 +367,8 @@ public class OverlayManagerSettingsTests { + " isEnabled='false'\n" + " category='dummy-category'\n" + " isStatic='false'\n" - + " priority='0' />\n" + + " priority='0'" + + " hasConfiguratorActorPolicy='true' />\n" + "</overlays>\n"; ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); @@ -380,6 +381,7 @@ public class OverlayManagerSettingsTests { assertEquals(1234, oi.userId); assertEquals(STATE_DISABLED, oi.state); assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234)); + assertTrue(mSettings.hasConfiguratorActorPolicy("com.dummy.overlay", 1234)); } @Test |