Merge "Upgrade profiles to custom user types"

This commit is contained in:
Iavor-Valentin Iftime
2020-11-30 16:44:19 +00:00
committed by Android (Google) Code Review
8 changed files with 421 additions and 16 deletions

View File

@@ -40,7 +40,7 @@ The following example modifies two AOSP user types (the FULL user android.os.use
and the PROFILE user android.os.usertype.profile.MANAGED) and creates a new PROFILE user type
(com.example.profilename):
<user-types>
<user-types version="0">
<full-type name="android.os.usertype.full.SECONDARY" >
<default-restrictions no_sms="true" />
</full-type>
@@ -65,6 +65,11 @@ and the PROFILE user android.os.usertype.profile.MANAGED) and creates a new PROF
<profile-type
name="com.example.profilename"
max-allowed-per-parent="2" />
<change-user-type
from="android.os.usertype.profile.MANAGED"
to="com.example.profilename"
whenVersionLeq="1" />
</user-types>
Mandatory attributes:
@@ -93,6 +98,10 @@ If this file is updated, the properties of any pre-existing user types will be u
Note, however, that default-restrictions refers to the restrictions applied at the time of user
creation; therefore, the active restrictions of any pre-existing users will not be updated.
The 'change-user-type' tag should be used in conjunction with the 'version' property of
'user-types'. It defines a type change for all pre-existing users of 'from' type to the new 'to'
type, if the former 'user-type's version of device is less than or equal to 'whenVersionLeq'.
-->
<user-types>
</user-types>

View File

@@ -119,7 +119,6 @@ import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileDescriptor;
@@ -175,6 +174,7 @@ public class UserManagerService extends IUserManager.Stub {
private static final String ATTR_CONVERTED_FROM_PRE_CREATED = "convertedFromPreCreated";
private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
private static final String ATTR_USER_VERSION = "version";
private static final String ATTR_USER_TYPE_VERSION = "userTypeConfigVersion";
private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
private static final String ATTR_PROFILE_BADGE = "profileBadge";
private static final String ATTR_RESTRICTED_PROFILE_PARENT_ID = "restrictedProfileParentId";
@@ -422,6 +422,7 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mPackagesLock")
private int mNextSerialNumber;
private int mUserVersion = 0;
private int mUserTypeVersion = 0;
private IAppOpsService mAppOpsService;
@@ -2565,6 +2566,8 @@ public class UserManagerService extends IUserManager.Stub {
parser.getAttributeInt(null, ATTR_NEXT_SERIAL_NO, mNextSerialNumber);
mUserVersion =
parser.getAttributeInt(null, ATTR_USER_VERSION, mUserVersion);
mUserTypeVersion =
parser.getAttributeInt(null, ATTR_USER_TYPE_VERSION, mUserTypeVersion);
}
// Pre-O global user restriction were stored as a single bundle (as opposed to per-user
@@ -2627,7 +2630,7 @@ public class UserManagerService extends IUserManager.Stub {
*/
@GuardedBy({"mRestrictionsLock", "mPackagesLock"})
private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
upgradeIfNecessaryLP(oldGlobalUserRestrictions, mUserVersion);
upgradeIfNecessaryLP(oldGlobalUserRestrictions, mUserVersion, mUserTypeVersion);
}
/**
@@ -2636,9 +2639,11 @@ public class UserManagerService extends IUserManager.Stub {
*/
@GuardedBy({"mRestrictionsLock", "mPackagesLock"})
@VisibleForTesting
void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions, int userVersion) {
void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions, int userVersion,
int userTypeVersion) {
Set<Integer> userIdsToWrite = new ArraySet<>();
final int originalVersion = mUserVersion;
final int originalUserTypeVersion = mUserTypeVersion;
if (userVersion < 1) {
// Assign a proper name for the owner, if not initialized correctly before
UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
@@ -2771,13 +2776,24 @@ public class UserManagerService extends IUserManager.Stub {
userVersion = 9;
}
// Done with userVersion changes, moving on to deal with userTypeVersion upgrades
// Upgrade from previous user type to a new user type
final int newUserTypeVersion = UserTypeFactory.getUserTypeVersion();
if (newUserTypeVersion > userTypeVersion) {
synchronized (mUsersLock) {
upgradeUserTypesLU(UserTypeFactory.getUserTypeUpgrades(), mUserTypes,
userTypeVersion, userIdsToWrite);
}
}
if (userVersion < USER_VERSION) {
Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
+ USER_VERSION);
} else {
mUserVersion = userVersion;
mUserTypeVersion = newUserTypeVersion;
if (originalVersion < mUserVersion) {
if (originalVersion < mUserVersion || originalUserTypeVersion < mUserTypeVersion) {
for (int userId : userIdsToWrite) {
UserData userData = getUserDataNoChecks(userId);
if (userData != null) {
@@ -2801,6 +2817,7 @@ public class UserManagerService extends IUserManager.Stub {
UserData userData = putUserInfo(system);
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
mUserTypeVersion = UserTypeFactory.getUserTypeVersion();
Bundle restrictions = new Bundle();
try {
@@ -2991,6 +3008,7 @@ public class UserManagerService extends IUserManager.Stub {
serializer.startTag(null, TAG_USERS);
serializer.attributeInt(null, ATTR_NEXT_SERIAL_NO, mNextSerialNumber);
serializer.attributeInt(null, ATTR_USER_VERSION, mUserVersion);
serializer.attributeInt(null, ATTR_USER_TYPE_VERSION, mUserTypeVersion);
serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
synchronized (mGuestRestrictions) {
@@ -4957,6 +4975,7 @@ public class UserManagerService extends IUserManager.Stub {
// Dump UserTypes
pw.println();
pw.println("User types version: " + mUserTypeVersion);
pw.println("User types (" + mUserTypes.size() + " types):");
for (int i = 0; i < mUserTypes.size(); i++) {
pw.println(" " + mUserTypes.keyAt(i) + ": ");
@@ -5447,6 +5466,9 @@ public class UserManagerService extends IUserManager.Stub {
* Returns the maximum number of users allowed for the given userTypeDetails per parent user.
* This is applicable for user types that are {@link UserTypeDetails#isProfile()}.
* If there is no maximum, {@link UserTypeDetails#UNLIMITED_NUMBER_OF_USERS} is returned.
* Under certain circumstances (such as after a change-user-type) the max value can actually
* be exceeded: this is allowed in order to keep the device in a usable state.
* An error is logged in {@link UserManagerService#upgradeProfileToTypeLU}
*/
private static int getMaxUsersOfTypePerParent(UserTypeDetails userTypeDetails) {
final int defaultMax = userTypeDetails.getMaxAllowedPerParent();
@@ -5534,4 +5556,98 @@ public class UserManagerService extends IUserManager.Stub {
}
return mDevicePolicyManagerInternal;
}
@GuardedBy("mUsersLock")
@VisibleForTesting
void upgradeUserTypesLU(@NonNull List<UserTypeFactory.UserTypeUpgrade> upgradeOps,
@NonNull ArrayMap<String, UserTypeDetails> userTypes,
final int formerUserTypeVersion,
@NonNull Set<Integer> userIdsToWrite) {
for (UserTypeFactory.UserTypeUpgrade userTypeUpgrade : upgradeOps) {
if (DBG) {
Slog.i(LOG_TAG, "Upgrade: " + userTypeUpgrade.getFromType() + " to: "
+ userTypeUpgrade.getToType() + " maxVersion: "
+ userTypeUpgrade.getUpToVersion());
}
// upgrade user type if version up to getUpToVersion()
if (formerUserTypeVersion <= userTypeUpgrade.getUpToVersion()) {
for (int i = 0; i < mUsers.size(); i++) {
UserData userData = mUsers.valueAt(i);
if (userTypeUpgrade.getFromType().equals(userData.info.userType)) {
final UserTypeDetails newUserType = userTypes.get(
userTypeUpgrade.getToType());
if (newUserType == null) {
throw new IllegalStateException(
"Upgrade destination user type not defined: "
+ userTypeUpgrade.getToType());
}
upgradeProfileToTypeLU(userData.info, newUserType);
userIdsToWrite.add(userData.info.id);
}
}
}
}
}
/**
* Changes the user type of a profile to a new user type.
* @param userInfo The user to be updated.
* @param newUserType The new user type.
*/
@GuardedBy("mUsersLock")
@VisibleForTesting
void upgradeProfileToTypeLU(@NonNull UserInfo userInfo, @NonNull UserTypeDetails newUserType) {
Slog.i(LOG_TAG, "Upgrading user " + userInfo.id
+ " from " + userInfo.userType
+ " to " + newUserType.getName());
if (!userInfo.isProfile()) {
throw new IllegalStateException(
"Can only upgrade profile types. " + userInfo.userType
+ " is not a profile type.");
}
// Exceeded maximum profiles for parent user: log error, but allow upgrade
if (!canAddMoreProfilesToUser(newUserType.getName(), userInfo.profileGroupId, false)) {
Slog.w(LOG_TAG,
"Exceeded maximum profiles of type " + newUserType.getName() + " for user "
+ userInfo.id + ". Maximum allowed= "
+ newUserType.getMaxAllowedPerParent());
}
final UserTypeDetails oldUserType = mUserTypes.get(userInfo.userType);
final int oldFlags;
if (oldUserType != null) {
oldFlags = oldUserType.getDefaultUserInfoFlags();
} else {
// if oldUserType is missing from config_user_types.xml -> can only assume FLAG_PROFILE
oldFlags = UserInfo.FLAG_PROFILE;
}
//convert userData to newUserType
userInfo.userType = newUserType.getName();
// remove old default flags and add newUserType's default flags
userInfo.flags = newUserType.getDefaultUserInfoFlags() | (userInfo.flags ^ oldFlags);
// merge existing base restrictions with the new type's default restrictions
synchronized (mRestrictionsLock) {
if (!UserRestrictionsUtils.isEmpty(newUserType.getDefaultRestrictions())) {
final Bundle newRestrictions = UserRestrictionsUtils.clone(
mBaseUserRestrictions.getRestrictions(userInfo.id));
UserRestrictionsUtils.merge(newRestrictions,
newUserType.getDefaultRestrictions());
updateUserRestrictionsInternalLR(newRestrictions, userInfo.id);
if (DBG) {
Slog.i(LOG_TAG, "Updated user " + userInfo.id
+ " restrictions to " + newRestrictions);
}
}
}
// re-compute badge index
userInfo.profileBadge = getFreeProfileBadgeLU(userInfo.profileGroupId, userInfo.userType);
}
}

View File

@@ -174,6 +174,9 @@ public final class UserTypeDetails {
/**
* Returns the maximum number of this user type allowed per parent (for user types, like
* profiles, that have parents).
* Under certain circumstances (such as after a change-user-type) the max value can actually
* be exceeded: this is allowed in order to keep the device in a usable state.
* An error is logged in {@link UserManagerService#upgradeProfileToTypeLU}
* <p>Returns {@link #UNLIMITED_NUMBER_OF_USERS} to indicate that there is no hard limit.
*/
public int getMaxAllowedPerParent() {

View File

@@ -49,6 +49,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
@@ -73,14 +74,7 @@ public final class UserTypeFactory {
* @return mapping from the name of each user type to its {@link UserTypeDetails} object
*/
public static ArrayMap<String, UserTypeDetails> getUserTypes() {
final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
builders.put(USER_TYPE_PROFILE_MANAGED, getDefaultTypeProfileManaged());
builders.put(USER_TYPE_FULL_SYSTEM, getDefaultTypeFullSystem());
builders.put(USER_TYPE_FULL_SECONDARY, getDefaultTypeFullSecondary());
builders.put(USER_TYPE_FULL_GUEST, getDefaultTypeFullGuest());
builders.put(USER_TYPE_FULL_DEMO, getDefaultTypeFullDemo());
builders.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted());
builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless());
final ArrayMap<String, UserTypeDetails.Builder> builders = getDefaultBuilders();
try (XmlResourceParser parser =
Resources.getSystem().getXml(com.android.internal.R.xml.config_user_types)) {
@@ -94,6 +88,20 @@ public final class UserTypeFactory {
return types;
}
private static ArrayMap<String, UserTypeDetails.Builder> getDefaultBuilders() {
final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
builders.put(USER_TYPE_PROFILE_MANAGED, getDefaultTypeProfileManaged());
builders.put(USER_TYPE_FULL_SYSTEM, getDefaultTypeFullSystem());
builders.put(USER_TYPE_FULL_SECONDARY, getDefaultTypeFullSecondary());
builders.put(USER_TYPE_FULL_GUEST, getDefaultTypeFullGuest());
builders.put(USER_TYPE_FULL_DEMO, getDefaultTypeFullDemo());
builders.put(USER_TYPE_FULL_RESTRICTED, getDefaultTypeFullRestricted());
builders.put(USER_TYPE_SYSTEM_HEADLESS, getDefaultTypeSystemHeadless());
return builders;
}
/**
* Returns the Builder for the default {@link UserManager#USER_TYPE_PROFILE_MANAGED}
* configuration.
@@ -232,6 +240,10 @@ public final class UserTypeFactory {
isProfile = true;
} else if ("full-type".equals(elementName)) {
isProfile = false;
} else if ("change-user-type".equals(elementName)) {
// parsed in parseUserUpgrades
XmlUtils.skipCurrentTag(parser);
continue;
} else {
Slog.w(LOG_TAG, "Skipping unknown element " + elementName + " in "
+ parser.getPositionDescription());
@@ -387,4 +399,132 @@ public final class UserTypeFactory {
}
fcn.accept(result);
}
/**
* Returns the user type version of the config XML file.
* @return user type version defined in XML file, 0 if none.
*/
public static int getUserTypeVersion() {
try (XmlResourceParser parser =
Resources.getSystem().getXml(com.android.internal.R.xml.config_user_types)) {
return getUserTypeVersion(parser);
}
}
@VisibleForTesting
static int getUserTypeVersion(XmlResourceParser parser) {
int version = 0;
try {
XmlUtils.beginDocument(parser, "user-types");
String versionValue = parser.getAttributeValue(null, "version");
if (versionValue != null) {
try {
version = Integer.parseInt(versionValue);
} catch (NumberFormatException e) {
Slog.e(LOG_TAG, "Cannot parse value of '" + versionValue + "' for version in "
+ parser.getPositionDescription(), e);
throw e;
}
}
} catch (XmlPullParserException | IOException e) {
Slog.w(LOG_TAG, "Cannot read user type configuration file.", e);
}
return version;
}
/**
* Obtains the user type upgrades for this device.
* @return The list of user type upgrades.
*/
public static List<UserTypeUpgrade> getUserTypeUpgrades() {
final List<UserTypeUpgrade> userUpgrades;
try (XmlResourceParser parser =
Resources.getSystem().getXml(com.android.internal.R.xml.config_user_types)) {
userUpgrades = parseUserUpgrades(getDefaultBuilders(), parser);
}
return userUpgrades;
}
@VisibleForTesting
static List<UserTypeUpgrade> parseUserUpgrades(
ArrayMap<String, UserTypeDetails.Builder> builders, XmlResourceParser parser) {
final List<UserTypeUpgrade> userUpgrades = new ArrayList<>();
try {
XmlUtils.beginDocument(parser, "user-types");
for (XmlUtils.nextElement(parser);
parser.getEventType() != XmlResourceParser.END_DOCUMENT;
XmlUtils.nextElement(parser)) {
final String elementName = parser.getName();
if ("change-user-type".equals(elementName)) {
final String fromType = parser.getAttributeValue(null, "from");
final String toType = parser.getAttributeValue(null, "to");
// Check that the base type doesn't change.
// Currently, only the base type of PROFILE is supported.
validateUserTypeIsProfile(fromType, builders);
validateUserTypeIsProfile(toType, builders);
final int maxVersionToConvert;
try {
maxVersionToConvert = Integer.parseInt(
parser.getAttributeValue(null, "whenVersionLeq"));
} catch (NumberFormatException e) {
Slog.e(LOG_TAG, "Cannot parse value of whenVersionLeq in "
+ parser.getPositionDescription(), e);
throw e;
}
UserTypeUpgrade userTypeUpgrade = new UserTypeUpgrade(fromType, toType,
maxVersionToConvert);
userUpgrades.add(userTypeUpgrade);
continue;
} else {
XmlUtils.skipCurrentTag(parser);
continue;
}
}
} catch (XmlPullParserException | IOException e) {
Slog.w(LOG_TAG, "Cannot read user type configuration file.", e);
}
return userUpgrades;
}
private static void validateUserTypeIsProfile(String userType,
ArrayMap<String, UserTypeDetails.Builder> builders) {
UserTypeDetails.Builder builder = builders.get(userType);
if (builder != null && builder.getBaseType() != FLAG_PROFILE) {
throw new IllegalArgumentException("Illegal upgrade of user type " + userType
+ " : Can only upgrade profiles user types");
}
}
/**
* Contains details required for an upgrade operation for {@link UserTypeDetails};
*/
public static class UserTypeUpgrade {
private final String mFromType;
private final String mToType;
private final int mUpToVersion;
public UserTypeUpgrade(String fromType, String toType, int upToVersion) {
mFromType = fromType;
mToType = toType;
mUpToVersion = upToVersion;
}
public String getFromType() {
return mFromType;
}
public String getToType() {
return mToType;
}
public int getUpToVersion() {
return mUpToVersion;
}
}
}

View File

@@ -22,4 +22,7 @@
<item res='@*android:color/profile_badge_1' />
</badge-colors>
</full-type>
<change-user-type from="android.old.name" to="android.test.1" whenVersionLeq="1" />
</user-types>

View File

@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<user-types>
<user-types version="1234">
<profile-type
name='android.test.2'
max-allowed-per-parent='12'
@@ -32,4 +32,7 @@
<default-restrictions no_remove_user='true' no_bluetooth='true' />
</profile-type>
<profile-type name='custom.test.1' max-allowed-per-parent='14' />
<change-user-type from="android.test.1" to="android.test.2" whenVersionLeq="1233" />
</user-types>

View File

@@ -21,6 +21,7 @@ import static android.content.pm.UserInfo.FLAG_DISABLED;
import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
import static android.content.pm.UserInfo.FLAG_FULL;
import static android.content.pm.UserInfo.FLAG_GUEST;
import static android.content.pm.UserInfo.FLAG_INITIALIZED;
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static android.content.pm.UserInfo.FLAG_PROFILE;
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
@@ -44,6 +45,7 @@ import android.content.pm.UserInfo.UserInfoFlag;
import android.os.Looper;
import android.os.Parcel;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import androidx.test.InstrumentationRegistry;
@@ -206,6 +208,8 @@ public class UserManagerServiceUserInfoTest {
@Test
public void testUpgradeIfNecessaryLP_9() {
final int versionToTest = 9;
// do not trigger a user type upgrade
final int userTypeVersion = UserTypeFactory.getUserTypeVersion();
mUserManagerService.putUserInfo(createUser(100, FLAG_MANAGED_PROFILE, null));
mUserManagerService.putUserInfo(createUser(101,
@@ -216,7 +220,7 @@ public class UserManagerServiceUserInfoTest {
mUserManagerService.putUserInfo(createUser(105, FLAG_SYSTEM | FLAG_FULL, null));
mUserManagerService.putUserInfo(createUser(106, FLAG_DEMO | FLAG_FULL, null));
mUserManagerService.upgradeIfNecessaryLP(null, versionToTest - 1);
mUserManagerService.upgradeIfNecessaryLP(null, versionToTest - 1, userTypeVersion);
assertTrue(mUserManagerService.isUserOfType(100, USER_TYPE_PROFILE_MANAGED));
assertTrue((mUserManagerService.getUserInfo(100).flags & FLAG_PROFILE) != 0);
@@ -278,4 +282,86 @@ public class UserManagerServiceUserInfoTest {
two.convertedFromPreCreated);
}
}
/** Tests upgrading profile types */
@Test
public void testUpgradeProfileType_updateTypeAndFlags() {
final int userId = 42;
final String newUserTypeName = "new.user.type";
final String oldUserTypeName = USER_TYPE_PROFILE_MANAGED;
UserTypeDetails.Builder oldUserTypeBuilder = new UserTypeDetails.Builder()
.setName(oldUserTypeName)
.setBaseType(FLAG_PROFILE)
.setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE)
.setMaxAllowedPerParent(32)
.setIconBadge(401)
.setBadgeColors(402, 403, 404)
.setBadgeLabels(23, 24, 25);
UserTypeDetails oldUserType = oldUserTypeBuilder.createUserTypeDetails();
UserInfo userInfo = createUser(userId,
oldUserType.getDefaultUserInfoFlags() | FLAG_INITIALIZED, oldUserTypeName);
mUserManagerService.putUserInfo(userInfo);
UserTypeDetails.Builder newUserTypeBuilder = new UserTypeDetails.Builder()
.setName(newUserTypeName)
.setBaseType(FLAG_PROFILE)
.setMaxAllowedPerParent(32)
.setIconBadge(401)
.setBadgeColors(402, 403, 404)
.setBadgeLabels(23, 24, 25);
UserTypeDetails newUserType = newUserTypeBuilder.createUserTypeDetails();
mUserManagerService.upgradeProfileToTypeLU(userInfo, newUserType);
assertTrue(mUserManagerService.isUserOfType(userId, newUserTypeName));
assertTrue((mUserManagerService.getUserInfo(userId).flags & FLAG_PROFILE) != 0);
assertTrue((mUserManagerService.getUserInfo(userId).flags & FLAG_MANAGED_PROFILE) == 0);
assertTrue((mUserManagerService.getUserInfo(userId).flags & FLAG_INITIALIZED) != 0);
}
@Test
public void testUpgradeProfileType_updateRestrictions() {
final int userId = 42;
final String newUserTypeName = "new.user.type";
final String oldUserTypeName = USER_TYPE_PROFILE_MANAGED;
UserTypeDetails.Builder oldUserTypeBuilder = new UserTypeDetails.Builder()
.setName(oldUserTypeName)
.setBaseType(FLAG_PROFILE)
.setDefaultUserInfoPropertyFlags(FLAG_MANAGED_PROFILE)
.setMaxAllowedPerParent(32)
.setIconBadge(401)
.setBadgeColors(402, 403, 404)
.setBadgeLabels(23, 24, 25);
UserTypeDetails oldUserType = oldUserTypeBuilder.createUserTypeDetails();
UserInfo userInfo = createUser(userId, oldUserType.getDefaultUserInfoFlags(),
oldUserTypeName);
mUserManagerService.putUserInfo(userInfo);
mUserManagerService.setUserRestriction(UserManager.DISALLOW_CAMERA, true, userId);
mUserManagerService.setUserRestriction(UserManager.DISALLOW_PRINTING, true, userId);
UserTypeDetails.Builder newUserTypeBuilder = new UserTypeDetails.Builder()
.setName(newUserTypeName)
.setBaseType(FLAG_PROFILE)
.setMaxAllowedPerParent(32)
.setIconBadge(401)
.setBadgeColors(402, 403, 404)
.setBadgeLabels(23, 24, 25)
.setDefaultRestrictions(
UserManagerServiceUserTypeTest.makeRestrictionsBundle(
UserManager.DISALLOW_WALLPAPER));
UserTypeDetails newUserType = newUserTypeBuilder.createUserTypeDetails();
mUserManagerService.upgradeProfileToTypeLU(userInfo, newUserType);
assertTrue(mUserManagerService.getUserRestrictions(userId).getBoolean(
UserManager.DISALLOW_PRINTING));
assertTrue(mUserManagerService.getUserRestrictions(userId).getBoolean(
UserManager.DISALLOW_CAMERA));
assertTrue(mUserManagerService.getUserRestrictions(userId).getBoolean(
UserManager.DISALLOW_WALLPAPER));
}
}

View File

@@ -51,6 +51,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
/**
* Tests for {@link UserTypeDetails} and {@link UserTypeFactory}.
*
@@ -358,13 +360,56 @@ public class UserManagerServiceUserTypeTest {
() -> UserTypeFactory.customizeBuilders(builders, parser));
}
@Test
public void testUserTypeFactoryVersion_versionMissing() {
final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_eraseArray);
assertEquals(0, UserTypeFactory.getUserTypeVersion(parser));
}
@Test
public void testUserTypeFactoryVersion_versionPresent() {
final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile);
assertEquals(1234, UserTypeFactory.getUserTypeVersion(parser));
}
@Test
public void testUserTypeFactoryUpgrades_validUpgrades() {
final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
builders.put("name", getMinimalBuilder());
final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile);
List<UserTypeFactory.UserTypeUpgrade> upgrades = UserTypeFactory.parseUserUpgrades(builders,
parser);
assertFalse(upgrades.isEmpty());
UserTypeFactory.UserTypeUpgrade upgrade = upgrades.get(0);
assertEquals("android.test.1", upgrade.getFromType());
assertEquals("android.test.2", upgrade.getToType());
assertEquals(1233, upgrade.getUpToVersion());
}
@Test
public void testUserTypeFactoryUpgrades_illegalBaseTypeUpgrade() {
final String userTypeFull = "android.test.1";
final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
builders.put(userTypeFull, new UserTypeDetails.Builder()
.setName(userTypeFull)
.setBaseType(FLAG_FULL));
final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full);
// parser is illegal because the "to" upgrade type is not a profile, but a full user
assertThrows(IllegalArgumentException.class,
() -> UserTypeFactory.parseUserUpgrades(builders, parser));
}
/** Returns a minimal {@link UserTypeDetails.Builder} that can legitimately be created. */
private UserTypeDetails.Builder getMinimalBuilder() {
return new UserTypeDetails.Builder().setName("name").setBaseType(FLAG_FULL);
}
/** Creates a Bundle of the given String restrictions, each set to true. */
private Bundle makeRestrictionsBundle(String ... restrictions) {
public static Bundle makeRestrictionsBundle(String ... restrictions) {
final Bundle bundle = new Bundle();
for (String restriction : restrictions) {
bundle.putBoolean(restriction, true);