Merge "Add component-override to sysconfig"
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 697825d..ea0389f 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -168,6 +168,10 @@
     // These are the permitted backup transport service components
     final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
 
+    // These are packages mapped to maps of component class name to default enabled state.
+    final ArrayMap<String, ArrayMap<String, Boolean>> mPackageComponentEnabledState =
+            new ArrayMap<>();
+
     // Package names that are exempted from private API blacklisting
     final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
 
@@ -301,6 +305,10 @@
         return mBackupTransportWhitelist;
     }
 
+    public ArrayMap<String, Boolean> getComponentsEnabledStates(String packageName) {
+        return mPackageComponentEnabledState.get(packageName);
+    }
+
     public ArraySet<String> getDisabledUntilUsedPreinstalledCarrierApps() {
         return mDisabledUntilUsedPreinstalledCarrierApps;
     }
@@ -846,6 +854,14 @@
                         }
                         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 @@
         }
     }
 
+    private void readComponentOverrides(XmlPullParser parser, File permFile)
+            throws IOException, XmlPullParserException {
+        String pkgname = parser.getAttributeValue(null, "package");
+        if (pkgname == null) {
+            Slog.w(TAG, "<component-override> 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, "<component> without class in "
+                            + permFile + " at " + parser.getPositionDescription());
+                    return;
+                } else if (enabled == null) {
+                    Slog.w(TAG, "<component> without enabled in "
+                            + permFile + " at " + parser.getPositionDescription());
+                    return;
+                }
+
+                if (clsname.startsWith(".")) {
+                    clsname = pkgname + clsname;
+                }
+
+                clsname = clsname.intern();
+
+                ArrayMap<String, Boolean> 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 ca577ee..10aeb7e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10685,6 +10685,50 @@
         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<String, Boolean> 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.
@@ -10852,6 +10896,10 @@
             pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM);
         }
 
+        if (pkg.isSystem()) {
+            configurePackageComponents(pkg);
+        }
+
         final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting);
 
         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {