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

Commit 7e96e0a1 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "createAndManageUser should communicate reason of failure to caller"

parents 2016c0f4 89386bac
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -6702,11 +6702,6 @@ package android.app.admin {
    field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
    field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
    field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
    field public static final int USER_OPERATION_ERROR_CURRENT_USER = 4; // 0x4
    field public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2; // 0x2
    field public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; // 0x3
    field public static final int USER_OPERATION_ERROR_UNKNOWN = 1; // 0x1
    field public static final int USER_OPERATION_SUCCESS = 0; // 0x0
    field public static final int WIPE_EUICC = 4; // 0x4
    field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
    field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
@@ -33630,6 +33625,17 @@ package android.os {
    field public static final java.lang.String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
    field public static final int USER_CREATION_FAILED_NOT_PERMITTED = 1; // 0x1
    field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2
    field public static final int USER_OPERATION_ERROR_CURRENT_USER = 4; // 0x4
    field public static final int USER_OPERATION_ERROR_LOW_STORAGE = 5; // 0x5
    field public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2; // 0x2
    field public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3; // 0x3
    field public static final int USER_OPERATION_ERROR_MAX_USERS = 6; // 0x6
    field public static final int USER_OPERATION_ERROR_UNKNOWN = 1; // 0x1
    field public static final int USER_OPERATION_SUCCESS = 0; // 0x0
  }
  public static class UserManager.UserOperationException extends java.lang.RuntimeException {
    method public int getUserOperationResult();
  }
  public abstract class VibrationEffect implements android.os.Parcelable {
+23 −74
Original line number Diff line number Diff line
@@ -56,8 +56,11 @@ import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager.UserOperationException;
import android.os.UserManager.UserOperationResult;
import android.provider.ContactsContract.Directory;
import android.provider.Settings;
import android.security.AttestedKeyPair;
@@ -6572,6 +6575,9 @@ public class DevicePolicyManager {
     * <p>
     * If the adminExtras are not null, they will be stored on the device until the user is started
     * for the first time. Then the extras will be passed to the admin when onEnable is called.
     * <p>From {@link android.os.Build.VERSION_CODES#P} onwards, if targeting
     * {@link android.os.Build.VERSION_CODES#P}, throws {@link UserOperationException} instead of
     * returning {@code null} on failure.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param name The user's name.
@@ -6586,6 +6592,9 @@ public class DevicePolicyManager {
     * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
     *         user could not be created.
     * @throws SecurityException if {@code admin} is not a device owner.
     * @throws UserOperationException if the user could not be created and the calling app is
     * targeting {@link android.os.Build.VERSION_CODES#P} and running on
     * {@link android.os.Build.VERSION_CODES#P}.
     */
    public @Nullable UserHandle createAndManageUser(@NonNull ComponentName admin,
            @NonNull String name,
@@ -6594,6 +6603,8 @@ public class DevicePolicyManager {
        throwIfParentInstance("createAndManageUser");
        try {
            return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
        } catch (ServiceSpecificException e) {
            throw new UserOperationException(e.getMessage(), e.errorCode);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
@@ -6636,78 +6647,16 @@ public class DevicePolicyManager {
        }
    }

    /**
     * Indicates user operation is successful.
     *
     * @see #startUserInBackground(ComponentName, UserHandle)
     * @see #stopUser(ComponentName, UserHandle)
     * @see #logoutUser(ComponentName)
     */
    public static final int USER_OPERATION_SUCCESS = 0;

    /**
     * Indicates user operation failed for unknown reason.
     *
     * @see #startUserInBackground(ComponentName, UserHandle)
     * @see #stopUser(ComponentName, UserHandle)
     * @see #logoutUser(ComponentName)
     */
    public static final int USER_OPERATION_ERROR_UNKNOWN = 1;

    /**
     * Indicates user operation failed because target user is a managed profile.
     *
     * @see #startUserInBackground(ComponentName, UserHandle)
     * @see #stopUser(ComponentName, UserHandle)
     * @see #logoutUser(ComponentName)
     */
    public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2;

    /**
     * Indicates user operation failed because maximum running user limit has reached.
     *
     * @see #startUserInBackground(ComponentName, UserHandle)
     */
    public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3;

    /**
     * Indicates user operation failed because the target user is in foreground.
     *
     * @see #stopUser(ComponentName, UserHandle)
     * @see #logoutUser(ComponentName)
     */
    public static final int USER_OPERATION_ERROR_CURRENT_USER = 4;

    /**
     * Result returned from
     * <ul>
     * <li>{@link #startUserInBackground(ComponentName, UserHandle)}</li>
     * <li>{@link #stopUser(ComponentName, UserHandle)}</li>
     * <li>{@link #logoutUser(ComponentName)}</li>
     * </ul>
     *
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "USER_OPERATION_" }, value = {
            USER_OPERATION_SUCCESS,
            USER_OPERATION_ERROR_UNKNOWN,
            USER_OPERATION_ERROR_MANAGED_PROFILE,
            USER_OPERATION_ERROR_MAX_RUNNING_USERS,
            USER_OPERATION_ERROR_CURRENT_USER
    })
    public @interface UserOperationResult {}

    /**
     * Called by a device owner to start the specified secondary user in background.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param userHandle the user to be started in background.
     * @return one of the following result codes:
     * {@link #USER_OPERATION_ERROR_UNKNOWN},
     * {@link #USER_OPERATION_SUCCESS},
     * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE},
     * {@link #USER_OPERATION_ERROR_MAX_RUNNING_USERS},
     * {@link UserManager#USER_OPERATION_ERROR_UNKNOWN},
     * {@link UserManager#USER_OPERATION_SUCCESS},
     * {@link UserManager#USER_OPERATION_ERROR_MANAGED_PROFILE},
     * {@link UserManager#USER_OPERATION_ERROR_MAX_RUNNING_USERS},
     * @throws SecurityException if {@code admin} is not a device owner.
     * @see #getSecondaryUsers(ComponentName)
     */
@@ -6727,10 +6676,10 @@ public class DevicePolicyManager {
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param userHandle the user to be stopped.
     * @return one of the following result codes:
     * {@link #USER_OPERATION_ERROR_UNKNOWN},
     * {@link #USER_OPERATION_SUCCESS},
     * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE},
     * {@link #USER_OPERATION_ERROR_CURRENT_USER}
     * {@link UserManager#USER_OPERATION_ERROR_UNKNOWN},
     * {@link UserManager#USER_OPERATION_SUCCESS},
     * {@link UserManager#USER_OPERATION_ERROR_MANAGED_PROFILE},
     * {@link UserManager#USER_OPERATION_ERROR_CURRENT_USER}
     * @throws SecurityException if {@code admin} is not a device owner.
     * @see #getSecondaryUsers(ComponentName)
     */
@@ -6750,10 +6699,10 @@ public class DevicePolicyManager {
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @return one of the following result codes:
     * {@link #USER_OPERATION_ERROR_UNKNOWN},
     * {@link #USER_OPERATION_SUCCESS},
     * {@link #USER_OPERATION_ERROR_MANAGED_PROFILE},
     * {@link #USER_OPERATION_ERROR_CURRENT_USER}
     * {@link UserManager#USER_OPERATION_ERROR_UNKNOWN},
     * {@link UserManager#USER_OPERATION_SUCCESS},
     * {@link UserManager#USER_OPERATION_ERROR_MANAGED_PROFILE},
     * {@link UserManager#USER_OPERATION_ERROR_CURRENT_USER}
     * @throws SecurityException if {@code admin} is not a profile owner affiliated with the device.
     * @see #getSecondaryUsers(ComponentName)
     */
+79 −0
Original line number Diff line number Diff line
@@ -1042,6 +1042,85 @@ public class UserManager {
     */
    public static final int USER_CREATION_FAILED_NO_MORE_USERS = Activity.RESULT_FIRST_USER + 1;

    /**
     * Indicates user operation is successful.
     */
    public static final int USER_OPERATION_SUCCESS = 0;

    /**
     * Indicates user operation failed for unknown reason.
     */
    public static final int USER_OPERATION_ERROR_UNKNOWN = 1;

    /**
     * Indicates user operation failed because target user is a managed profile.
     */
    public static final int USER_OPERATION_ERROR_MANAGED_PROFILE = 2;

    /**
     * Indicates user operation failed because maximum running user limit has been reached.
     */
    public static final int USER_OPERATION_ERROR_MAX_RUNNING_USERS = 3;

    /**
     * Indicates user operation failed because the target user is in the foreground.
     */
    public static final int USER_OPERATION_ERROR_CURRENT_USER = 4;

    /**
     * Indicates user operation failed because device has low data storage.
     */
    public static final int USER_OPERATION_ERROR_LOW_STORAGE = 5;

    /**
     * Indicates user operation failed because maximum user limit has been reached.
     */
    public static final int USER_OPERATION_ERROR_MAX_USERS = 6;

    /**
     * Result returned from various user operations.
     *
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "USER_OPERATION_" }, value = {
            USER_OPERATION_SUCCESS,
            USER_OPERATION_ERROR_UNKNOWN,
            USER_OPERATION_ERROR_MANAGED_PROFILE,
            USER_OPERATION_ERROR_MAX_RUNNING_USERS,
            USER_OPERATION_ERROR_CURRENT_USER,
            USER_OPERATION_ERROR_LOW_STORAGE,
            USER_OPERATION_ERROR_MAX_USERS
    })
    public @interface UserOperationResult {}

    /**
     * Thrown to indicate user operation failed.
     */
    public static class UserOperationException extends RuntimeException {
        private final @UserOperationResult int mUserOperationResult;

        /**
         * Constructs a UserOperationException with specific result code.
         *
         * @param message the detail message
         * @param userOperationResult the result code
         * @hide
         */
        public UserOperationException(String message,
                @UserOperationResult int userOperationResult) {
            super(message);
            mUserOperationResult = userOperationResult;
        }

        /**
         * Returns the operation result code.
         */
        public @UserOperationResult int getUserOperationResult() {
            return mUserOperationResult;
        }
    }

    /** @hide */
    public static UserManager get(Context context) {
        return (UserManager) context.getSystemService(Context.USER_SERVICE);
+54 −15
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ import android.os.RecoverySystem;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -220,6 +221,7 @@ import com.android.server.SystemService;
import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.pm.UserRestrictionsUtils;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.google.android.collect.Sets;
@@ -8884,13 +8886,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0
                && UserManager.isDeviceInDemoMode(mContext);
        final boolean leaveAllSystemAppsEnabled = (flags & LEAVE_ALL_SYSTEM_APPS_ENABLED) != 0;
        final int targetSdkVersion;
        // Create user.
        UserHandle user = null;
        synchronized (this) {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
            final int callingUid = mInjector.binderGetCallingUid();
            final long id = mInjector.binderClearCallingIdentity();
            try {
                targetSdkVersion = mInjector.getPackageManagerInternal().getUidTargetSdkVersion(
                        callingUid);
                // Return detail error code for checks inside
                // UserManagerService.createUserInternalUnchecked.
                DeviceStorageMonitorInternal deviceStorageMonitorInternal =
                        LocalServices.getService(DeviceStorageMonitorInternal.class);
                if (deviceStorageMonitorInternal.isMemoryLow()) {
                    if (targetSdkVersion >= Build.VERSION_CODES.P) {
                        throw new ServiceSpecificException(
                                UserManager.USER_OPERATION_ERROR_LOW_STORAGE, "low device storage");
                    } else {
                        return null;
                    }
                }
                if (!mUserManager.canAddMoreUsers()) {
                    if (targetSdkVersion >= Build.VERSION_CODES.P) {
                        throw new ServiceSpecificException(
                                UserManager.USER_OPERATION_ERROR_MAX_USERS, "user limit reached");
                    } else {
                        return null;
                    }
                }
                int userInfoFlags = 0;
                if (ephemeral) {
                    userInfoFlags |= UserInfo.FLAG_EPHEMERAL;
@@ -8914,8 +8943,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            }
        }
        if (user == null) {
            if (targetSdkVersion >= Build.VERSION_CODES.P) {
                throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN,
                        "failed to create user");
            } else {
                return null;
            }
        }
        final int userHandle = user.getIdentifier();
        final Intent intent = new Intent(DevicePolicyManager.ACTION_MANAGED_USER_CREATED)
@@ -8960,7 +8994,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            return user;
        } catch (Throwable re) {
            mUserManager.removeUser(userHandle);
            if (targetSdkVersion >= Build.VERSION_CODES.P) {
                throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN,
                        re.getMessage());
            } else {
                return null;
            }
        } finally {
            mInjector.binderRestoreCallingIdentity(id);
        }
@@ -9041,24 +9080,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final int userId = userHandle.getIdentifier();
        if (isManagedProfile(userId)) {
            Log.w(LOG_TAG, "Managed profile cannot be started in background");
            return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
            return UserManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
        }
        final long id = mInjector.binderClearCallingIdentity();
        try {
            if (!mInjector.getActivityManagerInternal().canStartMoreUsers()) {
                Log.w(LOG_TAG, "Cannot start more users in background");
                return DevicePolicyManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
                return UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
            }
            if (mInjector.getIActivityManager().startUserInBackground(userId)) {
                return DevicePolicyManager.USER_OPERATION_SUCCESS;
                return UserManager.USER_OPERATION_SUCCESS;
            } else {
                return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
                return UserManager.USER_OPERATION_ERROR_UNKNOWN;
            }
        } catch (RemoteException e) {
            // Same process, should not happen.
            return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
            return UserManager.USER_OPERATION_ERROR_UNKNOWN;
        } finally {
            mInjector.binderRestoreCallingIdentity(id);
        }
@@ -9076,7 +9115,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final int userId = userHandle.getIdentifier();
        if (isManagedProfile(userId)) {
            Log.w(LOG_TAG, "Managed profile cannot be stopped");
            return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
            return UserManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
        }
        return stopUserUnchecked(userId);
@@ -9097,7 +9136,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        if (isManagedProfile(callingUserId)) {
            Log.w(LOG_TAG, "Managed profile cannot be logout");
            return DevicePolicyManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
            return UserManager.USER_OPERATION_ERROR_MANAGED_PROFILE;
        }
        final long id = mInjector.binderClearCallingIdentity();
@@ -9105,11 +9144,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            if (!mInjector.getIActivityManager().switchUser(UserHandle.USER_SYSTEM)) {
                Log.w(LOG_TAG, "Failed to switch to primary user");
                // This should never happen as target user is UserHandle.USER_SYSTEM
                return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
                return UserManager.USER_OPERATION_ERROR_UNKNOWN;
            }
        } catch (RemoteException e) {
            // Same process, should not happen.
            return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
            return UserManager.USER_OPERATION_ERROR_UNKNOWN;
        } finally {
            mInjector.binderRestoreCallingIdentity(id);
        }
@@ -9122,15 +9161,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        try {
            switch (mInjector.getIActivityManager().stopUser(userId, true /*force*/, null)) {
                case ActivityManager.USER_OP_SUCCESS:
                    return DevicePolicyManager.USER_OPERATION_SUCCESS;
                    return UserManager.USER_OPERATION_SUCCESS;
                case ActivityManager.USER_OP_IS_CURRENT:
                    return DevicePolicyManager.USER_OPERATION_ERROR_CURRENT_USER;
                    return UserManager.USER_OPERATION_ERROR_CURRENT_USER;
                default:
                    return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
                    return UserManager.USER_OPERATION_ERROR_UNKNOWN;
            }
        } catch (RemoteException e) {
            // Same process, should not happen.
            return DevicePolicyManager.USER_OPERATION_ERROR_UNKNOWN;
            return UserManager.USER_OPERATION_ERROR_UNKNOWN;
        } finally {
            mInjector.binderRestoreCallingIdentity(id);
        }