Merge "Install auto-generrate overlay packages even when not included in whitelist" into rvc-dev am: b6ac0061fa am: 17d5ac8048

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11529815

Change-Id: Id4913a6d9ef9039d9008c12c65d112195111667d
diff --git a/data/etc/preinstalled-packages-platform.xml b/data/etc/preinstalled-packages-platform.xml
index 17e1f2e..6255584 100644
--- a/data/etc/preinstalled-packages-platform.xml
+++ b/data/etc/preinstalled-packages-platform.xml
@@ -17,7 +17,9 @@
 <!--
 This XML file declares which system packages should be initially installed for new users based on
 their user type. All system packages on the device should ideally have an entry in an xml file
-(keyed by its manifest name).
+(keyed by its manifest name), except auto-generated rro packages. Auto-generated RRO packages 
+(package name ends with ".auto_generated_rro_product__" or ".auto_generated_rro_vendor__")
+will be installed for new users according to corresponding overlay target packages.
 
 Base user-types (every user will be at least one of these types) are:
   SYSTEM    (user 0)
@@ -51,7 +53,7 @@
 
 
 2. For a system package to be pre-installed on all human users (e.g. a web browser), i.e. to be
-installed on any user of type type FULL or PROFILE (since this covers all human users):
+installed on any user of type FULL or PROFILE (since this covers all human users):
 
    <install-in-user-type package="com.android.example">
        <install-in user-type="FULL" />
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 58732b4..7c89b98 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -96,6 +96,8 @@
 class UserSystemPackageInstaller {
     private static final String TAG = "UserManagerService";
 
+    private static final boolean DEBUG = false;
+
     /**
      * System Property whether to only install system packages on a user if they're whitelisted for
      * that user type. These are flags and can be freely combined.
@@ -328,12 +330,15 @@
         // Check whether all whitelisted packages are indeed on the system.
         final String notPresentFmt = "%s is whitelisted but not present.";
         final String notSystemFmt = "%s is whitelisted and present but not a system package.";
+        final String overlayPackageFmt = "%s is whitelisted but it's auto-generated RRO package.";
         for (String pkgName : allWhitelistedPackages) {
             final AndroidPackage pkg = pmInt.getPackage(pkgName);
             if (pkg == null) {
                 warnings.add(String.format(notPresentFmt, pkgName));
             } else if (!pkg.isSystem()) {
                 warnings.add(String.format(notSystemFmt, pkgName));
+            } else if (isAutoGeneratedRRO(pkg)) {
+                warnings.add(String.format(overlayPackageFmt, pkgName));
             }
         }
         return warnings;
@@ -407,6 +412,23 @@
         return isImplicitWhitelistSystemMode(getWhitelistMode());
     }
 
+    /**
+     * Whether package name has auto-generated RRO package name suffix.
+     */
+    @VisibleForTesting
+    static boolean hasAutoGeneratedRROSuffix(String name) {
+        return name.endsWith(".auto_generated_rro_product__")
+                || name.endsWith(".auto_generated_rro_vendor__");
+    }
+
+    /**
+     * Whether the package is auto-generated RRO package.
+     */
+    private static boolean isAutoGeneratedRRO(AndroidPackage pkg) {
+        return pkg.isOverlay()
+                && (hasAutoGeneratedRROSuffix(pkg.getManifestPackageName()));
+    }
+
     /** See {@link #isEnforceMode()}. */
     private static boolean isEnforceMode(int whitelistMode) {
         return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE) != 0;
@@ -518,7 +540,18 @@
     static boolean shouldInstallPackage(AndroidPackage sysPkg,
             @NonNull ArrayMap<String, Long> userTypeWhitelist,
             @NonNull Set<String> userWhitelist, boolean implicitlyWhitelist) {
-        final String pkgName = sysPkg.getManifestPackageName();
+        final String pkgName;
+        if (isAutoGeneratedRRO(sysPkg)) {
+            pkgName = sysPkg.getOverlayTarget();
+            if (DEBUG) {
+                Slog.i(TAG, "shouldInstallPackage(): " + sysPkg.getManifestPackageName()
+                        + " is auto-generated RRO package, will look for overlay system package: "
+                        + pkgName);
+            }
+        } else {
+            pkgName = sysPkg.getManifestPackageName();
+        }
+
         return (implicitlyWhitelist && !userTypeWhitelist.containsKey(pkgName))
                 || userWhitelist.contains(pkgName);
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index c55df51..87979fb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -366,9 +366,75 @@
         for (PackageInfo p : packageInfos) {
             actualPackages.add(p.packageName);
         }
+
+        // Add auto-generated RRO package to expectedPackages since they are not (supposed to be)
+        // in the whitelist but they should be installed.
+        for (PackageInfo p : packageInfos) {
+            if (p.isOverlayPackage()
+                        && UserSystemPackageInstaller.hasAutoGeneratedRROSuffix(p.packageName)
+                        && expectedPackages.contains(p.overlayTarget)) {
+                expectedPackages.add(p.packageName);
+            }
+        }
         checkPackageDifferences(expectedPackages, actualPackages);
     }
 
+    @Test
+    public void testAutoGeneratedRROMatchesSuffix() {
+        final List<PackageInfo> packageInfos = mContext.getPackageManager()
+                .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
+
+        Log.v(TAG, "Found total packages: " + packageInfos.size());
+
+        for (PackageInfo p : packageInfos) {
+            if (p.packageName.contains(".auto_generated_rro_")) {
+                assertTrue("Auto-generated RRO package name does not match the suffix: "
+                        + p.packageName,
+                        UserSystemPackageInstaller.hasAutoGeneratedRROSuffix(p.packageName));
+            }
+        }
+    }
+
+    /**
+     * Test that overlay package not in whitelist should be installed for all user at Explicit mode.
+     */
+    @Test
+    public void testInstallOverlayPackagesExplicitMode() {
+        setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE);
+
+        final String[] userTypes = new String[]{"type"};
+        final long maskOfType = 0b0001L;
+
+        final String packageName1 = "whitelistedPkg";
+        final String packageName2 = "nonWhitelistedPkg";
+        final String overlayName1 = String.format("%s.auto_generated_rro_product__", packageName1);
+        final String overlayName2 = String.format("%s.auto_generated_rro_product__", packageName2);
+
+        final AndroidPackage overlayPackage1 = ((ParsedPackage) PackageImpl.forTesting(overlayName1)
+                .setOverlay(true)
+                .setOverlayTarget(packageName1)
+                .hideAsParsed())
+                .hideAsFinal();
+
+        final AndroidPackage overlayPackage2 = ((ParsedPackage) PackageImpl.forTesting(overlayName2)
+                .setOverlay(true)
+                .setOverlayTarget(packageName2)
+                .hideAsParsed())
+                .hideAsFinal();
+
+        final ArrayMap<String, Long> userTypeWhitelist = new ArrayMap<>();
+        userTypeWhitelist.put(packageName1, maskOfType);
+
+        final Set<String> userWhitelist = new ArraySet<>();
+        userWhitelist.add(packageName1);
+
+        boolean implicit = false;
+        assertTrue("Overlay for package1 should be installed", UserSystemPackageInstaller
+                .shouldInstallPackage(overlayPackage1, userTypeWhitelist, userWhitelist, implicit));
+        assertFalse("Overlay for package2 should not be installed", UserSystemPackageInstaller
+                .shouldInstallPackage(overlayPackage2, userTypeWhitelist, userWhitelist, implicit));
+    }
+
     /** Asserts that actual is a subset of expected. */
     private void checkPackageDifferences(Set<String> expected, Set<String> actual) {
         final Set<String> uniqueToExpected = new ArraySet<>(expected);