Merge "Fixed createAndManageUser() for headless system user mode." into sc-dev

This commit is contained in:
Felipe Leme
2021-03-01 16:46:04 +00:00
committed by Android (Google) Code Review
4 changed files with 117 additions and 47 deletions

View File

@@ -585,6 +585,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
* @param intent The received intent as per {@link #onReceive}.
*/
public void onEnabled(@NonNull Context context, @NonNull Intent intent) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onEnabled() on user " + context.getUserId());
}
}
/**
@@ -600,6 +603,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
public @Nullable CharSequence onDisableRequested(@NonNull Context context,
@NonNull Intent intent) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onDisableRequested() on user "
+ context.getUserId());
}
return null;
}
@@ -612,6 +619,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
* @param intent The received intent as per {@link #onReceive}.
*/
public void onDisabled(@NonNull Context context, @NonNull Intent intent) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onDisabled() on user " + context.getUserId());
}
}
/**
@@ -786,6 +796,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
* @param intent The received intent as per {@link #onReceive}.
*/
public void onProfileProvisioningComplete(@NonNull Context context, @NonNull Intent intent) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onProfileProvisioningComplete() on user "
+ context.getUserId());
}
}
/**
@@ -961,6 +975,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
public void onUserAdded(@NonNull Context context, @NonNull Intent intent,
@NonNull UserHandle addedUser) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onUserAdded() on user " + context.getUserId());
}
}
/**
@@ -974,6 +991,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
public void onUserRemoved(@NonNull Context context, @NonNull Intent intent,
@NonNull UserHandle removedUser) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onUserRemoved() on user " + context.getUserId());
}
}
/**
@@ -987,6 +1007,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
public void onUserStarted(@NonNull Context context, @NonNull Intent intent,
@NonNull UserHandle startedUser) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onUserStarted() on user " + context.getUserId());
}
}
/**
@@ -1000,6 +1023,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
public void onUserStopped(@NonNull Context context, @NonNull Intent intent,
@NonNull UserHandle stoppedUser) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onUserStopped() on user " + context.getUserId());
}
}
/**
@@ -1013,6 +1039,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
*/
public void onUserSwitched(@NonNull Context context, @NonNull Intent intent,
@NonNull UserHandle switchedUser) {
if (LOCAL_LOGV) {
Log.v(TAG, getClass().getName() + ".onUserSwitched() on user " + context.getUserId());
}
}
/**
@@ -1104,7 +1133,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
String action = intent.getAction();
if (LOCAL_LOGV) {
Log.v(TAG, "onReceive(): received " + action + " on user " + context.getUserId());
Log.v(TAG, getClass().getName() + ".onReceive(): received " + action + " on user "
+ context.getUserId());
}
if (ACTION_PASSWORD_CHANGED.equals(action)) {

View File

@@ -63,8 +63,13 @@ public abstract class UserManagerInternal {
*/
public interface UserLifecycleListener {
/** Called when a new user is created. */
default void onUserCreated(UserInfo user) {}
/**
* Called when a new user is created.
*
* @param user new user.
* @param token token passed to the method that created the user.
*/
default void onUserCreated(UserInfo user, @Nullable Object token) {}
/** Called when an existing user is removed. */
default void onUserRemoved(UserInfo user) {}
@@ -179,10 +184,12 @@ public abstract class UserManagerInternal {
* {@link UserManager#DISALLOW_ADD_USER} and {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}
*
* <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
* createAndManageUser is called by the device owner.
* createAndManageUser is called by the device owner; it uses {@code token} to block until
* 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)
int flags, String[] disallowedPackages, @Nullable Object token)
throws UserManager.CheckedUserOperationException;
/**

View File

@@ -3323,7 +3323,7 @@ public class UserManagerService extends IUserManager.Stub {
checkManageOrCreateUsersPermission(flags);
try {
return createUserInternalUnchecked(name, userType, flags, userId,
/* preCreate= */ false, disallowedPackages);
/* preCreate= */ false, disallowedPackages, /* token= */ null);
} catch (UserManager.CheckedUserOperationException e) {
throw e.toServiceSpecificException();
}
@@ -3356,7 +3356,7 @@ public class UserManagerService extends IUserManager.Stub {
try {
return createUserInternalUnchecked(/* name= */ null, userType, flags,
/* parentId= */ UserHandle.USER_NULL, /* preCreate= */ true,
/* disallowedPackages= */ null);
/* disallowedPackages= */ null, /* token= */ null);
} catch (UserManager.CheckedUserOperationException e) {
throw e.toServiceSpecificException();
}
@@ -3372,12 +3372,13 @@ public class UserManagerService extends IUserManager.Stub {
enforceUserRestriction(restriction, UserHandle.getCallingUserId(),
"Cannot add user");
return createUserInternalUnchecked(name, userType, flags, parentId,
/* preCreate= */ false, disallowedPackages);
/* 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)
boolean preCreate, @Nullable String[] disallowedPackages,
@Nullable Object token)
throws UserManager.CheckedUserOperationException {
final int nextProbableUserId = getNextAvailableId();
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
@@ -3386,7 +3387,7 @@ public class UserManagerService extends IUserManager.Stub {
UserInfo newUser = null;
try {
newUser = createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
preCreate, disallowedPackages, t);
preCreate, disallowedPackages, t, token);
return newUser;
} finally {
logUserCreateJourneyFinish(sessionId, nextProbableUserId, newUser != null);
@@ -3397,7 +3398,8 @@ 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,
@NonNull TimingsTraceAndSlog t) throws UserManager.CheckedUserOperationException {
@NonNull TimingsTraceAndSlog t, @Nullable Object token)
throws UserManager.CheckedUserOperationException {
final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
if (userTypeDetails == null) {
Slog.e(LOG_TAG, "Cannot create user of invalid user type: " + userType);
@@ -3423,7 +3425,8 @@ public class UserManagerService extends IUserManager.Stub {
// Try to use a pre-created user (if available).
if (!preCreate && parentId < 0 && isUserTypeEligibleForPreCreation(userTypeDetails)) {
final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name);
final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name,
token);
if (preCreatedUser != null) {
return preCreatedUser;
}
@@ -3602,7 +3605,7 @@ public class UserManagerService extends IUserManager.Stub {
Slog.w(LOG_TAG, "could not start pre-created user " + userId, e);
}
} else {
dispatchUserAdded(userInfo);
dispatchUserAdded(userInfo, token);
}
} finally {
@@ -3702,7 +3705,7 @@ public class UserManagerService extends IUserManager.Stub {
* @return the converted user, or {@code null} if no pre-created user could be converted.
*/
private @Nullable UserInfo convertPreCreatedUserIfPossible(String userType,
@UserInfoFlag int flags, String name) {
@UserInfoFlag int flags, String name, @Nullable Object token) {
final UserData preCreatedUserData;
synchronized (mUsersLock) {
preCreatedUserData = getPreCreatedUserLU(userType);
@@ -3740,7 +3743,7 @@ public class UserManagerService extends IUserManager.Stub {
}
updateUserIds();
mPm.onNewUserCreated(preCreatedUser.id, /* convertedFromPreCreated= */ true);
dispatchUserAdded(preCreatedUser);
dispatchUserAdded(preCreatedUser, token);
return preCreatedUser;
}
@@ -3772,11 +3775,11 @@ public class UserManagerService extends IUserManager.Stub {
return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
}
private void dispatchUserAdded(@NonNull UserInfo userInfo) {
private void dispatchUserAdded(@NonNull UserInfo userInfo, @Nullable Object token) {
// Notify internal listeners first...
synchronized (mUserLifecycleListeners) {
for (int i = 0; i < mUserLifecycleListeners.size(); i++) {
mUserLifecycleListeners.get(i).onUserCreated(userInfo);
mUserLifecycleListeners.get(i).onUserCreated(userInfo, token);
}
}
@@ -5381,10 +5384,10 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo createUserEvenWhenDisallowed(String name, @NonNull String userType,
@UserInfoFlag int flags, String[] disallowedPackages)
@UserInfoFlag int flags, String[] disallowedPackages, @Nullable Object token)
throws UserManager.CheckedUserOperationException {
return createUserInternalUnchecked(name, userType, flags,
UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages);
UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages, token);
}
@Override

View File

@@ -715,6 +715,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Nullable
private DevicePolicySafetyChecker mSafetyChecker;
@GuardedBy("getLockObject()")
private final ArrayList<Object> mPendingUserCreatedCallbackTokens = new ArrayList<>();
public static final class Lifecycle extends SystemService {
private BaseIDevicePolicyManager mService;
@@ -965,8 +968,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener {
@Override
public void onUserCreated(UserInfo user) {
mHandler.post(() -> handleNewUserCreated(user));
public void onUserCreated(UserInfo user, Object token) {
mHandler.post(() -> handleNewUserCreated(user, token));
}
}
@@ -3151,11 +3154,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
setActiveAdmin(adminReceiver, refreshing, userHandle, null);
}
private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
Bundle onEnableData) {
Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
final CallerIdentity caller = getCallerIdentity();
@@ -3198,7 +3196,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
saveSettingsLocked(userHandle);
sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
onEnableData, null);
/* adminExtras= */ null, /* result= */ null);
});
}
}
@@ -9190,6 +9188,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
pw.println();
if (mPendingUserCreatedCallbackTokens.isEmpty()) {
pw.println("no pending user created callback tokens");
} else {
int size = mPendingUserCreatedCallbackTokens.size();
pw.printf("%d pending user created callback token%s\n", size,
(size == 1 ? "" : "s"));
}
pw.println();
mPolicyCache.dump(pw);
pw.println();
mStateCache.dump(pw);
@@ -9946,8 +9954,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
clearInitBundle = sendAdminCommandLocked(admin,
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
initBundle == null ? null : new Bundle(initBundle),
null /* result receiver */,
true /* send in foreground */);
/* result= */ null ,
/* inForeground= */ true);
}
if (clearInitBundle) {
// If there's no admin or we've successfully called the admin, clear the init bundle
@@ -10020,9 +10028,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
UserHandle.myUserId(), ACTION_PROVISION_MANAGED_USER).toArray(
new String[0]);
}
Object token = new Object();
Slog.d(LOG_TAG, "Adding new pending token: " + token);
mPendingUserCreatedCallbackTokens.add(token);
try {
UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
userType, userInfoFlags, disallowedPackages);
userType, userInfoFlags, disallowedPackages, token);
if (userInfo != null) {
user = userInfo.getUserHandle();
}
@@ -10032,7 +10044,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
}
} // synchronized
if (user == null) {
if (targetSdkVersion >= Build.VERSION_CODES.P) {
throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN,
@@ -10054,14 +10067,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final long id = mInjector.binderClearCallingIdentity();
try {
if (!mInjector.userManagerIsHeadlessSystemUserMode()) {
manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
/* showDisclaimer= */ true);
} else if (VERBOSE_LOG) {
Slog.v(LOG_TAG, "createAndManageUser(): skipping manageUserUnchecked() on user "
+ userHandle + " on headless system user as it will be called by "
+ "handleNewUserCreated()");
}
manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
/* showDisclaimer= */ true);
if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -10083,7 +10090,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner,
@UserIdInt int userId, PersistableBundle adminExtras, boolean showDisclaimer) {
@UserIdInt int userId, @Nullable PersistableBundle adminExtras,
boolean showDisclaimer) {
synchronized (getLockObject()) {
if (VERBOSE_LOG) {
Slog.v(LOG_TAG, "manageUserUnchecked(): admin=" + admin + ", po=" + profileOwner
+ ", userId=" + userId + ", hasAdminExtras=" + (adminExtras != null)
+ ", showDisclaimer=" + showDisclaimer);
}
}
final String adminPkg = admin.getPackageName();
try {
// Install the profile owner if not present.
@@ -10113,23 +10128,37 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
? DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED
: DevicePolicyData.NEW_USER_DISCLAIMER_NOT_NEEDED;
saveSettingsLocked(userId);
}
}
private void handleNewUserCreated(UserInfo user) {
if (VERBOSE_LOG) Slog.v(LOG_TAG, "handleNewUserCreated(): " + user.toFullString());
if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
private void handleNewUserCreated(UserInfo user, @Nullable Object token) {
if (VERBOSE_LOG) {
Slog.v(LOG_TAG, "handleNewUserCreated(): user=" + user.toFullString()
+ ", token=" + token);
}
final int userId = user.id;
if (token != null) {
synchronized (getLockObject()) {
if (mPendingUserCreatedCallbackTokens.contains(token)) {
// Ignore because it was triggered by createAndManageUser()
Slog.d(LOG_TAG, "handleNewUserCreated(): ignoring for user " + userId
+ " due to token" + token);
mPendingUserCreatedCallbackTokens.remove(token);
return;
}
}
}
if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
if (mInjector.userManagerIsHeadlessSystemUserMode()) {
ComponentName admin = mOwners.getDeviceOwnerComponent();
Slog.i(LOG_TAG, "Automatically setting profile owner (" + admin + ") on new user "
+ userId);
manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
/* managedUser= */ userId, /* adminExtras= */ null,
/* showDisclaimer= */ true);
/* managedUser= */ userId, /* adminExtras= */ null, /* showDisclaimer= */ true);
} else {
Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
@@ -10250,11 +10279,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final long id = mInjector.binderClearCallingIdentity();
try {
if (!mInjector.getActivityManagerInternal().canStartMoreUsers()) {
Log.w(LOG_TAG, "Cannot start more users in background");
Log.w(LOG_TAG, "Cannot start user " + userId + ", too many users in background");
return UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
}
if (mInjector.getIActivityManager().startUserInBackground(userId)) {
Log.i(LOG_TAG, "Started used " + userId + " in background");
return UserManager.USER_OPERATION_SUCCESS;
} else {
return UserManager.USER_OPERATION_ERROR_UNKNOWN;