Merge "Change the data structure of restrictions in UM" into rvc-dev am: c444d10c27
Change-Id: Ifde555ce8b1b26d8c328dc192f105026e5825fc9
This commit is contained in:
256
services/core/java/com/android/server/pm/RestrictionsSet.java
Normal file
256
services/core/java/com/android/server/pm/RestrictionsSet.java
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Data structure that contains the mapping of users to user restrictions (either the user
|
||||
* restrictions that apply to them, or the user restrictions that they set, depending on the
|
||||
* circumstances).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class RestrictionsSet {
|
||||
|
||||
private static final String USER_ID = "user_id";
|
||||
private static final String TAG_RESTRICTIONS = "restrictions";
|
||||
private static final String TAG_RESTRICTIONS_USER = "restrictions_user";
|
||||
|
||||
/**
|
||||
* Mapping of user restrictions.
|
||||
* Only non-empty restriction bundles are stored.
|
||||
* The key is the user id of the user.
|
||||
* userId -> restrictionBundle
|
||||
*/
|
||||
private final SparseArray<Bundle> mUserRestrictions = new SparseArray<>(0);
|
||||
|
||||
public RestrictionsSet() {
|
||||
}
|
||||
|
||||
public RestrictionsSet(@UserIdInt int userId, @NonNull Bundle restrictions) {
|
||||
if (restrictions.isEmpty()) {
|
||||
throw new IllegalArgumentException("empty restriction bundle cannot be added.");
|
||||
}
|
||||
mUserRestrictions.put(userId, restrictions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates restriction bundle for a given user.
|
||||
* If new bundle is empty, record is removed from the array.
|
||||
*
|
||||
* @return whether restrictions bundle is different from the old one.
|
||||
*/
|
||||
public boolean updateRestrictions(@UserIdInt int userId, @Nullable Bundle restrictions) {
|
||||
final boolean changed =
|
||||
!UserRestrictionsUtils.areEqual(mUserRestrictions.get(userId), restrictions);
|
||||
if (!changed) {
|
||||
return false;
|
||||
}
|
||||
if (!UserRestrictionsUtils.isEmpty(restrictions)) {
|
||||
mUserRestrictions.put(userId, restrictions);
|
||||
} else {
|
||||
mUserRestrictions.delete(userId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a particular restriction from one restriction set to another, e.g. for all users.
|
||||
*/
|
||||
public void moveRestriction(@NonNull RestrictionsSet destRestrictions, String restriction) {
|
||||
for (int i = 0; i < mUserRestrictions.size(); i++) {
|
||||
final int userId = mUserRestrictions.keyAt(i);
|
||||
final Bundle from = mUserRestrictions.valueAt(i);
|
||||
|
||||
if (UserRestrictionsUtils.contains(from, restriction)) {
|
||||
from.remove(restriction);
|
||||
Bundle to = destRestrictions.getRestrictions(userId);
|
||||
if (to == null) {
|
||||
to = new Bundle();
|
||||
to.putBoolean(restriction, true);
|
||||
destRestrictions.updateRestrictions(userId, to);
|
||||
} else {
|
||||
to.putBoolean(restriction, true);
|
||||
}
|
||||
// Don't keep empty bundles.
|
||||
if (from.isEmpty()) {
|
||||
mUserRestrictions.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether restrictions set has no restrictions.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return mUserRestrictions.size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge all restrictions in restrictions set into one bundle. The original user restrictions
|
||||
* set does not get modified, instead a new bundle is returned.
|
||||
*
|
||||
* @return restrictions bundle containing all user restrictions.
|
||||
*/
|
||||
public @NonNull Bundle mergeAll() {
|
||||
final Bundle result = new Bundle();
|
||||
for (int i = 0; i < mUserRestrictions.size(); i++) {
|
||||
UserRestrictionsUtils.merge(result, mUserRestrictions.valueAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of enforcing users that enforce a particular restriction.
|
||||
*/
|
||||
public @NonNull List<UserManager.EnforcingUser> getEnforcingUsers(String restriction,
|
||||
@UserIdInt int deviceOwnerUserId) {
|
||||
final List<UserManager.EnforcingUser> result = new ArrayList<>();
|
||||
for (int i = 0; i < mUserRestrictions.size(); i++) {
|
||||
if (UserRestrictionsUtils.contains(mUserRestrictions.valueAt(i), restriction)) {
|
||||
result.add(getEnforcingUser(mUserRestrictions.keyAt(i), deviceOwnerUserId));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private UserManager.EnforcingUser getEnforcingUser(@UserIdInt int userId,
|
||||
@UserIdInt int deviceOwnerUserId) {
|
||||
int source = deviceOwnerUserId == userId
|
||||
? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER
|
||||
: UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
|
||||
return new UserManager.EnforcingUser(userId, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of user restrictions for a given user. Null is returned if the user does not
|
||||
* have any restrictions.
|
||||
*/
|
||||
public @Nullable Bundle getRestrictions(@UserIdInt int userId) {
|
||||
return mUserRestrictions.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a given user from the restrictions set, returning true if the user has non-empty
|
||||
* restrictions before removal.
|
||||
*/
|
||||
public boolean remove(@UserIdInt int userId) {
|
||||
boolean hasUserRestriction = mUserRestrictions.contains(userId);
|
||||
mUserRestrictions.remove(userId);
|
||||
return hasUserRestriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove list of users and user restrictions.
|
||||
*/
|
||||
public void removeAllRestrictions() {
|
||||
mUserRestrictions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a given {@link RestrictionsSet} to XML.
|
||||
*/
|
||||
public void writeRestrictions(@NonNull XmlSerializer serializer, @NonNull String outerTag)
|
||||
throws IOException {
|
||||
serializer.startTag(null, outerTag);
|
||||
for (int i = 0; i < mUserRestrictions.size(); i++) {
|
||||
serializer.startTag(null, TAG_RESTRICTIONS_USER);
|
||||
serializer.attribute(null, USER_ID, String.valueOf(mUserRestrictions.keyAt(i)));
|
||||
UserRestrictionsUtils.writeRestrictions(serializer, mUserRestrictions.valueAt(i),
|
||||
TAG_RESTRICTIONS);
|
||||
serializer.endTag(null, TAG_RESTRICTIONS_USER);
|
||||
}
|
||||
serializer.endTag(null, outerTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read restrictions from XML.
|
||||
*/
|
||||
public static RestrictionsSet readRestrictions(@NonNull XmlPullParser parser,
|
||||
@NonNull String outerTag) throws IOException, XmlPullParserException {
|
||||
RestrictionsSet restrictionsSet = new RestrictionsSet();
|
||||
int userId = 0;
|
||||
int type;
|
||||
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
|
||||
String tag = parser.getName();
|
||||
if (type == XmlPullParser.END_TAG && outerTag.equals(tag)) {
|
||||
return restrictionsSet;
|
||||
} else if (type == XmlPullParser.START_TAG && TAG_RESTRICTIONS_USER.equals(tag)) {
|
||||
userId = Integer.parseInt(parser.getAttributeValue(null, USER_ID));
|
||||
} else if (type == XmlPullParser.START_TAG && TAG_RESTRICTIONS.equals(tag)) {
|
||||
Bundle restrictions = UserRestrictionsUtils.readRestrictions(parser);
|
||||
restrictionsSet.updateRestrictions(userId, restrictions);
|
||||
}
|
||||
}
|
||||
throw new XmlPullParserException("restrictions cannot be read as xml is malformed.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps {@link RestrictionsSet}.
|
||||
*/
|
||||
public void dumpRestrictions(PrintWriter pw, String prefix) {
|
||||
boolean noneSet = true;
|
||||
for (int i = 0; i < mUserRestrictions.size(); i++) {
|
||||
pw.println(prefix + "User Id: " + mUserRestrictions.keyAt(i));
|
||||
UserRestrictionsUtils.dumpRestrictions(pw, prefix + " ", mUserRestrictions.valueAt(i));
|
||||
noneSet = false;
|
||||
}
|
||||
if (noneSet) {
|
||||
pw.println(prefix + "none");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(@UserIdInt int userId) {
|
||||
return mUserRestrictions.contains(userId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int size() {
|
||||
return mUserRestrictions.size();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public int keyAt(int index) {
|
||||
return mUserRestrictions.keyAt(index);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Bundle valueAt(int index) {
|
||||
return mUserRestrictions.valueAt(index);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -182,6 +182,8 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
private static final String TAG_USER = "user";
|
||||
private static final String TAG_RESTRICTIONS = "restrictions";
|
||||
private static final String TAG_DEVICE_POLICY_RESTRICTIONS = "device_policy_restrictions";
|
||||
private static final String TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS =
|
||||
"device_policy_local_restrictions";
|
||||
private static final String TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS =
|
||||
"device_policy_global_restrictions";
|
||||
/** Legacy name for device owner id tag. */
|
||||
@@ -329,7 +331,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
* {@link #updateUserRestrictionsInternalLR}.
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
|
||||
private final RestrictionsSet mBaseUserRestrictions = new RestrictionsSet();
|
||||
|
||||
/**
|
||||
* Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined
|
||||
@@ -344,7 +346,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
* {@link #updateUserRestrictionsInternalLR}.
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
|
||||
private final RestrictionsSet mCachedEffectiveUserRestrictions = new RestrictionsSet();
|
||||
|
||||
/**
|
||||
* User restrictions that have already been applied in
|
||||
@@ -353,7 +355,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
* {@link #updateUserRestrictionsInternalLR(Bundle, int)} call.
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
|
||||
private final RestrictionsSet mAppliedUserRestrictions = new RestrictionsSet();
|
||||
|
||||
/**
|
||||
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
|
||||
@@ -362,7 +364,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
* The key is the user id of the user whom the restriction originated from.
|
||||
*/
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private final SparseArray<Bundle> mDevicePolicyGlobalUserRestrictions = new SparseArray<>();
|
||||
private final RestrictionsSet mDevicePolicyGlobalUserRestrictions = new RestrictionsSet();
|
||||
|
||||
/**
|
||||
* Id of the user that set global restrictions.
|
||||
@@ -372,11 +374,15 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
/**
|
||||
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
|
||||
* for each user. Only non-empty restriction bundles are stored.
|
||||
* The key is the user id of the user whom the restriction originated from.
|
||||
* for each user.
|
||||
* 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")
|
||||
private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
|
||||
private final SparseArray<RestrictionsSet> mDevicePolicyLocalUserRestrictions =
|
||||
new SparseArray<>();
|
||||
|
||||
@GuardedBy("mGuestRestrictions")
|
||||
private final Bundle mGuestRestrictions = new Bundle();
|
||||
@@ -1710,9 +1716,6 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
|
||||
*/
|
||||
private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId,
|
||||
@Nullable Bundle restrictions,
|
||||
@UserManagerInternal.OwnerType int restrictionOwnerType) {
|
||||
@@ -1722,16 +1725,36 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
// Sort restrictions into local and global ensuring they don't overlap.
|
||||
UserRestrictionsUtils.sortToGlobalAndLocal(restrictions, restrictionOwnerType, global,
|
||||
local);
|
||||
boolean isDeviceOwner = restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
|
||||
|
||||
RestrictionsSet localRestrictionsSet;
|
||||
if (UserRestrictionsUtils.isEmpty(local)) {
|
||||
localRestrictionsSet = new RestrictionsSet();
|
||||
} else {
|
||||
localRestrictionsSet = new RestrictionsSet(originatingUserId, local);
|
||||
}
|
||||
setDevicePolicyUserRestrictionsInner(originatingUserId, global, localRestrictionsSet,
|
||||
isDeviceOwner);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
|
||||
*/
|
||||
private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId,
|
||||
@NonNull Bundle global, @NonNull RestrictionsSet local,
|
||||
boolean isDeviceOwner) {
|
||||
boolean globalChanged, localChanged;
|
||||
List<Integer> updatedLocalTargetUserIds;
|
||||
synchronized (mRestrictionsLock) {
|
||||
// Update global and local restrictions if they were changed.
|
||||
globalChanged = updateRestrictionsIfNeededLR(
|
||||
originatingUserId, global, mDevicePolicyGlobalUserRestrictions);
|
||||
localChanged = updateRestrictionsIfNeededLR(
|
||||
originatingUserId, local, mDevicePolicyLocalUserRestrictions);
|
||||
globalChanged = mDevicePolicyGlobalUserRestrictions
|
||||
.updateRestrictions(originatingUserId, global);
|
||||
updatedLocalTargetUserIds = getUpdatedTargetUserIdsFromLocalRestrictions(
|
||||
originatingUserId, local);
|
||||
localChanged = updateLocalRestrictionsForTargetUsersLR(originatingUserId, local,
|
||||
updatedLocalTargetUserIds);
|
||||
|
||||
if (restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER) {
|
||||
if (isDeviceOwner) {
|
||||
// Remember the global restriction owner userId to be able to make a distinction
|
||||
// in getUserRestrictionSource on who set local policies.
|
||||
mDeviceOwnerUserId = originatingUserId;
|
||||
@@ -1754,8 +1777,20 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
// Don't call them within the mRestrictionsLock.
|
||||
synchronized (mPackagesLock) {
|
||||
if (localChanged || globalChanged) {
|
||||
writeUserLP(getUserDataNoChecks(originatingUserId));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1763,44 +1798,88 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
if (globalChanged) {
|
||||
applyUserRestrictionsForAllUsersLR();
|
||||
} else if (localChanged) {
|
||||
applyUserRestrictionsLR(originatingUserId);
|
||||
for (int targetUserId : updatedLocalTargetUserIds) {
|
||||
applyUserRestrictionsLR(targetUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates restriction bundle for a given user in a given restriction array. If new bundle is
|
||||
* empty, record is removed from the array.
|
||||
* @return whether restrictions bundle is different from the old one.
|
||||
* @return the list of updated target user ids in device policy local restrictions for a
|
||||
* given originating user id.
|
||||
*/
|
||||
private boolean updateRestrictionsIfNeededLR(@UserIdInt int userId,
|
||||
@Nullable Bundle restrictions, SparseArray<Bundle> restrictionsArray) {
|
||||
final boolean changed =
|
||||
!UserRestrictionsUtils.areEqual(restrictionsArray.get(userId), restrictions);
|
||||
if (changed) {
|
||||
if (!UserRestrictionsUtils.isEmpty(restrictions)) {
|
||||
restrictionsArray.put(userId, restrictions);
|
||||
} else {
|
||||
restrictionsArray.delete(userId);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update restrictions for all target users in the restriction set. If a target user does not
|
||||
* exist in device policy local restrictions, remove the restrictions bundle for that target
|
||||
* user originating from the specified originating user.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* A new restriction set is created if a restriction set does not already exist for a given
|
||||
* target user.
|
||||
*
|
||||
* @return restrictions set for a given target user.
|
||||
*/
|
||||
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")
|
||||
private Bundle computeEffectiveUserRestrictionsLR(@UserIdInt int userId) {
|
||||
final Bundle baseRestrictions =
|
||||
UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId));
|
||||
final Bundle global = UserRestrictionsUtils.mergeAll(mDevicePolicyGlobalUserRestrictions);
|
||||
final Bundle local = mDevicePolicyLocalUserRestrictions.get(userId);
|
||||
UserRestrictionsUtils.nonNull(mBaseUserRestrictions.getRestrictions(userId));
|
||||
final Bundle global = mDevicePolicyGlobalUserRestrictions.mergeAll();
|
||||
final RestrictionsSet local = getDevicePolicyLocalRestrictionsForTargetUserLR(userId);
|
||||
|
||||
if (UserRestrictionsUtils.isEmpty(global) && UserRestrictionsUtils.isEmpty(local)) {
|
||||
if (UserRestrictionsUtils.isEmpty(global) && local.isEmpty()) {
|
||||
// Common case first.
|
||||
return baseRestrictions;
|
||||
}
|
||||
final Bundle effective = UserRestrictionsUtils.clone(baseRestrictions);
|
||||
UserRestrictionsUtils.merge(effective, global);
|
||||
UserRestrictionsUtils.merge(effective, local);
|
||||
UserRestrictionsUtils.merge(effective, local.mergeAll());
|
||||
|
||||
return effective;
|
||||
}
|
||||
@@ -1815,10 +1894,10 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
private Bundle getEffectiveUserRestrictions(@UserIdInt int userId) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
|
||||
Bundle restrictions = mCachedEffectiveUserRestrictions.getRestrictions(userId);
|
||||
if (restrictions == null) {
|
||||
restrictions = computeEffectiveUserRestrictionsLR(userId);
|
||||
mCachedEffectiveUserRestrictions.put(userId, restrictions);
|
||||
mCachedEffectiveUserRestrictions.updateRestrictions(userId, restrictions);
|
||||
}
|
||||
return restrictions;
|
||||
}
|
||||
@@ -1921,31 +2000,17 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
|
||||
synchronized (mRestrictionsLock) {
|
||||
// Check if it is set by profile owner.
|
||||
Bundle profileOwnerRestrictions = mDevicePolicyLocalUserRestrictions.get(userId);
|
||||
if (UserRestrictionsUtils.contains(profileOwnerRestrictions, restrictionKey)) {
|
||||
result.add(getEnforcingUserLocked(userId));
|
||||
}
|
||||
// Check if it is set as a local restriction.
|
||||
result.addAll(getDevicePolicyLocalRestrictionsForTargetUserLR(userId).getEnforcingUsers(
|
||||
restrictionKey, mDeviceOwnerUserId));
|
||||
|
||||
// Iterate over all users who enforce global restrictions.
|
||||
for (int i = mDevicePolicyGlobalUserRestrictions.size() - 1; i >= 0; i--) {
|
||||
Bundle globalRestrictions = mDevicePolicyGlobalUserRestrictions.valueAt(i);
|
||||
int profileUserId = mDevicePolicyGlobalUserRestrictions.keyAt(i);
|
||||
if (UserRestrictionsUtils.contains(globalRestrictions, restrictionKey)) {
|
||||
result.add(getEnforcingUserLocked(profileUserId));
|
||||
}
|
||||
}
|
||||
// Check if it is set as a global restriction.
|
||||
result.addAll(mDevicePolicyGlobalUserRestrictions.getEnforcingUsers(restrictionKey,
|
||||
mDeviceOwnerUserId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@GuardedBy("mRestrictionsLock")
|
||||
private EnforcingUser getEnforcingUserLocked(@UserIdInt int userId) {
|
||||
int source = mDeviceOwnerUserId == userId ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER
|
||||
: UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
|
||||
return new EnforcingUser(userId, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserRestrictions that are in effect currently. This always returns a new
|
||||
* {@link Bundle}.
|
||||
@@ -1963,7 +2028,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
return false;
|
||||
}
|
||||
synchronized (mRestrictionsLock) {
|
||||
Bundle bundle = mBaseUserRestrictions.get(userId);
|
||||
Bundle bundle = mBaseUserRestrictions.getRestrictions(userId);
|
||||
return (bundle != null && bundle.getBoolean(restrictionKey, false));
|
||||
}
|
||||
}
|
||||
@@ -1978,7 +2043,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
// Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
|
||||
// a copy.
|
||||
final Bundle newRestrictions = UserRestrictionsUtils.clone(
|
||||
mBaseUserRestrictions.get(userId));
|
||||
mBaseUserRestrictions.getRestrictions(userId));
|
||||
newRestrictions.putBoolean(key, value);
|
||||
|
||||
updateUserRestrictionsInternalLR(newRestrictions, userId);
|
||||
@@ -1997,25 +2062,25 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
private void updateUserRestrictionsInternalLR(
|
||||
@Nullable Bundle newBaseRestrictions, @UserIdInt int userId) {
|
||||
final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull(
|
||||
mAppliedUserRestrictions.get(userId));
|
||||
mAppliedUserRestrictions.getRestrictions(userId));
|
||||
|
||||
// Update base restrictions.
|
||||
if (newBaseRestrictions != null) {
|
||||
// If newBaseRestrictions == the current one, it's probably a bug.
|
||||
final Bundle prevBaseRestrictions = mBaseUserRestrictions.get(userId);
|
||||
final Bundle prevBaseRestrictions = mBaseUserRestrictions.getRestrictions(userId);
|
||||
|
||||
Preconditions.checkState(prevBaseRestrictions != newBaseRestrictions);
|
||||
Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
|
||||
Preconditions.checkState(mCachedEffectiveUserRestrictions.getRestrictions(userId)
|
||||
!= newBaseRestrictions);
|
||||
|
||||
if (updateRestrictionsIfNeededLR(userId, newBaseRestrictions, mBaseUserRestrictions)) {
|
||||
if (mBaseUserRestrictions.updateRestrictions(userId, newBaseRestrictions)) {
|
||||
scheduleWriteUser(getUserDataNoChecks(userId));
|
||||
}
|
||||
}
|
||||
|
||||
final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
|
||||
|
||||
mCachedEffectiveUserRestrictions.put(userId, effective);
|
||||
mCachedEffectiveUserRestrictions.updateRestrictions(userId, effective);
|
||||
|
||||
// Apply the new restrictions.
|
||||
if (DBG) {
|
||||
@@ -2038,7 +2103,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions);
|
||||
|
||||
mAppliedUserRestrictions.put(userId, new Bundle(effective));
|
||||
mAppliedUserRestrictions.updateRestrictions(userId, new Bundle(effective));
|
||||
}
|
||||
|
||||
private void propagateUserRestrictionsLR(final int userId,
|
||||
@@ -2090,7 +2155,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
debug("applyUserRestrictionsForAllUsersLR");
|
||||
}
|
||||
// First, invalidate all cached values.
|
||||
mCachedEffectiveUserRestrictions.clear();
|
||||
mCachedEffectiveUserRestrictions.removeAllRestrictions();
|
||||
|
||||
// We don't want to call into ActivityManagerService while taking a lock, so we'll call
|
||||
// it on a handler.
|
||||
@@ -2566,7 +2631,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
synchronized (mRestrictionsLock) {
|
||||
if (!UserRestrictionsUtils.isEmpty(oldGlobalUserRestrictions)
|
||||
&& mDeviceOwnerUserId != UserHandle.USER_NULL) {
|
||||
mDevicePolicyGlobalUserRestrictions.put(
|
||||
mDevicePolicyGlobalUserRestrictions.updateRestrictions(
|
||||
mDeviceOwnerUserId, oldGlobalUserRestrictions);
|
||||
}
|
||||
// ENSURE_VERIFY_APPS is now enforced globally even if put by profile owner, so move
|
||||
@@ -2691,7 +2756,8 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
if (!restrictions.isEmpty()) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
|
||||
mBaseUserRestrictions.updateRestrictions(UserHandle.USER_SYSTEM,
|
||||
restrictions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2718,6 +2784,16 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeUserLP(UserData userData) {
|
||||
if (DBG) {
|
||||
debug("writeUserLP " + userData);
|
||||
@@ -2802,12 +2878,11 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
synchronized (mRestrictionsLock) {
|
||||
UserRestrictionsUtils.writeRestrictions(serializer,
|
||||
mBaseUserRestrictions.get(userInfo.id), TAG_RESTRICTIONS);
|
||||
mBaseUserRestrictions.getRestrictions(userInfo.id), TAG_RESTRICTIONS);
|
||||
getDevicePolicyLocalRestrictionsForTargetUserLR(userInfo.id).writeRestrictions(
|
||||
serializer, TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
|
||||
UserRestrictionsUtils.writeRestrictions(serializer,
|
||||
mDevicePolicyLocalUserRestrictions.get(userInfo.id),
|
||||
TAG_DEVICE_POLICY_RESTRICTIONS);
|
||||
UserRestrictionsUtils.writeRestrictions(serializer,
|
||||
mDevicePolicyGlobalUserRestrictions.get(userInfo.id),
|
||||
mDevicePolicyGlobalUserRestrictions.getRestrictions(userInfo.id),
|
||||
TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS);
|
||||
}
|
||||
|
||||
@@ -2937,7 +3012,8 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
String seedAccountType = null;
|
||||
PersistableBundle seedAccountOptions = null;
|
||||
Bundle baseRestrictions = null;
|
||||
Bundle localRestrictions = null;
|
||||
Bundle legacyLocalRestrictions = null;
|
||||
RestrictionsSet localRestrictions = null;
|
||||
Bundle globalRestrictions = null;
|
||||
|
||||
XmlPullParser parser = Xml.newPullParser();
|
||||
@@ -3007,7 +3083,10 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
} else if (TAG_RESTRICTIONS.equals(tag)) {
|
||||
baseRestrictions = UserRestrictionsUtils.readRestrictions(parser);
|
||||
} else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
|
||||
localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
|
||||
legacyLocalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
|
||||
} else if (TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS.equals(tag)) {
|
||||
localRestrictions = RestrictionsSet.readRestrictions(parser,
|
||||
TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
|
||||
} else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) {
|
||||
globalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
|
||||
} else if (TAG_ACCOUNT.equals(tag)) {
|
||||
@@ -3052,13 +3131,20 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
|
||||
synchronized (mRestrictionsLock) {
|
||||
if (baseRestrictions != null) {
|
||||
mBaseUserRestrictions.put(id, baseRestrictions);
|
||||
mBaseUserRestrictions.updateRestrictions(id, baseRestrictions);
|
||||
}
|
||||
if (localRestrictions != null) {
|
||||
mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
|
||||
if (legacyLocalRestrictions != null) {
|
||||
Slog.wtf(LOG_TAG, "Seeing both legacy and current local restrictions in xml");
|
||||
}
|
||||
} else if (legacyLocalRestrictions != null) {
|
||||
mDevicePolicyLocalUserRestrictions.put(id,
|
||||
new RestrictionsSet(id, legacyLocalRestrictions));
|
||||
}
|
||||
if (globalRestrictions != null) {
|
||||
mDevicePolicyGlobalUserRestrictions.put(id, globalRestrictions);
|
||||
mDevicePolicyGlobalUserRestrictions.updateRestrictions(id,
|
||||
globalRestrictions);
|
||||
}
|
||||
}
|
||||
return userData;
|
||||
@@ -3374,7 +3460,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
userTypeDetails.addDefaultRestrictionsTo(restrictions);
|
||||
}
|
||||
synchronized (mRestrictionsLock) {
|
||||
mBaseUserRestrictions.append(userId, restrictions);
|
||||
mBaseUserRestrictions.updateRestrictions(userId, restrictions);
|
||||
}
|
||||
|
||||
t.traceBegin("PM.onNewUserCreated-" + userId);
|
||||
@@ -3845,9 +3931,17 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
mBaseUserRestrictions.remove(userId);
|
||||
mAppliedUserRestrictions.remove(userId);
|
||||
mCachedEffectiveUserRestrictions.remove(userId);
|
||||
mDevicePolicyLocalUserRestrictions.remove(userId);
|
||||
if (mDevicePolicyGlobalUserRestrictions.get(userId) != null) {
|
||||
mDevicePolicyGlobalUserRestrictions.remove(userId);
|
||||
// Remove local restrictions affecting user
|
||||
mDevicePolicyLocalUserRestrictions.delete(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();
|
||||
}
|
||||
}
|
||||
@@ -4540,16 +4634,18 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
pw.println(" Restrictions:");
|
||||
synchronized (mRestrictionsLock) {
|
||||
UserRestrictionsUtils.dumpRestrictions(
|
||||
pw, " ", mBaseUserRestrictions.get(userInfo.id));
|
||||
pw, " ", mBaseUserRestrictions.getRestrictions(userInfo.id));
|
||||
pw.println(" Device policy global restrictions:");
|
||||
UserRestrictionsUtils.dumpRestrictions(
|
||||
pw, " ", mDevicePolicyGlobalUserRestrictions.get(userInfo.id));
|
||||
pw, " ",
|
||||
mDevicePolicyGlobalUserRestrictions.getRestrictions(userInfo.id));
|
||||
pw.println(" Device policy local restrictions:");
|
||||
UserRestrictionsUtils.dumpRestrictions(
|
||||
pw, " ", mDevicePolicyLocalUserRestrictions.get(userInfo.id));
|
||||
getDevicePolicyLocalRestrictionsForTargetUserLR(
|
||||
userInfo.id).dumpRestrictions(pw, " ");
|
||||
pw.println(" Effective restrictions:");
|
||||
UserRestrictionsUtils.dumpRestrictions(
|
||||
pw, " ", mCachedEffectiveUserRestrictions.get(userInfo.id));
|
||||
pw, " ",
|
||||
mCachedEffectiveUserRestrictions.getRestrictions(userInfo.id));
|
||||
}
|
||||
|
||||
if (userData.account != null) {
|
||||
@@ -4665,7 +4761,7 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
@Override
|
||||
public Bundle getBaseUserRestrictions(@UserIdInt int userId) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
return mBaseUserRestrictions.get(userId);
|
||||
return mBaseUserRestrictions.getRestrictions(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4673,8 +4769,8 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
public void setBaseUserRestrictionsByDpmsForMigration(
|
||||
@UserIdInt int userId, Bundle baseRestrictions) {
|
||||
synchronized (mRestrictionsLock) {
|
||||
if (updateRestrictionsIfNeededLR(
|
||||
userId, new Bundle(baseRestrictions), mBaseUserRestrictions)) {
|
||||
if (mBaseUserRestrictions.updateRestrictions(userId,
|
||||
new Bundle(baseRestrictions))) {
|
||||
invalidateEffectiveUserRestrictionsLR(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,22 +394,6 @@ public class UserRestrictionsUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a sparse array of restrictions bundles into one.
|
||||
*/
|
||||
@Nullable
|
||||
public static Bundle mergeAll(SparseArray<Bundle> restrictions) {
|
||||
if (restrictions.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
final Bundle result = new Bundle();
|
||||
for (int i = 0; i < restrictions.size(); i++) {
|
||||
merge(result, restrictions.valueAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a restriction is settable by device owner.
|
||||
*/
|
||||
@@ -864,27 +848,15 @@ public class UserRestrictionsUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a particular restriction from one array of bundles to another, e.g. for all users.
|
||||
* Moves a particular restriction from one array of restrictions sets to a restriction set,
|
||||
* e.g. for all users.
|
||||
*/
|
||||
public static void moveRestriction(String restrictionKey, SparseArray<Bundle> srcRestrictions,
|
||||
SparseArray<Bundle> destRestrictions) {
|
||||
for (int i = 0; i < srcRestrictions.size(); i++) {
|
||||
final int key = srcRestrictions.keyAt(i);
|
||||
final Bundle from = srcRestrictions.valueAt(i);
|
||||
if (contains(from, restrictionKey)) {
|
||||
from.remove(restrictionKey);
|
||||
Bundle to = destRestrictions.get(key);
|
||||
if (to == null) {
|
||||
to = new Bundle();
|
||||
destRestrictions.append(key, to);
|
||||
}
|
||||
to.putBoolean(restrictionKey, true);
|
||||
// Don't keep empty bundles.
|
||||
if (from.isEmpty()) {
|
||||
srcRestrictions.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
public static void moveRestriction(String restrictionKey,
|
||||
SparseArray<RestrictionsSet> sourceRestrictionsSets,
|
||||
RestrictionsSet destRestrictionSet) {
|
||||
for (int i = 0; i < sourceRestrictionsSets.size(); i++) {
|
||||
final RestrictionsSet sourceRestrictionsSet = sourceRestrictionsSets.valueAt(i);
|
||||
sourceRestrictionsSet.moveRestriction(destRestrictionSet, restrictionKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ import android.test.AndroidTestCase;
|
||||
import android.util.Log;
|
||||
import android.util.Printer;
|
||||
|
||||
import com.android.server.pm.RestrictionsSet;
|
||||
|
||||
import libcore.io.Streams;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
@@ -35,7 +37,6 @@ import org.junit.Assert;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
@@ -58,6 +59,13 @@ public class DpmTestUtils extends AndroidTestCase {
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
|
||||
public static RestrictionsSet newRestrictions(int userId, String... restrictions) {
|
||||
Bundle localRestrictionsBundle = newRestrictions(restrictions);
|
||||
RestrictionsSet localRestrictions = new RestrictionsSet();
|
||||
localRestrictions.updateRestrictions(userId, localRestrictionsBundle);
|
||||
return localRestrictions;
|
||||
}
|
||||
|
||||
public static Bundle newRestrictions(String... restrictions) {
|
||||
final Bundle ret = new Bundle();
|
||||
for (String restriction : restrictions) {
|
||||
@@ -66,6 +74,17 @@ public class DpmTestUtils extends AndroidTestCase {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void assertRestrictions(RestrictionsSet expected, RestrictionsSet actual) {
|
||||
assertEquals(expected.size(), actual.size());
|
||||
|
||||
for (int i = 0; i < expected.size(); i++) {
|
||||
int originatingUserId = expected.keyAt(i);
|
||||
Bundle actualRestrictions = actual.getRestrictions(originatingUserId);
|
||||
assertFalse(actualRestrictions.isEmpty());
|
||||
assertRestrictions(expected.getRestrictions(originatingUserId), actualRestrictions);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertRestrictions(Bundle expected, Bundle actual) {
|
||||
final ArrayList<String> elist;
|
||||
if (expected == null) {
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static com.android.server.devicepolicy.DpmTestUtils.assertRestrictions;
|
||||
import static com.android.server.devicepolicy.DpmTestUtils.newRestrictions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** Test for {@link RestrictionsSet}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class RestrictionsSetTest {
|
||||
|
||||
private RestrictionsSet mRestrictionsSet = new RestrictionsSet();
|
||||
private final int originatingUserId = 0;
|
||||
|
||||
@Test
|
||||
public void testUpdateRestrictions_addRestrictions() {
|
||||
Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS);
|
||||
|
||||
assertTrue(mRestrictionsSet.updateRestrictions(originatingUserId, restrictions));
|
||||
|
||||
assertRestrictions(restrictions, mRestrictionsSet.getRestrictions(originatingUserId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateRestrictions_removeRestrictions() {
|
||||
Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS);
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId, restrictions);
|
||||
|
||||
assertTrue(mRestrictionsSet.updateRestrictions(originatingUserId, new Bundle()));
|
||||
|
||||
assertNull(mRestrictionsSet.getRestrictions(originatingUserId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateRestrictions_noChange() {
|
||||
Bundle restrictions = newRestrictions(UserManager.ENSURE_VERIFY_APPS);
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId, restrictions);
|
||||
|
||||
assertFalse(mRestrictionsSet.updateRestrictions(originatingUserId, restrictions));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveRestriction_containsRestriction() {
|
||||
RestrictionsSet destRestrictionsSet = new RestrictionsSet();
|
||||
|
||||
String restriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(restriction));
|
||||
|
||||
mRestrictionsSet.moveRestriction(destRestrictionsSet, restriction);
|
||||
|
||||
assertNull(mRestrictionsSet.getRestrictions(originatingUserId));
|
||||
assertNotNull(destRestrictionsSet.getRestrictions(originatingUserId));
|
||||
assertRestrictions(newRestrictions(restriction),
|
||||
destRestrictionsSet.getRestrictions(originatingUserId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveRestriction_doesNotContainRestriction() {
|
||||
RestrictionsSet destRestrictionsSet = new RestrictionsSet();
|
||||
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS));
|
||||
|
||||
mRestrictionsSet.moveRestriction(destRestrictionsSet,
|
||||
UserManager.DISALLOW_CONFIG_DATE_TIME);
|
||||
|
||||
assertRestrictions(newRestrictions(UserManager.ENSURE_VERIFY_APPS),
|
||||
mRestrictionsSet.getRestrictions(originatingUserId));
|
||||
assertNull(destRestrictionsSet.getRestrictions(originatingUserId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty_noRestrictions() {
|
||||
assertTrue(mRestrictionsSet.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsEmpty_hasRestrictions() {
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS,
|
||||
UserManager.DISALLOW_CONFIG_DATE_TIME));
|
||||
|
||||
assertFalse(mRestrictionsSet.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeAll_noRestrictions() {
|
||||
assertTrue(mRestrictionsSet.mergeAll().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeAll_hasRestrictions() {
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS,
|
||||
UserManager.DISALLOW_CONFIG_DATE_TIME));
|
||||
mRestrictionsSet.updateRestrictions(10,
|
||||
newRestrictions(UserManager.DISALLOW_ADD_USER,
|
||||
UserManager.DISALLOW_AIRPLANE_MODE));
|
||||
|
||||
Bundle actual = mRestrictionsSet.mergeAll();
|
||||
assertRestrictions(newRestrictions(UserManager.ENSURE_VERIFY_APPS,
|
||||
UserManager.DISALLOW_CONFIG_DATE_TIME, UserManager.DISALLOW_ADD_USER,
|
||||
UserManager.DISALLOW_AIRPLANE_MODE), actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnforcingUsers_hasEnforcingUser() {
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS));
|
||||
mRestrictionsSet.updateRestrictions(10,
|
||||
newRestrictions(UserManager.DISALLOW_ADD_USER));
|
||||
|
||||
List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers(
|
||||
UserManager.ENSURE_VERIFY_APPS, originatingUserId);
|
||||
|
||||
UserManager.EnforcingUser enforcingUser1 = enforcingUsers.get(0);
|
||||
assertEquals(UserHandle.of(originatingUserId), enforcingUser1.getUserHandle());
|
||||
assertEquals(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER,
|
||||
enforcingUser1.getUserRestrictionSource());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnforcingUsers_hasMultipleEnforcingUsers() {
|
||||
int originatingUserId2 = 10;
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS));
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId2,
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS));
|
||||
|
||||
List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers(
|
||||
UserManager.ENSURE_VERIFY_APPS, originatingUserId);
|
||||
|
||||
assertEquals(2, enforcingUsers.size());
|
||||
for (UserManager.EnforcingUser enforcingUser : enforcingUsers) {
|
||||
int userId = enforcingUser.getUserHandle().getIdentifier();
|
||||
assertTrue((userId == originatingUserId) || (userId == originatingUserId2));
|
||||
if (userId == originatingUserId) {
|
||||
assertEquals(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER,
|
||||
enforcingUser.getUserRestrictionSource());
|
||||
}
|
||||
if (userId == originatingUserId2) {
|
||||
assertEquals(UserManager.RESTRICTION_SOURCE_PROFILE_OWNER,
|
||||
enforcingUser.getUserRestrictionSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEnforcingUsers_noEnforcingUsers() {
|
||||
mRestrictionsSet.updateRestrictions(originatingUserId,
|
||||
newRestrictions(UserManager.DISALLOW_USER_SWITCH));
|
||||
|
||||
List<UserManager.EnforcingUser> enforcingUsers = mRestrictionsSet.getEnforcingUsers(
|
||||
UserManager.ENSURE_VERIFY_APPS, originatingUserId);
|
||||
|
||||
assertTrue(enforcingUsers.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -247,60 +247,43 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
|
||||
assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), local);
|
||||
}
|
||||
|
||||
public void testMergeAll() {
|
||||
SparseArray<Bundle> restrictions = new SparseArray<>();
|
||||
assertNull(UserRestrictionsUtils.mergeAll(restrictions));
|
||||
|
||||
restrictions.put(0, newRestrictions(UserManager.DISALLOW_ADJUST_VOLUME));
|
||||
restrictions.put(1, newRestrictions(UserManager.DISALLOW_USB_FILE_TRANSFER));
|
||||
restrictions.put(2, newRestrictions(UserManager.DISALLOW_APPS_CONTROL));
|
||||
|
||||
Bundle result = UserRestrictionsUtils.mergeAll(restrictions);
|
||||
assertRestrictions(
|
||||
newRestrictions(
|
||||
UserManager.DISALLOW_ADJUST_VOLUME,
|
||||
UserManager.DISALLOW_USB_FILE_TRANSFER,
|
||||
UserManager.DISALLOW_APPS_CONTROL),
|
||||
result);
|
||||
}
|
||||
|
||||
public void testMoveRestriction() {
|
||||
SparseArray<Bundle> localRestrictions = new SparseArray<>();
|
||||
SparseArray<Bundle> globalRestrictions = new SparseArray<>();
|
||||
SparseArray<RestrictionsSet> localRestrictions = new SparseArray<>();
|
||||
RestrictionsSet globalRestrictions = new RestrictionsSet();
|
||||
|
||||
// User 0 has only local restrictions, nothing should change.
|
||||
localRestrictions.put(0, newRestrictions(UserManager.DISALLOW_ADJUST_VOLUME));
|
||||
localRestrictions.put(0, newRestrictions(0, UserManager.DISALLOW_ADJUST_VOLUME));
|
||||
// User 1 has a local restriction to be moved to global and some global already. Local
|
||||
// restrictions should be removed for this user.
|
||||
localRestrictions.put(1, newRestrictions(UserManager.ENSURE_VERIFY_APPS));
|
||||
globalRestrictions.put(1, newRestrictions(UserManager.DISALLOW_ADD_USER));
|
||||
localRestrictions.put(1, newRestrictions(1, UserManager.ENSURE_VERIFY_APPS));
|
||||
globalRestrictions.updateRestrictions(1,
|
||||
newRestrictions(UserManager.DISALLOW_ADD_USER));
|
||||
// User 2 has a local restriction to be moved and one to leave local.
|
||||
localRestrictions.put(2, newRestrictions(
|
||||
UserManager.ENSURE_VERIFY_APPS,
|
||||
UserManager.DISALLOW_CONFIG_VPN));
|
||||
localRestrictions.put(2, newRestrictions(2,
|
||||
UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_CONFIG_VPN));
|
||||
|
||||
UserRestrictionsUtils.moveRestriction(
|
||||
UserManager.ENSURE_VERIFY_APPS, localRestrictions, globalRestrictions);
|
||||
|
||||
// Check user 0.
|
||||
assertRestrictions(
|
||||
newRestrictions(UserManager.DISALLOW_ADJUST_VOLUME),
|
||||
newRestrictions(0, UserManager.DISALLOW_ADJUST_VOLUME),
|
||||
localRestrictions.get(0));
|
||||
assertNull(globalRestrictions.get(0));
|
||||
assertNull(globalRestrictions.getRestrictions(0));
|
||||
|
||||
// Check user 1.
|
||||
assertNull(localRestrictions.get(1));
|
||||
assertTrue(localRestrictions.get(1).isEmpty());
|
||||
assertRestrictions(
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_ADD_USER),
|
||||
globalRestrictions.get(1));
|
||||
globalRestrictions.getRestrictions(1));
|
||||
|
||||
// Check user 2.
|
||||
assertRestrictions(
|
||||
newRestrictions(UserManager.DISALLOW_CONFIG_VPN),
|
||||
newRestrictions(2, UserManager.DISALLOW_CONFIG_VPN),
|
||||
localRestrictions.get(2));
|
||||
assertRestrictions(
|
||||
newRestrictions(UserManager.ENSURE_VERIFY_APPS),
|
||||
globalRestrictions.get(2));
|
||||
globalRestrictions.getRestrictions(2));
|
||||
}
|
||||
|
||||
public void testAreEqual() {
|
||||
|
||||
Reference in New Issue
Block a user