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

Commit e05fb429 authored by Alex Johnston's avatar Alex Johnston
Browse files

Allow the device policy management role to migrate accounts

Update copyAccountToUser to a SystemAPI

This is part of the work to split up the DevicePolicyManager
API createAndProvisionManagedProfile. The only caller of this
copyAccountToUser hidden SystemAPI will be the device policy
management role holder

Add permissions to gate the copyAccountToUser API and the
removeAccount API to allow the device policy management
role holder to call these APIs

Bug: 375382324
Test: atest AccountMigrationTest
Test: Manual testing by calling this SystemAPI in CloudDPC
 CTS tests will be added as a follow-up
Flag: android.app.admin.flags.split_create_managed_profile_enabled
Change-Id: I243f7ce53c6b8c8db1b946981895782f9d1c59dd
parent c319a30b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3830,7 +3830,7 @@ package android.accounts {
    method @RequiresPermission(value="android.permission.AUTHENTICATE_ACCOUNTS", apis="..22") public boolean notifyAccountAuthenticated(android.accounts.Account);
    method @RequiresPermission(value="android.permission.AUTHENTICATE_ACCOUNTS", apis="..22") public String peekAuthToken(android.accounts.Account, String);
    method @Deprecated @RequiresPermission(value="android.permission.MANAGE_ACCOUNTS", apis="..22") public android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
    method @RequiresPermission(value="android.permission.MANAGE_ACCOUNTS", apis="..22") public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
    method @FlaggedApi("android.app.admin.flags.split_create_managed_profile_enabled") @RequiresPermission(value="android.permission.REMOVE_ACCOUNTS", conditional=true) public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
    method @RequiresPermission(value="android.permission.AUTHENTICATE_ACCOUNTS", apis="..22") public boolean removeAccountExplicitly(android.accounts.Account);
    method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
    method @RequiresPermission(value="android.permission.AUTHENTICATE_ACCOUNTS", apis="..22") public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, @Size(min=1) String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
+3 −0
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ package android {
    field public static final String CONTROL_KEYGUARD_SECURE_NOTIFICATIONS = "android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS";
    field public static final String CONTROL_OEM_PAID_NETWORK_PREFERENCE = "android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE";
    field public static final String CONTROL_VPN = "android.permission.CONTROL_VPN";
    field @FlaggedApi("android.app.admin.flags.split_create_managed_profile_enabled") public static final String COPY_ACCOUNTS = "android.permission.COPY_ACCOUNTS";
    field public static final String CREATE_USERS = "android.permission.CREATE_USERS";
    field public static final String CREATE_VIRTUAL_DEVICE = "android.permission.CREATE_VIRTUAL_DEVICE";
    field public static final String CRYPT_KEEPER = "android.permission.CRYPT_KEEPER";
@@ -345,6 +346,7 @@ package android {
    field public static final String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
    field public static final String REGISTER_STATS_PULL_ATOM = "android.permission.REGISTER_STATS_PULL_ATOM";
    field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
    field @FlaggedApi("android.app.admin.flags.split_create_managed_profile_enabled") public static final String REMOVE_ACCOUNTS = "android.permission.REMOVE_ACCOUNTS";
    field public static final String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
    field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
    field public static final String RENOUNCE_PERMISSIONS = "android.permission.RENOUNCE_PERMISSIONS";
@@ -570,6 +572,7 @@ package android.accessibilityservice {
package android.accounts {
  public class AccountManager {
    method @FlaggedApi("android.app.admin.flags.split_create_managed_profile_enabled") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.COPY_ACCOUNTS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public android.accounts.AccountManagerFuture<java.lang.Boolean> copyAccountToUser(@NonNull android.accounts.Account, @NonNull android.os.UserHandle, @NonNull android.os.UserHandle, @Nullable android.accounts.AccountManagerCallback<java.lang.Boolean>, @Nullable android.os.Handler);
    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public android.accounts.AccountManagerFuture<android.os.Bundle> finishSessionAsUser(android.os.Bundle, android.app.Activity, android.os.UserHandle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
  }
+17 −3
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@

package android.accounts;

import static android.Manifest.permission.COPY_ACCOUNTS;
import static android.Manifest.permission.REMOVE_ACCOUNTS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.app.admin.flags.Flags.FLAG_SPLIT_CREATE_MANAGED_PROFILE_ENABLED;

import android.annotation.BroadcastBehavior;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,6 +30,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.Size;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.UserHandleAware;
@@ -1312,7 +1317,8 @@ public class AccountManager {
     * {@link AccountManagerFuture} must not be used on the main thread.
     *
     * <p>This method requires the caller to have a signature match with the
     * authenticator that manages the specified account.
     * authenticator that manages the specified account, be a profile owner or have the
     * {@link android.Manifest.permission#REMOVE_ACCOUNTS} permission.
     *
     * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
     * MANAGE_ACCOUNTS permission is needed for those platforms. See docs for
@@ -1344,6 +1350,8 @@ public class AccountManager {
     * </ul>
     */
    @UserHandleAware
    @RequiresPermission(value = REMOVE_ACCOUNTS, conditional = true)
    @FlaggedApi(FLAG_SPLIT_CREATE_MANAGED_PROFILE_ENABLED)
    public AccountManagerFuture<Bundle> removeAccount(final Account account,
            final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
        return removeAccountAsUser(account, activity, callback, handler, mContext.getUser());
@@ -2019,9 +2027,15 @@ public class AccountManager {
     * succeeded.
     * @hide
     */
    @SuppressLint("SamShouldBeLast")
    @NonNull
    @SystemApi
    @RequiresPermission(anyOf = {COPY_ACCOUNTS, INTERACT_ACROSS_USERS_FULL})
    @FlaggedApi(FLAG_SPLIT_CREATE_MANAGED_PROFILE_ENABLED)
    public AccountManagerFuture<Boolean> copyAccountToUser(
            final Account account, final UserHandle fromUser, final UserHandle toUser,
            AccountManagerCallback<Boolean> callback, Handler handler) {
            @NonNull final Account account, @NonNull final UserHandle fromUser,
            @NonNull final UserHandle toUser, @Nullable AccountManagerCallback<Boolean> callback,
            @Nullable Handler handler) {
        if (account == null) throw new IllegalArgumentException("account is null");
        if (toUser == null || fromUser == null) {
            throw new IllegalArgumentException("fromUser and toUser cannot be null");
+9 −0
Original line number Diff line number Diff line
@@ -418,3 +418,12 @@ flag {
    description: "Add new checkOp APIs that accept attributionTag"
    bug: "240617242"
}

flag {
    name: "device_policy_management_role_split_create_managed_profile_enabled"
    is_fixed_read_only: true
    is_exported: true
    namespace: "enterprise"
    description: "Gives the device policy management role the ability to create a managed profile using new APIs"
    bug: "375382324"
}
+1 −0
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ android_app {
        "android.os.vibrator.flags-aconfig",
        "android.media.tv.flags-aconfig",
        "android.security.flags-aconfig",
        "device_policy_aconfig_flags",
        "com.android.hardware.input.input-aconfig",
        "aconfig_trade_in_mode_flags",
        "art-aconfig-flags",
Loading