Merge "Improve headless system user's DO setup flow"
This commit is contained in:
@@ -2056,7 +2056,9 @@ public class DevicePolicyManager {
|
||||
/**
|
||||
* Result code for {@link #checkProvisioningPreCondition}.
|
||||
*
|
||||
* <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user.
|
||||
* <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user and
|
||||
* for {@link #ACTION_PROVISION_MANAGED_DEVICE} on devices running headless system user mode
|
||||
* and the user is a system user.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -6112,9 +6112,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
private void forceWipeUser(int userId, String wipeReasonForUser, boolean wipeSilently) {
|
||||
boolean success = false;
|
||||
try {
|
||||
IActivityManager am = mInjector.getIActivityManager();
|
||||
if (am.getCurrentUser().id == userId) {
|
||||
am.switchUser(UserHandle.USER_SYSTEM);
|
||||
if (getCurrentForegroundUser() == userId) {
|
||||
mInjector.getIActivityManager().switchUser(UserHandle.USER_SYSTEM);
|
||||
}
|
||||
|
||||
success = mUserManagerInternal.removeUserEvenWhenDisallowed(userId);
|
||||
@@ -7578,9 +7577,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
Slog.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId);
|
||||
|
||||
if (mInjector.userManagerIsHeadlessSystemUserMode()) {
|
||||
Slog.i(LOG_TAG, "manageUser: " + admin + " on user " + userId);
|
||||
|
||||
manageUser(admin, admin, caller.getUserId(), null);
|
||||
int currentForegroundUser = getCurrentForegroundUser();
|
||||
Slog.i(LOG_TAG, "setDeviceOwner(): setting " + admin
|
||||
+ " as profile owner on user " + currentForegroundUser);
|
||||
// Sets profile owner on current foreground user since
|
||||
// the human user will complete the DO setup workflow from there.
|
||||
mInjector.binderWithCleanCallingIdentity(() ->
|
||||
manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
|
||||
/* managedUser= */ currentForegroundUser,
|
||||
/* adminExtras= */ null));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -8565,16 +8570,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
* permission.
|
||||
*/
|
||||
private void enforceCanSetDeviceOwnerLocked(CallerIdentity caller,
|
||||
@Nullable ComponentName owner, @UserIdInt int userId) {
|
||||
@Nullable ComponentName owner, @UserIdInt int deviceOwnerUserId) {
|
||||
if (!isAdb(caller)) {
|
||||
Preconditions.checkCallAuthorization(
|
||||
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|
||||
}
|
||||
|
||||
final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner, userId,
|
||||
isAdb(caller), hasIncompatibleAccountsOrNonAdbNoLock(caller, userId, owner));
|
||||
final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner,
|
||||
/* deviceOwnerUserId= */ deviceOwnerUserId, /* callingUserId*/ caller.getUserId(),
|
||||
isAdb(caller),
|
||||
hasIncompatibleAccountsOrNonAdbNoLock(caller, deviceOwnerUserId, owner));
|
||||
if (code != CODE_OK) {
|
||||
throw new IllegalStateException(computeProvisioningErrorString(code, userId));
|
||||
throw new IllegalStateException(
|
||||
computeProvisioningErrorString(code, deviceOwnerUserId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8702,6 +8710,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
return UserHandle.isSameApp(caller.getUid(), Process.SHELL_UID);
|
||||
}
|
||||
|
||||
private @UserIdInt int getCurrentForegroundUser() {
|
||||
try {
|
||||
return mInjector.getIActivityManager().getCurrentUser().id;
|
||||
} catch (RemoteException e) {
|
||||
Slog.wtf(LOG_TAG, "cannot get current user");
|
||||
}
|
||||
return UserHandle.USER_NULL;
|
||||
}
|
||||
|
||||
protected int getProfileParentId(int userHandle) {
|
||||
return mInjector.binderWithCleanCallingIdentity(() -> {
|
||||
UserInfo parentUser = mUserManager.getProfileParent(userHandle);
|
||||
@@ -9613,7 +9630,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
|
||||
final long id = mInjector.binderClearCallingIdentity();
|
||||
try {
|
||||
manageUser(admin, profileOwner, userHandle, adminExtras);
|
||||
manageUserUnchecked(admin, profileOwner, userHandle, adminExtras);
|
||||
|
||||
if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
|
||||
Settings.Secure.putIntForUser(mContext.getContentResolver(),
|
||||
@@ -9634,43 +9651,34 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void manageUser(ComponentName admin, ComponentName profileOwner,
|
||||
private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner,
|
||||
@UserIdInt int userId, PersistableBundle adminExtras) {
|
||||
// Check for permission
|
||||
final CallerIdentity caller = getCallerIdentity();
|
||||
Preconditions.checkCallAuthorization(canManageUsers(caller));
|
||||
Preconditions.checkCallAuthorization(
|
||||
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|
||||
mInjector.binderWithCleanCallingIdentity(() ->
|
||||
manageUserNoCheck(admin, profileOwner, userId, adminExtras));
|
||||
}
|
||||
|
||||
private void manageUserNoCheck(ComponentName admin, ComponentName profileOwner,
|
||||
int user, PersistableBundle adminExtras) {
|
||||
|
||||
final String adminPkg = admin.getPackageName();
|
||||
try {
|
||||
// Install the profile owner if not present.
|
||||
if (!mIPackageManager.isPackageAvailable(adminPkg, user)) {
|
||||
mIPackageManager.installExistingPackageAsUser(adminPkg, user,
|
||||
if (!mIPackageManager.isPackageAvailable(adminPkg, userId)) {
|
||||
mIPackageManager.installExistingPackageAsUser(adminPkg, userId,
|
||||
PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
|
||||
PackageManager.INSTALL_REASON_POLICY, null);
|
||||
PackageManager.INSTALL_REASON_POLICY,
|
||||
/* allowlistedRestrictedPermissions= */ null);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Does not happen, same process
|
||||
Slog.wtf(LOG_TAG, String.format("Failed to install admin package %s for user %d",
|
||||
adminPkg, userId), e);
|
||||
}
|
||||
|
||||
// Set admin.
|
||||
setActiveAdmin(profileOwner, true, user);
|
||||
setActiveAdmin(profileOwner, /* refreshing= */ true, userId);
|
||||
final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
|
||||
setProfileOwner(profileOwner, ownerName, user);
|
||||
setProfileOwner(profileOwner, ownerName, userId);
|
||||
|
||||
synchronized (getLockObject()) {
|
||||
DevicePolicyData policyData = getUserData(user);
|
||||
DevicePolicyData policyData = getUserData(userId);
|
||||
policyData.mInitBundle = adminExtras;
|
||||
policyData.mAdminBroadcastPending = true;
|
||||
|
||||
saveSettingsLocked(user);
|
||||
saveSettingsLocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12304,7 +12312,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
* except for adb command if no accounts or additional users are present on the device.
|
||||
*/
|
||||
private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner,
|
||||
@UserIdInt int deviceOwnerUserId, boolean isAdb,
|
||||
@UserIdInt int deviceOwnerUserId, @UserIdInt int callingUserId, boolean isAdb,
|
||||
boolean hasIncompatibleAccountsOrNonAdb) {
|
||||
if (mOwners.hasDeviceOwner()) {
|
||||
return CODE_HAS_DEVICE_OWNER;
|
||||
@@ -12320,6 +12328,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
|
||||
return CODE_HAS_PAIRED;
|
||||
}
|
||||
|
||||
if (mInjector.userManagerIsHeadlessSystemUserMode()) {
|
||||
if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
|
||||
Slog.e(LOG_TAG, "In headless system user mode, "
|
||||
+ "device owner can only be set on headless system user.");
|
||||
return CODE_NOT_SYSTEM_USER;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (b/137101239): clean up split system user codes
|
||||
if (isAdb) {
|
||||
// If shell command runs after user setup completed check device status. Otherwise, OK.
|
||||
@@ -12331,6 +12348,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
&& mUserManager.getUserCount() > 1) {
|
||||
return CODE_NONSYSTEM_USER_EXISTS;
|
||||
}
|
||||
|
||||
int currentForegroundUser = getCurrentForegroundUser();
|
||||
if (callingUserId != currentForegroundUser
|
||||
&& mInjector.userManagerIsHeadlessSystemUserMode()
|
||||
&& currentForegroundUser == UserHandle.USER_SYSTEM) {
|
||||
Slog.wtf(LOG_TAG, "In headless system user mode, "
|
||||
+ "current user cannot be system user when setting device owner");
|
||||
return CODE_SYSTEM_USER;
|
||||
}
|
||||
if (hasIncompatibleAccountsOrNonAdb) {
|
||||
return CODE_ACCOUNTS_NOT_EMPTY;
|
||||
}
|
||||
@@ -12362,7 +12388,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
callingUserId, deviceOwnerUserId));
|
||||
// hasIncompatibleAccountsOrNonAdb doesn't matter since the caller is not adb.
|
||||
return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null,
|
||||
deviceOwnerUserId, /* isAdb= */ false,
|
||||
deviceOwnerUserId, callingUserId, /* isAdb= */ false,
|
||||
/* hasIncompatibleAccountsOrNonAdb=*/ true);
|
||||
}
|
||||
}
|
||||
@@ -14901,8 +14927,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
}
|
||||
|
||||
private boolean isLockTaskFeatureEnabled(int lockTaskFeature) throws RemoteException {
|
||||
//TODO(b/175285301): Explicitly get the user's identity to check.
|
||||
int lockTaskFeatures =
|
||||
getUserData(mInjector.getIActivityManager().getCurrentUser().id).mLockTaskFeatures;
|
||||
getUserData(getCurrentForegroundUser()).mLockTaskFeatures;
|
||||
return (lockTaskFeatures & lockTaskFeature) == lockTaskFeature;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user