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

Commit 3c5ceae1 authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Add test method to remove admins." into nyc-dev

parents 976f28b9 38dcca51
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public final class Dpm extends BaseCommand {
    private static final String COMMAND_SET_ACTIVE_ADMIN = "set-active-admin";
    private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner";
    private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner";
    private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin";

    private IDevicePolicyManager mDevicePolicyManager;
    private int mUserId = UserHandle.USER_SYSTEM;
@@ -60,6 +61,8 @@ public final class Dpm extends BaseCommand {
                "[ --name <NAME> ] <COMPONENT>\n" +
                "usage: dpm set-profile-owner [ --user <USER_ID> | current ] [ --name <NAME> ] " +
                "<COMPONENT>\n" +
                "usage: dpm remove-active-admin [ --user <USER_ID> | current ] [ --name <NAME> ] " +
                "<COMPONENT>\n" +
                "\n" +
                "dpm set-active-admin: Sets the given component as active admin" +
                " for an existing user.\n" +
@@ -68,7 +71,11 @@ public final class Dpm extends BaseCommand {
                " package as device owner.\n" +
                "\n" +
                "dpm set-profile-owner: Sets the given component as active admin and profile" +
                " owner for an existing user.\n");
                " owner for an existing user.\n" +
                "\n" +
                "dpm remove-active-admin: Disables an active admin, the admin must have declared" +
                " android:testOnly in the application in its manifest. This will also remove" +
                " device and profile owners\n");
    }

    @Override
@@ -91,6 +98,9 @@ public final class Dpm extends BaseCommand {
            case COMMAND_SET_PROFILE_OWNER:
                runSetProfileOwner();
                break;
            case COMMAND_REMOVE_ACTIVE_ADMIN:
                runRemoveActiveAdmin();
                break;
            default:
                throw new IllegalArgumentException ("unknown command '" + command + "'");
        }
@@ -152,6 +162,12 @@ public final class Dpm extends BaseCommand {
        System.out.println("Active admin set to component " + mComponent.toShortString());
    }

    private void runRemoveActiveAdmin() throws RemoteException {
        parseArgs(/*canHaveName=*/ false);
        mDevicePolicyManager.forceRemoveActiveAdmin(mComponent, mUserId);
        System.out.println("Success: Admin removed " + mComponent);
    }

    private void runSetProfileOwner() throws RemoteException {
        parseArgs(/*canHaveName=*/ true);
        mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);
+18 −0
Original line number Diff line number Diff line
@@ -6391,6 +6391,24 @@ public class DevicePolicyManager {
        }
    }

    /**
     * @hide
     * Remove a test admin synchronously without sending it a broadcast about being removed.
     * If the admin is a profile owner or device owner it will still be removed.
     *
     * @param userHandle user id to remove the admin for.
     * @param admin The administration compononent to remove.
     * @throws SecurityException if the caller is not shell / root or the admin package
     *         isn't a test application see {@link ApplicationInfo#FLAG_TEST_APP}.
     */
    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) {
        try {
            mService.forceRemoveActiveAdmin(adminReceiver, userHandle);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    private void throwIfParentInstance(String functionName) {
        if (mParentInstance) {
            throw new SecurityException(functionName + " cannot be called on the parent instance");
+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ interface IDevicePolicyManager {
    boolean packageHasActiveAdmins(String packageName, int userHandle);
    void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle);
    void removeActiveAdmin(in ComponentName policyReceiver, int userHandle);
    void forceRemoveActiveAdmin(in ComponentName policyReceiver, int userHandle);
    boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle);

    void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase,
+82 −26
Original line number Diff line number Diff line
@@ -2909,6 +2909,54 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) {
        if (!mHasFeature) {
            return;
        }
        Preconditions.checkNotNull(adminReceiver, "ComponentName is null");
        enforceShell("forceRemoveActiveAdmin");
        long ident = mInjector.binderClearCallingIdentity();
        try {
            final ApplicationInfo ai;
            try {
                ai = mIPackageManager.getApplicationInfo(adminReceiver.getPackageName(),
                        0, userHandle);
            } catch (RemoteException e) {
                throw new IllegalStateException(e);
            }
            if (ai == null) {
                throw new IllegalStateException("Couldn't find package to remove admin "
                        + adminReceiver.getPackageName() + " " + userHandle);
            }
            if ((ai.flags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
                throw new SecurityException("Attempt to remove non-test admin " + adminReceiver
                        + adminReceiver + " " + userHandle);
            }
            // If admin is a device or profile owner tidy that up first.
            synchronized (this)  {
                if (isDeviceOwner(adminReceiver, userHandle)) {
                    clearDeviceOwnerLocked(getDeviceOwnerAdminLocked(), userHandle);
                }
                if (isProfileOwner(adminReceiver, userHandle)) {
                    final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver,
                            userHandle, /* parent */ false);
                    clearProfileOwnerLocked(admin, userHandle);
                }
            }
            // Remove the admin skipping sending the broadcast.
            removeAdminArtifacts(adminReceiver, userHandle);
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
        }
    }

    private void enforceShell(String method) {
        final int callingUid = Binder.getCallingUid();
        if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
            throw new SecurityException("Non-shell user attempted to call " + method);
        }
    }

    @Override
    public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
        if (!mHasFeature) {
@@ -5732,29 +5780,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            enforceUserUnlocked(deviceOwnerUserId);

            final ActiveAdmin admin = getDeviceOwnerAdminLocked();
            long ident = mInjector.binderClearCallingIdentity();
            try {
                clearDeviceOwnerLocked(admin, deviceOwnerUserId);
                removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
            } finally {
                mInjector.binderRestoreCallingIdentity(ident);
            }
        }
    }

    private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) {
        if (admin != null) {
            admin.disableCamera = false;
            admin.userRestrictions = null;
            admin.forceEphemeralUsers = false;
            mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
        }
            clearUserPoliciesLocked(deviceOwnerUserId);
        clearUserPoliciesLocked(userId);

        mOwners.clearDeviceOwner();
        mOwners.writeDeviceOwner();
        updateDeviceOwnerLocked();
        disableSecurityLoggingIfNotCompliant();
            // Reactivate backup service.
            long ident = mInjector.binderClearCallingIdentity();
        try {
            // Reactivate backup service.
            mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true);

                removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
        } catch (RemoteException e) {
            throw new IllegalStateException("Failed reactivating backup service.", e);
            } finally {
                mInjector.binderRestoreCallingIdentity(ident);
            }
        }
    }

@@ -5794,14 +5847,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        final ActiveAdmin admin =
                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
        synchronized (this) {
            admin.disableCamera = false;
            admin.userRestrictions = null;
            clearUserPoliciesLocked(userId);
            mOwners.removeProfileOwner(userId);
            mOwners.writeProfileOwner(userId);

            final long ident = mInjector.binderClearCallingIdentity();
            try {
                clearProfileOwnerLocked(admin, userId);
                removeActiveAdminLocked(who, userId);
            } finally {
                mInjector.binderRestoreCallingIdentity(ident);
@@ -5809,6 +5857,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    public void clearProfileOwnerLocked(ActiveAdmin admin, int userId) {
        if (admin != null) {
            admin.disableCamera = false;
            admin.userRestrictions = null;
        }
        clearUserPoliciesLocked(userId);
        mOwners.removeProfileOwner(userId);
        mOwners.writeProfileOwner(userId);
    }

    @Override
    public void setDeviceOwnerLockScreenInfo(ComponentName who, CharSequence info) {
        Preconditions.checkNotNull(who, "ComponentName is null");
@@ -5842,15 +5900,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;
        saveSettingsLocked(userId);

        final long ident = mInjector.binderClearCallingIdentity();
        try {
            mIPackageManager.updatePermissionFlagsForAllApps(
                    PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                    0  /* flagValues */, userId);
            pushUserRestrictions(userId);
        } catch (RemoteException re) {
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
            // Shouldn't happen.
        }
    }