From 4fd8e6f6934e1707e8e2ff8f7c7101fdf3453b1b Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Mon, 7 Oct 2019 16:31:34 -0700 Subject: [PATCH] Add component-override to sysconfig The tag in sys config allows an OEM to configure the enabled state of package components. Eg. The value in the sys config file overrides the value defined within the package manifest. Bug: 135048762 Test: adb shell pm resolve-activity com.android.settings/com.android.settings.RegulatoryInfoDisplayActivity Change-Id: I71de31601bb175d4be1cc5996142ef93ca279fc1 --- .../java/com/android/server/SystemConfig.java | 64 +++++++++++++++++++ .../server/pm/PackageManagerService.java | 48 ++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 697825dcefd7b..ea0389f49a458 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -168,6 +168,10 @@ public class SystemConfig { // These are the permitted backup transport service components final ArraySet mBackupTransportWhitelist = new ArraySet<>(); + // These are packages mapped to maps of component class name to default enabled state. + final ArrayMap> mPackageComponentEnabledState = + new ArrayMap<>(); + // Package names that are exempted from private API blacklisting final ArraySet mHiddenApiPackageWhitelist = new ArraySet<>(); @@ -301,6 +305,10 @@ public class SystemConfig { return mBackupTransportWhitelist; } + public ArrayMap getComponentsEnabledStates(String packageName) { + return mPackageComponentEnabledState.get(packageName); + } + public ArraySet getDisabledUntilUsedPreinstalledCarrierApps() { return mDisabledUntilUsedPreinstalledCarrierApps; } @@ -846,6 +854,14 @@ public class SystemConfig { } XmlUtils.skipCurrentTag(parser); } break; + case "component-override": { + if (allowAppConfigs) { + readComponentOverrides(parser, permFile); + } else { + logNotAllowedInPartition(name, permFile, parser); + } + XmlUtils.skipCurrentTag(parser); + } break; case "backup-transport-whitelisted-service": { if (allowFeatures) { String serviceName = parser.getAttributeValue(null, "service"); @@ -1269,6 +1285,54 @@ public class SystemConfig { } } + private void readComponentOverrides(XmlPullParser parser, File permFile) + throws IOException, XmlPullParserException { + String pkgname = parser.getAttributeValue(null, "package"); + if (pkgname == null) { + Slog.w(TAG, " without package in " + + permFile + " at " + parser.getPositionDescription()); + return; + } + + pkgname = pkgname.intern(); + + final int depth = parser.getDepth(); + while (XmlUtils.nextElementWithin(parser, depth)) { + String name = parser.getName(); + if ("component".equals(name)) { + String clsname = parser.getAttributeValue(null, "class"); + String enabled = parser.getAttributeValue(null, "enabled"); + if (clsname == null) { + Slog.w(TAG, " without class in " + + permFile + " at " + parser.getPositionDescription()); + return; + } else if (enabled == null) { + Slog.w(TAG, " without enabled in " + + permFile + " at " + parser.getPositionDescription()); + return; + } + + if (clsname.startsWith(".")) { + clsname = pkgname + clsname; + } + + clsname = clsname.intern(); + + ArrayMap componentEnabledStates = + mPackageComponentEnabledState.get(pkgname); + if (componentEnabledStates == null) { + componentEnabledStates = new ArrayMap<>(); + mPackageComponentEnabledState.put(pkgname, + componentEnabledStates); + } + + componentEnabledStates.put(clsname, !"false".equals(enabled)); + } else { + XmlUtils.skipCurrentTag(parser); + } + } + } + private static boolean isSystemProcess() { return Process.myUid() == Process.SYSTEM_UID; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 5bf484b4ba1f6..4e9d5d22eb15b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -10657,6 +10657,50 @@ public class PackageManagerService extends IPackageManager.Stub return changedAbiCodePath; } + /** + * Sets the enabled state of components configured through {@link SystemConfig}. + * This modifies the {@link PackageSetting} object. + **/ + static void configurePackageComponents(PackageParser.Package pkg) { + final ArrayMap componentsEnabledStates = SystemConfig.getInstance() + .getComponentsEnabledStates(pkg.packageName); + if (componentsEnabledStates == null) { + return; + } + + for (int i = pkg.activities.size() - 1; i >= 0; i--) { + final PackageParser.Activity component = pkg.activities.get(i); + final Boolean enabled = componentsEnabledStates.get(component.className); + if (enabled != null) { + component.info.enabled = enabled; + } + } + + for (int i = pkg.receivers.size() - 1; i >= 0; i--) { + final PackageParser.Activity component = pkg.receivers.get(i); + final Boolean enabled = componentsEnabledStates.get(component.className); + if (enabled != null) { + component.info.enabled = enabled; + } + } + + for (int i = pkg.providers.size() - 1; i >= 0; i--) { + final PackageParser.Provider component = pkg.providers.get(i); + final Boolean enabled = componentsEnabledStates.get(component.className); + if (enabled != null) { + component.info.enabled = enabled; + } + } + + for (int i = pkg.services.size() - 1; i >= 0; i--) { + final PackageParser.Service component = pkg.services.get(i); + final Boolean enabled = componentsEnabledStates.get(component.className); + if (enabled != null) { + component.info.enabled = enabled; + } + } + } + /** * Just scans the package without any side effects. @@ -10824,6 +10868,10 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM); } + if (pkg.isSystem()) { + configurePackageComponents(pkg); + } + final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting); if ((scanFlags & SCAN_NEW_INSTALL) == 0) {