Prevent the disabling of specified apps

Prevent the disabling of specified apps, avoiding cases
where disabling the app may result in an unusable system.

Bug: 200043113
Change-Id: I5b0ed8c34a40428e8d18072582e46854737c000a
diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl
index 61b24aa..b7649ba 100644
--- a/core/java/android/os/ISystemConfig.aidl
+++ b/core/java/android/os/ISystemConfig.aidl
@@ -52,4 +52,9 @@
      * @see SystemConfigManager#getDefaultVrComponents
      */
     List<ComponentName> getDefaultVrComponents();
+
+    /**
+     * @see SystemConfigManager#getPreventUserDisablePackages
+     */
+    List<String> getPreventUserDisablePackages();
 }
diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java
index 77843d9..21ffbf1 100644
--- a/core/java/android/os/SystemConfigManager.java
+++ b/core/java/android/os/SystemConfigManager.java
@@ -161,4 +161,18 @@
         }
         return Collections.emptyList();
     }
+
+    /**
+     * Return the packages that are prevented from being disabled, where if
+     * disabled it would result in a non-functioning system or similar.
+     * @hide
+     */
+    @NonNull
+    public List<String> getPreventUserDisablePackages() {
+        try {
+            return mInterface.getPreventUserDisablePackages();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index bca2d60..b04c7c5 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -316,6 +316,11 @@
     private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
     private final ArraySet<String> mAppDataIsolationWhitelistedApps = new ArraySet<>();
 
+    // These packages will be set as 'prevent disable', where they are no longer possible
+    // for the end user to disable via settings. This flag should only be used for packages
+    // which meet the 'force or keep enabled apps' policy.
+    private final ArrayList<String> mPreventUserDisablePackages = new ArrayList<>();
+
     // Map of packagesNames to userTypes. Stored temporarily until cleared by UserManagerService().
     private ArrayMap<String, Set<String>> mPackageToUserTypeWhitelist = new ArrayMap<>();
     private ArrayMap<String, Set<String>> mPackageToUserTypeBlacklist = new ArrayMap<>();
@@ -501,6 +506,10 @@
         return mAppDataIsolationWhitelistedApps;
     }
 
+    public @NonNull ArrayList<String> getPreventUserDisablePackages() {
+        return mPreventUserDisablePackages;
+    }
+
     /**
      * Gets map of packagesNames to userTypes, dictating on which user types each package should be
      * initially installed, and then removes this map from SystemConfig.
@@ -1303,6 +1312,16 @@
                         }
                         XmlUtils.skipCurrentTag(parser);
                     } break;
+                    case "prevent-disable": {
+                        String pkgname = parser.getAttributeValue(null, "package");
+                        if (pkgname == null) {
+                            Slog.w(TAG, "<" + name + "> without package in " + permFile
+                                    + " at " + parser.getPositionDescription());
+                        } else {
+                            mPreventUserDisablePackages.add(pkgname);
+                        }
+                        XmlUtils.skipCurrentTag(parser);
+                    } break;
                     case "install-in-user-type": {
                         // NB: We allow any directory permission to declare install-in-user-type.
                         readInstallInUserType(parser,
diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java
index 6e82907..fd21a32 100644
--- a/services/java/com/android/server/SystemConfigService.java
+++ b/services/java/com/android/server/SystemConfigService.java
@@ -21,6 +21,8 @@
 import android.Manifest;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
 import android.os.ISystemConfig;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -108,6 +110,15 @@
                     "Caller must hold " + Manifest.permission.QUERY_ALL_PACKAGES);
             return new ArrayList<>(SystemConfig.getInstance().getDefaultVrComponents());
         }
+
+        @Override
+        public List<String> getPreventUserDisablePackages() {
+            PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+            return SystemConfig.getInstance().getPreventUserDisablePackages().stream()
+                    .filter(preventUserDisablePackage ->
+                            pmi.canQueryPackage(Binder.getCallingUid(), preventUserDisablePackage))
+                    .collect(toList());
+        }
     };
 
     public SystemConfigService(Context context) {