1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm; 18 19 import static android.content.pm.UserInfo.FLAG_DEMO; 20 import static android.content.pm.UserInfo.FLAG_EPHEMERAL; 21 import static android.content.pm.UserInfo.FLAG_FULL; 22 import static android.content.pm.UserInfo.FLAG_GUEST; 23 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 24 import static android.content.pm.UserInfo.FLAG_PROFILE; 25 import static android.content.pm.UserInfo.FLAG_RESTRICTED; 26 import static android.content.pm.UserInfo.FLAG_SYSTEM; 27 28 import static com.android.server.pm.UserTypeDetails.UNLIMITED_NUMBER_OF_USERS; 29 30 import static org.junit.Assert.assertEquals; 31 import static org.junit.Assert.assertFalse; 32 import static org.junit.Assert.assertNotNull; 33 import static org.junit.Assert.assertNotSame; 34 import static org.junit.Assert.assertTrue; 35 import static org.testng.Assert.assertThrows; 36 37 import android.content.pm.UserInfo; 38 import android.content.pm.UserProperties; 39 import android.content.res.Resources; 40 import android.content.res.XmlResourceParser; 41 import android.os.Bundle; 42 import android.os.UserManager; 43 import android.platform.test.annotations.Presubmit; 44 import android.util.ArrayMap; 45 46 import androidx.test.InstrumentationRegistry; 47 import androidx.test.filters.MediumTest; 48 import androidx.test.runner.AndroidJUnit4; 49 50 import com.android.frameworks.servicestests.R; 51 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 56 import java.util.List; 57 58 /** 59 * Tests for {@link UserTypeDetails} and {@link UserTypeFactory}. 60 * 61 * <p>Run with: atest UserManagerServiceUserTypeTest 62 */ 63 @Presubmit 64 @RunWith(AndroidJUnit4.class) 65 @MediumTest 66 public class UserManagerServiceUserTypeTest { 67 68 private Resources mResources; 69 70 @Before setup()71 public void setup() { 72 mResources = InstrumentationRegistry.getTargetContext().getResources(); 73 } 74 75 @Test testUserTypeBuilder_createUserType()76 public void testUserTypeBuilder_createUserType() { 77 final Bundle restrictions = makeRestrictionsBundle("r1", "r2"); 78 final Bundle systemSettings = makeSettingsBundle("s1", "s2"); 79 final Bundle secureSettings = makeSettingsBundle("secure_s1", "secure_s2"); 80 final List<DefaultCrossProfileIntentFilter> filters = List.of( 81 new DefaultCrossProfileIntentFilter.Builder( 82 DefaultCrossProfileIntentFilter.Direction.TO_PARENT, 83 /* flags= */0, 84 /* letsPersonalDataIntoProfile= */false).build()); 85 final UserProperties.Builder userProps = new UserProperties.Builder() 86 .setShowInLauncher(17) 87 .setUseParentsContacts(true) 88 .setCrossProfileIntentFilterAccessControl(10) 89 .setCrossProfileIntentResolutionStrategy(1) 90 .setMediaSharedWithParent(true) 91 .setCredentialShareableWithParent(false) 92 .setShowInSettings(900) 93 .setInheritDevicePolicy(340) 94 .setDeleteAppWithParent(true); 95 96 final UserTypeDetails type = new UserTypeDetails.Builder() 97 .setName("a.name") 98 .setEnabled(1) 99 .setMaxAllowed(21) 100 .setBaseType(FLAG_PROFILE) 101 .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL) 102 .setBadgeLabels(23, 24, 25) 103 .setBadgeColors(26, 27) 104 .setIconBadge(28) 105 .setBadgePlain(29) 106 .setBadgeNoBackground(30) 107 .setLabel(31) 108 .setMaxAllowedPerParent(32) 109 .setDefaultRestrictions(restrictions) 110 .setDefaultSystemSettings(systemSettings) 111 .setDefaultSecureSettings(secureSettings) 112 .setDefaultCrossProfileIntentFilters(filters) 113 .setDefaultUserProperties(userProps) 114 .createUserTypeDetails(); 115 116 assertEquals("a.name", type.getName()); 117 assertTrue(type.isEnabled()); 118 assertEquals(21, type.getMaxAllowed()); 119 assertEquals(FLAG_PROFILE | FLAG_EPHEMERAL, type.getDefaultUserInfoFlags()); 120 assertEquals(28, type.getIconBadge()); 121 assertEquals(29, type.getBadgePlain()); 122 assertEquals(30, type.getBadgeNoBackground()); 123 assertEquals(31, type.getLabel()); 124 assertEquals(32, type.getMaxAllowedPerParent()); 125 126 assertTrue(UserRestrictionsUtils.areEqual(restrictions, type.getDefaultRestrictions())); 127 assertNotSame(restrictions, type.getDefaultRestrictions()); 128 129 assertNotSame(systemSettings, type.getDefaultSystemSettings()); 130 assertEquals(systemSettings.size(), type.getDefaultSystemSettings().size()); 131 for (String key : systemSettings.keySet()) { 132 assertEquals( 133 systemSettings.getString(key), 134 type.getDefaultSystemSettings().getString(key)); 135 } 136 137 assertNotSame(secureSettings, type.getDefaultSecureSettings()); 138 assertEquals(secureSettings.size(), type.getDefaultSecureSettings().size()); 139 for (String key : secureSettings.keySet()) { 140 assertEquals( 141 secureSettings.getString(key), 142 type.getDefaultSecureSettings().getString(key)); 143 } 144 145 assertNotSame(filters, type.getDefaultCrossProfileIntentFilters()); 146 assertEquals(filters.size(), type.getDefaultCrossProfileIntentFilters().size()); 147 for (int i = 0; i < filters.size(); i++) { 148 assertEquals(filters.get(i), type.getDefaultCrossProfileIntentFilters().get(i)); 149 } 150 151 assertEquals(17, type.getDefaultUserPropertiesReference().getShowInLauncher()); 152 assertTrue(type.getDefaultUserPropertiesReference().getUseParentsContacts()); 153 assertEquals(10, type.getDefaultUserPropertiesReference() 154 .getCrossProfileIntentFilterAccessControl()); 155 assertEquals(1, type.getDefaultUserPropertiesReference() 156 .getCrossProfileIntentResolutionStrategy()); 157 assertTrue(type.getDefaultUserPropertiesReference().isMediaSharedWithParent()); 158 assertFalse(type.getDefaultUserPropertiesReference().isCredentialShareableWithParent()); 159 assertEquals(900, type.getDefaultUserPropertiesReference().getShowInSettings()); 160 assertEquals(340, type.getDefaultUserPropertiesReference() 161 .getInheritDevicePolicy()); 162 assertTrue(type.getDefaultUserPropertiesReference().getDeleteAppWithParent()); 163 164 assertEquals(23, type.getBadgeLabel(0)); 165 assertEquals(24, type.getBadgeLabel(1)); 166 assertEquals(25, type.getBadgeLabel(2)); 167 assertEquals(25, type.getBadgeLabel(3)); 168 assertEquals(25, type.getBadgeLabel(4)); 169 assertEquals(Resources.ID_NULL, type.getBadgeLabel(-1)); 170 171 assertEquals(26, type.getBadgeColor(0)); 172 assertEquals(27, type.getBadgeColor(1)); 173 assertEquals(27, type.getBadgeColor(2)); 174 assertEquals(27, type.getBadgeColor(3)); 175 assertEquals(Resources.ID_NULL, type.getBadgeColor(-100)); 176 177 assertTrue(type.hasBadge()); 178 } 179 180 @Test testUserTypeBuilder_defaults()181 public void testUserTypeBuilder_defaults() { 182 UserTypeDetails type = new UserTypeDetails.Builder() 183 .setName("name") // Required (no default allowed) 184 .setBaseType(FLAG_FULL) // Required (no default allowed) 185 .createUserTypeDetails(); 186 187 assertTrue(type.isEnabled()); 188 assertEquals(UNLIMITED_NUMBER_OF_USERS, type.getMaxAllowed()); 189 assertEquals(UNLIMITED_NUMBER_OF_USERS, type.getMaxAllowedPerParent()); 190 assertEquals(FLAG_FULL, type.getDefaultUserInfoFlags()); 191 assertEquals(Resources.ID_NULL, type.getIconBadge()); 192 assertEquals(Resources.ID_NULL, type.getBadgePlain()); 193 assertEquals(Resources.ID_NULL, type.getBadgeNoBackground()); 194 assertEquals(Resources.ID_NULL, type.getBadgeLabel(0)); 195 assertEquals(Resources.ID_NULL, type.getBadgeColor(0)); 196 assertEquals(Resources.ID_NULL, type.getLabel()); 197 assertTrue(type.getDefaultRestrictions().isEmpty()); 198 assertTrue(type.getDefaultSystemSettings().isEmpty()); 199 assertTrue(type.getDefaultSecureSettings().isEmpty()); 200 assertTrue(type.getDefaultCrossProfileIntentFilters().isEmpty()); 201 202 final UserProperties props = type.getDefaultUserPropertiesReference(); 203 assertNotNull(props); 204 assertFalse(props.getStartWithParent()); 205 assertFalse(props.getUseParentsContacts()); 206 assertEquals(UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL, 207 props.getCrossProfileIntentFilterAccessControl()); 208 assertEquals(UserProperties.SHOW_IN_LAUNCHER_WITH_PARENT, props.getShowInLauncher()); 209 assertEquals(UserProperties.CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT, 210 props.getCrossProfileIntentResolutionStrategy()); 211 assertFalse(props.isMediaSharedWithParent()); 212 assertFalse(props.isCredentialShareableWithParent()); 213 214 assertFalse(type.hasBadge()); 215 } 216 217 @Test testUserTypeBuilder_nameIsRequired()218 public void testUserTypeBuilder_nameIsRequired() { 219 assertThrows(IllegalArgumentException.class, 220 () -> new UserTypeDetails.Builder() 221 .setMaxAllowed(21) 222 .setBaseType(FLAG_FULL) 223 .createUserTypeDetails()); 224 } 225 226 @Test testUserTypeBuilder_baseTypeIsRequired()227 public void testUserTypeBuilder_baseTypeIsRequired() { 228 assertThrows(IllegalArgumentException.class, 229 () -> new UserTypeDetails.Builder() 230 .setName("name") 231 .createUserTypeDetails()); 232 } 233 234 @Test testUserTypeBuilder_colorIsRequiredIfBadged()235 public void testUserTypeBuilder_colorIsRequiredIfBadged() { 236 assertThrows(IllegalArgumentException.class, 237 () -> getMinimalBuilder() 238 .setIconBadge(1) 239 .setBadgeLabels(2) 240 .createUserTypeDetails()); 241 } 242 243 @Test testUserTypeBuilder_badgeLabelIsRequiredIfBadged()244 public void testUserTypeBuilder_badgeLabelIsRequiredIfBadged() { 245 assertThrows(IllegalArgumentException.class, 246 () -> getMinimalBuilder() 247 .setIconBadge(1) 248 .setBadgeColors(2) 249 .createUserTypeDetails()); 250 } 251 252 @Test testCheckUserTypeConsistency()253 public void testCheckUserTypeConsistency() { 254 assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_GUEST)); 255 assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_GUEST | FLAG_EPHEMERAL)); 256 assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE)); 257 258 assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_DEMO | FLAG_RESTRICTED)); 259 assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE | FLAG_SYSTEM)); 260 assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE | FLAG_FULL)); 261 } 262 263 @Test testGetDefaultUserType()264 public void testGetDefaultUserType() { 265 // Simple example. 266 assertEquals(UserManager.USER_TYPE_FULL_RESTRICTED, 267 UserInfo.getDefaultUserType(FLAG_RESTRICTED)); 268 269 // Type plus a non-type flag. 270 assertEquals(UserManager.USER_TYPE_FULL_GUEST, 271 UserInfo.getDefaultUserType(FLAG_GUEST | FLAG_EPHEMERAL)); 272 273 // Two types, which is illegal. 274 assertThrows(IllegalArgumentException.class, 275 () -> UserInfo.getDefaultUserType(FLAG_MANAGED_PROFILE | FLAG_GUEST)); 276 277 // No type, which defaults to {@link UserManager#USER_TYPE_FULL_SECONDARY}. 278 assertEquals(UserManager.USER_TYPE_FULL_SECONDARY, 279 UserInfo.getDefaultUserType(FLAG_EPHEMERAL)); 280 } 281 282 /** Tests {@link UserTypeFactory#customizeBuilders} for a reasonable xml file. */ 283 @Test testUserTypeFactoryCustomize_profile()284 public void testUserTypeFactoryCustomize_profile() throws Exception { 285 final String userTypeAosp1 = "android.test.1"; // Profile user that is not customized 286 final String userTypeAosp2 = "android.test.2"; // Profile user that is customized 287 final String userTypeOem1 = "custom.test.1"; // Custom-defined profile 288 289 // Mock some "AOSP defaults". 290 final Bundle restrictions = makeRestrictionsBundle("no_config_vpn", "no_config_tethering"); 291 final UserProperties.Builder props = new UserProperties.Builder() 292 .setShowInLauncher(19) 293 .setStartWithParent(true) 294 .setUseParentsContacts(true) 295 .setCrossProfileIntentFilterAccessControl(10) 296 .setCrossProfileIntentResolutionStrategy(1) 297 .setMediaSharedWithParent(false) 298 .setCredentialShareableWithParent(true) 299 .setShowInSettings(20) 300 .setInheritDevicePolicy(21) 301 .setDeleteAppWithParent(true); 302 303 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 304 builders.put(userTypeAosp1, new UserTypeDetails.Builder() 305 .setName(userTypeAosp1) 306 .setBaseType(FLAG_PROFILE) 307 .setMaxAllowedPerParent(31) 308 .setDefaultRestrictions(restrictions) 309 .setDefaultUserProperties(props)); 310 builders.put(userTypeAosp2, new UserTypeDetails.Builder() 311 .setName(userTypeAosp1) 312 .setBaseType(FLAG_PROFILE) 313 .setMaxAllowedPerParent(32) 314 .setIconBadge(401) 315 .setBadgeColors(402, 403, 404) 316 .setDefaultRestrictions(restrictions) 317 .setDefaultUserProperties(props)); 318 319 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile); 320 UserTypeFactory.customizeBuilders(builders, parser); 321 322 // userTypeAosp1 should not be modified. 323 UserTypeDetails aospType = builders.get(userTypeAosp1).createUserTypeDetails(); 324 assertEquals(31, aospType.getMaxAllowedPerParent()); 325 assertEquals(Resources.ID_NULL, aospType.getIconBadge()); 326 assertTrue(UserRestrictionsUtils.areEqual(restrictions, aospType.getDefaultRestrictions())); 327 assertEquals(19, aospType.getDefaultUserPropertiesReference().getShowInLauncher()); 328 assertEquals(10, aospType.getDefaultUserPropertiesReference() 329 .getCrossProfileIntentFilterAccessControl()); 330 assertEquals(1, aospType.getDefaultUserPropertiesReference() 331 .getCrossProfileIntentResolutionStrategy()); 332 assertTrue(aospType.getDefaultUserPropertiesReference().getStartWithParent()); 333 assertTrue(aospType.getDefaultUserPropertiesReference() 334 .getUseParentsContacts()); 335 assertFalse(aospType.getDefaultUserPropertiesReference().isMediaSharedWithParent()); 336 assertTrue(aospType.getDefaultUserPropertiesReference() 337 .isCredentialShareableWithParent()); 338 assertEquals(20, aospType.getDefaultUserPropertiesReference().getShowInSettings()); 339 assertEquals(21, aospType.getDefaultUserPropertiesReference() 340 .getInheritDevicePolicy()); 341 assertTrue(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent()); 342 343 // userTypeAosp2 should be modified. 344 aospType = builders.get(userTypeAosp2).createUserTypeDetails(); 345 assertEquals(12, aospType.getMaxAllowedPerParent()); 346 assertEquals(com.android.internal.R.drawable.ic_corp_icon_badge_case, 347 aospType.getIconBadge()); 348 assertEquals(Resources.ID_NULL, aospType.getBadgePlain()); // No resId for 'garbage' 349 assertEquals(com.android.internal.R.drawable.ic_corp_badge_no_background, 350 aospType.getBadgeNoBackground()); 351 assertEquals(com.android.internal.R.string.managed_profile_label_badge, 352 aospType.getBadgeLabel(0)); 353 assertEquals(com.android.internal.R.string.managed_profile_label_badge_2, 354 aospType.getBadgeLabel(1)); 355 assertEquals(com.android.internal.R.string.managed_profile_label_badge_2, 356 aospType.getBadgeLabel(2)); 357 assertEquals(com.android.internal.R.string.managed_profile_label_badge_2, 358 aospType.getBadgeLabel(3)); 359 assertEquals(com.android.internal.R.color.profile_badge_1, 360 aospType.getBadgeColor(0)); 361 assertEquals(com.android.internal.R.color.profile_badge_2, 362 aospType.getBadgeColor(1)); 363 assertEquals(com.android.internal.R.color.profile_badge_2, 364 aospType.getBadgeColor(2)); 365 assertEquals(com.android.internal.R.color.profile_badge_2, 366 aospType.getBadgeColor(3)); 367 assertTrue(UserRestrictionsUtils.areEqual( 368 makeRestrictionsBundle("no_remove_user", "no_bluetooth"), 369 aospType.getDefaultRestrictions())); 370 assertEquals(2020, aospType.getDefaultUserPropertiesReference().getShowInLauncher()); 371 assertEquals(20, aospType.getDefaultUserPropertiesReference() 372 .getCrossProfileIntentFilterAccessControl()); 373 assertEquals(0, aospType.getDefaultUserPropertiesReference() 374 .getCrossProfileIntentResolutionStrategy()); 375 assertFalse(aospType.getDefaultUserPropertiesReference().getStartWithParent()); 376 assertFalse(aospType.getDefaultUserPropertiesReference() 377 .getUseParentsContacts()); 378 assertTrue(aospType.getDefaultUserPropertiesReference().isMediaSharedWithParent()); 379 assertFalse(aospType.getDefaultUserPropertiesReference() 380 .isCredentialShareableWithParent()); 381 assertEquals(23, aospType.getDefaultUserPropertiesReference().getShowInSettings()); 382 assertEquals(450, aospType.getDefaultUserPropertiesReference() 383 .getInheritDevicePolicy()); 384 assertFalse(aospType.getDefaultUserPropertiesReference() 385 .getDeleteAppWithParent()); 386 387 // userTypeOem1 should be created. 388 UserTypeDetails.Builder customType = builders.get(userTypeOem1); 389 assertNotNull(customType); 390 assertEquals(14, customType.createUserTypeDetails().getMaxAllowedPerParent()); 391 } 392 393 /** Tests {@link UserTypeFactory#customizeBuilders} for customizing a FULL user. */ 394 @Test testUserTypeFactoryCustomize_full()395 public void testUserTypeFactoryCustomize_full() throws Exception { 396 final String userTypeFull = "android.test.1"; 397 398 // Mock "AOSP default". 399 final Bundle restrictions = makeRestrictionsBundle("no_config_vpn", "no_config_tethering"); 400 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 401 builders.put(userTypeFull, new UserTypeDetails.Builder() 402 .setName(userTypeFull) 403 .setBaseType(FLAG_FULL) 404 .setEnabled(0) 405 .setDefaultRestrictions(restrictions)); 406 407 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full); 408 UserTypeFactory.customizeBuilders(builders, parser); 409 410 UserTypeDetails details = builders.get(userTypeFull).createUserTypeDetails(); 411 assertEquals(UNLIMITED_NUMBER_OF_USERS, details.getMaxAllowedPerParent()); 412 assertFalse(details.isEnabled()); 413 assertEquals(17, details.getMaxAllowed()); 414 assertTrue(UserRestrictionsUtils.areEqual( 415 makeRestrictionsBundle("no_remove_user", "no_bluetooth"), 416 details.getDefaultRestrictions())); 417 assertEquals(Resources.ID_NULL, details.getBadgeColor(0)); 418 } 419 420 /** 421 * Tests {@link UserTypeFactory#customizeBuilders} when custom user type deletes the 422 * badge-colors and restrictions. 423 */ 424 @Test testUserTypeFactoryCustomize_eraseArray()425 public void testUserTypeFactoryCustomize_eraseArray() throws Exception { 426 final String typeName = "android.test"; 427 428 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 429 builders.put(typeName, new UserTypeDetails.Builder() 430 .setName(typeName) 431 .setBaseType(FLAG_PROFILE) 432 .setMaxAllowedPerParent(1) 433 .setBadgeColors(501, 502) 434 .setDefaultRestrictions(makeRestrictionsBundle("r1"))); 435 436 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_eraseArray); 437 UserTypeFactory.customizeBuilders(builders, parser); 438 439 UserTypeDetails typeDetails = builders.get(typeName).createUserTypeDetails(); 440 assertEquals(2, typeDetails.getMaxAllowedPerParent()); 441 assertEquals(Resources.ID_NULL, typeDetails.getBadgeColor(0)); 442 assertEquals(Resources.ID_NULL, typeDetails.getBadgeColor(1)); 443 assertTrue(typeDetails.getDefaultRestrictions().isEmpty()); 444 } 445 446 /** Tests {@link UserTypeFactory#customizeBuilders} when custom user type has illegal name. */ 447 @Test testUserTypeFactoryCustomize_illegalOemName()448 public void testUserTypeFactoryCustomize_illegalOemName() throws Exception { 449 final String userTypeAosp = "android.aosp.legal"; 450 final String userTypeOem = "android.oem.illegal.name"; // Custom-defined profile 451 452 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 453 builders.put(userTypeAosp, new UserTypeDetails.Builder() 454 .setName(userTypeAosp) 455 .setBaseType(FLAG_PROFILE) 456 .setMaxAllowedPerParent(21)); 457 458 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_illegalOemName); 459 460 // parser is illegal because non-AOSP user types cannot be prefixed with "android.". 461 assertThrows(IllegalArgumentException.class, 462 () -> UserTypeFactory.customizeBuilders(builders, parser)); 463 } 464 465 /** 466 * Tests {@link UserTypeFactory#customizeBuilders} when illegally customizing a non-profile as 467 * a profile. 468 */ 469 @Test testUserTypeFactoryCustomize_illegalUserBaseType()470 public void testUserTypeFactoryCustomize_illegalUserBaseType() throws Exception { 471 final String userTypeFull = "android.test"; 472 473 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 474 builders.put(userTypeFull, new UserTypeDetails.Builder() 475 .setName(userTypeFull) 476 .setBaseType(FLAG_FULL) 477 .setMaxAllowedPerParent(21)); 478 479 XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_illegalUserBaseType); 480 481 // parser is illegal because userTypeFull is FULL but the tag is for profile-type. 482 assertThrows(IllegalArgumentException.class, 483 () -> UserTypeFactory.customizeBuilders(builders, parser)); 484 } 485 486 @Test testUserTypeFactoryVersion_versionMissing()487 public void testUserTypeFactoryVersion_versionMissing() { 488 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_eraseArray); 489 assertEquals(0, UserTypeFactory.getUserTypeVersion(parser)); 490 } 491 492 @Test testUserTypeFactoryVersion_versionPresent()493 public void testUserTypeFactoryVersion_versionPresent() { 494 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile); 495 assertEquals(1234, UserTypeFactory.getUserTypeVersion(parser)); 496 } 497 498 @Test testUserTypeFactoryUpgrades_validUpgrades()499 public void testUserTypeFactoryUpgrades_validUpgrades() { 500 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 501 builders.put("name", getMinimalBuilder()); 502 503 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile); 504 List<UserTypeFactory.UserTypeUpgrade> upgrades = UserTypeFactory.parseUserUpgrades(builders, 505 parser); 506 507 assertFalse(upgrades.isEmpty()); 508 UserTypeFactory.UserTypeUpgrade upgrade = upgrades.get(0); 509 assertEquals("android.test.1", upgrade.getFromType()); 510 assertEquals("android.test.2", upgrade.getToType()); 511 assertEquals(1233, upgrade.getUpToVersion()); 512 } 513 514 @Test testUserTypeFactoryUpgrades_illegalBaseTypeUpgrade()515 public void testUserTypeFactoryUpgrades_illegalBaseTypeUpgrade() { 516 final String userTypeFull = "android.test.1"; 517 final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>(); 518 builders.put(userTypeFull, new UserTypeDetails.Builder() 519 .setName(userTypeFull) 520 .setBaseType(FLAG_FULL)); 521 522 final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full); 523 524 // parser is illegal because the "to" upgrade type is not a profile, but a full user 525 assertThrows(IllegalArgumentException.class, 526 () -> UserTypeFactory.parseUserUpgrades(builders, parser)); 527 } 528 529 /** Returns a minimal {@link UserTypeDetails.Builder} that can legitimately be created. */ getMinimalBuilder()530 private UserTypeDetails.Builder getMinimalBuilder() { 531 return new UserTypeDetails.Builder().setName("name").setBaseType(FLAG_FULL); 532 } 533 534 /** Creates a Bundle of the given String restrictions, each set to true. */ makeRestrictionsBundle(String .... restrictions)535 public static Bundle makeRestrictionsBundle(String ... restrictions) { 536 final Bundle bundle = new Bundle(); 537 for (String restriction : restrictions) { 538 bundle.putBoolean(restriction, true); 539 } 540 return bundle; 541 } 542 543 /** Creates a Bundle of the given settings keys and puts true for the value. */ makeSettingsBundle(String .... settings)544 private static Bundle makeSettingsBundle(String ... settings) { 545 final Bundle bundle = new Bundle(); 546 for (String setting : settings) { 547 bundle.putBoolean(setting, true); 548 } 549 return bundle; 550 } 551 } 552