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

Commit b0521256 authored by Benjamin Franz's avatar Benjamin Franz Committed by Android (Google) Code Review
Browse files

Merge "Allow device and profile owner to modify accounts"

parents e06900b7 b6c0ce4a
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -4142,6 +4142,10 @@ public class DevicePolicyManager {
     * <p>When account management is disabled for an account type, adding or removing an account
     * <p>When account management is disabled for an account type, adding or removing an account
     * of that type will not be possible.
     * of that type will not be possible.
     *
     *
     * <p>From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use
     * {@link android.accounts.AccountManager} APIs to add or remove accounts when account
     * management for a specific type is disabled.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param accountType For which account management is disabled or enabled.
     * @param accountType For which account management is disabled or enabled.
     * @param disabled The boolean indicating that account management will be disabled (true) or
     * @param disabled The boolean indicating that account management will be disabled (true) or
+4 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,10 @@ public class UserManager {
     * Authenticator.
     * Authenticator.
     * The default value is <code>false</code>.
     * The default value is <code>false</code>.
     *
     *
     * <p>From {@link android.os.Build.VERSION_CODES#N} a profile or device owner app can still
     * use {@link android.accounts.AccountManager} APIs to add or remove accounts when account
     * management is disallowed.
     *
     * <p/>Key for user restrictions.
     * <p/>Key for user restrictions.
     * <p/>Type: Boolean
     * <p/>Type: Boolean
     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+38 −22
Original line number Original line Diff line number Diff line
@@ -37,7 +37,9 @@ import android.app.AppOpsManager;
import android.app.Notification;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.PendingIntent;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.ContentValues;
@@ -82,6 +84,7 @@ import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.google.android.collect.Lists;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
import com.google.android.collect.Sets;


@@ -830,7 +833,8 @@ public class AccountManagerService
            throw new SecurityException(msg);
            throw new SecurityException(msg);
        }
        }


        if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
        if (!canUserModifyAccounts(userId, callingUid) ||
                !canUserModifyAccountsForType(userId, account.type, callingUid)) {
            return false;
            return false;
        }
        }


@@ -1259,7 +1263,7 @@ public class AccountManagerService
                    account.type);
                    account.type);
            throw new SecurityException(msg);
            throw new SecurityException(msg);
        }
        }
        if (!canUserModifyAccounts(userId)) {
        if (!canUserModifyAccounts(userId, callingUid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                        "User cannot modify accounts");
                        "User cannot modify accounts");
@@ -1267,7 +1271,7 @@ public class AccountManagerService
            }
            }
            return;
            return;
        }
        }
        if (!canUserModifyAccountsForType(userId, account.type)) {
        if (!canUserModifyAccountsForType(userId, account.type, callingUid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                        "User cannot modify accounts of this type (policy).");
                        "User cannot modify accounts of this type (policy).");
@@ -1321,9 +1325,6 @@ public class AccountManagerService
            throw new SecurityException(msg);
            throw new SecurityException(msg);
        }
        }
        UserAccounts accounts = getUserAccountsForCaller();
        UserAccounts accounts = getUserAccountsForCaller();
        if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
            return false;
        }
        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
        logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
        long identityToken = clearCallingIdentity();
        long identityToken = clearCallingIdentity();
        try {
        try {
@@ -2146,8 +2147,9 @@ public class AccountManagerService
        if (accountType == null) throw new IllegalArgumentException("accountType is null");
        if (accountType == null) throw new IllegalArgumentException("accountType is null");


        // Is user disallowed from modifying accounts?
        // Is user disallowed from modifying accounts?
        int userId = Binder.getCallingUserHandle().getIdentifier();
        final int uid = Binder.getCallingUid();
        if (!canUserModifyAccounts(userId)) {
        final int userId = UserHandle.getUserId(uid);
        if (!canUserModifyAccounts(userId, uid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                        "User is not allowed to add an account!");
                        "User is not allowed to add an account!");
@@ -2156,7 +2158,7 @@ public class AccountManagerService
            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
            return;
            return;
        }
        }
        if (!canUserModifyAccountsForType(userId, accountType)) {
        if (!canUserModifyAccountsForType(userId, accountType, uid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                        "User cannot modify accounts of this type (policy).");
                        "User cannot modify accounts of this type (policy).");
@@ -2168,7 +2170,6 @@ public class AccountManagerService
        }
        }


        final int pid = Binder.getCallingPid();
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
        options.putInt(AccountManager.KEY_CALLER_UID, uid);
        options.putInt(AccountManager.KEY_CALLER_UID, uid);
        options.putInt(AccountManager.KEY_CALLER_PID, pid);
        options.putInt(AccountManager.KEY_CALLER_PID, pid);
@@ -2230,7 +2231,7 @@ public class AccountManagerService
        }
        }


        // Is user disallowed from modifying accounts?
        // Is user disallowed from modifying accounts?
        if (!canUserModifyAccounts(userId)) {
        if (!canUserModifyAccounts(userId, callingUid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                        "User is not allowed to add an account!");
                        "User is not allowed to add an account!");
@@ -2239,7 +2240,7 @@ public class AccountManagerService
            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
            return;
            return;
        }
        }
        if (!canUserModifyAccountsForType(userId, accountType)) {
        if (!canUserModifyAccountsForType(userId, accountType, callingUid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                        "User cannot modify accounts of this type (policy).");
                        "User cannot modify accounts of this type (policy).");
@@ -2310,8 +2311,9 @@ public class AccountManagerService
            throw new IllegalArgumentException("accountType is null");
            throw new IllegalArgumentException("accountType is null");
        }
        }


        int userId = Binder.getCallingUserHandle().getIdentifier();
        final int uid = Binder.getCallingUid();
        if (!canUserModifyAccounts(userId)) {
        final int userId = UserHandle.getUserId(uid);
        if (!canUserModifyAccounts(userId, uid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
                        "User is not allowed to add an account!");
                        "User is not allowed to add an account!");
@@ -2320,7 +2322,7 @@ public class AccountManagerService
            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
            return;
            return;
        }
        }
        if (!canUserModifyAccountsForType(userId, accountType)) {
        if (!canUserModifyAccountsForType(userId, accountType, uid)) {
            try {
            try {
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                        "User cannot modify accounts of this type (policy).");
                        "User cannot modify accounts of this type (policy).");
@@ -2332,7 +2334,6 @@ public class AccountManagerService
        }
        }


        final int pid = Binder.getCallingPid();
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
        options.putInt(AccountManager.KEY_CALLER_UID, uid);
        options.putInt(AccountManager.KEY_CALLER_UID, uid);
        options.putInt(AccountManager.KEY_CALLER_PID, pid);
        options.putInt(AccountManager.KEY_CALLER_PID, pid);
@@ -2497,8 +2498,9 @@ public class AccountManagerService
            throw new IllegalArgumentException("sessionBundle is empty");
            throw new IllegalArgumentException("sessionBundle is empty");
        }
        }


        int userId = Binder.getCallingUserHandle().getIdentifier();
        final int uid = Binder.getCallingUid();
        if (!canUserModifyAccounts(userId)) {
        final int userId = UserHandle.getUserId(uid);
        if (!canUserModifyAccounts(userId, uid)) {
            sendErrorResponse(response,
            sendErrorResponse(response,
                    AccountManager.ERROR_CODE_USER_RESTRICTED,
                    AccountManager.ERROR_CODE_USER_RESTRICTED,
                    "User is not allowed to add an account!");
                    "User is not allowed to add an account!");
@@ -2507,7 +2509,6 @@ public class AccountManagerService
        }
        }


        final int pid = Binder.getCallingPid();
        final int pid = Binder.getCallingPid();
        final int uid = Binder.getCallingUid();
        final Bundle decryptedBundle;
        final Bundle decryptedBundle;
        final String accountType;
        final String accountType;
        // First decrypt session bundle to get account type for checking permission.
        // First decrypt session bundle to get account type for checking permission.
@@ -2554,7 +2555,7 @@ public class AccountManagerService
            return;
            return;
        }
        }


        if (!canUserModifyAccountsForType(userId, accountType)) {
        if (!canUserModifyAccountsForType(userId, accountType, uid)) {
            sendErrorResponse(
            sendErrorResponse(
                    response,
                    response,
                    AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
                    AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
@@ -4319,7 +4320,11 @@ public class AccountManagerService
        }
        }
    }
    }


    private boolean canUserModifyAccounts(int userId) {
    private boolean canUserModifyAccounts(int userId, int callingUid) {
        // the managing app can always modify accounts
        if (isProfileOwner(callingUid)) {
            return true;
        }
        if (getUserManager().getUserRestrictions(new UserHandle(userId))
        if (getUserManager().getUserRestrictions(new UserHandle(userId))
                .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
                .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
            return false;
            return false;
@@ -4327,7 +4332,11 @@ public class AccountManagerService
        return true;
        return true;
    }
    }


    private boolean canUserModifyAccountsForType(int userId, String accountType) {
    private boolean canUserModifyAccountsForType(int userId, String accountType, int callingUid) {
        // the managing app can always modify accounts
        if (isProfileOwner(callingUid)) {
            return true;
        }
        DevicePolicyManager dpm = (DevicePolicyManager) mContext
        DevicePolicyManager dpm = (DevicePolicyManager) mContext
                .getSystemService(Context.DEVICE_POLICY_SERVICE);
                .getSystemService(Context.DEVICE_POLICY_SERVICE);
        String[] typesArray = dpm.getAccountTypesWithManagementDisabledAsUser(userId);
        String[] typesArray = dpm.getAccountTypesWithManagementDisabledAsUser(userId);
@@ -4342,6 +4351,13 @@ public class AccountManagerService
        return true;
        return true;
    }
    }


    private boolean isProfileOwner(int uid) {
        final DevicePolicyManagerInternal dpmi =
                LocalServices.getService(DevicePolicyManagerInternal.class);
        return (dpmi != null)
                && dpmi.isActiveAdminWithPolicy(uid, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
    }

    @Override
    @Override
    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
            throws RemoteException {
            throws RemoteException {