Merge "Make ENSURE_VERIFY_APPS global even when set by PO."

This commit is contained in:
Pavel Grafov
2017-01-18 11:15:20 +00:00
committed by Android (Google) Code Review
10 changed files with 620 additions and 221 deletions

View File

@@ -32748,7 +32748,8 @@ package android.os {
method public android.os.UserHandle getUserForSerialNumber(long);
method public java.lang.String getUserName();
method public java.util.List<android.os.UserHandle> getUserProfiles();
method public int getUserRestrictionSource(java.lang.String, android.os.UserHandle);
method public deprecated int getUserRestrictionSource(java.lang.String, android.os.UserHandle);
method public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(java.lang.String, android.os.UserHandle);
method public android.os.Bundle getUserRestrictions();
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(java.lang.String);
@@ -32814,6 +32815,14 @@ package android.os {
field public static final int USER_CREATION_FAILED_NO_MORE_USERS = 2; // 0x2
}
public static final class UserManager.EnforcingUser implements android.os.Parcelable {
method public int describeContents();
method public android.os.UserHandle getUserHandle();
method public int getUserRestrictionSource();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.os.UserManager.EnforcingUser> CREATOR;
}
public static abstract class UserManager.UserRestrictionSource implements java.lang.annotation.Annotation {
}

View File

@@ -19,6 +19,7 @@ package android.os;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.content.pm.UserInfo;
import android.content.IntentSender;
import android.content.RestrictionEntry;
@@ -61,6 +62,7 @@ interface IUserManager {
int getUserSerialNumber(int userHandle);
int getUserHandle(int userSerialNumber);
int getUserRestrictionSource(String restrictionKey, int userHandle);
List<UserManager.EnforcingUser> getUserRestrictionSources(String restrictionKey, int userHandle);
Bundle getUserRestrictions(int userHandle);
boolean hasBaseUserRestriction(String restrictionKey, int userHandle);
boolean hasUserRestriction(in String restrictionKey, int userHandle);

View File

@@ -0,0 +1,20 @@
/*
**
** Copyright 2016, 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 android.os;
parcelable UserManager.EnforcingUser;

View File

@@ -1187,7 +1187,9 @@ public class UserManager {
* @return The source of user restriction. Any combination of {@link #RESTRICTION_NOT_SET},
* {@link #RESTRICTION_SOURCE_SYSTEM}, {@link #RESTRICTION_SOURCE_DEVICE_OWNER}
* and {@link #RESTRICTION_SOURCE_PROFILE_OWNER}
* @deprecated use {@link #getUserRestrictionSources(String, int)} instead.
*/
@Deprecated
@SystemApi
@UserRestrictionSource
public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) {
@@ -1198,6 +1200,25 @@ public class UserManager {
}
}
/**
* @hide
*
* Returns a list of users who set a user restriction on a given user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param restrictionKey the string key representing the restriction
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
* @return a list of user ids enforcing this restriction.
*/
@SystemApi
public List<EnforcingUser> getUserRestrictionSources(
String restrictionKey, UserHandle userHandle) {
try {
return mService.getUserRestrictionSources(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Returns the user-wide restrictions imposed on this user.
* @return a Bundle containing all the restrictions.
@@ -2310,8 +2331,8 @@ public class UserManager {
* @hide
* Checks if any uninitialized user has the specific seed account name and type.
*
* @param mAccountName The account name to check for
* @param mAccountType The account type of the account to check for
* @param accountName The account name to check for
* @param accountType The account type of the account to check for
* @return whether the seed account was found
*/
public boolean someUserHasSeedAccount(String accountName, String accountType) {
@@ -2321,4 +2342,73 @@ public class UserManager {
throw re.rethrowFromSystemServer();
}
}
/**
* @hide
* User that enforces a restriction.
*
* @see #getUserRestrictionSources(String, UserHandle)
*/
@SystemApi
public static final class EnforcingUser implements Parcelable {
private final @UserIdInt int userId;
private final @UserRestrictionSource int userRestrictionSource;
/**
* @hide
*/
public EnforcingUser(
@UserIdInt int userId, @UserRestrictionSource int userRestrictionSource) {
this.userId = userId;
this.userRestrictionSource = userRestrictionSource;
}
private EnforcingUser(Parcel in) {
userId = in.readInt();
userRestrictionSource = in.readInt();
}
public static final Creator<EnforcingUser> CREATOR = new Creator<EnforcingUser>() {
@Override
public EnforcingUser createFromParcel(Parcel in) {
return new EnforcingUser(in);
}
@Override
public EnforcingUser[] newArray(int size) {
return new EnforcingUser[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(userId);
dest.writeInt(userRestrictionSource);
}
/**
* Returns an id of the enforcing user.
*
* <p> Will be UserHandle.USER_NULL when restriction is set by the system.
*/
public UserHandle getUserHandle() {
return UserHandle.of(userId);
}
/**
* Returns the status of the enforcing user.
*
* <p> One of {@link #RESTRICTION_SOURCE_SYSTEM},
* {@link #RESTRICTION_SOURCE_DEVICE_OWNER} and
* {@link #RESTRICTION_SOURCE_PROFILE_OWNER}
*/
public @UserRestrictionSource int getUserRestrictionSource() {
return userRestrictionSource;
}
}
}

View File

@@ -15,7 +15,6 @@
*/
package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
@@ -24,6 +23,10 @@ import android.graphics.Bitmap;
* @hide Only for use within the system server.
*/
public abstract class UserManagerInternal {
public static final int CAMERA_NOT_DISABLED = 0;
public static final int CAMERA_DISABLED_LOCALLY = 1;
public static final int CAMERA_DISABLED_GLOBALLY = 2;
public interface UserRestrictionsListener {
/**
* Called when a user restriction changes.
@@ -36,18 +39,19 @@ public abstract class UserManagerInternal {
}
/**
* Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
* to set per-user as well as global user restrictions.
* Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set
* restrictions enforced by the user.
*
* @param userId target user id for the local restrictions.
* @param localRestrictions per-user restrictions.
* Caller must not change it once passed to this method.
* @param globalRestrictions global restrictions set by DO. Must be null when PO changed user
* restrictions, in which case global restrictions won't change.
* Caller must not change it once passed to this method.
* @param restrictions a bundle of user restrictions.
* @param isDeviceOwner whether {@code userId} corresponds to device owner user id.
* @param cameraRestrictionScope is camera disabled and if so what is the scope of restriction.
* Should be one of {@link #CAMERA_NOT_DISABLED}, {@link #CAMERA_DISABLED_LOCALLY} or
* {@link #CAMERA_DISABLED_GLOBALLY}
*/
public abstract void setDevicePolicyUserRestrictions(int userId,
@NonNull Bundle localRestrictions, @Nullable Bundle globalRestrictions);
public abstract void setDevicePolicyUserRestrictions(int userId, @Nullable Bundle restrictions,
boolean isDeviceOwner, int cameraRestrictionScope);
/**
* Returns the "base" user restrictions.
*

View File

@@ -67,6 +67,7 @@ import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager.EnforcingUser;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.os.storage.StorageManager;
@@ -118,6 +119,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -162,7 +164,11 @@ 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_GLOBAL_RESTRICTIONS =
"device_policy_global_restrictions";
/** Legacy name for device owner id tag. */
private static final String TAG_GLOBAL_RESTRICTION_OWNER_ID = "globalRestrictionOwnerUserId";
private static final String TAG_DEVICE_OWNER_USER_ID = "deviceOwnerUserId";
private static final String TAG_ENTRY = "entry";
private static final String TAG_VALUE = "value";
private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
@@ -202,7 +208,7 @@ public class UserManagerService extends IUserManager.Stub {
@VisibleForTesting
static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;
private static final int USER_VERSION = 6;
private static final int USER_VERSION = 7;
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
@@ -267,7 +273,7 @@ public class UserManagerService extends IUserManager.Stub {
/**
* User restrictions set via UserManager. This doesn't include restrictions set by
* device owner / profile owners.
* device owner / profile owners. Only non-empty restriction bundles are stored.
*
* DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
* a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
@@ -305,20 +311,21 @@ public class UserManagerService extends IUserManager.Stub {
/**
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
* that should be applied to all users, including guests.
* that should be applied to all users, including guests. Only non-empty restriction bundles are
* stored.
*/
@GuardedBy("mRestrictionsLock")
private Bundle mDevicePolicyGlobalUserRestrictions;
private final SparseArray<Bundle> mDevicePolicyGlobalUserRestrictions = new SparseArray<>();
/**
* Id of the user that set global restrictions.
*/
@GuardedBy("mRestrictionsLock")
private int mGlobalRestrictionOwnerUserId = UserHandle.USER_NULL;
private int mDeviceOwnerUserId = UserHandle.USER_NULL;
/**
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
* for each user.
* for each user. Only non-empty restriction bundles are stored.
*/
@GuardedBy("mRestrictionsLock")
private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
@@ -1176,39 +1183,36 @@ public class UserManagerService extends IUserManager.Stub {
}
/**
* See {@link UserManagerInternal#setDevicePolicyUserRestrictions(int, Bundle, Bundle)}
* See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
*/
void setDevicePolicyUserRestrictionsInner(int userId, @NonNull Bundle local,
@Nullable Bundle global) {
Preconditions.checkNotNull(local);
boolean globalChanged = false;
boolean localChanged;
private void setDevicePolicyUserRestrictionsInner(int userId, @Nullable Bundle restrictions,
boolean isDeviceOwner, int cameraRestrictionScope) {
final Bundle global = new Bundle();
final Bundle local = new Bundle();
// Sort restrictions into local and global ensuring they don't overlap.
UserRestrictionsUtils.sortToGlobalAndLocal(restrictions, isDeviceOwner,
cameraRestrictionScope, global, local);
boolean globalChanged, localChanged;
synchronized (mRestrictionsLock) {
if (global != null) {
// Update global.
globalChanged = !UserRestrictionsUtils.areEqual(
mDevicePolicyGlobalUserRestrictions, global);
if (globalChanged) {
mDevicePolicyGlobalUserRestrictions = global;
}
// Update global and local restrictions if they were changed.
globalChanged = updateRestrictionsIfNeededLR(
userId, global, mDevicePolicyGlobalUserRestrictions);
localChanged = updateRestrictionsIfNeededLR(
userId, local, mDevicePolicyLocalUserRestrictions);
if (isDeviceOwner) {
// Remember the global restriction owner userId to be able to make a distinction
// in getUserRestrictionSource on who set local policies.
mGlobalRestrictionOwnerUserId = userId;
mDeviceOwnerUserId = userId;
} else {
if (mGlobalRestrictionOwnerUserId == userId) {
if (mDeviceOwnerUserId == userId) {
// 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.
mGlobalRestrictionOwnerUserId = UserHandle.USER_NULL;
}
}
{
// Update local.
final Bundle prev = mDevicePolicyLocalUserRestrictions.get(userId);
localChanged = !UserRestrictionsUtils.areEqual(prev, local);
if (localChanged) {
mDevicePolicyLocalUserRestrictions.put(userId, local);
mDeviceOwnerUserId = UserHandle.USER_NULL;
}
}
}
@@ -1220,12 +1224,9 @@ public class UserManagerService extends IUserManager.Stub {
}
// Don't call them within the mRestrictionsLock.
synchronized (mPackagesLock) {
if (localChanged) {
if (localChanged || globalChanged) {
writeUserLP(getUserDataNoChecks(userId));
}
if (globalChanged) {
writeUserListLP();
}
}
synchronized (mRestrictionsLock) {
@@ -1237,11 +1238,30 @@ public class UserManagerService extends IUserManager.Stub {
}
}
/**
* 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.
*/
private boolean updateRestrictionsIfNeededLR(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);
}
}
return changed;
}
@GuardedBy("mRestrictionsLock")
private Bundle computeEffectiveUserRestrictionsLR(int userId) {
final Bundle baseRestrictions =
UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId));
final Bundle global = mDevicePolicyGlobalUserRestrictions;
final Bundle global = UserRestrictionsUtils.mergeAll(mDevicePolicyGlobalUserRestrictions);
final Bundle local = mDevicePolicyLocalUserRestrictions.get(userId);
if (UserRestrictionsUtils.isEmpty(global) && UserRestrictionsUtils.isEmpty(local)) {
@@ -1299,39 +1319,58 @@ public class UserManagerService extends IUserManager.Stub {
*/
@Override
public int getUserRestrictionSource(String restrictionKey, int userId) {
checkManageUsersPermission("getUserRestrictionSource");
List<EnforcingUser> enforcingUsers = getUserRestrictionSources(restrictionKey, userId);
// Get "bitwise or" of restriction sources for all enforcing users.
int result = UserManager.RESTRICTION_NOT_SET;
for (int i = enforcingUsers.size() - 1; i >= 0; i--) {
result |= enforcingUsers.get(i).getUserRestrictionSource();
}
return result;
}
@Override
public List<EnforcingUser> getUserRestrictionSources(
String restrictionKey, @UserIdInt int userId) {
checkManageUsersPermission("getUserRestrictionSource");
// Shortcut for the most common case
if (!hasUserRestriction(restrictionKey, userId)) {
return result;
return Collections.emptyList();
}
final List<EnforcingUser> result = new ArrayList<>();
// Check if it is base restriction.
if (hasBaseUserRestriction(restrictionKey, userId)) {
result |= UserManager.RESTRICTION_SOURCE_SYSTEM;
result.add(new EnforcingUser(
UserHandle.USER_NULL, UserManager.RESTRICTION_SOURCE_SYSTEM));
}
synchronized(mRestrictionsLock) {
Bundle localRestrictions = mDevicePolicyLocalUserRestrictions.get(userId);
if (!UserRestrictionsUtils.isEmpty(localRestrictions)
&& localRestrictions.getBoolean(restrictionKey)) {
// Local restrictions may have been set by device owner the userId of which is
// stored in mGlobalRestrictionOwnerUserId.
if (mGlobalRestrictionOwnerUserId == userId) {
result |= UserManager.RESTRICTION_SOURCE_DEVICE_OWNER;
} else {
result |= UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
synchronized (mRestrictionsLock) {
// Check if it is set by profile owner.
Bundle profileOwnerRestrictions = mDevicePolicyLocalUserRestrictions.get(userId);
if (UserRestrictionsUtils.contains(profileOwnerRestrictions, restrictionKey)) {
result.add(getEnforcingUserLocked(userId));
}
// 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));
}
}
if (!UserRestrictionsUtils.isEmpty(mDevicePolicyGlobalUserRestrictions)
&& mDevicePolicyGlobalUserRestrictions.getBoolean(restrictionKey)) {
result |= UserManager.RESTRICTION_SOURCE_DEVICE_OWNER;
}
}
return result;
}
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}.
@@ -1374,28 +1413,26 @@ public class UserManagerService extends IUserManager.Stub {
* Optionally updating user restrictions, calculate the effective user restrictions and also
* propagate to other services and system settings.
*
* @param newRestrictions User restrictions to set.
* @param newBaseRestrictions User restrictions to set.
* If null, will not update user restrictions and only does the propagation.
* @param userId target user ID.
*/
@GuardedBy("mRestrictionsLock")
private void updateUserRestrictionsInternalLR(
@Nullable Bundle newRestrictions, int userId) {
@Nullable Bundle newBaseRestrictions, int userId) {
final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull(
mAppliedUserRestrictions.get(userId));
// Update base restrictions.
if (newRestrictions != null) {
// If newRestrictions == the current one, it's probably a bug.
if (newBaseRestrictions != null) {
// If newBaseRestrictions == the current one, it's probably a bug.
final Bundle prevBaseRestrictions = mBaseUserRestrictions.get(userId);
Preconditions.checkState(prevBaseRestrictions != newRestrictions);
Preconditions.checkState(prevBaseRestrictions != newBaseRestrictions);
Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
!= newRestrictions);
!= newBaseRestrictions);
if (!UserRestrictionsUtils.areEqual(prevBaseRestrictions, newRestrictions)) {
mBaseUserRestrictions.put(userId, newRestrictions);
if (updateRestrictionsIfNeededLR(userId, newBaseRestrictions, mBaseUserRestrictions)) {
scheduleWriteUser(getUserDataNoChecks(userId));
}
}
@@ -1746,7 +1783,9 @@ public class UserManagerService extends IUserManager.Stub {
}
}
final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle();
// 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) {
if (type == XmlPullParser.START_TAG) {
@@ -1771,29 +1810,30 @@ public class UserManagerService extends IUserManager.Stub {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
synchronized (mGuestRestrictions) {
UserRestrictionsUtils
.readRestrictions(parser, mGuestRestrictions);
mGuestRestrictions.putAll(
UserRestrictionsUtils.readRestrictions(parser));
}
}
break;
}
}
} else if (name.equals(TAG_DEVICE_POLICY_RESTRICTIONS)) {
UserRestrictionsUtils.readRestrictions(parser,
newDevicePolicyGlobalUserRestrictions);
} else if (name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
} 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)) {
String ownerUserId = parser.getAttributeValue(null, ATTR_ID);
if (ownerUserId != null) {
mGlobalRestrictionOwnerUserId = Integer.parseInt(ownerUserId);
mDeviceOwnerUserId = Integer.parseInt(ownerUserId);
}
} else if (name.equals(TAG_DEVICE_POLICY_RESTRICTIONS)) {
// Should only happen when upgrading from pre-O (version < 7).
oldDevicePolicyGlobalUserRestrictions =
UserRestrictionsUtils.readRestrictions(parser);
}
}
}
synchronized (mRestrictionsLock) {
mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions;
}
updateUserIds();
upgradeIfNecessaryLP();
upgradeIfNecessaryLP(oldDevicePolicyGlobalUserRestrictions);
} catch (IOException | XmlPullParserException e) {
fallbackToSingleUserLP();
} finally {
@@ -1803,8 +1843,9 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Upgrade steps between versions, either for fixing bugs or changing the data format.
* @param oldGlobalUserRestrictions Pre-O global device policy restrictions.
*/
private void upgradeIfNecessaryLP() {
private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
final int originalVersion = mUserVersion;
int userVersion = mUserVersion;
if (userVersion < 1) {
@@ -1855,6 +1896,23 @@ public class UserManagerService extends IUserManager.Stub {
userVersion = 6;
}
if (userVersion < 7) {
// Previously only one user could enforce global restrictions, now it is per-user.
synchronized (mRestrictionsLock) {
if (!UserRestrictionsUtils.isEmpty(oldGlobalUserRestrictions)
&& mDeviceOwnerUserId != UserHandle.USER_NULL) {
mDevicePolicyGlobalUserRestrictions.put(
mDeviceOwnerUserId, oldGlobalUserRestrictions);
}
// 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
);
}
userVersion = 7;
}
if (userVersion < USER_VERSION) {
Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
+ USER_VERSION);
@@ -1893,8 +1951,10 @@ public class UserManagerService extends IUserManager.Stub {
Log.e(LOG_TAG, "Couldn't find resource: config_defaultFirstUserRestrictions", e);
}
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
if (!restrictions.isEmpty()) {
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
}
}
updateUserIds();
@@ -2004,6 +2064,9 @@ public class UserManagerService extends IUserManager.Stub {
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyLocalUserRestrictions.get(userInfo.id),
TAG_DEVICE_POLICY_RESTRICTIONS);
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyGlobalUserRestrictions.get(userInfo.id),
TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS);
}
if (userData.account != null) {
@@ -2057,13 +2120,9 @@ public class UserManagerService extends IUserManager.Stub {
.writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
}
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
synchronized (mRestrictionsLock) {
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyGlobalUserRestrictions, TAG_DEVICE_POLICY_RESTRICTIONS);
}
serializer.startTag(null, TAG_GLOBAL_RESTRICTION_OWNER_ID);
serializer.attribute(null, ATTR_ID, Integer.toString(mGlobalRestrictionOwnerUserId));
serializer.endTag(null, TAG_GLOBAL_RESTRICTION_OWNER_ID);
serializer.startTag(null, TAG_DEVICE_OWNER_USER_ID);
serializer.attribute(null, ATTR_ID, Integer.toString(mDeviceOwnerUserId));
serializer.endTag(null, TAG_DEVICE_OWNER_USER_ID);
int[] userIdsToWrite;
synchronized (mUsersLock) {
userIdsToWrite = new int[mUsers.size()];
@@ -2125,8 +2184,9 @@ public class UserManagerService extends IUserManager.Stub {
String seedAccountName = null;
String seedAccountType = null;
PersistableBundle seedAccountOptions = null;
Bundle baseRestrictions = new Bundle();
Bundle localRestrictions = new Bundle();
Bundle baseRestrictions = null;
Bundle localRestrictions = null;
Bundle globalRestrictions = null;
XmlPullParser parser = Xml.newPullParser();
parser.setInput(is, StandardCharsets.UTF_8.name());
@@ -2187,9 +2247,11 @@ public class UserManagerService extends IUserManager.Stub {
name = parser.getText();
}
} else if (TAG_RESTRICTIONS.equals(tag)) {
UserRestrictionsUtils.readRestrictions(parser, baseRestrictions);
baseRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
UserRestrictionsUtils.readRestrictions(parser, localRestrictions);
localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) {
globalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_ACCOUNT.equals(tag)) {
type = parser.next();
if (type == XmlPullParser.TEXT) {
@@ -2224,8 +2286,15 @@ public class UserManagerService extends IUserManager.Stub {
userData.seedAccountOptions = seedAccountOptions;
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.put(id, baseRestrictions);
mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
if (baseRestrictions != null) {
mBaseUserRestrictions.put(id, baseRestrictions);
}
if (localRestrictions != null) {
mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
}
if (globalRestrictions != null) {
mDevicePolicyGlobalUserRestrictions.put(id, globalRestrictions);
}
}
return userData;
}
@@ -2731,6 +2800,10 @@ public class UserManagerService extends IUserManager.Stub {
mAppliedUserRestrictions.remove(userHandle);
mCachedEffectiveUserRestrictions.remove(userHandle);
mDevicePolicyLocalUserRestrictions.remove(userHandle);
if (mDevicePolicyGlobalUserRestrictions.get(userHandle) != null) {
mDevicePolicyGlobalUserRestrictions.remove(userHandle);
applyUserRestrictionsForAllUsersLR();
}
}
// Update the user list
synchronized (mPackagesLock) {
@@ -3420,6 +3493,9 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
UserRestrictionsUtils.dumpRestrictions(
pw, " ", mBaseUserRestrictions.get(userInfo.id));
pw.println(" Device policy global restrictions:");
UserRestrictionsUtils.dumpRestrictions(
pw, " ", mDevicePolicyGlobalUserRestrictions.get(userInfo.id));
pw.println(" Device policy local restrictions:");
UserRestrictionsUtils.dumpRestrictions(
pw, " ", mDevicePolicyLocalUserRestrictions.get(userInfo.id));
@@ -3448,13 +3524,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
pw.println();
pw.println(" Device policy global restrictions:");
synchronized (mRestrictionsLock) {
UserRestrictionsUtils
.dumpRestrictions(pw, " ", mDevicePolicyGlobalUserRestrictions);
}
pw.println();
pw.println(" Global restrictions owner id:" + mGlobalRestrictionOwnerUserId);
pw.println(" Device owner id:" + mDeviceOwnerUserId);
pw.println();
pw.println(" Guest restrictions:");
synchronized (mGuestRestrictions) {
@@ -3508,10 +3578,10 @@ public class UserManagerService extends IUserManager.Stub {
private class LocalService extends UserManagerInternal {
@Override
public void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle localRestrictions,
@Nullable Bundle globalRestrictions) {
UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, localRestrictions,
globalRestrictions);
public void setDevicePolicyUserRestrictions(int userId, @Nullable Bundle restrictions,
boolean isDeviceOwner, int cameraRestrictionScope) {
UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, restrictions,
isDeviceOwner, cameraRestrictionScope);
}
@Override
@@ -3525,8 +3595,10 @@ public class UserManagerService extends IUserManager.Stub {
public void setBaseUserRestrictionsByDpmsForMigration(
int userId, Bundle baseRestrictions) {
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions));
invalidateEffectiveUserRestrictionsLR(userId);
if (updateRestrictionsIfNeededLR(
userId, new Bundle(baseRestrictions), mBaseUserRestrictions)) {
invalidateEffectiveUserRestrictionsLR(userId);
}
}
final UserData userData = getUserDataNoChecks(userId);

View File

@@ -30,11 +30,13 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.service.persistentdata.PersistentDataBlockManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
@@ -117,9 +119,10 @@ public class UserRestrictionsUtils {
);
/**
* User restrictions that can not be set by profile owners.
* User restrictions that cannot be set by profile owners of secondary users. When set by DO
* they will be applied to all users.
*/
private static final Set<String> DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet(
private static final Set<String> PRIMARY_USER_ONLY_RESTRICTIONS = Sets.newArraySet(
UserManager.DISALLOW_BLUETOOTH,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING,
@@ -163,6 +166,13 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_ADD_MANAGED_PROFILE
);
/*
* Special user restrictions that are always applied to all users no matter who sets them.
*/
private static final Set<String> PROFILE_GLOBAL_RESTRICTIONS = Sets.newArraySet(
UserManager.ENSURE_VERIFY_APPS
);
/**
* Throws {@link IllegalArgumentException} if the given restriction name is invalid.
*/
@@ -205,6 +215,12 @@ public class UserRestrictionsUtils {
}
}
public static Bundle readRestrictions(XmlPullParser parser) {
final Bundle result = new Bundle();
readRestrictions(parser, result);
return result;
}
/**
* @return {@code in} itself when it's not null, or an empty bundle (which can writable).
*/
@@ -216,6 +232,14 @@ public class UserRestrictionsUtils {
return (in == null) || (in.size() == 0);
}
/**
* Returns {@code true} if given bundle is not null and contains {@code true} for a given
* restriction.
*/
public static boolean contains(@Nullable Bundle in, String restriction) {
return in != null && in.getBoolean(restriction);
}
/**
* Creates a copy of the {@code in} Bundle. If {@code in} is null, it'll return an empty
* bundle.
@@ -240,6 +264,22 @@ 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.
*/
@@ -254,7 +294,7 @@ public class UserRestrictionsUtils {
public static boolean canProfileOwnerChange(String restriction, int userId) {
return !IMMUTABLE_BY_OWNERS.contains(restriction)
&& !(userId != UserHandle.USER_SYSTEM
&& DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction));
&& PRIMARY_USER_ONLY_RESTRICTIONS.contains(restriction));
}
/**
@@ -269,8 +309,15 @@ public class UserRestrictionsUtils {
* Takes restrictions that can be set by device owner, and sort them into what should be applied
* globally and what should be applied only on the current user.
*/
public static void sortToGlobalAndLocal(@Nullable Bundle in, @NonNull Bundle global,
@NonNull Bundle local) {
public static void sortToGlobalAndLocal(@Nullable Bundle in, boolean isDeviceOwner,
int cameraRestrictionScope,
@NonNull Bundle global, @NonNull Bundle local) {
// Camera restriction (as well as all others) goes to at most one bundle.
if (cameraRestrictionScope == UserManagerInternal.CAMERA_DISABLED_GLOBALLY) {
global.putBoolean(UserManager.DISALLOW_CAMERA, true);
} else if (cameraRestrictionScope == UserManagerInternal.CAMERA_DISABLED_LOCALLY) {
local.putBoolean(UserManager.DISALLOW_CAMERA, true);
}
if (in == null || in.size() == 0) {
return;
}
@@ -278,7 +325,7 @@ public class UserRestrictionsUtils {
if (!in.getBoolean(key)) {
continue;
}
if (DEVICE_OWNER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)) {
if (isGlobal(isDeviceOwner, key)) {
global.putBoolean(key, true);
} else {
local.putBoolean(key, true);
@@ -286,6 +333,15 @@ public class UserRestrictionsUtils {
}
}
/**
* Whether given user restriction should be enforced globally.
*/
private static boolean isGlobal(boolean isDeviceOwner, String key) {
return (isDeviceOwner &&
(PRIMARY_USER_ONLY_RESTRICTIONS.contains(key)|| GLOBAL_RESTRICTIONS.contains(key)))
|| PROFILE_GLOBAL_RESTRICTIONS.contains(key);
}
/**
* @return true if two Bundles contain the same user restriction.
* A null bundle and an empty bundle are considered to be equal.
@@ -485,4 +541,29 @@ public class UserRestrictionsUtils {
pw.println(prefix + "null");
}
}
/**
* Moves a particular restriction from one array of bundles to another, 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++) {
int key = srcRestrictions.keyAt(i);
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--;
}
}
}
}
}

View File

@@ -1154,7 +1154,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
keepUninstalledPackages = readPackageList(parser, tag);
} else if (TAG_USER_RESTRICTIONS.equals(tag)) {
UserRestrictionsUtils.readRestrictions(parser, ensureUserRestrictions());
userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
readAttributeValues(
parser, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
@@ -7767,7 +7767,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (this) {
ActiveAdmin activeAdmin =
final ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
final boolean isDeviceOwner = isDeviceOwner(who, userHandle);
@@ -7782,7 +7782,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
// Save the restriction to ActiveAdmin.
activeAdmin.ensureUserRestrictions().putBoolean(key, enabledFromThisOwner);
final Bundle restrictions = activeAdmin.ensureUserRestrictions();
if (enabledFromThisOwner) {
restrictions.putBoolean(key, true);
} else {
restrictions.remove(key);
}
saveUserRestrictionsLocked(userHandle);
}
}
@@ -7795,39 +7800,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void pushUserRestrictions(int userId) {
synchronized (this) {
final Bundle global;
final Bundle local = new Bundle();
if (mOwners.isDeviceOwnerUserId(userId)) {
global = new Bundle();
final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId);
final Bundle userRestrictions;
// Whether device owner enforces camera restriction.
boolean disallowCameraGlobally = false;
if (isDeviceOwner) {
final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
if (deviceOwner == null) {
return; // Shouldn't happen.
}
UserRestrictionsUtils.sortToGlobalAndLocal(deviceOwner.userRestrictions,
global, local);
userRestrictions = deviceOwner.userRestrictions;
// DO can disable camera globally.
if (deviceOwner.disableCamera) {
global.putBoolean(UserManager.DISALLOW_CAMERA, true);
}
disallowCameraGlobally = deviceOwner.disableCamera;
} else {
global = null;
final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
userRestrictions = profileOwner != null ? profileOwner.userRestrictions : null;
}
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
if (profileOwner != null) {
UserRestrictionsUtils.merge(local, profileOwner.userRestrictions);
}
}
// Also merge in *local* camera restriction.
if (getCameraDisabled(/* who= */ null,
userId, /* mergeDeviceOwnerRestriction= */ false)) {
local.putBoolean(UserManager.DISALLOW_CAMERA, true);
}
mUserManagerInternal.setDevicePolicyUserRestrictions(userId, local, global);
// Whether any admin enforces camera restriction.
final int cameraRestrictionScope =
getCameraRestrictionScopeLocked(userId, disallowCameraGlobally);
mUserManagerInternal.setDevicePolicyUserRestrictions(userId, userRestrictions,
isDeviceOwner, cameraRestrictionScope);
}
}
/**
* Get the scope of camera restriction for a given user if any.
*/
private int getCameraRestrictionScopeLocked(int userId, boolean disallowCameraGlobally) {
if (disallowCameraGlobally) {
return UserManagerInternal.CAMERA_DISABLED_GLOBALLY;
} else if (getCameraDisabled(
/* who= */ null, userId, /* mergeDeviceOwnerRestriction= */ false)) {
return UserManagerInternal.CAMERA_DISABLED_LOCALLY;
}
return UserManagerInternal.CAMERA_NOT_DISABLED;
}
@Override
public Bundle getUserRestrictions(ComponentName who) {
if (!mHasFeature) {

View File

@@ -15,6 +15,10 @@
*/
package com.android.server.devicepolicy;
import static android.os.UserManagerInternal.CAMERA_DISABLED_GLOBALLY;
import static android.os.UserManagerInternal.CAMERA_DISABLED_LOCALLY;
import static android.os.UserManagerInternal.CAMERA_NOT_DISABLED;
import android.Manifest.permission;
import android.app.Activity;
import android.app.admin.DeviceAdminReceiver;
@@ -39,6 +43,7 @@ import android.os.IBinder;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.test.MoreAsserts;
@@ -928,9 +933,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions()
);
eq(null),
eq(true), eq(CAMERA_NOT_DISABLED));
assertFalse(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM));
@@ -1287,7 +1291,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(defaultRestrictions),
MockUtils.checkUserRestrictions()
eq(true) /* isDeviceOwner */,
eq(CAMERA_NOT_DISABLED)
);
reset(mContext.userManagerInternal);
@@ -1296,21 +1301,21 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
assertNoDeviceOwnerRestrictions();
reset(mContext.userManagerInternal);
dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER)
);
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER),
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER)
);
MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS,
UserManager.DISALLOW_ADD_USER),
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
DpmTestUtils.assertRestrictions(
@@ -1328,8 +1333,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
MockUtils.checkUserRestrictions()
);
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
DpmTestUtils.assertRestrictions(
@@ -1345,8 +1349,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions()
);
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
assertNoDeviceOwnerRestrictions();
@@ -1358,42 +1361,38 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.addUserRestriction(admin1, UserManager.DISALLOW_UNMUTE_MICROPHONE);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE)
);
UserManager.DISALLOW_UNMUTE_MICROPHONE),
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
dpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADJUST_VOLUME);
dpm.clearUserRestriction(admin1, UserManager.DISALLOW_UNMUTE_MICROPHONE);
reset(mContext.userManagerInternal);
// More tests.
dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER)
);
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADD_USER),
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
dpm.addUserRestriction(admin1, UserManager.DISALLOW_FUN);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN,
UserManager.DISALLOW_ADD_USER)
);
UserManager.DISALLOW_ADD_USER),
eq(true), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
dpm.setCameraDisabled(admin1, true);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
// DISALLOW_CAMERA will be applied to both local and global.
MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN,
UserManager.DISALLOW_CAMERA, UserManager.DISALLOW_ADD_USER)
);
UserManager.DISALLOW_ADD_USER),
eq(true), eq(CAMERA_DISABLED_GLOBALLY));
reset(mContext.userManagerInternal);
// Set up another DA and let it disable camera. Now DISALLOW_CAMERA will only be applied
@@ -1407,11 +1406,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
// DISALLOW_CAMERA will be applied to both local and global.
MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA),
// DISALLOW_CAMERA will be applied to both local and global. <- TODO: fix this
MockUtils.checkUserRestrictions(UserManager.DISALLOW_FUN,
UserManager.DISALLOW_ADD_USER)
);
UserManager.DISALLOW_ADD_USER),
eq(true), eq(CAMERA_DISABLED_LOCALLY));
reset(mContext.userManagerInternal);
// TODO Make sure restrictions are written to the file.
}
@@ -1429,8 +1427,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(DpmMockContext.CALLER_USER_HANDLE),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES),
isNull(Bundle.class)
);
eq(false), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
dpm.addUserRestriction(admin1, UserManager.DISALLOW_OUTGOING_CALLS);
@@ -1438,8 +1435,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(DpmMockContext.CALLER_USER_HANDLE),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
UserManager.DISALLOW_OUTGOING_CALLS),
isNull(Bundle.class)
);
eq(false), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
DpmTestUtils.assertRestrictions(
@@ -1462,8 +1458,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(DpmMockContext.CALLER_USER_HANDLE),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_OUTGOING_CALLS),
isNull(Bundle.class)
);
eq(false), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
DpmTestUtils.assertRestrictions(
@@ -1484,8 +1479,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(DpmMockContext.CALLER_USER_HANDLE),
MockUtils.checkUserRestrictions(),
isNull(Bundle.class)
);
eq(false), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
DpmTestUtils.assertRestrictions(
@@ -1507,18 +1501,15 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(DpmMockContext.CALLER_USER_HANDLE),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE),
isNull(Bundle.class)
);
eq(false), eq(CAMERA_NOT_DISABLED));
reset(mContext.userManagerInternal);
dpm.setCameraDisabled(admin1, true);
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(DpmMockContext.CALLER_USER_HANDLE),
MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA,
UserManager.DISALLOW_ADJUST_VOLUME,
MockUtils.checkUserRestrictions(UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE),
isNull(Bundle.class)
);
eq(false), eq(CAMERA_DISABLED_LOCALLY));
reset(mContext.userManagerInternal);
// TODO Make sure restrictions are written to the file.
@@ -1558,7 +1549,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(defaultRestrictions),
MockUtils.checkUserRestrictions()
eq(true) /* isDeviceOwner */,
eq(CAMERA_NOT_DISABLED)
);
reset(mContext.userManagerInternal);
@@ -1600,7 +1592,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.userManagerInternal, atLeast(1)).setDevicePolicyUserRestrictions(
eq(UserHandle.USER_SYSTEM),
MockUtils.checkUserRestrictions(newDefaultEnabledRestriction),
MockUtils.checkUserRestrictions()
eq(true) /* isDeviceOwner */,
eq(CAMERA_NOT_DISABLED)
);
reset(mContext.userManagerInternal);

View File

@@ -16,13 +16,16 @@
package com.android.server.pm;
import static com.android.server.devicepolicy.DpmTestUtils.assertRestrictions;
import static com.android.server.devicepolicy.DpmTestUtils.newRestrictions;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.devicepolicy.DpmTestUtils;
import android.util.SparseArray;
/**
* Tests for {@link com.android.server.pm.UserRestrictionsUtils}.
@@ -49,14 +52,14 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
public void testIsEmpty() {
assertTrue(UserRestrictionsUtils.isEmpty(null));
assertTrue(UserRestrictionsUtils.isEmpty(new Bundle()));
assertFalse(UserRestrictionsUtils.isEmpty(DpmTestUtils.newRestrictions("a")));
assertFalse(UserRestrictionsUtils.isEmpty(newRestrictions("a")));
}
public void testClone() {
Bundle in = new Bundle();
Bundle out = UserRestrictionsUtils.clone(in);
assertNotSame(in, out);
DpmTestUtils.assertRestrictions(out, new Bundle());
assertRestrictions(out, new Bundle());
out = UserRestrictionsUtils.clone(null);
assertNotNull(out);
@@ -64,16 +67,16 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
}
public void testMerge() {
Bundle a = DpmTestUtils.newRestrictions("a", "d");
Bundle b = DpmTestUtils.newRestrictions("b", "d", "e");
Bundle a = newRestrictions("a", "d");
Bundle b = newRestrictions("b", "d", "e");
UserRestrictionsUtils.merge(a, b);
DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions("a", "b", "d", "e"), a);
assertRestrictions(newRestrictions("a", "b", "d", "e"), a);
UserRestrictionsUtils.merge(a, null);
DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions("a", "b", "d", "e"), a);
assertRestrictions(newRestrictions("a", "b", "d", "e"), a);
try {
UserRestrictionsUtils.merge(a, a);
@@ -114,25 +117,32 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
final Bundle local = new Bundle();
final Bundle global = new Bundle();
UserRestrictionsUtils.sortToGlobalAndLocal(null, global, local);
UserRestrictionsUtils.sortToGlobalAndLocal(null, false /* isDeviceOwner */,
UserManagerInternal.CAMERA_NOT_DISABLED, global, local);
assertEquals(0, global.size());
assertEquals(0, local.size());
UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY, global, local);
UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY, false /* isDeviceOwner */,
UserManagerInternal.CAMERA_NOT_DISABLED, global, local);
assertEquals(0, global.size());
assertEquals(0, local.size());
UserRestrictionsUtils.sortToGlobalAndLocal(DpmTestUtils.newRestrictions(
// Restrictions set by DO.
UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(
UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_OUTGOING_BEAM,
UserManager.DISALLOW_APPS_CONTROL
), global, local);
UserManager.DISALLOW_APPS_CONTROL,
UserManager.ENSURE_VERIFY_APPS
), true /* isDeviceOwner */, UserManagerInternal.CAMERA_NOT_DISABLED, global, local);
DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions(
assertRestrictions(newRestrictions(
// This one is global no matter who sets it.
UserManager.ENSURE_VERIFY_APPS,
// These can be set by PO too, but when DO sets them, they're global.
UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE,
@@ -142,11 +152,117 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
UserManager.DISALLOW_CONFIG_TETHERING
), global);
DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions(
assertRestrictions(newRestrictions(
// They can be set by both DO/PO.
UserManager.DISALLOW_OUTGOING_BEAM,
UserManager.DISALLOW_APPS_CONTROL
), local);
local.clear();
global.clear();
// Restrictions set by PO.
UserRestrictionsUtils.sortToGlobalAndLocal(newRestrictions(
UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE,
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_OUTGOING_BEAM,
UserManager.DISALLOW_APPS_CONTROL,
UserManager.ENSURE_VERIFY_APPS
), false /* isDeviceOwner */, UserManagerInternal.CAMERA_NOT_DISABLED, global, local);
assertRestrictions(newRestrictions(
// This one is global no matter who sets it.
UserManager.ENSURE_VERIFY_APPS
), global);
assertRestrictions(newRestrictions(
// These can be set by PO too, but when PO sets them, they're local.
UserManager.DISALLOW_ADJUST_VOLUME,
UserManager.DISALLOW_UNMUTE_MICROPHONE,
// They can be set by both DO/PO.
UserManager.DISALLOW_OUTGOING_BEAM,
UserManager.DISALLOW_APPS_CONTROL,
// These can only be set by DO.
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_TETHERING
), local);
}
public void testSortToLocalAndGlobalWithCameraDisabled() {
final Bundle local = new Bundle();
final Bundle global = new Bundle();
UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY, false,
UserManagerInternal.CAMERA_DISABLED_GLOBALLY, global, local);
assertRestrictions(newRestrictions(UserManager.DISALLOW_CAMERA), global);
assertEquals(0, local.size());
global.clear();
UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY, false,
UserManagerInternal.CAMERA_DISABLED_LOCALLY, global, local);
assertEquals(0, global.size());
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<>();
// User 0 has only local restrictions, nothing should change.
localRestrictions.put(0, newRestrictions(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));
// 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));
UserRestrictionsUtils.moveRestriction(
UserManager.ENSURE_VERIFY_APPS, localRestrictions, globalRestrictions);
// Check user 0.
assertRestrictions(
newRestrictions(UserManager.DISALLOW_ADJUST_VOLUME),
localRestrictions.get(0));
assertNull(globalRestrictions.get(0));
// Check user 1.
assertNull(localRestrictions.get(1));
assertRestrictions(
newRestrictions(UserManager.ENSURE_VERIFY_APPS, UserManager.DISALLOW_ADD_USER),
globalRestrictions.get(1));
// Check user 2.
assertRestrictions(
newRestrictions(UserManager.DISALLOW_CONFIG_VPN),
localRestrictions.get(2));
assertRestrictions(
newRestrictions(UserManager.ENSURE_VERIFY_APPS),
globalRestrictions.get(2));
}
public void testAreEqual() {
@@ -172,33 +288,33 @@ public class UserRestrictionsUtilsTest extends AndroidTestCase {
assertFalse(UserRestrictionsUtils.areEqual(
null,
DpmTestUtils.newRestrictions("a")));
newRestrictions("a")));
assertFalse(UserRestrictionsUtils.areEqual(
DpmTestUtils.newRestrictions("a"),
newRestrictions("a"),
null));
assertTrue(UserRestrictionsUtils.areEqual(
DpmTestUtils.newRestrictions("a"),
DpmTestUtils.newRestrictions("a")));
newRestrictions("a"),
newRestrictions("a")));
assertFalse(UserRestrictionsUtils.areEqual(
DpmTestUtils.newRestrictions("a"),
DpmTestUtils.newRestrictions("a", "b")));
newRestrictions("a"),
newRestrictions("a", "b")));
assertFalse(UserRestrictionsUtils.areEqual(
DpmTestUtils.newRestrictions("a", "b"),
DpmTestUtils.newRestrictions("a")));
newRestrictions("a", "b"),
newRestrictions("a")));
assertFalse(UserRestrictionsUtils.areEqual(
DpmTestUtils.newRestrictions("b", "a"),
DpmTestUtils.newRestrictions("a", "a")));
newRestrictions("b", "a"),
newRestrictions("a", "a")));
// Make sure false restrictions are handled correctly.
final Bundle a = DpmTestUtils.newRestrictions("a");
final Bundle a = newRestrictions("a");
a.putBoolean("b", true);
final Bundle b = DpmTestUtils.newRestrictions("a");
final Bundle b = newRestrictions("a");
b.putBoolean("b", false);
assertFalse(UserRestrictionsUtils.areEqual(a, b));