Loading cmds/dpm/src/com/android/commands/dpm/Dpm.java +17 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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" + Loading @@ -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 Loading @@ -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 + "'"); } Loading Loading @@ -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); Loading core/java/android/app/admin/DevicePolicyManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -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"); Loading core/java/android/app/admin/IDevicePolicyManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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, Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +82 −26 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } } Loading Loading @@ -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); Loading @@ -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"); Loading Loading @@ -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. } } Loading Loading
cmds/dpm/src/com/android/commands/dpm/Dpm.java +17 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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" + Loading @@ -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 Loading @@ -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 + "'"); } Loading Loading @@ -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); Loading
core/java/android/app/admin/DevicePolicyManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -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"); Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +82 −26 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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); } } } Loading Loading @@ -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); Loading @@ -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"); Loading Loading @@ -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. } } Loading