1 /*
2  * Copyright (C) 2016 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.os.UserManager.USER_TYPE_PROFILE_MANAGED;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23 
24 import android.app.PropertyInvalidatedCache;
25 import android.content.pm.UserInfo;
26 import android.os.Looper;
27 import android.os.ServiceSpecificException;
28 import android.os.UserHandle;
29 import android.os.UserManager;
30 import android.platform.test.annotations.Postsubmit;
31 
32 import androidx.test.InstrumentationRegistry;
33 import androidx.test.filters.MediumTest;
34 import androidx.test.runner.AndroidJUnit4;
35 
36 import com.android.server.LocalServices;
37 import com.android.server.storage.DeviceStorageMonitorInternal;
38 
39 import org.junit.After;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.mockito.Mockito;
44 
45 import java.util.List;
46 
47 /**
48  * <p>Run with:<pre>
49  * runtest -c com.android.server.pm.UserManagerServiceCreateProfileTest frameworks-services
50  * </pre>
51  */
52 @Postsubmit
53 @RunWith(AndroidJUnit4.class)
54 @MediumTest
55 public class UserManagerServiceCreateProfileTest {
56     private UserManagerService mUserManagerService;
57 
58     @Before
setup()59     public void setup() {
60         // Currently UserManagerService cannot be instantiated twice inside a VM without a cleanup
61         // TODO: Remove once UMS supports proper dependency injection
62         if (Looper.myLooper() == null) {
63             Looper.prepare();
64         }
65         // Disable binder caches in this process.
66         PropertyInvalidatedCache.disableForTestMode();
67 
68         LocalServices.removeServiceForTest(UserManagerInternal.class);
69         mUserManagerService = new UserManagerService(InstrumentationRegistry.getContext());
70 
71         // The tests assume that the device has one user and its the system user.
72         List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
73         assertEquals("Multiple users so this test can't run.", 1, users.size());
74         assertEquals("Only user present isn't the system user.",
75                 UserHandle.USER_SYSTEM, users.get(0).id);
76     }
77 
78     @After
tearDown()79     public void tearDown() {
80         removeUsers();
81     }
82 
83     /** Tests UMS.getProfileIds() when no specific userType is specified. */
84     @Test
testGetProfiles()85     public void testGetProfiles() {
86         // Pretend we have a secondary user with a profile.
87         UserInfo secondaryUser = addUser();
88         UserInfo profile = addProfile(secondaryUser);
89 
90         // System user should still have no profile so getProfiles should just return 1 user.
91         List<UserInfo> users =
92                 mUserManagerService.getProfiles(UserHandle.USER_SYSTEM, /*excludeDying*/ false);
93         assertEquals("Profiles returned where none should exist", 1, users.size());
94         assertEquals("Missing system user from profile list of system user",
95                 UserHandle.USER_SYSTEM, users.get(0).id);
96 
97         // Secondary user should have 1 profile, so return that and itself.
98         users = mUserManagerService.getProfiles(secondaryUser.id, /*excludeDying*/ false);
99         assertEquals("Profiles returned where none should exist", 2, users.size());
100         assertTrue("Missing secondary user id", users.get(0).id == secondaryUser.id
101                 || users.get(1).id == secondaryUser.id);
102         assertTrue("Missing profile user id", users.get(0).id == profile.id
103                 || users.get(1).id == profile.id);
104     }
105 
106     /** Tests UMS.getProfileIds() when a specific userType is specified. */
107     @Test
testGetProfileIds_specifyType()108     public void testGetProfileIds_specifyType() {
109         // Pretend we have a secondary user with a profile.
110         UserInfo secondaryUser = addUser();
111         UserInfo profile = addProfile(secondaryUser);
112 
113         // TODO: When there are multiple profiles types, ensure correct output for mixed types.
114         final String userType1 = USER_TYPE_PROFILE_MANAGED;
115 
116         // System user should still have no userType1 profile so getProfileIds should be empty.
117         int[] users = mUserManagerService.getProfileIds(UserHandle.USER_SYSTEM, userType1, false);
118         assertEquals("System user should have no managed profiles", 0, users.length);
119 
120         // Secondary user should have one userType1 profile, so return just that.
121         users = mUserManagerService.getProfileIds(secondaryUser.id, userType1, false);
122         assertEquals("Wrong number of profiles", 1, users.length);
123         assertEquals("Wrong profile id", profile.id, users[0]);
124 
125         // The profile itself is a userType1 profile, so it should return just itself.
126         users = mUserManagerService.getProfileIds(profile.id, userType1, false);
127         assertEquals("Wrong number of profiles", 1, users.length);
128         assertEquals("Wrong profile id", profile.id, users[0]);
129     }
130 
131     @Test
testProfileBadge()132     public void testProfileBadge() {
133         // First profile for system user should get badge 0
134         assertEquals("First profile isn't given badge index 0", 0,
135                 mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
136                         USER_TYPE_PROFILE_MANAGED));
137 
138         // Pretend we have a secondary user.
139         UserInfo secondaryUser = addUser();
140 
141         // Check first profile badge for secondary user is also 0.
142         assertEquals("First profile for secondary user isn't given badge index 0", 0,
143                 mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id,
144                         USER_TYPE_PROFILE_MANAGED));
145 
146         // Shouldn't impact the badge for profile in system user
147         assertEquals("First profile isn't given badge index 0 with secondary user", 0,
148                 mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
149                         USER_TYPE_PROFILE_MANAGED));
150 
151         // Pretend a secondary user has a profile.
152         addProfile(secondaryUser);
153 
154         // Shouldn't have impacted the badge for the system user
155         assertEquals("First profile isn't given badge index 0 in secondary user", 0,
156                 mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
157                         USER_TYPE_PROFILE_MANAGED));
158     }
159 
160     @Test
testProfileBadgeUnique()161     public void testProfileBadgeUnique() {
162         List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
163         UserInfo system = users.get(0);
164         int max = mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED);
165         if (max < 0) {
166             // Indicates no max. Instead of infinite, we'll just do 10.
167             max = 10;
168         }
169         // Badges should get allocated 0 -> max
170         for (int i = 0; i < max; ++i) {
171             int nextBadge = mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM,
172                     USER_TYPE_PROFILE_MANAGED);
173             assertEquals("Wrong badge allocated", i, nextBadge);
174             UserInfo profile = addProfile(system);
175             profile.profileBadge = nextBadge;
176         }
177     }
178 
179     @Test
testProfileBadgeReuse()180     public void testProfileBadgeReuse() {
181         // Pretend we have a secondary user with a profile.
182         UserInfo secondaryUser = addUser();
183         UserInfo profile = addProfile(secondaryUser);
184         // Add the profile it to the users being removed.
185         mUserManagerService.addRemovingUserId(profile.id);
186         // We should reuse the badge from the profile being removed.
187         assertEquals("Badge index not reused while removing a user", 0,
188                 mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id,
189                         USER_TYPE_PROFILE_MANAGED));
190 
191         // Edge case of reuse that only applies if we ever support 3 managed profiles
192         // We should prioritise using lower badge indexes
193         int max = mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED);
194         if (max < 0 || max > 2) {
195             UserInfo profileBadgeOne = addProfile(secondaryUser);
196             profileBadgeOne.profileBadge = 1;
197             // 0 and 2 are free, we should reuse 0 rather than 2.
198             assertEquals("Lower index not used", 0,
199                     mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id,
200                             USER_TYPE_PROFILE_MANAGED));
201         }
202     }
203 
204     @Test
testCanAddMoreManagedProfiles_removeProfile()205     public void testCanAddMoreManagedProfiles_removeProfile() {
206         // if device is low-ram or doesn't support managed profiles for some other reason, just
207         // skip the test
208         if (!mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
209                 false /* disallow remove */)) {
210             return;
211         }
212         if (mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED) < 0) {
213             // Indicates no limit, so we cannot run this test;
214             return;
215         }
216 
217         // GIVEN we've reached the limit of managed profiles possible on the system user
218         while (mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
219                 false /* disallow remove */)) {
220             addProfile(mUserManagerService.getPrimaryUser());
221         }
222 
223         // THEN you should be able to add a new profile if you remove an existing one
224         assertTrue("Cannot add a managed profile by removing another one",
225                 mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
226                         true /* allow remove */));
227     }
228 
229     @Test
testCanAddMoreManagedProfiles_removeDisabledProfile()230     public void testCanAddMoreManagedProfiles_removeDisabledProfile() {
231         // if device is low-ram or doesn't support managed profiles for some other reason, just
232         // skip the test
233         if (!mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
234                 false /* disallow remove */)) {
235             return;
236         }
237         if (mUserManagerService.getMaxUsersOfTypePerParent(USER_TYPE_PROFILE_MANAGED) < 0) {
238             // Indicates no limit, so we cannot run this test;
239             return;
240         }
241 
242         // GIVEN we've reached the limit of managed profiles possible on the system user
243         // GIVEN that the profiles are not enabled yet
244         while (mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
245                 false /* disallow remove */)) {
246             addProfile(mUserManagerService.getPrimaryUser(), true /* disabled */);
247         }
248 
249         // THEN you should be able to add a new profile if you remove an existing one
250         assertTrue("Cannot add a managed profile by removing another one",
251                 mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
252                         true /* allow remove */));
253     }
254 
255     @Test
testCreateProfileForUser_lowStorageException()256     public void testCreateProfileForUser_lowStorageException() {
257         DeviceStorageMonitorInternal dsmMock = Mockito.mock(DeviceStorageMonitorInternal.class);
258         Mockito.when(dsmMock.isMemoryLow()).thenReturn(true);
259         LocalServices.addService(DeviceStorageMonitorInternal.class, dsmMock);
260 
261         try {
262             mUserManagerService.createProfileForUserWithThrow("user2", USER_TYPE_PROFILE_MANAGED, 0,
263                     UserHandle.USER_SYSTEM, null);
264         } catch (ServiceSpecificException e) {
265             assertEquals(UserManager.USER_OPERATION_ERROR_LOW_STORAGE,
266                     UserManager.UserOperationException.from(e).getUserOperationResult());
267         } finally {
268             LocalServices.removeServiceForTest(DeviceStorageMonitorInternal.class);
269         }
270     }
271 
272     @Test
testCreateProfileForUser_unknownParentUser()273     public void testCreateProfileForUser_unknownParentUser() {
274         DeviceStorageMonitorInternal dsmMock = Mockito.mock(DeviceStorageMonitorInternal.class);
275         Mockito.when(dsmMock.isMemoryLow()).thenReturn(false);
276         LocalServices.addService(DeviceStorageMonitorInternal.class, dsmMock);
277 
278         try {
279             final int badParentUserId = 1234;
280             mUserManagerService.createProfileForUserWithThrow("profile", USER_TYPE_PROFILE_MANAGED,
281                     0, badParentUserId, null);
282         } catch (ServiceSpecificException e) {
283             assertEquals(UserManager.USER_OPERATION_ERROR_UNKNOWN,
284                     UserManager.UserOperationException.from(e).getUserOperationResult());
285         } finally {
286             LocalServices.removeServiceForTest(DeviceStorageMonitorInternal.class);
287         }
288     }
289 
290     @Test
testCreateManagedProfileForUser_maxManagedUsersException()291     public void testCreateManagedProfileForUser_maxManagedUsersException() {
292         DeviceStorageMonitorInternal dsmMock = Mockito.mock(DeviceStorageMonitorInternal.class);
293         Mockito.when(dsmMock.isMemoryLow()).thenReturn(false);
294         LocalServices.addService(DeviceStorageMonitorInternal.class, dsmMock);
295 
296         UserManagerService userManagerServiceSpy = Mockito.spy(mUserManagerService);
297         Mockito.doReturn(false).when(userManagerServiceSpy).canAddMoreManagedProfiles(
298                 Mockito.anyInt(), Mockito.anyBoolean());
299 
300         Mockito.doReturn(false).when(userManagerServiceSpy).canAddMoreProfilesToUser(
301                 Mockito.anyString(), Mockito.anyInt(), Mockito.anyBoolean());
302 
303         try {
304             userManagerServiceSpy.createProfileForUserWithThrow("profile",
305                     USER_TYPE_PROFILE_MANAGED, 0, UserHandle.USER_SYSTEM, null);
306         } catch (ServiceSpecificException e) {
307             assertEquals(UserManager.USER_OPERATION_ERROR_MAX_USERS,
308                     UserManager.UserOperationException.from(e).getUserOperationResult());
309         } finally {
310             LocalServices.removeServiceForTest(DeviceStorageMonitorInternal.class);
311         }
312     }
313 
removeUsers()314     private void removeUsers() {
315         List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
316         for (UserInfo user: users) {
317             if (user.id != UserHandle.USER_SYSTEM) {
318                 mUserManagerService.removeUserInfo(user.id);
319             }
320         }
321     }
322 
addProfile(UserInfo user)323     private UserInfo addProfile(UserInfo user) {
324         return addProfile(user, false);
325     }
326 
addProfile(UserInfo user, boolean disabled)327     private UserInfo addProfile(UserInfo user, boolean disabled) {
328         user.profileGroupId = user.id;
329         int flags = UserInfo.FLAG_MANAGED_PROFILE;
330         if (disabled) {
331             flags |= UserInfo.FLAG_DISABLED;
332         }
333         UserInfo profile = new UserInfo(
334                 mUserManagerService.getNextAvailableId(), "profile", flags);
335         profile.profileGroupId = user.id;
336         mUserManagerService.putUserInfo(profile);
337         return profile;
338     }
339 
addUser()340     private UserInfo addUser() {
341         UserInfo secondaryUser = new UserInfo(
342                 mUserManagerService.getNextAvailableId(), "secondary", /* flags */ 0);
343         mUserManagerService.putUserInfo(secondaryUser);
344         return secondaryUser;
345     }
346 }
347