Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1414931 authored by Adam Bookatz's avatar Adam Bookatz
Browse files

UserSystemPackageInstaller only (un)installs when appropriate

The UserSystemPackageInstaller (USPI) uninstalls system
packages that are not needed, depending on the user type.
When that determination changes (or the feature is disabled)
it can also re-install those packages.
This cl specifies when it is appropriate for USPI to actually
perform the (un)installation.

1.
Introduces uninstallReason: records the reason why a package
was uninstalled from a given user. Right now, the only values
are UNKNOWN and USER_TYPE. The latter indicates that the USPI
system uninstalled the package. If the USPI whitelist changes
(or the USPI feature is disabled), uninstalled packages will
only be installed by USPI if the uninstallReason was USER_TYPE.
Any further uninstalls (e.g. by ManagedProvisioning) will reset
the uninstallReason to UNKNOWN, so USPI will no longer install
such packages in the future.
This prevents USPI from reinstalling system packages that other
mechanisms (such as ManagedProvisioning) uninstalled.

2.
USPI will uninstall a system package if it is blacklisted, but
only if that system package is new, i.e in two circumstances:
a. on first boot
b. on an OTA where the package was not present prior to the OTA

Bug: 143200798
Test: atest UserSystemPackageInstallerTest
Test: Confirmed (un)installations during manually simulated OTAs
Change-Id: Ia0714d1faa8f7c79082f2cc93a92ae36b9a4c918
parent 285e4fe0
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1031,6 +1031,27 @@ public abstract class PackageManager {
     */
    public static final int INSTALL_REASON_ROLLBACK = 5;

    /** @hide */
    @IntDef(prefix = { "UNINSTALL_REASON_" }, value = {
            UNINSTALL_REASON_UNKNOWN,
            UNINSTALL_REASON_USER_TYPE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface UninstallReason {}

    /**
     * Code indicating that the reason for uninstalling this package is unknown.
     * @hide
     */
    public static final int UNINSTALL_REASON_UNKNOWN = 0;

    /**
     * Code indicating that this package was uninstalled due to the type of user.
     * See UserSystemPackageInstaller
     * @hide
     */
    public static final int UNINSTALL_REASON_USER_TYPE = 1;

    /**
     * @hide
     */
+7 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ public class PackageUserState {
    public int appLinkGeneration;
    public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
    public int installReason;
    public @PackageManager.UninstallReason int uninstallReason;
    public String harmfulAppWarning;

    public ArraySet<String> disabledComponents;
@@ -92,6 +93,7 @@ public class PackageUserState {
        domainVerificationStatus =
                PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
        installReason = PackageManager.INSTALL_REASON_UNKNOWN;
        uninstallReason = PackageManager.UNINSTALL_REASON_UNKNOWN;
    }

    @VisibleForTesting
@@ -112,6 +114,7 @@ public class PackageUserState {
        appLinkGeneration = o.appLinkGeneration;
        categoryHint = o.categoryHint;
        installReason = o.installReason;
        uninstallReason = o.uninstallReason;
        disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
        enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
        overlayPaths =
@@ -353,6 +356,9 @@ public class PackageUserState {
        if (installReason != oldState.installReason) {
            return false;
        }
        if (uninstallReason != oldState.uninstallReason) {
            return false;
        }
        if ((disabledComponents == null && oldState.disabledComponents != null)
                || (disabledComponents != null && oldState.disabledComponents == null)) {
            return false;
@@ -407,6 +413,7 @@ public class PackageUserState {
        hashCode = 31 * hashCode + appLinkGeneration;
        hashCode = 31 * hashCode + categoryHint;
        hashCode = 31 * hashCode + installReason;
        hashCode = 31 * hashCode + uninstallReason;
        hashCode = 31 * hashCode + Objects.hashCode(disabledComponents);
        hashCode = 31 * hashCode + Objects.hashCode(enabledComponents);
        hashCode = 31 * hashCode + Objects.hashCode(harmfulAppWarning);
+1 −2
Original line number Diff line number Diff line
@@ -2406,8 +2406,7 @@
          - to henceforth disable feature and try to undo its previous effects: 0
        Note: This list must be kept current with PACKAGE_WHITELIST_MODE_PROP in
        frameworks/base/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java -->
    <integer name="config_userTypePackageWhitelistMode">29</integer> <!-- 1+4+8+16 -->
    <!-- TODO(b/143200798): Change to value 13, i.e. 1+4+8, when b/143200798 is resolved. -->
    <integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->

    <!-- Whether UI for multi user should be shown -->
    <bool name="config_enableMultiUserUI">false</bool>
+2 −2
Original line number Diff line number Diff line
@@ -97,8 +97,8 @@ The way that a device treats system packages that do not have any entry (for any
is determined by the config resource value config_userTypePackageWhitelistMode.
See frameworks/base/core/res/res/values/config.xml#config_userTypePackageWhitelistMode.

Changes to the whitelist during system updates can result in installing new system packages
to pre-existing users, but cannot uninstall system packages from pre-existing users.
Changes to the whitelist during system updates can result in installing additional system packages
to pre-existing users, but cannot uninstall pre-existing system packages from pre-existing users.
-->
<config>
    <install-in-user-type package="com.android.providers.settings">
+0 −17
Original line number Diff line number Diff line
@@ -428,17 +428,6 @@ public abstract class PackageManagerInternal {
     */
    public abstract String getNameForUid(int uid);

    /**
     * Marks a package as installed (or not installed) for a given user.
     *
     * @param pkg the package whose installation is to be set
     * @param userId the user for whom to set it
     * @param installed the new installed state
     * @return true if the installed state changed as a result
     */
    public abstract boolean setInstalled(AndroidPackage pkg,
            @UserIdInt int userId, boolean installed);

    /**
     * Request to perform the second phase of ephemeral resolution.
     * @param responseObj The response of the first phase of ephemeral resolution
@@ -523,12 +512,6 @@ public abstract class PackageManagerInternal {
     */
    public abstract boolean isPackagePersistent(String packageName);

    /**
     * Returns whether or not the given package represents a legacy system application released
     * prior to runtime permissions.
     */
    public abstract boolean isLegacySystemApp(AndroidPackage pkg);

    /**
     * Get all overlay packages for a user.
     * @param userId The user for which to get the overlays.
Loading