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     @Test
testUserTypeBuilder_createUserType()75     public void testUserTypeBuilder_createUserType() {
76         final Bundle restrictions = makeRestrictionsBundle("r1", "r2");
77         final Bundle systemSettings = makeSettingsBundle("s1", "s2");
78         final Bundle secureSettings = makeSettingsBundle("secure_s1", "secure_s2");
79         final List<DefaultCrossProfileIntentFilter> filters = List.of(
80                 new DefaultCrossProfileIntentFilter.Builder(
81                 DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
82                 /* flags= */0,
83                 /* letsPersonalDataIntoProfile= */false).build());
84         final UserProperties.Builder userProps = new UserProperties.Builder()
85                 .setShowInLauncher(17)
86                 .setUseParentsContacts(true)
87                 .setCrossProfileIntentFilterAccessControl(10)
88                 .setCrossProfileIntentResolutionStrategy(1)
89                 .setMediaSharedWithParent(true)
90                 .setCredentialShareableWithParent(false)
91                 .setAuthAlwaysRequiredToDisableQuietMode(true)
92                 .setAllowStoppingUserWithDelayedLocking(true)
93                 .setShowInSettings(900)
94                 .setShowInSharingSurfaces(20)
95                 .setShowInQuietMode(30)
96                 .setInheritDevicePolicy(340)
97                 .setDeleteAppWithParent(true)
98                 .setAlwaysVisible(true)
99                 .setCrossProfileContentSharingStrategy(1)
100                 .setProfileApiVisibility(34)
101                 .setItemsRestrictedOnHomeScreen(true);
102 
103         final UserTypeDetails type = new UserTypeDetails.Builder()
104                 .setName("a.name")
105                 .setEnabled(1)
106                 .setMaxAllowed(21)
107                 .setBaseType(FLAG_PROFILE)
108                 .setDefaultUserInfoPropertyFlags(FLAG_EPHEMERAL)
109                 .setBadgeLabels(23, 24, 25)
110                 .setBadgeColors(26, 27)
111                 .setIconBadge(28)
112                 .setBadgePlain(29)
113                 .setBadgeNoBackground(30)
114                 .setMaxAllowedPerParent(32)
115                 .setStatusBarIcon(33)
116                 .setLabels(34, 35, 36)
117                 .setDefaultRestrictions(restrictions)
118                 .setDefaultSystemSettings(systemSettings)
119                 .setDefaultSecureSettings(secureSettings)
120                 .setDefaultCrossProfileIntentFilters(filters)
121                 .setDefaultUserProperties(userProps)
122                 .createUserTypeDetails();
123 
124         assertEquals("a.name", type.getName());
125         assertTrue(type.isEnabled());
126         assertEquals(21, type.getMaxAllowed());
127         assertEquals(FLAG_PROFILE | FLAG_EPHEMERAL, type.getDefaultUserInfoFlags());
128         assertEquals(28, type.getIconBadge());
129         assertEquals(29, type.getBadgePlain());
130         assertEquals(30, type.getBadgeNoBackground());
131         assertEquals(32, type.getMaxAllowedPerParent());
132         assertEquals(33, type.getStatusBarIcon());
133         assertEquals(34, type.getLabel(0));
134         assertEquals(35, type.getLabel(1));
135         assertEquals(36, type.getLabel(2));
136 
137         assertTrue(UserRestrictionsUtils.areEqual(restrictions, type.getDefaultRestrictions()));
138         assertNotSame(restrictions, type.getDefaultRestrictions());
139 
140         assertNotSame(systemSettings, type.getDefaultSystemSettings());
141         assertEquals(systemSettings.size(), type.getDefaultSystemSettings().size());
142         for (String key : systemSettings.keySet()) {
143             assertEquals(
144                     systemSettings.getString(key),
145                     type.getDefaultSystemSettings().getString(key));
146         }
147 
148         assertNotSame(secureSettings, type.getDefaultSecureSettings());
149         assertEquals(secureSettings.size(), type.getDefaultSecureSettings().size());
150         for (String key : secureSettings.keySet()) {
151             assertEquals(
152                     secureSettings.getString(key),
153                     type.getDefaultSecureSettings().getString(key));
154         }
155 
156         assertNotSame(filters, type.getDefaultCrossProfileIntentFilters());
157         assertEquals(filters.size(), type.getDefaultCrossProfileIntentFilters().size());
158         for (int i = 0; i < filters.size(); i++) {
159             assertEquals(filters.get(i), type.getDefaultCrossProfileIntentFilters().get(i));
160         }
161 
162         assertEquals(17, type.getDefaultUserPropertiesReference().getShowInLauncher());
163         assertTrue(type.getDefaultUserPropertiesReference().getUseParentsContacts());
164         assertEquals(10, type.getDefaultUserPropertiesReference()
165                 .getCrossProfileIntentFilterAccessControl());
166         assertEquals(1, type.getDefaultUserPropertiesReference()
167                 .getCrossProfileIntentResolutionStrategy());
168         assertTrue(type.getDefaultUserPropertiesReference().isMediaSharedWithParent());
169         assertFalse(type.getDefaultUserPropertiesReference().isCredentialShareableWithParent());
170         assertTrue(type.getDefaultUserPropertiesReference()
171                 .isAuthAlwaysRequiredToDisableQuietMode());
172         assertTrue(type.getDefaultUserPropertiesReference()
173                 .getAllowStoppingUserWithDelayedLocking());
174         assertEquals(900, type.getDefaultUserPropertiesReference().getShowInSettings());
175         assertEquals(20, type.getDefaultUserPropertiesReference().getShowInSharingSurfaces());
176         assertEquals(30,
177                 type.getDefaultUserPropertiesReference().getShowInQuietMode());
178         assertEquals(340, type.getDefaultUserPropertiesReference()
179                 .getInheritDevicePolicy());
180         assertTrue(type.getDefaultUserPropertiesReference().getDeleteAppWithParent());
181         assertTrue(type.getDefaultUserPropertiesReference().getAlwaysVisible());
182         assertEquals(1, type.getDefaultUserPropertiesReference()
183                 .getCrossProfileContentSharingStrategy());
184         assertEquals(34, type.getDefaultUserPropertiesReference().getProfileApiVisibility());
185         assertTrue(type.getDefaultUserPropertiesReference().areItemsRestrictedOnHomeScreen());
186 
187         assertEquals(23, type.getBadgeLabel(0));
188         assertEquals(24, type.getBadgeLabel(1));
189         assertEquals(25, type.getBadgeLabel(2));
190         assertEquals(25, type.getBadgeLabel(3));
191         assertEquals(25, type.getBadgeLabel(4));
192         assertEquals(Resources.ID_NULL, type.getBadgeLabel(-1));
193 
194         assertEquals(26, type.getBadgeColor(0));
195         assertEquals(27, type.getBadgeColor(1));
196         assertEquals(27, type.getBadgeColor(2));
197         assertEquals(27, type.getBadgeColor(3));
198         assertEquals(Resources.ID_NULL, type.getBadgeColor(-100));
199 
200         assertTrue(type.hasBadge());
201     }
202 
203     @Test
testUserTypeBuilder_defaults()204     public void testUserTypeBuilder_defaults() {
205         UserTypeDetails type = new UserTypeDetails.Builder()
206                 .setName("name") // Required (no default allowed)
207                 .setBaseType(FLAG_FULL) // Required (no default allowed)
208                 .createUserTypeDetails();
209 
210         assertTrue(type.isEnabled());
211         assertEquals(UNLIMITED_NUMBER_OF_USERS, type.getMaxAllowed());
212         assertEquals(UNLIMITED_NUMBER_OF_USERS, type.getMaxAllowedPerParent());
213         assertEquals(FLAG_FULL, type.getDefaultUserInfoFlags());
214         assertEquals(Resources.ID_NULL, type.getIconBadge());
215         assertEquals(Resources.ID_NULL, type.getBadgePlain());
216         assertEquals(Resources.ID_NULL, type.getBadgeNoBackground());
217         assertEquals(Resources.ID_NULL, type.getStatusBarIcon());
218         assertEquals(Resources.ID_NULL, type.getBadgeLabel(0));
219         assertEquals(Resources.ID_NULL, type.getBadgeColor(0));
220         assertEquals(Resources.ID_NULL, type.getLabel(0));
221         assertTrue(type.getDefaultRestrictions().isEmpty());
222         assertTrue(type.getDefaultSystemSettings().isEmpty());
223         assertTrue(type.getDefaultSecureSettings().isEmpty());
224         assertTrue(type.getDefaultCrossProfileIntentFilters().isEmpty());
225 
226         final UserProperties props = type.getDefaultUserPropertiesReference();
227         assertNotNull(props);
228         assertFalse(props.getStartWithParent());
229         assertFalse(props.getUseParentsContacts());
230         assertEquals(UserProperties.CROSS_PROFILE_INTENT_FILTER_ACCESS_LEVEL_ALL,
231                 props.getCrossProfileIntentFilterAccessControl());
232         assertEquals(UserProperties.SHOW_IN_LAUNCHER_WITH_PARENT, props.getShowInLauncher());
233         assertEquals(UserProperties.CROSS_PROFILE_INTENT_RESOLUTION_STRATEGY_DEFAULT,
234                 props.getCrossProfileIntentResolutionStrategy());
235         assertFalse(props.isMediaSharedWithParent());
236         assertFalse(props.isCredentialShareableWithParent());
237         assertFalse(props.getDeleteAppWithParent());
238         assertFalse(props.getAlwaysVisible());
239         assertEquals(UserProperties.SHOW_IN_LAUNCHER_SEPARATE, props.getShowInSharingSurfaces());
240         assertEquals(UserProperties.SHOW_IN_QUIET_MODE_PAUSED,
241                 props.getShowInQuietMode());
242         assertEquals(UserProperties.CROSS_PROFILE_CONTENT_SHARING_NO_DELEGATION,
243                 props.getCrossProfileContentSharingStrategy());
244         assertEquals(UserProperties.PROFILE_API_VISIBILITY_VISIBLE,
245                 props.getProfileApiVisibility());
246 
247         assertFalse(type.hasBadge());
248     }
249 
250     @Test
testUserTypeBuilder_nameIsRequired()251     public void testUserTypeBuilder_nameIsRequired() {
252         assertThrows(IllegalArgumentException.class,
253                 () -> new UserTypeDetails.Builder()
254                         .setMaxAllowed(21)
255                         .setBaseType(FLAG_FULL)
256                         .createUserTypeDetails());
257     }
258 
259     @Test
testUserTypeBuilder_baseTypeIsRequired()260     public void testUserTypeBuilder_baseTypeIsRequired() {
261         assertThrows(IllegalArgumentException.class,
262                 () -> new UserTypeDetails.Builder()
263                         .setName("name")
264                         .createUserTypeDetails());
265     }
266 
267     @Test
testUserTypeBuilder_colorIsRequiredIfBadged()268     public void testUserTypeBuilder_colorIsRequiredIfBadged() {
269         assertThrows(IllegalArgumentException.class,
270                 () -> getMinimalBuilder()
271                         .setIconBadge(1)
272                         .setBadgeLabels(2)
273                         .createUserTypeDetails());
274     }
275 
276     @Test
testUserTypeBuilder_badgeLabelIsRequiredIfBadged()277     public void testUserTypeBuilder_badgeLabelIsRequiredIfBadged() {
278         assertThrows(IllegalArgumentException.class,
279                 () -> getMinimalBuilder()
280                         .setIconBadge(1)
281                         .setBadgeColors(2)
282                         .createUserTypeDetails());
283     }
284 
285     @Test
testCheckUserTypeConsistency()286     public void testCheckUserTypeConsistency() {
287         assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_GUEST));
288         assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_GUEST | FLAG_EPHEMERAL));
289         assertTrue(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE));
290 
291         assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_DEMO | FLAG_RESTRICTED));
292         assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE | FLAG_SYSTEM));
293         assertFalse(UserManagerService.checkUserTypeConsistency(FLAG_PROFILE | FLAG_FULL));
294     }
295 
296     @Test
testGetDefaultUserType()297     public void testGetDefaultUserType() {
298         // Simple example.
299         assertEquals(UserManager.USER_TYPE_FULL_RESTRICTED,
300                 UserInfo.getDefaultUserType(FLAG_RESTRICTED));
301 
302         // Type plus a non-type flag.
303         assertEquals(UserManager.USER_TYPE_FULL_GUEST,
304                 UserInfo.getDefaultUserType(FLAG_GUEST | FLAG_EPHEMERAL));
305 
306         // Two types, which is illegal.
307         assertThrows(IllegalArgumentException.class,
308                 () -> UserInfo.getDefaultUserType(FLAG_MANAGED_PROFILE | FLAG_GUEST));
309 
310         // No type, which defaults to {@link UserManager#USER_TYPE_FULL_SECONDARY}.
311         assertEquals(UserManager.USER_TYPE_FULL_SECONDARY,
312                 UserInfo.getDefaultUserType(FLAG_EPHEMERAL));
313     }
314 
315     /** Tests {@link UserTypeFactory#customizeBuilders} for a reasonable xml file. */
316     @Test
testUserTypeFactoryCustomize_profile()317     public void testUserTypeFactoryCustomize_profile() throws Exception {
318         final String userTypeAosp1 = "android.test.1"; // Profile user that is not customized
319         final String userTypeAosp2 = "android.test.2"; // Profile user that is customized
320         final String userTypeOem1 = "custom.test.1"; // Custom-defined profile
321 
322         // Mock some "AOSP defaults".
323         final Bundle restrictions = makeRestrictionsBundle("no_config_vpn", "no_config_tethering");
324         final UserProperties.Builder props = new UserProperties.Builder()
325                 .setShowInLauncher(19)
326                 .setStartWithParent(true)
327                 .setUseParentsContacts(true)
328                 .setCrossProfileIntentFilterAccessControl(10)
329                 .setCrossProfileIntentResolutionStrategy(1)
330                 .setMediaSharedWithParent(false)
331                 .setCredentialShareableWithParent(true)
332                 .setAuthAlwaysRequiredToDisableQuietMode(false)
333                 .setAllowStoppingUserWithDelayedLocking(false)
334                 .setShowInSettings(20)
335                 .setInheritDevicePolicy(21)
336                 .setShowInSharingSurfaces(22)
337                 .setShowInQuietMode(24)
338                 .setDeleteAppWithParent(true)
339                 .setAlwaysVisible(false)
340                 .setCrossProfileContentSharingStrategy(1)
341                 .setProfileApiVisibility(36)
342                 .setItemsRestrictedOnHomeScreen(false);
343 
344         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
345         builders.put(userTypeAosp1, new UserTypeDetails.Builder()
346                 .setName(userTypeAosp1)
347                 .setBaseType(FLAG_PROFILE)
348                 .setMaxAllowedPerParent(31)
349                 .setDefaultRestrictions(restrictions)
350                 .setDefaultUserProperties(props));
351         builders.put(userTypeAosp2, new UserTypeDetails.Builder()
352                 .setName(userTypeAosp1)
353                 .setBaseType(FLAG_PROFILE)
354                 .setMaxAllowedPerParent(32)
355                 .setIconBadge(401)
356                 .setBadgeColors(402, 403, 404)
357                 .setDefaultRestrictions(restrictions)
358                 .setDefaultUserProperties(props));
359 
360         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile);
361         UserTypeFactory.customizeBuilders(builders, parser);
362 
363         // userTypeAosp1 should not be modified.
364         UserTypeDetails aospType = builders.get(userTypeAosp1).createUserTypeDetails();
365         assertEquals(31, aospType.getMaxAllowedPerParent());
366         assertEquals(Resources.ID_NULL, aospType.getIconBadge());
367         assertTrue(UserRestrictionsUtils.areEqual(restrictions, aospType.getDefaultRestrictions()));
368         assertEquals(19, aospType.getDefaultUserPropertiesReference().getShowInLauncher());
369         assertEquals(10, aospType.getDefaultUserPropertiesReference()
370                 .getCrossProfileIntentFilterAccessControl());
371         assertEquals(1, aospType.getDefaultUserPropertiesReference()
372                 .getCrossProfileIntentResolutionStrategy());
373         assertTrue(aospType.getDefaultUserPropertiesReference().getStartWithParent());
374         assertTrue(aospType.getDefaultUserPropertiesReference()
375                 .getUseParentsContacts());
376         assertFalse(aospType.getDefaultUserPropertiesReference().isMediaSharedWithParent());
377         assertTrue(aospType.getDefaultUserPropertiesReference()
378                 .isCredentialShareableWithParent());
379         assertFalse(aospType.getDefaultUserPropertiesReference()
380                 .isAuthAlwaysRequiredToDisableQuietMode());
381         assertFalse(aospType.getDefaultUserPropertiesReference()
382                 .getAllowStoppingUserWithDelayedLocking());
383         assertEquals(20, aospType.getDefaultUserPropertiesReference().getShowInSettings());
384         assertEquals(21, aospType.getDefaultUserPropertiesReference()
385                 .getInheritDevicePolicy());
386         assertEquals(22, aospType.getDefaultUserPropertiesReference().getShowInSharingSurfaces());
387         assertEquals(24,
388                 aospType.getDefaultUserPropertiesReference().getShowInQuietMode());
389         assertTrue(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent());
390         assertFalse(aospType.getDefaultUserPropertiesReference().getAlwaysVisible());
391         assertEquals(1, aospType.getDefaultUserPropertiesReference()
392                 .getCrossProfileContentSharingStrategy());
393         assertEquals(36, aospType.getDefaultUserPropertiesReference().getProfileApiVisibility());
394         assertFalse(aospType.getDefaultUserPropertiesReference().areItemsRestrictedOnHomeScreen());
395 
396         // userTypeAosp2 should be modified.
397         aospType = builders.get(userTypeAosp2).createUserTypeDetails();
398         assertEquals(12, aospType.getMaxAllowedPerParent());
399         assertEquals(com.android.internal.R.drawable.ic_corp_icon_badge_case,
400                 aospType.getIconBadge());
401         assertEquals(Resources.ID_NULL, aospType.getBadgePlain()); // No resId for 'garbage'
402         assertEquals(com.android.internal.R.drawable.ic_corp_badge_no_background,
403                 aospType.getBadgeNoBackground());
404         assertEquals(com.android.internal.R.drawable.ic_test_badge_experiment,
405                 aospType.getStatusBarIcon());
406         assertEquals(com.android.internal.R.string.managed_profile_label_badge,
407                 aospType.getBadgeLabel(0));
408         assertEquals(com.android.internal.R.string.managed_profile_label_badge_2,
409                 aospType.getBadgeLabel(1));
410         assertEquals(com.android.internal.R.string.managed_profile_label_badge_2,
411                 aospType.getBadgeLabel(2));
412         assertEquals(com.android.internal.R.string.managed_profile_label_badge_2,
413                 aospType.getBadgeLabel(3));
414         assertEquals(com.android.internal.R.color.profile_badge_1,
415                 aospType.getBadgeColor(0));
416         assertEquals(com.android.internal.R.color.profile_badge_2,
417                 aospType.getBadgeColor(1));
418         assertEquals(com.android.internal.R.color.profile_badge_2,
419                 aospType.getBadgeColor(2));
420         assertEquals(com.android.internal.R.color.profile_badge_2,
421                 aospType.getBadgeColor(3));
422         assertTrue(UserRestrictionsUtils.areEqual(
423                 makeRestrictionsBundle("no_remove_user", "no_bluetooth"),
424                 aospType.getDefaultRestrictions()));
425         assertEquals(2020, aospType.getDefaultUserPropertiesReference().getShowInLauncher());
426         assertEquals(20, aospType.getDefaultUserPropertiesReference()
427                 .getCrossProfileIntentFilterAccessControl());
428         assertEquals(0, aospType.getDefaultUserPropertiesReference()
429                 .getCrossProfileIntentResolutionStrategy());
430         assertFalse(aospType.getDefaultUserPropertiesReference().getStartWithParent());
431         assertFalse(aospType.getDefaultUserPropertiesReference()
432                 .getUseParentsContacts());
433         assertTrue(aospType.getDefaultUserPropertiesReference().isMediaSharedWithParent());
434         assertFalse(aospType.getDefaultUserPropertiesReference()
435                 .isCredentialShareableWithParent());
436         assertTrue(aospType.getDefaultUserPropertiesReference()
437                 .isAuthAlwaysRequiredToDisableQuietMode());
438         assertTrue(aospType.getDefaultUserPropertiesReference()
439                 .getAllowStoppingUserWithDelayedLocking());
440         assertEquals(23, aospType.getDefaultUserPropertiesReference().getShowInSettings());
441         assertEquals(22,
442                 aospType.getDefaultUserPropertiesReference().getShowInSharingSurfaces());
443         assertEquals(24,
444                 aospType.getDefaultUserPropertiesReference().getShowInQuietMode());
445         assertEquals(450, aospType.getDefaultUserPropertiesReference()
446                 .getInheritDevicePolicy());
447         assertFalse(aospType.getDefaultUserPropertiesReference().getDeleteAppWithParent());
448         assertTrue(aospType.getDefaultUserPropertiesReference().getAlwaysVisible());
449         assertEquals(0, aospType.getDefaultUserPropertiesReference()
450                 .getCrossProfileContentSharingStrategy());
451         assertEquals(36, aospType.getDefaultUserPropertiesReference().getProfileApiVisibility());
452         assertTrue(aospType.getDefaultUserPropertiesReference().areItemsRestrictedOnHomeScreen());
453 
454         // userTypeOem1 should be created.
455         UserTypeDetails.Builder customType = builders.get(userTypeOem1);
456         assertNotNull(customType);
457         assertEquals(14, customType.createUserTypeDetails().getMaxAllowedPerParent());
458     }
459 
460     /** Tests {@link UserTypeFactory#customizeBuilders} for customizing a FULL user. */
461     @Test
testUserTypeFactoryCustomize_full()462     public void testUserTypeFactoryCustomize_full() throws Exception {
463         final String userTypeFull = "android.test.1";
464 
465         // Mock "AOSP default".
466         final Bundle restrictions = makeRestrictionsBundle("no_config_vpn", "no_config_tethering");
467         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
468         builders.put(userTypeFull, new UserTypeDetails.Builder()
469                 .setName(userTypeFull)
470                 .setBaseType(FLAG_FULL)
471                 .setEnabled(0)
472                 .setDefaultRestrictions(restrictions));
473 
474         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full);
475         UserTypeFactory.customizeBuilders(builders, parser);
476 
477         UserTypeDetails details = builders.get(userTypeFull).createUserTypeDetails();
478         assertEquals(UNLIMITED_NUMBER_OF_USERS, details.getMaxAllowedPerParent());
479         assertFalse(details.isEnabled());
480         assertEquals(17, details.getMaxAllowed());
481         assertTrue(UserRestrictionsUtils.areEqual(
482                 makeRestrictionsBundle("no_remove_user", "no_bluetooth"),
483                 details.getDefaultRestrictions()));
484         assertEquals(Resources.ID_NULL, details.getBadgeColor(0));
485     }
486 
487     /**
488      * Tests {@link UserTypeFactory#customizeBuilders} when custom user type deletes the
489      * badge-colors and restrictions.
490      */
491     @Test
testUserTypeFactoryCustomize_eraseArray()492     public void testUserTypeFactoryCustomize_eraseArray() throws Exception {
493         final String typeName = "android.test";
494 
495         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
496         builders.put(typeName, new UserTypeDetails.Builder()
497                 .setName(typeName)
498                 .setBaseType(FLAG_PROFILE)
499                 .setMaxAllowedPerParent(1)
500                 .setBadgeColors(501, 502)
501                 .setDefaultRestrictions(makeRestrictionsBundle("r1")));
502 
503         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_eraseArray);
504         UserTypeFactory.customizeBuilders(builders, parser);
505 
506         UserTypeDetails typeDetails =  builders.get(typeName).createUserTypeDetails();
507         assertEquals(2, typeDetails.getMaxAllowedPerParent());
508         assertEquals(Resources.ID_NULL, typeDetails.getBadgeColor(0));
509         assertEquals(Resources.ID_NULL, typeDetails.getBadgeColor(1));
510         assertTrue(typeDetails.getDefaultRestrictions().isEmpty());
511     }
512 
513     /** Tests {@link UserTypeFactory#customizeBuilders} when custom user type has illegal name. */
514     @Test
testUserTypeFactoryCustomize_illegalOemName()515     public void testUserTypeFactoryCustomize_illegalOemName() throws Exception {
516         final String userTypeAosp = "android.aosp.legal";
517         final String userTypeOem = "android.oem.illegal.name"; // Custom-defined profile
518 
519         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
520         builders.put(userTypeAosp, new UserTypeDetails.Builder()
521                 .setName(userTypeAosp)
522                 .setBaseType(FLAG_PROFILE)
523                 .setMaxAllowedPerParent(21));
524 
525         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_illegalOemName);
526 
527         // parser is illegal because non-AOSP user types cannot be prefixed with "android.".
528         assertThrows(IllegalArgumentException.class,
529                 () -> UserTypeFactory.customizeBuilders(builders, parser));
530     }
531 
532     /**
533      * Tests {@link UserTypeFactory#customizeBuilders} when illegally customizing a non-profile as
534      * a profile.
535      */
536     @Test
testUserTypeFactoryCustomize_illegalUserBaseType()537     public void testUserTypeFactoryCustomize_illegalUserBaseType() throws Exception {
538         final String userTypeFull = "android.test";
539 
540         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
541         builders.put(userTypeFull, new UserTypeDetails.Builder()
542                 .setName(userTypeFull)
543                 .setBaseType(FLAG_FULL)
544                 .setMaxAllowedPerParent(21));
545 
546         XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_illegalUserBaseType);
547 
548         // parser is illegal because userTypeFull is FULL but the tag is for profile-type.
549         assertThrows(IllegalArgumentException.class,
550                 () -> UserTypeFactory.customizeBuilders(builders, parser));
551     }
552 
553     @Test
testUserTypeFactoryVersion_versionMissing()554     public void testUserTypeFactoryVersion_versionMissing() {
555         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_eraseArray);
556         assertEquals(0, UserTypeFactory.getUserTypeVersion(parser));
557     }
558 
559     @Test
testUserTypeFactoryVersion_versionPresent()560     public void testUserTypeFactoryVersion_versionPresent() {
561         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile);
562         assertEquals(1234, UserTypeFactory.getUserTypeVersion(parser));
563     }
564 
565     @Test
testUserTypeFactoryUpgrades_validUpgrades()566     public void testUserTypeFactoryUpgrades_validUpgrades() {
567         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
568         builders.put("name", getMinimalBuilder());
569 
570         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_profile);
571         List<UserTypeFactory.UserTypeUpgrade> upgrades = UserTypeFactory.parseUserUpgrades(builders,
572                 parser);
573 
574         assertFalse(upgrades.isEmpty());
575         UserTypeFactory.UserTypeUpgrade upgrade = upgrades.get(0);
576         assertEquals("android.test.1", upgrade.getFromType());
577         assertEquals("android.test.2", upgrade.getToType());
578         assertEquals(1233, upgrade.getUpToVersion());
579     }
580 
581     @Test
testUserTypeFactoryUpgrades_illegalBaseTypeUpgrade()582     public void testUserTypeFactoryUpgrades_illegalBaseTypeUpgrade() {
583         final String userTypeFull = "android.test.1";
584         final ArrayMap<String, UserTypeDetails.Builder> builders = new ArrayMap<>();
585         builders.put(userTypeFull, new UserTypeDetails.Builder()
586                 .setName(userTypeFull)
587                 .setBaseType(FLAG_FULL));
588 
589         final XmlResourceParser parser = mResources.getXml(R.xml.usertypes_test_full);
590 
591         // parser is illegal because the "to" upgrade type is not a profile, but a full user
592         assertThrows(IllegalArgumentException.class,
593                 () -> UserTypeFactory.parseUserUpgrades(builders, parser));
594     }
595 
596     /** Returns a minimal {@link UserTypeDetails.Builder} that can legitimately be created. */
getMinimalBuilder()597     private UserTypeDetails.Builder getMinimalBuilder() {
598         return new UserTypeDetails.Builder().setName("name").setBaseType(FLAG_FULL);
599     }
600 
601     /** Creates a Bundle of the given String restrictions, each set to true. */
makeRestrictionsBundle(String .... restrictions)602     public static Bundle makeRestrictionsBundle(String ... restrictions) {
603         final Bundle bundle = new Bundle();
604         for (String restriction : restrictions) {
605             bundle.putBoolean(restriction, true);
606         }
607         return bundle;
608     }
609 
610     /** Creates a Bundle of the given settings keys and puts true for the value. */
makeSettingsBundle(String .... settings)611     private static Bundle makeSettingsBundle(String ... settings) {
612         final Bundle bundle = new Bundle();
613         for (String setting : settings) {
614             bundle.putBoolean(setting, true);
615         }
616         return bundle;
617     }
618 }
619