Rework device policy user restrctions.

Removed the "global" and "local" restriction sets. All restrictions
set from the DPM are now stored as a single restriction set. "global"
restrictions are stored with the userID ALL_USERS.

Test: btest "android.devicepolicy.cts.UserRestrictionsTest"
Change-Id: I504b16bbbac99ac731580247b57f55a9b213609f
This commit is contained in:
Jason Parks
2022-12-06 18:09:13 +00:00
parent cac70c6f1e
commit d3ecb37848
5 changed files with 143 additions and 254 deletions

View File

@@ -20,7 +20,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.util.IntArray;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
@@ -37,9 +39,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Data structure that contains the mapping of users to user restrictions (either the user * Data structure that contains the mapping of users to user restrictions.
* restrictions that apply to them, or the user restrictions that they set, depending on the
* circumstances).
* *
* @hide * @hide
*/ */
@@ -87,6 +87,24 @@ public class RestrictionsSet {
return true; return true;
} }
/**
* Removes a particular restriction for all users.
*
* @return whether the restriction was removed or not.
*/
public boolean removeRestrictionsForAllUsers(String restriction) {
boolean removed = false;
for (int i = 0; i < mUserRestrictions.size(); i++) {
final Bundle restrictions = mUserRestrictions.valueAt(i);
if (UserRestrictionsUtils.contains(restrictions, restriction)) {
restrictions.remove(restriction);
removed = true;
}
}
return removed;
}
/** /**
* Moves a particular restriction from one restriction set to another, e.g. for all users. * Moves a particular restriction from one restriction set to another, e.g. for all users.
*/ */
@@ -139,22 +157,19 @@ public class RestrictionsSet {
* @return list of enforcing users that enforce a particular restriction. * @return list of enforcing users that enforce a particular restriction.
*/ */
public @NonNull List<UserManager.EnforcingUser> getEnforcingUsers(String restriction, public @NonNull List<UserManager.EnforcingUser> getEnforcingUsers(String restriction,
@UserIdInt int deviceOwnerUserId) { @UserIdInt int userId) {
final List<UserManager.EnforcingUser> result = new ArrayList<>(); final List<UserManager.EnforcingUser> result = new ArrayList<>();
for (int i = 0; i < mUserRestrictions.size(); i++) { if (getRestrictionsNonNull(userId).containsKey(restriction)) {
if (UserRestrictionsUtils.contains(mUserRestrictions.valueAt(i), restriction)) { result.add(new UserManager.EnforcingUser(userId,
result.add(getEnforcingUser(mUserRestrictions.keyAt(i), deviceOwnerUserId)); UserManager.RESTRICTION_SOURCE_PROFILE_OWNER));
}
} }
return result;
}
private UserManager.EnforcingUser getEnforcingUser(@UserIdInt int userId, if (getRestrictionsNonNull(UserHandle.USER_ALL).containsKey(restriction)) {
@UserIdInt int deviceOwnerUserId) { result.add(new UserManager.EnforcingUser(UserHandle.USER_ALL,
int source = deviceOwnerUserId == userId UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER }
: UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
return new UserManager.EnforcingUser(userId, source); return result;
} }
/** /**
@@ -165,6 +180,11 @@ public class RestrictionsSet {
return mUserRestrictions.get(userId); return mUserRestrictions.get(userId);
} }
/** @return list of user restrictions for a given user that is not null. */
public @NonNull Bundle getRestrictionsNonNull(@UserIdInt int userId) {
return UserRestrictionsUtils.nonNull(mUserRestrictions.get(userId));
}
/** /**
* Removes a given user from the restrictions set, returning true if the user has non-empty * Removes a given user from the restrictions set, returning true if the user has non-empty
* restrictions before removal. * restrictions before removal.
@@ -236,6 +256,15 @@ public class RestrictionsSet {
} }
} }
/** @return list of users in this restriction set. */
public IntArray getUserIds() {
IntArray userIds = new IntArray(mUserRestrictions.size());
for (int i = 0; i < mUserRestrictions.size(); i++) {
userIds.add(mUserRestrictions.keyAt(i));
}
return userIds;
}
public boolean containsKey(@UserIdInt int userId) { public boolean containsKey(@UserIdInt int userId) {
return mUserRestrictions.contains(userId); return mUserRestrictions.contains(userId);
} }

View File

@@ -141,6 +141,18 @@ public abstract class UserManagerInternal {
public abstract void setDevicePolicyUserRestrictions(int originatingUserId, public abstract void setDevicePolicyUserRestrictions(int originatingUserId,
@Nullable Bundle global, @Nullable RestrictionsSet local, boolean isDeviceOwner); @Nullable Bundle global, @Nullable RestrictionsSet local, boolean isDeviceOwner);
/**
* Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set a
* user restriction.
*
* @param userId user id to apply the restriction to. {@link com.android.os.UserHandle.USER_ALL}
* will apply the restriction to all users globally.
* @param key The key of the restriction.
* @param value The value of the restriction.
*/
public abstract void setUserRestriction(@UserIdInt int userId, @NonNull String key,
boolean value);
/** Return a user restriction. */ /** Return a user restriction. */
public abstract boolean getUserRestriction(int userId, String key); public abstract boolean getUserRestriction(int userId, String key);

View File

@@ -457,30 +457,12 @@ public class UserManagerService extends IUserManager.Stub {
/** /**
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService} * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
* that should be applied to all users, including guests. Only non-empty restriction bundles are * for each user. Restrictions that apply to all users (global) are represented by
* stored. * {@link com.android.os.UserHandle.USER_ALL}.
* The key is the user id of the user whom the restriction originated from.
*/
@GuardedBy("mRestrictionsLock")
private final RestrictionsSet mDevicePolicyGlobalUserRestrictions = new RestrictionsSet();
/**
* Id of the user that set global restrictions.
*/
@GuardedBy("mRestrictionsLock")
private int mDeviceOwnerUserId = UserHandle.USER_NULL;
/**
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
* for each user.
* The key is the user id of the user whom the restrictions are targeting. * The key is the user id of the user whom the restrictions are targeting.
* The key inside the restrictionsSet is the user id of the user whom the restriction
* originated from.
* targetUserId -> originatingUserId -> restrictionBundle
*/ */
@GuardedBy("mRestrictionsLock") @GuardedBy("mRestrictionsLock")
private final SparseArray<RestrictionsSet> mDevicePolicyLocalUserRestrictions = private final RestrictionsSet mDevicePolicyUserRestrictions = new RestrictionsSet();
new SparseArray<>();
@GuardedBy("mGuestRestrictions") @GuardedBy("mGuestRestrictions")
private final Bundle mGuestRestrictions = new Bundle(); private final Bundle mGuestRestrictions = new Bundle();
@@ -2567,150 +2549,69 @@ public class UserManagerService extends IUserManager.Stub {
} }
} }
private void setUserRestrictionInner(int userId, @NonNull String key, boolean value) {
if (!UserRestrictionsUtils.isValidRestriction(key)) {
return;
}
synchronized (mRestrictionsLock) {
final Bundle newRestrictions = BundleUtils.clone(
mDevicePolicyUserRestrictions.getRestrictions(userId));
newRestrictions.putBoolean(key, value);
if (mDevicePolicyUserRestrictions.updateRestrictions(userId, newRestrictions)) {
if (userId == UserHandle.USER_ALL) {
applyUserRestrictionsForAllUsersLR();
} else {
applyUserRestrictionsLR(userId);
}
}
}
}
/** /**
* See {@link UserManagerInternal#setDevicePolicyUserRestrictions} * See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
*/ */
private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId, private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId,
@NonNull Bundle global, @NonNull RestrictionsSet local, @NonNull Bundle global, @NonNull RestrictionsSet local,
boolean isDeviceOwner) { boolean isDeviceOwner) {
boolean globalChanged, localChanged;
List<Integer> updatedLocalTargetUserIds;
synchronized (mRestrictionsLock) { synchronized (mRestrictionsLock) {
// Update global and local restrictions if they were changed. final IntArray updatedUserIds = mDevicePolicyUserRestrictions.getUserIds();
globalChanged = mDevicePolicyGlobalUserRestrictions
.updateRestrictions(originatingUserId, global);
updatedLocalTargetUserIds = getUpdatedTargetUserIdsFromLocalRestrictions(
originatingUserId, local);
localChanged = updateLocalRestrictionsForTargetUsersLR(originatingUserId, local,
updatedLocalTargetUserIds);
if (isDeviceOwner) {
// Remember the global restriction owner userId to be able to make a distinction
// in getUserRestrictionSource on who set local policies.
mDeviceOwnerUserId = originatingUserId;
} else {
if (mDeviceOwnerUserId == originatingUserId) {
// When profile owner sets restrictions it passes null global bundle and we
// reset global restriction owner userId.
// This means this user used to have DO, but now the DO is gone and the user
// instead has PO.
mDeviceOwnerUserId = UserHandle.USER_NULL;
}
}
}
if (DBG) {
Slog.d(LOG_TAG, "setDevicePolicyUserRestrictions: "
+ " originatingUserId=" + originatingUserId
+ " global=" + global + (globalChanged ? " (changed)" : "")
+ " local=" + local + (localChanged ? " (changed)" : "")
);
}
// Don't call them within the mRestrictionsLock.
synchronized (mPackagesLock) {
if (globalChanged || localChanged) {
if (updatedLocalTargetUserIds.size() == 1
&& updatedLocalTargetUserIds.contains(originatingUserId)) {
writeUserLP(getUserDataNoChecks(originatingUserId));
} else {
if (globalChanged) {
writeUserLP(getUserDataNoChecks(originatingUserId));
}
if (localChanged) {
for (int targetUserId : updatedLocalTargetUserIds) {
writeAllTargetUsersLP(targetUserId);
}
}
}
}
}
synchronized (mRestrictionsLock) { mCachedEffectiveUserRestrictions.removeAllRestrictions();
if (globalChanged) { mDevicePolicyUserRestrictions.removeAllRestrictions();
applyUserRestrictionsForAllUsersLR();
} else if (localChanged) {
for (int targetUserId : updatedLocalTargetUserIds) {
applyUserRestrictionsLR(targetUserId);
}
}
}
}
/** mDevicePolicyUserRestrictions.updateRestrictions(UserHandle.USER_ALL, global);
* @return the list of updated target user ids in device policy local restrictions for a
* given originating user id.
*/
private List<Integer> getUpdatedTargetUserIdsFromLocalRestrictions(int originatingUserId,
@NonNull RestrictionsSet local) {
List<Integer> targetUserIds = new ArrayList<>();
// Update all the target user ids from the local restrictions set
for (int i = 0; i < local.size(); i++) {
targetUserIds.add(local.keyAt(i));
}
// Update the target user id from device policy local restrictions if the local
// restrictions set does not contain the target user id.
for (int i = 0; i < mDevicePolicyLocalUserRestrictions.size(); i++) {
int targetUserId = mDevicePolicyLocalUserRestrictions.keyAt(i);
RestrictionsSet restrictionsSet = mDevicePolicyLocalUserRestrictions.valueAt(i);
if (!local.containsKey(targetUserId)
&& restrictionsSet.containsKey(originatingUserId)) {
targetUserIds.add(targetUserId);
}
}
return targetUserIds;
}
/** final IntArray localUserIds = local.getUserIds();
* Update restrictions for all target users in the restriction set. If a target user does not for (int i = 0; i < localUserIds.size(); i++) {
* exist in device policy local restrictions, remove the restrictions bundle for that target final int userId = localUserIds.get(i);
* user originating from the specified originating user. mDevicePolicyUserRestrictions.updateRestrictions(userId,
*/ local.getRestrictions(userId));
@GuardedBy("mRestrictionsLock") updatedUserIds.add(userId);
private boolean updateLocalRestrictionsForTargetUsersLR(int originatingUserId,
RestrictionsSet local, List<Integer> updatedTargetUserIds) {
boolean changed = false;
for (int targetUserId : updatedTargetUserIds) {
Bundle restrictions = local.getRestrictions(targetUserId);
if (restrictions == null) {
restrictions = new Bundle();
} }
if (getDevicePolicyLocalRestrictionsForTargetUserLR(targetUserId)
.updateRestrictions(originatingUserId, restrictions)) {
changed = true;
}
}
return changed;
}
/** applyUserRestrictionsForAllUsersLR();
* A new restriction set is created if a restriction set does not already exist for a given for (int i = 0; i < updatedUserIds.size(); i++) {
* target user. applyUserRestrictionsLR(updatedUserIds.get(i));
* }
* @return restrictions set for a given target user.
*/
@GuardedBy("mRestrictionsLock")
private @NonNull RestrictionsSet getDevicePolicyLocalRestrictionsForTargetUserLR(
int targetUserId) {
RestrictionsSet result = mDevicePolicyLocalUserRestrictions.get(targetUserId);
if (result == null) {
result = new RestrictionsSet();
mDevicePolicyLocalUserRestrictions.put(targetUserId, result);
} }
return result;
} }
@GuardedBy("mRestrictionsLock") @GuardedBy("mRestrictionsLock")
private Bundle computeEffectiveUserRestrictionsLR(@UserIdInt int userId) { private Bundle computeEffectiveUserRestrictionsLR(@UserIdInt int userId) {
final Bundle baseRestrictions = final Bundle baseRestrictions = mBaseUserRestrictions.getRestrictionsNonNull(userId);
UserRestrictionsUtils.nonNull(mBaseUserRestrictions.getRestrictions(userId));
final Bundle global = mDevicePolicyGlobalUserRestrictions.mergeAll();
final RestrictionsSet local = getDevicePolicyLocalRestrictionsForTargetUserLR(userId);
if (BundleUtils.isEmpty(global) && local.isEmpty()) { final Bundle global = mDevicePolicyUserRestrictions.getRestrictionsNonNull(
UserHandle.USER_ALL);
final Bundle local = mDevicePolicyUserRestrictions.getRestrictionsNonNull(userId);
if (global.isEmpty() && local.isEmpty()) {
// Common case first. // Common case first.
return baseRestrictions; return baseRestrictions;
} }
final Bundle effective = BundleUtils.clone(baseRestrictions); final Bundle effective = BundleUtils.clone(baseRestrictions);
UserRestrictionsUtils.merge(effective, global); UserRestrictionsUtils.merge(effective, global);
UserRestrictionsUtils.merge(effective, local.mergeAll()); UserRestrictionsUtils.merge(effective, local);
return effective; return effective;
} }
@@ -2834,13 +2735,7 @@ public class UserManagerService extends IUserManager.Stub {
} }
synchronized (mRestrictionsLock) { synchronized (mRestrictionsLock) {
// Check if it is set as a local restriction. result.addAll(mDevicePolicyUserRestrictions.getEnforcingUsers(restrictionKey, userId));
result.addAll(getDevicePolicyLocalRestrictionsForTargetUserLR(userId).getEnforcingUsers(
restrictionKey, mDeviceOwnerUserId));
// Check if it is set as a global restriction.
result.addAll(mDevicePolicyGlobalUserRestrictions.getEnforcingUsers(restrictionKey,
mDeviceOwnerUserId));
} }
return result; return result;
} }
@@ -2990,6 +2885,7 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mRestrictionsLock") @GuardedBy("mRestrictionsLock")
private void applyUserRestrictionsLR(@UserIdInt int userId) { private void applyUserRestrictionsLR(@UserIdInt int userId) {
updateUserRestrictionsInternalLR(null, userId); updateUserRestrictionsInternalLR(null, userId);
scheduleWriteUser(getUserDataNoChecks(userId));
} }
@GuardedBy("mRestrictionsLock") @GuardedBy("mRestrictionsLock")
@@ -3666,10 +3562,6 @@ public class UserManagerService extends IUserManager.Stub {
parser.getAttributeInt(null, ATTR_USER_TYPE_VERSION, mUserTypeVersion); parser.getAttributeInt(null, ATTR_USER_TYPE_VERSION, mUserTypeVersion);
} }
// Pre-O global user restriction were stored as a single bundle (as opposed to per-user
// currently), take care of it in case of upgrade.
Bundle oldDevicePolicyGlobalUserRestrictions = null;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) { if (type == XmlPullParser.START_TAG) {
final String name = parser.getName(); final String name = parser.getName();
@@ -3698,23 +3590,12 @@ public class UserManagerService extends IUserManager.Stub {
break; break;
} }
} }
} else if (name.equals(TAG_DEVICE_OWNER_USER_ID)
// Legacy name, should only be encountered when upgrading from pre-O.
|| name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
synchronized (mRestrictionsLock) {
mDeviceOwnerUserId =
parser.getAttributeInt(null, ATTR_ID, mDeviceOwnerUserId);
}
} else if (name.equals(TAG_DEVICE_POLICY_RESTRICTIONS)) {
// Should only happen when upgrading from pre-O (version < 7).
oldDevicePolicyGlobalUserRestrictions =
UserRestrictionsUtils.readRestrictions(parser);
} }
} }
} }
updateUserIds(); updateUserIds();
upgradeIfNecessaryLP(oldDevicePolicyGlobalUserRestrictions); upgradeIfNecessaryLP();
} catch (IOException | XmlPullParserException e) { } catch (IOException | XmlPullParserException e) {
fallbackToSingleUserLP(); fallbackToSingleUserLP();
} finally { } finally {
@@ -3724,21 +3605,19 @@ public class UserManagerService extends IUserManager.Stub {
/** /**
* Upgrade steps between versions, either for fixing bugs or changing the data format. * Upgrade steps between versions, either for fixing bugs or changing the data format.
* @param oldGlobalUserRestrictions Pre-O global device policy restrictions.
*/ */
@GuardedBy({"mPackagesLock"}) @GuardedBy({"mPackagesLock"})
private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) { private void upgradeIfNecessaryLP() {
upgradeIfNecessaryLP(oldGlobalUserRestrictions, mUserVersion, mUserTypeVersion); upgradeIfNecessaryLP(mUserVersion, mUserTypeVersion);
} }
/** /**
* Version of {@link #upgradeIfNecessaryLP(Bundle)} that takes in the userVersion for testing * Version of {@link #upgradeIfNecessaryLP()} that takes in the userVersion for testing
* purposes. For non-tests, use {@link #upgradeIfNecessaryLP(Bundle)}. * purposes. For non-tests, use {@link #upgradeIfNecessaryLP()}.
*/ */
@GuardedBy({"mPackagesLock"}) @GuardedBy({"mPackagesLock"})
@VisibleForTesting @VisibleForTesting
void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions, int userVersion, void upgradeIfNecessaryLP(int userVersion, int userTypeVersion) {
int userTypeVersion) {
Slog.i(LOG_TAG, "Upgrading users from userVersion " + userVersion + " to " + USER_VERSION); Slog.i(LOG_TAG, "Upgrading users from userVersion " + userVersion + " to " + USER_VERSION);
Set<Integer> userIdsToWrite = new ArraySet<>(); Set<Integer> userIdsToWrite = new ArraySet<>();
final int originalVersion = mUserVersion; final int originalVersion = mUserVersion;
@@ -3792,16 +3671,11 @@ public class UserManagerService extends IUserManager.Stub {
if (userVersion < 7) { if (userVersion < 7) {
// Previously only one user could enforce global restrictions, now it is per-user. // Previously only one user could enforce global restrictions, now it is per-user.
synchronized (mRestrictionsLock) { synchronized (mRestrictionsLock) {
if (!BundleUtils.isEmpty(oldGlobalUserRestrictions) if (mDevicePolicyUserRestrictions.removeRestrictionsForAllUsers(
&& mDeviceOwnerUserId != UserHandle.USER_NULL) { UserManager.ENSURE_VERIFY_APPS)) {
mDevicePolicyGlobalUserRestrictions.updateRestrictions( mDevicePolicyUserRestrictions.getRestrictionsNonNull(UserHandle.USER_ALL)
mDeviceOwnerUserId, oldGlobalUserRestrictions); .putBoolean(UserManager.ENSURE_VERIFY_APPS, true);
} }
// ENSURE_VERIFY_APPS is now enforced globally even if put by profile owner, so move
// it from local to global bundle for all users who set it.
UserRestrictionsUtils.moveRestriction(UserManager.ENSURE_VERIFY_APPS,
mDevicePolicyLocalUserRestrictions, mDevicePolicyGlobalUserRestrictions
);
} }
// DISALLOW_CONFIG_WIFI was made a default guest restriction some time during version 6. // DISALLOW_CONFIG_WIFI was made a default guest restriction some time during version 6.
final List<UserInfo> guestUsers = getGuestUsers(); final List<UserInfo> guestUsers = getGuestUsers();
@@ -4134,17 +4008,6 @@ public class UserManagerService extends IUserManager.Stub {
} }
} }
@GuardedBy({"mPackagesLock"})
private void writeAllTargetUsersLP(int originatingUserId) {
for (int i = 0; i < mDevicePolicyLocalUserRestrictions.size(); i++) {
int targetUserId = mDevicePolicyLocalUserRestrictions.keyAt(i);
RestrictionsSet restrictionsSet = mDevicePolicyLocalUserRestrictions.valueAt(i);
if (restrictionsSet.containsKey(originatingUserId)) {
writeUserLP(getUserDataNoChecks(targetUserId));
}
}
}
@GuardedBy({"mPackagesLock"}) @GuardedBy({"mPackagesLock"})
private void writeUserLP(UserData userData) { private void writeUserLP(UserData userData) {
if (DBG) { if (DBG) {
@@ -4231,11 +4094,14 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) { synchronized (mRestrictionsLock) {
UserRestrictionsUtils.writeRestrictions(serializer, UserRestrictionsUtils.writeRestrictions(serializer,
mBaseUserRestrictions.getRestrictions(userInfo.id), TAG_RESTRICTIONS); mBaseUserRestrictions.getRestrictions(userInfo.id), TAG_RESTRICTIONS);
getDevicePolicyLocalRestrictionsForTargetUserLR(userInfo.id).writeRestrictions(
serializer, TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
UserRestrictionsUtils.writeRestrictions(serializer, UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyGlobalUserRestrictions.getRestrictions(userInfo.id), mDevicePolicyUserRestrictions.getRestrictions(UserHandle.USER_ALL),
TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS); TAG_DEVICE_POLICY_RESTRICTIONS);
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyUserRestrictions.getRestrictions(userInfo.id),
TAG_DEVICE_POLICY_RESTRICTIONS);
} }
if (userData.account != null) { if (userData.account != null) {
@@ -4303,11 +4169,6 @@ public class UserManagerService extends IUserManager.Stub {
.writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS); .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
} }
serializer.endTag(null, TAG_GUEST_RESTRICTIONS); serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
serializer.startTag(null, TAG_DEVICE_OWNER_USER_ID);
synchronized (mRestrictionsLock) {
serializer.attributeInt(null, ATTR_ID, mDeviceOwnerUserId);
}
serializer.endTag(null, TAG_DEVICE_OWNER_USER_ID);
int[] userIdsToWrite; int[] userIdsToWrite;
synchronized (mUsersLock) { synchronized (mUsersLock) {
userIdsToWrite = new int[mUsers.size()]; userIdsToWrite = new int[mUsers.size()];
@@ -4379,7 +4240,7 @@ public class UserManagerService extends IUserManager.Stub {
UserProperties userProperties = null; UserProperties userProperties = null;
Bundle baseRestrictions = null; Bundle baseRestrictions = null;
Bundle legacyLocalRestrictions = null; Bundle legacyLocalRestrictions = null;
RestrictionsSet localRestrictions = null; Bundle localRestrictions = null;
Bundle globalRestrictions = null; Bundle globalRestrictions = null;
boolean ignorePrepareStorageErrors = true; // default is true for old users boolean ignorePrepareStorageErrors = true; // default is true for old users
@@ -4445,8 +4306,7 @@ public class UserManagerService extends IUserManager.Stub {
} else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) { } else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
legacyLocalRestrictions = UserRestrictionsUtils.readRestrictions(parser); legacyLocalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS.equals(tag)) { } else if (TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS.equals(tag)) {
localRestrictions = RestrictionsSet.readRestrictions(parser, localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
} else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) { } else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) {
globalRestrictions = UserRestrictionsUtils.readRestrictions(parser); globalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_ACCOUNT.equals(tag)) { } else if (TAG_ACCOUNT.equals(tag)) {
@@ -4516,19 +4376,15 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.updateRestrictions(id, baseRestrictions); mBaseUserRestrictions.updateRestrictions(id, baseRestrictions);
} }
if (localRestrictions != null) { if (localRestrictions != null) {
mDevicePolicyLocalUserRestrictions.put(id, localRestrictions); mDevicePolicyUserRestrictions.updateRestrictions(id, localRestrictions);
if (legacyLocalRestrictions != null) { if (legacyLocalRestrictions != null) {
Slog.wtf(LOG_TAG, "Seeing both legacy and current local restrictions in xml"); Slog.wtf(LOG_TAG, "Seeing both legacy and current local restrictions in xml");
} }
} else if (legacyLocalRestrictions != null) { } else if (legacyLocalRestrictions != null) {
RestrictionsSet legacyLocalRestrictionsSet = mDevicePolicyUserRestrictions.updateRestrictions(id, legacyLocalRestrictions);
legacyLocalRestrictions.isEmpty()
? new RestrictionsSet()
: new RestrictionsSet(id, legacyLocalRestrictions);
mDevicePolicyLocalUserRestrictions.put(id, legacyLocalRestrictionsSet);
} }
if (globalRestrictions != null) { if (globalRestrictions != null) {
mDevicePolicyGlobalUserRestrictions.updateRestrictions(id, mDevicePolicyUserRestrictions.updateRestrictions(UserHandle.USER_ALL,
globalRestrictions); globalRestrictions);
} }
} }
@@ -5364,18 +5220,12 @@ public class UserManagerService extends IUserManager.Stub {
} }
} else if (atomTag == FrameworkStatsLog.MULTI_USER_INFO) { } else if (atomTag == FrameworkStatsLog.MULTI_USER_INFO) {
if (UserManager.getMaxSupportedUsers() > 1) { if (UserManager.getMaxSupportedUsers() > 1) {
int deviceOwnerUserId = UserHandle.USER_NULL;
synchronized (mRestrictionsLock) {
deviceOwnerUserId = mDeviceOwnerUserId;
}
data.add(FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.MULTI_USER_INFO, data.add(FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.MULTI_USER_INFO,
UserManager.getMaxSupportedUsers(), UserManager.getMaxSupportedUsers(),
isUserSwitcherEnabled(deviceOwnerUserId), isUserSwitcherEnabled(UserHandle.USER_ALL),
UserManager.supportsMultipleUsers() UserManager.supportsMultipleUsers()
&& !hasUserRestriction(UserManager.DISALLOW_ADD_USER, && !hasUserRestriction(UserManager.DISALLOW_ADD_USER,
deviceOwnerUserId))); UserHandle.USER_ALL)));
} }
} else { } else {
Slogf.e(LOG_TAG, "Unexpected atom tag: %d", atomTag); Slogf.e(LOG_TAG, "Unexpected atom tag: %d", atomTag);
@@ -5843,17 +5693,8 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.remove(userId); mBaseUserRestrictions.remove(userId);
mAppliedUserRestrictions.remove(userId); mAppliedUserRestrictions.remove(userId);
mCachedEffectiveUserRestrictions.remove(userId); mCachedEffectiveUserRestrictions.remove(userId);
// Remove local restrictions affecting user // Remove restrictions affecting the user
mDevicePolicyLocalUserRestrictions.delete(userId); if (mDevicePolicyUserRestrictions.remove(userId)) {
// Remove local restrictions set by user
boolean changed = false;
for (int i = 0; i < mDevicePolicyLocalUserRestrictions.size(); i++) {
int targetUserId = mDevicePolicyLocalUserRestrictions.keyAt(i);
changed |= getDevicePolicyLocalRestrictionsForTargetUserLR(targetUserId)
.remove(userId);
}
changed |= mDevicePolicyGlobalUserRestrictions.remove(userId);
if (changed) {
applyUserRestrictionsForAllUsersLR(); applyUserRestrictionsForAllUsersLR();
} }
} }
@@ -6587,10 +6428,12 @@ public class UserManagerService extends IUserManager.Stub {
pw.println(); pw.println();
pw.println("Device properties:"); pw.println("Device properties:");
pw.println(" Device policy global restrictions:");
synchronized (mRestrictionsLock) { synchronized (mRestrictionsLock) {
pw.println(" Device owner id:" + mDeviceOwnerUserId); UserRestrictionsUtils.dumpRestrictions(
pw, " ",
mDevicePolicyUserRestrictions.getRestrictions(UserHandle.USER_ALL));
} }
pw.println();
pw.println(" Guest restrictions:"); pw.println(" Guest restrictions:");
synchronized (mGuestRestrictions) { synchronized (mGuestRestrictions) {
UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions); UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
@@ -6768,13 +6611,10 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) { synchronized (mRestrictionsLock) {
UserRestrictionsUtils.dumpRestrictions( UserRestrictionsUtils.dumpRestrictions(
pw, " ", mBaseUserRestrictions.getRestrictions(userInfo.id)); pw, " ", mBaseUserRestrictions.getRestrictions(userInfo.id));
pw.println(" Device policy global restrictions:"); pw.println(" Device policy restrictions:");
UserRestrictionsUtils.dumpRestrictions( UserRestrictionsUtils.dumpRestrictions(
pw, " ", pw, " ",
mDevicePolicyGlobalUserRestrictions.getRestrictions(userInfo.id)); mDevicePolicyUserRestrictions.getRestrictions(userInfo.id));
pw.println(" Device policy local restrictions:");
getDevicePolicyLocalRestrictionsForTargetUserLR(
userInfo.id).dumpRestrictions(pw, " ");
pw.println(" Effective restrictions:"); pw.println(" Effective restrictions:");
UserRestrictionsUtils.dumpRestrictions( UserRestrictionsUtils.dumpRestrictions(
pw, " ", pw, " ",
@@ -6856,6 +6696,11 @@ public class UserManagerService extends IUserManager.Stub {
global, local, isDeviceOwner); global, local, isDeviceOwner);
} }
@Override
public void setUserRestriction(int userId, @NonNull String key, boolean value) {
UserManagerService.this.setUserRestrictionInner(userId, key, value);
}
@Override @Override
public boolean getUserRestriction(@UserIdInt int userId, String key) { public boolean getUserRestriction(@UserIdInt int userId, String key) {
return getUserRestrictions(userId).getBoolean(key); return getUserRestrictions(userId).getBoolean(key);

View File

@@ -32,6 +32,7 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -138,6 +139,7 @@ public class RestrictionsSetTest {
} }
@Test @Test
@Ignore("b/268334580")
public void testGetEnforcingUsers_hasEnforcingUser() { public void testGetEnforcingUsers_hasEnforcingUser() {
mRestrictionsSet.updateRestrictions(originatingUserId, mRestrictionsSet.updateRestrictions(originatingUserId,
newRestrictions(UserManager.ENSURE_VERIFY_APPS)); newRestrictions(UserManager.ENSURE_VERIFY_APPS));
@@ -154,6 +156,7 @@ public class RestrictionsSetTest {
} }
@Test @Test
@Ignore("b/268334580")
public void testGetEnforcingUsers_hasMultipleEnforcingUsers() { public void testGetEnforcingUsers_hasMultipleEnforcingUsers() {
int originatingUserId2 = 10; int originatingUserId2 = 10;
mRestrictionsSet.updateRestrictions(originatingUserId, mRestrictionsSet.updateRestrictions(originatingUserId,

View File

@@ -230,7 +230,7 @@ public class UserManagerServiceUserInfoTest {
mUserManagerService.putUserInfo(createUser(105, FLAG_SYSTEM | FLAG_FULL, null)); mUserManagerService.putUserInfo(createUser(105, FLAG_SYSTEM | FLAG_FULL, null));
mUserManagerService.putUserInfo(createUser(106, FLAG_DEMO | FLAG_FULL, null)); mUserManagerService.putUserInfo(createUser(106, FLAG_DEMO | FLAG_FULL, null));
mUserManagerService.upgradeIfNecessaryLP(null, versionToTest - 1, userTypeVersion); mUserManagerService.upgradeIfNecessaryLP(versionToTest - 1, userTypeVersion);
assertTrue(mUserManagerService.isUserOfType(100, USER_TYPE_PROFILE_MANAGED)); assertTrue(mUserManagerService.isUserOfType(100, USER_TYPE_PROFILE_MANAGED));
assertTrue((mUserManagerService.getUserInfo(100).flags & FLAG_PROFILE) != 0); assertTrue((mUserManagerService.getUserInfo(100).flags & FLAG_PROFILE) != 0);