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

Commit 5343fcb7 authored by Alex Chau's avatar Alex Chau
Browse files

Introduce API to enable existing packages on shared users

- Also unhide setKeepUninstalledPackages
- installExistingPackage accpets delegation API because all app
  managemnet PIs did the same, including setKeepUninstalledPackages and
  enableSytemApp

Bug: 70017947
Bug: 65842106
Test: Install apps already installed in u0 in shared user should succeed
Test: Install apps in setKeepUninstalledPackages cache in shared user
      should succeed
Test: Install apps via delegated package should succeed
Test: Install apps via unaffiliated profile owner should fail
Test: Install apps not installed in any user or in APK cache shoudl fail
Change-Id: Iba563b2050abd0d1f46bfa06cfc0526b7b476b3b
parent 0b62766d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -6344,6 +6344,7 @@ package android.app.admin {
    method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String);
    method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
    method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
    method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName);
    method public int getKeyguardDisabledFeatures(android.content.ComponentName);
    method public int getLockTaskFeatures(android.content.ComponentName);
    method public java.lang.String[] getLockTaskPackages(android.content.ComponentName);
@@ -6384,6 +6385,7 @@ package android.app.admin {
    method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
    method public boolean hasGrantedPolicy(android.content.ComponentName, int);
    method public boolean installCaCert(android.content.ComponentName, byte[]);
    method public boolean installExistingPackage(android.content.ComponentName, java.lang.String);
    method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
    method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean);
    method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean);
@@ -6434,6 +6436,7 @@ package android.app.admin {
    method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
    method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
    method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
    method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
    method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
    method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
    method public void setLockTaskFeatures(android.content.ComponentName, int);
@@ -6503,6 +6506,8 @@ package android.app.admin {
    field public static final java.lang.String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall";
    field public static final java.lang.String DELEGATION_CERT_INSTALL = "delegation-cert-install";
    field public static final java.lang.String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";
    field public static final java.lang.String DELEGATION_INSTALL_EXISTING_PACKAGE = "delegation-install-existing-package";
    field public static final java.lang.String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages";
    field public static final java.lang.String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
    field public static final java.lang.String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
    field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
+38 −3
Original line number Diff line number Diff line
@@ -1320,10 +1320,16 @@ public class DevicePolicyManager {
     */
    public static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";

    /**
     * Delegation for installing existing packages. This scope grants access to the
     * {@link #installExistingPackage} API.
     */
    public static final String DELEGATION_INSTALL_EXISTING_PACKAGE =
            "delegation-install-existing-package";

    /**
     * Delegation of management of uninstalled packages. This scope grants access to the
     * {@code #setKeepUninstalledPackages} and {@code #getKeepUninstalledPackages} APIs.
     * @hide
     */
    public static final String DELEGATION_KEEP_UNINSTALLED_PACKAGES =
            "delegation-keep-uninstalled-packages";
@@ -6085,7 +6091,6 @@ public class DevicePolicyManager {
     * @return List of package names to keep cached.
     * @see #setDelegatedScopes
     * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES
     * @hide
     */
    public @Nullable List<String> getKeepUninstalledPackages(@Nullable ComponentName admin) {
        throwIfParentInstance("getKeepUninstalledPackages");
@@ -6113,7 +6118,6 @@ public class DevicePolicyManager {
     * @throws SecurityException if {@code admin} is not a device owner.
     * @see #setDelegatedScopes
     * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES
     * @hide
     */
    public void setKeepUninstalledPackages(@Nullable ComponentName admin,
            @NonNull List<String> packageNames) {
@@ -6590,6 +6594,37 @@ public class DevicePolicyManager {
        return 0;
    }

    /**
     * Install an existing package that has been installed in another user, or has been kept after
     * removal via {@link #setKeepUninstalledPackages}.
     * This function can be called by a device owner, profile owner or a delegate given
     * the {@link #DELEGATION_INSTALL_EXISTING_PACKAGE} scope via {@link #setDelegatedScopes}.
     * When called in a secondary user or managed profile, the user/profile must be affiliated with
     * the device owner. See {@link #setAffiliationIds}.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param packageName The package to be installed in the calling profile.
     * @return {@code true} if the app is installed; {@code false} otherwise.
     * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of
     * an affiliated user or profile.
     * @see #setKeepUninstalledPackages
     * @see #setDelegatedScopes
     * @see #setAffiliationIds
     * @see #DELEGATION_PACKAGE_ACCESS
     */
    public boolean installExistingPackage(@NonNull ComponentName admin, String packageName) {
        throwIfParentInstance("installExistingPackage");
        if (mService != null) {
            try {
                return mService.installExistingPackage(admin, mContext.getPackageName(),
                        packageName);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return false;
    }

    /**
     * Called by a device owner or profile owner to disable account management for a specific type
     * of account.
+1 −0
Original line number Diff line number Diff line
@@ -223,6 +223,7 @@ interface IDevicePolicyManager {

    void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName);
    int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent);
    boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName);

    void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
    String[] getAccountTypesWithManagementDisabled();
+37 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS;
import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL;
import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP;
import static android.app.admin.DevicePolicyManager.DELEGATION_INSTALL_EXISTING_PACKAGE;
import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
@@ -296,7 +297,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        DELEGATION_ENABLE_SYSTEM_APP,
        DELEGATION_KEEP_UNINSTALLED_PACKAGES,
        DELEGATION_PACKAGE_ACCESS,
        DELEGATION_PERMISSION_GRANT
        DELEGATION_PERMISSION_GRANT,
        DELEGATION_INSTALL_EXISTING_PACKAGE,
        DELEGATION_KEEP_UNINSTALLED_PACKAGES
    };

    /**
@@ -8842,6 +8845,39 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
    }

    @Override
    public boolean installExistingPackage(ComponentName who, String callerPackage,
            String packageName) {
        synchronized (this) {
            // Ensure the caller is a PO or an install existing package delegate
            enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
                    DELEGATION_INSTALL_EXISTING_PACKAGE);
            final int callingUserId = mInjector.userHandleGetCallingUserId();
            if (!isUserAffiliatedWithDeviceLocked(callingUserId)) {
                throw new SecurityException("Admin " + who +
                        " is neither the device owner or affiliated user's profile owner.");
            }

            final long id = mInjector.binderClearCallingIdentity();
            try {
                if (VERBOSE_LOG) {
                    Slog.v(LOG_TAG, "installing " + packageName + " for "
                            + callingUserId);
                }

                // Install the package.
                return mIPackageManager.installExistingPackageAsUser(packageName, callingUserId,
                        0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY)
                        == PackageManager.INSTALL_SUCCEEDED;
            } catch (RemoteException re) {
                // shouldn't happen
                return false;
            } finally {
                mInjector.binderRestoreCallingIdentity(id);
            }
        }
    }

    @Override
    public void setAccountManagementDisabled(ComponentName who, String accountType,
            boolean disabled) {