Merge "Add removeManagedProfile API: Checks if the given user is a managed profile and deletes it" into main
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a152c22..f9ef62f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1368,6 +1368,7 @@
method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, android.Manifest.permission.PROVISION_DEMO_DEVICE}) public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException;
+ method @FlaggedApi("android.app.admin.flags.remove_managed_profile_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean removeManagedProfile();
method @RequiresPermission(android.Manifest.permission.TRIGGER_LOST_MODE) public void sendLostModeLocationUpdate(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public boolean setActiveProfileOwner(@NonNull android.content.ComponentName, String) throws java.lang.IllegalArgumentException;
method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_APP_EXEMPTIONS) public void setApplicationExemptions(@NonNull String, @NonNull java.util.Set<java.lang.Integer>) throws android.content.pm.PackageManager.NameNotFoundException;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 102540c..707ba34 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -55,6 +55,7 @@
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
import static android.app.admin.flags.Flags.FLAG_DEVICE_THEFT_API_ENABLED;
+import static android.app.admin.flags.Flags.FLAG_REMOVE_MANAGED_PROFILE_ENABLED;
import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
import static android.app.admin.flags.Flags.onboardingConsentlessBugreports;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
@@ -16962,6 +16963,30 @@
}
/**
+ * Removes a manged profile from the device only when called from a managed profile's context
+ *
+ * @param user UserHandle of the profile to be removed
+ * @return {@code true} when removal of managed profile was successful, {@code false} when
+ * removal was unsuccessful or throws IllegalArgumentException when provided user was not a
+ * managed profile
+ * @hide
+ */
+ @SystemApi
+ @UserHandleAware
+ @FlaggedApi(FLAG_REMOVE_MANAGED_PROFILE_ENABLED)
+ @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public boolean removeManagedProfile() {
+ if (mService == null) {
+ throw new IllegalStateException("Could not find DevicePolicyManagerService");
+ }
+ try {
+ return mService.removeManagedProfile(myUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Called when a managed profile has been provisioned.
*
* @throws SecurityException if the caller does not hold
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a4e2b8f..ba97edb 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -567,6 +567,8 @@
void finalizeWorkProfileProvisioning(in UserHandle managedProfileUser, in Account migratedAccount);
+ boolean removeManagedProfile(int userId);
+
void setDeviceOwnerType(in ComponentName admin, in int deviceOwnerType);
int getDeviceOwnerType(in ComponentName admin);
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index be24bfa..5f868be 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -343,13 +343,20 @@
}
flag {
- name: "user_provisioning_same_state"
- namespace: "enterprise"
- description: "Handle exceptions while setting same provisioning state."
- bug: "326441417"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
+ name: "user_provisioning_same_state"
+ namespace: "enterprise"
+ description: "Handle exceptions while setting same provisioning state."
+ bug: "326441417"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "remove_managed_profile_enabled"
+ namespace: "enterprise"
+ description: "API that removes a given managed profile."
+ bug: "372652841"
}
flag {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c653038..50f3f39 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21030,6 +21030,27 @@
}
@Override
+ public boolean removeManagedProfile(int userId) {
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
+ if (!isManagedProfile(userId)){
+ throw new IllegalArgumentException("Cannot remove user as it is not a managed profile");
+ }
+
+ boolean success = false;
+ final long identity = Binder.clearCallingIdentity();
+ try{
+ success = mUserManager.removeUserEvenWhenDisallowed(userId);
+ } catch (Exception e) {
+ Slogf.e(LOG_TAG, "Remove managed profile failed due to: ", e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return success;
+ }
+
+ @Override
public UserHandle createAndProvisionManagedProfile(
@NonNull ManagedProfileProvisioningParams provisioningParams,
@NonNull String callerPackage) {