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

Commit 09b108e2 authored by Fyodor Kupolov's avatar Fyodor Kupolov Committed by Android (Google) Code Review
Browse files

Merge "Added keep-uninstalled-packages DO policy"

parents 930240e8 cb6fd807
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -3615,6 +3615,48 @@ public class DevicePolicyManager {
        return null;
    }

    /**
     * Called by a device owner to get the list of apps to keep around as APKs even if no user has
     * currently installed it.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     *
     * @return List of package names to keep cached.
     * @hide
     */
    public List<String> getKeepUninstalledPackages(@NonNull ComponentName admin) {
        if (mService != null) {
            try {
                return mService.getKeepUninstalledPackages(admin);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
        return null;
    }

    /**
     * Called by a device owner to set a list of apps to keep around as APKs even if no user has
     * currently installed it.
     *
     * <p>Please note that setting this policy does not imply that specified apps will be
     * automatically pre-cached.</p>
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param packageNames List of package names to keep cached.
     * @hide
     */
    public void setKeepUninstalledPackages(@NonNull ComponentName admin,
            @NonNull List<String> packageNames) {
        if (mService != null) {
            try {
                mService.setKeepUninstalledPackages(admin, packageNames);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
    }

    /**
     * Called by a device owner to create a user with the specified name. The UserHandle returned
     * by this method should not be persisted as user handles are recycled as users are removed and
+2 −0
Original line number Diff line number Diff line
@@ -231,4 +231,6 @@ interface IDevicePolicyManager {
            String permission, int grantState);
    int getPermissionGrantState(in ComponentName admin, String packageName, String permission);
    boolean isProvisioningAllowed(String action);
    void setKeepUninstalledPackages(in ComponentName admin,in List<String> packageList);
    List<String> getKeepUninstalledPackages(in ComponentName admin);
}
+8 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.content.pm;

import android.annotation.NonNull;
import java.util.List;

/**
 * Package manager local system service interface.
@@ -115,4 +115,11 @@ public abstract class PackageManagerInternal {
     */
    public abstract void grantDefaultPermissionsToDefaultSimCallManager(String packageName,
            int userId);

    /**
     * Sets a list of apps to keep in PM's internal data structures and as APKs even if no user has
     * currently installed it. The apps are not preloaded.
     * @param packageList List of package names to keep cached.
     */
    public abstract void setKeepUninstalledPackages(List<String> packageList);
}
+70 −10
Original line number Diff line number Diff line
@@ -617,6 +617,9 @@ public class PackageManagerService extends IPackageManager.Stub {
    final DefaultPermissionGrantPolicy mDefaultPermissionPolicy =
            new DefaultPermissionGrantPolicy(this);
    // List of packages names to keep cached, even if they are uninstalled for all users
    private List<String> mKeepUninstalledPackages;
    private static class IFVerificationParams {
        PackageParser.Package pkg;
        boolean replacing;
@@ -13015,7 +13018,7 @@ public class PackageManagerService extends IPackageManager.Stub {
        final boolean deleteAllUsers = (flags & PackageManager.DELETE_ALL_USERS) != 0;
        final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
        if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
            mContext.enforceCallingPermission(
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                    "deletePackage for user " + userId);
        }
@@ -13090,6 +13093,10 @@ public class PackageManagerService extends IPackageManager.Stub {
        return false;
    }
    private boolean shouldKeepUninstalledPackageLPr(String packageName) {
        return mKeepUninstalledPackages != null && mKeepUninstalledPackages.contains(packageName);
    }
    /**
     *  This method is an internal method that could be get invoked either
     *  to delete an installed package or to clean up a failed installation.
@@ -13512,7 +13519,9 @@ public class PackageManagerService extends IPackageManager.Stub {
                        false, // blockUninstall
                        ps.readUserState(userId).domainVerificationStatus, 0);
                if (!isSystemApp(ps)) {
                    if (ps.isAnyInstalled(sUserManager.getUserIds())) {
                    // Do not uninstall the APK if an app should be cached
                    boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
                    if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
                        // Other user still have this package installed, so all
                        // we need to do is clear this user's data and save that
                        // it is uninstalled.
@@ -16686,7 +16695,12 @@ public class PackageManagerService extends IPackageManager.Stub {
            if (DEBUG_CLEAN_APKS) {
                Slog.i(TAG, "Checking package " + packageName);
            }
            boolean keep = false;
            boolean keep = shouldKeepUninstalledPackageLPr(packageName);
            if (keep) {
                if (DEBUG_CLEAN_APKS) {
                    Slog.i(TAG, "  Keeping package " + packageName + " - requested by DO");
                }
            } else {
                for (int i = 0; i < users.length; i++) {
                    if (users[i] != userHandle && ps.getInstalled(users[i])) {
                        keep = true;
@@ -16697,6 +16711,7 @@ public class PackageManagerService extends IPackageManager.Stub {
                        break;
                    }
                }
            }
            if (!keep) {
                if (DEBUG_CLEAN_APKS) {
                    Slog.i(TAG, "  Removing package " + packageName);
@@ -16896,6 +16911,23 @@ public class PackageManagerService extends IPackageManager.Stub {
        }
    }
    private void deletePackageIfUnusedLPr(final String packageName) {
        PackageSetting ps = mSettings.mPackages.get(packageName);
        if (ps == null) {
            return;
        }
        if (!ps.isAnyInstalled(sUserManager.getUserIds())) {
            // TODO Implement atomic delete if package is unused
            // It is currently possible that the package will be deleted even if it is installed
            // after this method returns.
            mHandler.post(new Runnable() {
                public void run() {
                    deletePackageX(packageName, 0, PackageManager.DELETE_ALL_USERS);
                }
            });
        }
    }
    /**
     * Check and throw if the given before/after packages would be considered a
     * downgrade.
@@ -17133,6 +17165,34 @@ public class PackageManagerService extends IPackageManager.Stub {
                        packageName, userId);
            }
        }
        @Override
        public void setKeepUninstalledPackages(final List<String> packageList) {
            Preconditions.checkNotNull(packageList);
            List<String> removedFromList = null;
            synchronized (mPackages) {
                if (mKeepUninstalledPackages != null) {
                    final int packagesCount = mKeepUninstalledPackages.size();
                    for (int i = 0; i < packagesCount; i++) {
                        String oldPackage = mKeepUninstalledPackages.get(i);
                        if (packageList != null && packageList.contains(oldPackage)) {
                            continue;
                        }
                        if (removedFromList == null) {
                            removedFromList = new ArrayList<>();
                        }
                        removedFromList.add(oldPackage);
                    }
                }
                mKeepUninstalledPackages = new ArrayList<>(packageList);
                if (removedFromList != null) {
                    final int removedCount = removedFromList.size();
                    for (int i = 0; i < removedCount; i++) {
                        deletePackageIfUnusedLPr(removedFromList.get(i));
                    }
                }
            }
        }
    }
    @Override
+64 −5
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -416,7 +417,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                "cross-profile-widget-providers";
        private static final String TAG_PROVIDER = "provider";
        private static final String TAG_PACKAGE_LIST_ITEM  = "item";

        private static final String TAG_KEEP_UNINSTALLED_PACKAGES  = "keep-uninstalled-packages";
        private static final String TAG_USER_RESTRICTIONS = "user-restrictions";

        final DeviceAdminInfo info;
@@ -489,6 +490,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        // allowed.
        List<String> permittedInputMethods;

        // List of package names to keep cached.
        List<String> keepUninstalledPackages;

        // TODO: review implementation decisions with frameworks team
        boolean specifiesGlobalProxy = false;
        String globalProxySpec = null;
@@ -674,6 +678,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
                    permittedAccessiblityServices);
            writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
            writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
            if (hasUserRestrictions()) {
                UserRestrictionsUtils.writeRestrictions(
                        out, userRestrictions, TAG_USER_RESTRICTIONS);
@@ -787,6 +792,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    permittedAccessiblityServices = readPackageList(parser, tag);
                } else if (TAG_PERMITTED_IMES.equals(tag)) {
                    permittedInputMethods = readPackageList(parser, tag);
                } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
                    keepUninstalledPackages = readPackageList(parser, tag);
                } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
                    UserRestrictionsUtils.readRestrictions(parser, ensureUserRestrictions());
                } else {
@@ -981,13 +988,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    pw.println(disabledKeyguardFeatures);
            pw.print(prefix); pw.print("crossProfileWidgetProviders=");
                    pw.println(crossProfileWidgetProviders);
            if (!(permittedAccessiblityServices == null)) {
            if (permittedAccessiblityServices != null) {
                pw.print(prefix); pw.print("permittedAccessibilityServices=");
                        pw.println(permittedAccessiblityServices.toString());
                    pw.println(permittedAccessiblityServices);
            }
            if (!(permittedInputMethods == null)) {
            if (permittedInputMethods != null) {
                pw.print(prefix); pw.print("permittedInputMethods=");
                        pw.println(permittedInputMethods.toString());
                    pw.println(permittedInputMethods);
            }
            if (keepUninstalledPackages != null) {
                pw.print(prefix); pw.print("keepUninstalledPackages=");
                    pw.println(keepUninstalledPackages);
            }
            pw.print(prefix); pw.println("userRestrictions:");
            UserRestrictionsUtils.dumpRestrictions(pw, prefix + "  ", userRestrictions);
@@ -1068,6 +1079,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return LocalServices.getService(UserManagerInternal.class);
        }

        PackageManagerInternal getPackageManagerInternal() {
            return LocalServices.getService(PackageManagerInternal.class);
        }

        NotificationManager getNotificationManager() {
            return mContext.getSystemService(NotificationManager.class);
        }
@@ -2101,6 +2116,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        new SetupContentObserver(mHandler).register(mContext.getContentResolver());
        // Initialize the user setup state, to handle the upgrade case.
        updateUserSetupComplete();

        List<String> packageList;
        synchronized (this) {
            packageList = getKeepUninstalledPackagesLocked();
        }
        if (packageList != null) {
            mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
        }
    }

    private void ensureDeviceOwnerUserStarted() {
@@ -4489,6 +4512,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    @Override
    public void setKeepUninstalledPackages(ComponentName who, List<String> packageList) {
        if (!mHasFeature) {
            return;
        }
        Preconditions.checkNotNull(who, "ComponentName is null");
        Preconditions.checkNotNull(packageList, "packageList is null");
        final int userHandle = UserHandle.getCallingUserId();
        synchronized (this) {
            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                    DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
            admin.keepUninstalledPackages = packageList;
            saveSettingsLocked(userHandle);
            mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
        }
    }

    @Override
    public List<String> getKeepUninstalledPackages(ComponentName who) {
        Preconditions.checkNotNull(who, "ComponentName is null");
        if (!mHasFeature) {
            return null;
        }
        // TODO In split system user mode, allow apps on user 0 to query the list
        synchronized (this) {
            // Check if this is the device owner who is calling
            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
            return getKeepUninstalledPackagesLocked();
        }
    }

    private List<String> getKeepUninstalledPackagesLocked() {
        ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
        return (deviceOwner != null) ? deviceOwner.keepUninstalledPackages : null;
    }

    @Override
    public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) {
        if (!mHasFeature) {
Loading