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
17package com.android.server.pm;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertTrue;
21
22import android.app.ApplicationPackageManager;
23import android.content.pm.UserInfo;
24import android.os.Looper;
25import android.os.UserHandle;
26import android.os.UserManagerInternal;
27import android.support.test.InstrumentationRegistry;
28import android.support.test.filters.MediumTest;
29import android.support.test.runner.AndroidJUnit4;
30import android.util.IconDrawableFactory;
31
32import com.android.server.LocalServices;
33
34import java.util.List;
35
36import org.junit.After;
37import org.junit.Before;
38import org.junit.Test;
39import org.junit.runner.RunWith;
40
41/**
42 * <p>Run with:<pre>
43 * runtest -c com.android.server.pm.UserManagerServiceCreateProfileTest frameworks-services
44 * </pre>
45 */
46@RunWith(AndroidJUnit4.class)
47@MediumTest
48public class UserManagerServiceCreateProfileTest {
49    private UserManagerService mUserManagerService;
50
51    @Before
52    public void setup() {
53        // Currently UserManagerService cannot be instantiated twice inside a VM without a cleanup
54        // TODO: Remove once UMS supports proper dependency injection
55        if (Looper.myLooper() == null) {
56            Looper.prepare();
57        }
58        LocalServices.removeServiceForTest(UserManagerInternal.class);
59        mUserManagerService = new UserManagerService(InstrumentationRegistry.getContext());
60
61        // The tests assume that the device has one user and its the system user.
62        List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
63        assertEquals("Multiple users so this test can't run.", 1, users.size());
64        assertEquals("Only user present isn't the system user.",
65                UserHandle.USER_SYSTEM, users.get(0).id);
66    }
67
68    @After
69    public void tearDown() {
70        removeUsers();
71    }
72
73    @Test
74    public void testGetProfiles() {
75        // Pretend we have a secondary user with a profile.
76        UserInfo secondaryUser = addUser();
77        UserInfo profile = addProfile(secondaryUser);
78
79        // System user should still have no profile so getProfiles should just return 1 user.
80        List<UserInfo> users =
81                mUserManagerService.getProfiles(UserHandle.USER_SYSTEM, /*excludeDying*/ false);
82        assertEquals("Profiles returned where none should exist", 1, users.size());
83        assertEquals("Missing system user from profile list of system user",
84                UserHandle.USER_SYSTEM, users.get(0).id);
85
86        // Secondary user should have 1 profile, so return that and itself.
87        users = mUserManagerService.getProfiles(secondaryUser.id, /*excludeDying*/ false);
88        assertEquals("Profiles returned where none should exist", 2, users.size());
89        assertTrue("Missing secondary user id", users.get(0).id == secondaryUser.id
90                || users.get(1).id == secondaryUser.id);
91        assertTrue("Missing profile user id", users.get(0).id == profile.id
92                || users.get(1).id == profile.id);
93    }
94
95    @Test
96    public void testProfileBadge() {
97        // First profile for system user should get badge 0
98        assertEquals("First profile isn't given badge index 0", 0,
99                mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM));
100
101        // Pretend we have a secondary user.
102        UserInfo secondaryUser = addUser();
103
104        // Check first profile badge for secondary user is also 0.
105        assertEquals("First profile for secondary user isn't given badge index 0", 0,
106                mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id));
107
108        // Shouldn't impact the badge for profile in system user
109        assertEquals("First profile isn't given badge index 0 with secondary user", 0,
110                mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM));
111
112        // Pretend a secondary user has a profile.
113        addProfile(secondaryUser);
114
115        // Shouldn't have impacted the badge for the system user
116        assertEquals("First profile isn't given badge index 0 in secondary user", 0,
117                mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM));
118    }
119
120    @Test
121    public void testProfileBadgeUnique() {
122        List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
123        UserInfo system = users.get(0);
124        // Badges should get allocated 0 -> max
125        for (int i = 0; i < UserManagerService.getMaxManagedProfiles(); ++i) {
126            int nextBadge = mUserManagerService.getFreeProfileBadgeLU(UserHandle.USER_SYSTEM);
127            assertEquals("Wrong badge allocated", i, nextBadge);
128            UserInfo profile = addProfile(system);
129            profile.profileBadge = nextBadge;
130        }
131    }
132
133    @Test
134    public void testProfileBadgeReuse() {
135        // Pretend we have a secondary user with a profile.
136        UserInfo secondaryUser = addUser();
137        UserInfo profile = addProfile(secondaryUser);
138        // Add the profile it to the users being removed.
139        mUserManagerService.addRemovingUserIdLocked(profile.id);
140        // We should reuse the badge from the profile being removed.
141        assertEquals("Badge index not reused while removing a user", 0,
142                mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id));
143
144        // Edge case of reuse that only applies if we ever support 3 managed profiles
145        // We should prioritise using lower badge indexes
146        if (UserManagerService.getMaxManagedProfiles() > 2) {
147            UserInfo profileBadgeOne = addProfile(secondaryUser);
148            profileBadgeOne.profileBadge = 1;
149            // 0 and 2 are free, we should reuse 0 rather than 2.
150            assertEquals("Lower index not used", 0,
151                    mUserManagerService.getFreeProfileBadgeLU(secondaryUser.id));
152        }
153    }
154
155    @Test
156    public void testNumberOfBadges() {
157        assertTrue("Max profiles greater than number of badges",
158                UserManagerService.MAX_MANAGED_PROFILES
159                <= IconDrawableFactory.CORP_BADGE_COLORS.length);
160        assertEquals("Num colors doesn't match number of badge labels",
161                IconDrawableFactory.CORP_BADGE_COLORS.length,
162                ApplicationPackageManager.CORP_BADGE_LABEL_RES_ID.length);
163    }
164
165    @Test
166    public void testCanAddMoreManagedProfiles_removeProfile() {
167        // if device is low-ram or doesn't support managed profiles for some other reason, just
168        // skip the test
169        if (!mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
170                false /* disallow remove */)) {
171            return;
172        }
173
174        // GIVEN we've reached the limit of managed profiles possible on the system user
175        while (mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
176                false /* disallow remove */)) {
177            addProfile(mUserManagerService.getPrimaryUser());
178        }
179
180        // THEN you should be able to add a new profile if you remove an existing one
181        assertTrue("Cannot add a managed profile by removing another one",
182                mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
183                        true /* allow remove */));
184    }
185
186    @Test
187    public void testCanAddMoreManagedProfiles_removeDisabledProfile() {
188        // if device is low-ram or doesn't support managed profiles for some other reason, just
189        // skip the test
190        if (!mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
191                false /* disallow remove */)) {
192            return;
193        }
194
195        // GIVEN we've reached the limit of managed profiles possible on the system user
196        // GIVEN that the profiles are not enabled yet
197        while (mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
198                false /* disallow remove */)) {
199            addProfile(mUserManagerService.getPrimaryUser(), true /* disabled */);
200        }
201
202        // THEN you should be able to add a new profile if you remove an existing one
203        assertTrue("Cannot add a managed profile by removing another one",
204                mUserManagerService.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
205                        true /* allow remove */));
206    }
207
208    private void removeUsers() {
209        List<UserInfo> users = mUserManagerService.getUsers(/* excludeDying */ false);
210        for (UserInfo user: users) {
211            if (user.id != UserHandle.USER_SYSTEM) {
212                mUserManagerService.removeUserInfo(user.id);
213            }
214        }
215    }
216
217    private UserInfo addProfile(UserInfo user) {
218        return addProfile(user, false);
219    }
220
221    private UserInfo addProfile(UserInfo user, boolean disabled) {
222        user.profileGroupId = user.id;
223        int flags = UserInfo.FLAG_MANAGED_PROFILE;
224        if (disabled) {
225            flags |= UserInfo.FLAG_DISABLED;
226        }
227        UserInfo profile = new UserInfo(
228                mUserManagerService.getNextAvailableId(), "profile", flags);
229        profile.profileGroupId = user.id;
230        mUserManagerService.putUserInfo(profile);
231        return profile;
232    }
233
234    private UserInfo addUser() {
235        UserInfo secondaryUser = new UserInfo(
236                mUserManagerService.getNextAvailableId(), "secondary", /* flags */ 0);
237        mUserManagerService.putUserInfo(secondaryUser);
238        return secondaryUser;
239    }
240}
241