Merge "Fixed createAndManageUser() for headless system user mode." into sc-dev
This commit is contained in:
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user