diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 1df45d132f345..c60f55868c006 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -3612,7 +3612,7 @@ public class UserManager { * *
Requires {@link android.Manifest.permission#MANAGE_USERS}. * {@link android.Manifest.permission#CREATE_USERS} suffices if flags are in - * com.android.server.pm.UserManagerService#ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION}. + * com.android.server.pm.UserManagerService#ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION. * * @param name the user's name * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_GUEST}. @@ -3686,7 +3686,7 @@ public class UserManager { * *
Requires {@link android.Manifest.permission#MANAGE_USERS}. * {@link android.Manifest.permission#CREATE_USERS} suffices if flags are in - * com.android.server.pm.UserManagerService#ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION}. + * com.android.server.pm.UserManagerService#ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION. * * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_GUEST}. * @return the {@link UserInfo} object for the created user. @@ -3718,25 +3718,23 @@ public class UserManager { */ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.CREATE_USERS}) - public UserInfo createGuest(Context context) { + public @Nullable UserInfo createGuest(Context context) { try { final UserInfo guest = mService.createUserWithThrow(null, USER_TYPE_FULL_GUEST, 0); - if (guest != null) { - Settings.Secure.putStringForUser(context.getContentResolver(), - Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id); + Settings.Secure.putStringForUser(context.getContentResolver(), + Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id); - if (UserManager.isGuestUserAllowEphemeralStateChange()) { - // Mark guest as (changeably) ephemeral if REMOVE_GUEST_ON_EXIT is 1 - // This is done so that a user via a UI controller can choose to - // make a guest as ephemeral or not. - // Settings.Global.REMOVE_GUEST_ON_EXIT holds the choice on what the guest state - // should be, with default being ephemeral. - boolean resetGuestOnExit = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.REMOVE_GUEST_ON_EXIT, 1) == 1; + if (UserManager.isGuestUserAllowEphemeralStateChange()) { + // Mark guest as (changeably) ephemeral if REMOVE_GUEST_ON_EXIT is 1 + // This is done so that a user via a UI controller can choose to + // make a guest as ephemeral or not. + // Settings.Global.REMOVE_GUEST_ON_EXIT holds the choice on what the guest state + // should be, with default being ephemeral. + boolean resetGuestOnExit = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.REMOVE_GUEST_ON_EXIT, 1) == 1; - if (resetGuestOnExit && !guest.isEphemeral()) { - setUserEphemeral(guest.id, true); - } + if (resetGuestOnExit && !guest.isEphemeral()) { + setUserEphemeral(guest.id, true); } } return guest; @@ -3855,7 +3853,7 @@ public class UserManager { */ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.CREATE_USERS}) - public UserInfo createProfileForUser(String name, @NonNull String userType, + public @Nullable UserInfo createProfileForUser(String name, @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId) { return createProfileForUser(name, userType, flags, userId, null); } @@ -3900,7 +3898,7 @@ public class UserManager { */ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, Manifest.permission.CREATE_USERS}) - public UserInfo createProfileForUserEvenWhenDisallowed(String name, + public @Nullable UserInfo createProfileForUserEvenWhenDisallowed(String name, @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId, String[] disallowedPackages) { try { @@ -3931,11 +3929,9 @@ public class UserManager { try { final int parentUserId = mUserId; final UserInfo profile = mService.createRestrictedProfileWithThrow(name, parentUserId); - if (profile != null) { - final UserHandle parentUserHandle = UserHandle.of(parentUserId); - AccountManager.get(mContext).addSharedAccountsFromParentUser(parentUserHandle, - UserHandle.of(profile.id)); - } + final UserHandle parentUserHandle = UserHandle.of(parentUserId); + AccountManager.get(mContext).addSharedAccountsFromParentUser(parentUserHandle, + UserHandle.of(profile.id)); return profile; } catch (ServiceSpecificException e) { return null; diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java index 3cbaebe4101e6..36efc0ddfc44f 100644 --- a/services/core/java/com/android/server/pm/UserManagerInternal.java +++ b/services/core/java/com/android/server/pm/UserManagerInternal.java @@ -238,8 +238,9 @@ public abstract class UserManagerInternal { * the user is created (as it will be passed back to it through * {@link UserLifecycleListener#onUserCreated(UserInfo, Object)}); */ - public abstract UserInfo createUserEvenWhenDisallowed(String name, String userType, - int flags, String[] disallowedPackages, @Nullable Object token) + public abstract @NonNull UserInfo createUserEvenWhenDisallowed( + @Nullable String name, @NonNull String userType, @UserInfo.UserInfoFlag int flags, + @Nullable String[] disallowedPackages, @Nullable Object token) throws UserManager.CheckedUserOperationException; /** diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 372b580214cd1..a22ea9626bc0c 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -4495,9 +4495,11 @@ public class UserManagerService extends IUserManager.Stub { * as well as for {@link UserManager#USER_TYPE_FULL_RESTRICTED}. */ @Override - public UserInfo createProfileForUserWithThrow(@Nullable String name, @NonNull String userType, - @UserInfoFlag int flags, @UserIdInt int userId, @Nullable String[] disallowedPackages) + public @NonNull UserInfo createProfileForUserWithThrow( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, + @UserIdInt int userId, @Nullable String[] disallowedPackages) throws ServiceSpecificException { + checkCreateUsersPermission(flags); try { return createUserInternal(name, userType, flags, userId, disallowedPackages); @@ -4510,10 +4512,11 @@ public class UserManagerService extends IUserManager.Stub { * @see #createProfileForUser */ @Override - public UserInfo createProfileForUserEvenWhenDisallowedWithThrow(String name, - @NonNull String userType, - @UserInfoFlag int flags, @UserIdInt int userId, @Nullable String[] disallowedPackages) + public @NonNull UserInfo createProfileForUserEvenWhenDisallowedWithThrow( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, + @UserIdInt int userId, @Nullable String[] disallowedPackages) throws ServiceSpecificException { + checkCreateUsersPermission(flags); try { return createUserInternalUnchecked(name, userType, flags, userId, @@ -4524,9 +4527,10 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo createUserWithThrow(String name, @NonNull String userType, - @UserInfoFlag int flags) + public @NonNull UserInfo createUserWithThrow( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags) throws ServiceSpecificException { + checkCreateUsersPermission(flags); try { return createUserInternal(name, userType, flags, UserHandle.USER_NULL, @@ -4537,7 +4541,10 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo preCreateUserWithThrow(String userType) throws ServiceSpecificException { + public @NonNull UserInfo preCreateUserWithThrow( + @NonNull String userType) + throws ServiceSpecificException { + final UserTypeDetails userTypeDetails = mUserTypes.get(userType); final int flags = userTypeDetails != null ? userTypeDetails.getDefaultUserInfoFlags() : 0; @@ -4557,10 +4564,12 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserHandle createUserWithAttributes( - String userName, String userType, @UserInfoFlag int flags, - Bitmap userIcon, - String accountName, String accountType, PersistableBundle accountOptions) { + public @NonNull UserHandle createUserWithAttributes( + @Nullable String userName, @NonNull String userType, @UserInfoFlag int flags, + @Nullable Bitmap userIcon, @Nullable String accountName, @Nullable String accountType, + @Nullable PersistableBundle accountOptions) + throws ServiceSpecificException { + checkCreateUsersPermission(flags); if (someUserHasAccountNoChecks(accountName, accountType)) { @@ -4570,12 +4579,7 @@ public class UserManagerService extends IUserManager.Stub { UserInfo userInfo; try { - userInfo = createUserInternal(userName, userType, flags, - UserHandle.USER_NULL, null); - - if (userInfo == null) { - throw new ServiceSpecificException(USER_OPERATION_ERROR_UNKNOWN); - } + userInfo = createUserInternal(userName, userType, flags, UserHandle.USER_NULL, null); } catch (UserManager.CheckedUserOperationException e) { throw e.toServiceSpecificException(); } @@ -4589,7 +4593,8 @@ public class UserManagerService extends IUserManager.Stub { return userInfo.getUserHandle(); } - private UserInfo createUserInternal(@Nullable String name, @NonNull String userType, + private @NonNull UserInfo createUserInternal( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId, @Nullable String[] disallowedPackages) throws UserManager.CheckedUserOperationException { @@ -4611,11 +4616,12 @@ public class UserManagerService extends IUserManager.Stub { /* preCreate= */ false, disallowedPackages, /* token= */ null); } - private UserInfo createUserInternalUnchecked(@Nullable String name, - @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId, - boolean preCreate, @Nullable String[] disallowedPackages, + private @NonNull UserInfo createUserInternalUnchecked( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, + @UserIdInt int parentId, boolean preCreate, @Nullable String[] disallowedPackages, @Nullable Object token) throws UserManager.CheckedUserOperationException { + final int noneUserId = -1; final TimingsTraceAndSlog t = new TimingsTraceAndSlog(); t.traceBegin("createUser-" + flags); @@ -4633,27 +4639,31 @@ public class UserManagerService extends IUserManager.Stub { } } - private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name, - @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId, - boolean preCreate, @Nullable String[] disallowedPackages, + private @NonNull UserInfo createUserInternalUncheckedNoTracing( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, + @UserIdInt int parentId, boolean preCreate, @Nullable String[] disallowedPackages, @NonNull TimingsTraceAndSlog t, @Nullable Object token) - throws UserManager.CheckedUserOperationException { + throws UserManager.CheckedUserOperationException { + final UserTypeDetails userTypeDetails = mUserTypes.get(userType); if (userTypeDetails == null) { - Slog.e(LOG_TAG, "Cannot create user of invalid user type: " + userType); - return null; + throwCheckedUserOperationException( + "Cannot create user of invalid user type: " + userType, + USER_OPERATION_ERROR_UNKNOWN); } userType = userType.intern(); // Now that we know it's valid, we can intern it. flags |= userTypeDetails.getDefaultUserInfoFlags(); if (!checkUserTypeConsistency(flags)) { - Slog.e(LOG_TAG, "Cannot add user. Flags (" + Integer.toHexString(flags) - + ") and userTypeDetails (" + userType + ") are inconsistent."); - return null; + throwCheckedUserOperationException( + "Cannot add user. Flags (" + Integer.toHexString(flags) + + ") and userTypeDetails (" + userType + ") are inconsistent.", + USER_OPERATION_ERROR_UNKNOWN); } if ((flags & UserInfo.FLAG_SYSTEM) != 0) { - Slog.e(LOG_TAG, "Cannot add user. Flags (" + Integer.toHexString(flags) - + ") indicated SYSTEM user, which cannot be created."); - return null; + throwCheckedUserOperationException( + "Cannot add user. Flags (" + Integer.toHexString(flags) + + ") indicated SYSTEM user, which cannot be created.", + USER_OPERATION_ERROR_UNKNOWN); } if (!isUserTypeEnabled(userTypeDetails)) { throwCheckedUserOperationException( @@ -4679,7 +4689,8 @@ public class UserManagerService extends IUserManager.Stub { DeviceStorageMonitorInternal dsm = LocalServices .getService(DeviceStorageMonitorInternal.class); if (dsm.isMemoryLow()) { - throwCheckedUserOperationException("Cannot add user. Not enough space on disk.", + throwCheckedUserOperationException( + "Cannot add user. Not enough space on disk.", UserManager.USER_OPERATION_ERROR_LOW_STORAGE); } @@ -4707,7 +4718,8 @@ public class UserManagerService extends IUserManager.Stub { } } if (!preCreate && !canAddMoreUsersOfType(userTypeDetails)) { - throwCheckedUserOperationException("Cannot add more users of type " + userType + throwCheckedUserOperationException( + "Cannot add more users of type " + userType + ". Maximum number of that type already exists.", UserManager.USER_OPERATION_ERROR_MAX_USERS); } @@ -5332,13 +5344,13 @@ public class UserManagerService extends IUserManager.Stub { * @hide */ @Override - public UserInfo createRestrictedProfileWithThrow(@Nullable String name, int parentUserId) { + public @NonNull UserInfo createRestrictedProfileWithThrow( + @Nullable String name, @UserIdInt int parentUserId) + throws ServiceSpecificException { + checkCreateUsersPermission("setupRestrictedProfile"); final UserInfo user = createProfileForUserWithThrow( name, UserManager.USER_TYPE_FULL_RESTRICTED, 0, parentUserId, null); - if (user == null) { - return null; - } final long identity = Binder.clearCallingIdentity(); try { setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user.id); @@ -6339,8 +6351,10 @@ public class UserManagerService extends IUserManager.Stub { setSeedAccountDataNoChecks(userId, accountName, accountType, accountOptions, persist); } - private void setSeedAccountDataNoChecks(@UserIdInt int userId, String accountName, - String accountType, PersistableBundle accountOptions, boolean persist) { + private void setSeedAccountDataNoChecks(@UserIdInt int userId, @Nullable String accountName, + @Nullable String accountType, @Nullable PersistableBundle accountOptions, + boolean persist) { + synchronized (mPackagesLock) { final UserData userData; synchronized (mUsersLock) { @@ -6909,9 +6923,11 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo createUserEvenWhenDisallowed(String name, @NonNull String userType, - @UserInfoFlag int flags, String[] disallowedPackages, @Nullable Object token) + public @NonNull UserInfo createUserEvenWhenDisallowed( + @Nullable String name, @NonNull String userType, @UserInfoFlag int flags, + @Nullable String[] disallowedPackages, @Nullable Object token) throws UserManager.CheckedUserOperationException { + return createUserInternalUnchecked(name, userType, flags, UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages, token); } diff --git a/services/java/com/android/server/HsumBootUserInitializer.java b/services/java/com/android/server/HsumBootUserInitializer.java index a1853b4632fcf..50113feb558b4 100644 --- a/services/java/com/android/server/HsumBootUserInitializer.java +++ b/services/java/com/android/server/HsumBootUserInitializer.java @@ -113,11 +113,7 @@ final class HsumBootUserInitializer { UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN, /* disallowedPackages= */ null, /* token= */ null); - if (newInitialUser == null) { - Slogf.wtf(TAG, "Initial bootable MainUser creation failed: returned null"); - } else { - Slogf.i(TAG, "Successfully created MainUser, userId=%d", newInitialUser.id); - } + Slogf.i(TAG, "Successfully created MainUser, userId=%d", newInitialUser.id); } catch (UserManager.CheckedUserOperationException e) { Slogf.wtf(TAG, "Initial bootable MainUser creation failed", e); }