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

Commit fd4a3b44 authored by Rubin Xu's avatar Rubin Xu
Browse files

Implement DELEGATION_PACKAGE_INSTALLATION

Previously a Device Owner or an affliated Profile Owner of the DO can silently
install APKs via PackageInstaller APIs. This CL additionally grants delegates
of DO the same access.

Bug: 112982695
Test: atest com.android.cts.devicepolicy.MixedProfileOwnerTest#testDelegation
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testDelegation
Test: atest com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testDelegation
Change-Id: I777ee6aa1ecd036ee56270fc6b4e86b74d1042a6
parent 7b1e7a38
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ import android.util.Log;
 *
 * <p>The callback methods happen on the main thread of the process.  Thus long running
 * operations must be done on another thread.  Note that because a receiver
 * is done once returning from its receive function, such long-running operations
 * is done once returning from its onReceive function, such long-running operations
 * should probably be done in a {@link Service}.
 *
 * @see DevicePolicyManager#setDelegatedScopes
+6 −0
Original line number Diff line number Diff line
@@ -117,6 +117,12 @@ public abstract class DevicePolicyManagerInternal {
     */
    public abstract boolean isUserAffiliatedWithDevice(int userId);

    /**
     * Returns whether the calling package can install or uninstall packages without user
     * interaction.
     */
    public abstract boolean canSilentlyInstallPackage(String callerPackage, int callerUid);

    /**
     * Reports that a profile has changed to use a unified or separate credential.
     *
+10 −1
Original line number Diff line number Diff line
@@ -68,7 +68,14 @@ import java.util.List;
 * {@link PackageInstaller.Session}, which any app can create. Once the session
 * is created, the installer can stream one or more APKs into place until it
 * decides to either commit or destroy the session. Committing may require user
 * intervention to complete the installation.
 * intervention to complete the installation, unless the caller falls into one of the
 * following categories, in which case the installation will complete automatically.
 * <ul>
 * <li>the device owner
 * <li>the affiliated profile owner
 * <li>the device owner delegated app with
 *     {@link android.app.admin.DevicePolicyManager#DELEGATION_PACKAGE_INSTALLATION}
 * </ul>
 * <p>
 * Sessions can install brand new apps, upgrade existing apps, or add new splits
 * into an existing app.
@@ -481,6 +488,8 @@ public class PackageInstaller {
     * <li>the current "installer of record" for the package
     * <li>the device owner
     * <li>the affiliated profile owner
     * <li>the device owner delegated app with
     *     {@link android.app.admin.DevicePolicyManager#DELEGATION_PACKAGE_INSTALLATION}
     * </ul>
     *
     * @param packageName The package to uninstall.
+4 −8
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PackageDeleteObserver;
import android.app.PackageInstallObserver;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
import android.content.Intent;
@@ -738,22 +737,19 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements

        // Check whether the caller is device owner or affiliated profile owner, in which case we do
        // it silently.
        final int callingUserId = UserHandle.getUserId(callingUid);
        DevicePolicyManagerInternal dpmi =
                LocalServices.getService(DevicePolicyManagerInternal.class);
        final boolean isDeviceOwnerOrAffiliatedProfileOwner =
                dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
                        DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
                        && dpmi.isUserAffiliatedWithDevice(callingUserId);
        final boolean canSilentlyInstallPackage =
                dpmi != null && dpmi.canSilentlyInstallPackage(callerPackageName, callingUid);

        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
                statusReceiver, versionedPackage.getPackageName(),
                isDeviceOwnerOrAffiliatedProfileOwner, userId);
                canSilentlyInstallPackage, userId);
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                    == PackageManager.PERMISSION_GRANTED) {
            // Sweet, call straight through!
            mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags);
        } else if (isDeviceOwnerOrAffiliatedProfileOwner) {
        } else if (canSilentlyInstallPackage) {
            // Allow the device owner and affiliated profile owner to silently delete packages
            // Need to clear the calling identity to get DELETE_PACKAGES permission
            long ident = Binder.clearCallingIdentity();
+5 −5
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.apex.IApexService;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.Context;
import android.content.IIntentReceiver;
@@ -194,7 +193,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

    /** Package of the owner of the installer session */
    @GuardedBy("mLock")
    private String mInstallerPackageName;
    private @Nullable String mInstallerPackageName;

    /** Uid of the owner of the installer session */
    @GuardedBy("mLock")
@@ -340,11 +339,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     */
    @GuardedBy("mLock")
    private boolean isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked() {
        if (userId != UserHandle.getUserId(mInstallerUid)) {
            return false;
        }
        DevicePolicyManagerInternal dpmi =
                LocalServices.getService(DevicePolicyManagerInternal.class);
        return dpmi != null && dpmi.isActiveAdminWithPolicy(mInstallerUid,
                DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) && dpmi.isUserAffiliatedWithDevice(
                userId);
        return dpmi != null && dpmi.canSilentlyInstallPackage(mInstallerPackageName, mInstallerUid);
    }

    /**
Loading