1/*
2 * Copyright (C) 2011 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 android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.pm.PackageManager;
24import android.content.pm.UserInfo;
25import android.app.ActivityManager;
26import android.os.Bundle;
27import android.os.UserHandle;
28import android.os.UserManager;
29import android.provider.Settings;
30import android.test.AndroidTestCase;
31import android.test.suitebuilder.annotation.LargeTest;
32import android.test.suitebuilder.annotation.MediumTest;
33import android.test.suitebuilder.annotation.SmallTest;
34
35import com.android.internal.util.ArrayUtils;
36
37import java.util.ArrayList;
38import java.util.Arrays;
39import java.util.List;
40import java.util.concurrent.ExecutorService;
41import java.util.concurrent.Executors;
42import java.util.concurrent.TimeUnit;
43import java.util.concurrent.atomic.AtomicInteger;
44
45/** Test {@link UserManager} functionality. */
46public class UserManagerTest extends AndroidTestCase {
47    // Taken from UserManagerService
48    private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // 30 years
49
50    private static final int REMOVE_CHECK_INTERVAL_MILLIS = 500; // 0.5 seconds
51    private static final int REMOVE_TIMEOUT_MILLIS = 60 * 1000; // 60 seconds
52    private static final int SWITCH_USER_TIMEOUT_MILLIS = 40 * 1000; // 40 seconds
53
54    // Packages which are used during tests.
55    private static final String[] PACKAGES = new String[] {
56            "com.android.egg"
57    };
58
59    private final Object mUserRemoveLock = new Object();
60    private final Object mUserSwitchLock = new Object();
61
62    private UserManager mUserManager = null;
63    private PackageManager mPackageManager;
64    private List<Integer> usersToRemove;
65
66    @Override
67    public void setUp() throws Exception {
68        super.setUp();
69        mUserManager = UserManager.get(getContext());
70        mPackageManager = getContext().getPackageManager();
71
72        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
73        filter.addAction(Intent.ACTION_USER_SWITCHED);
74        getContext().registerReceiver(new BroadcastReceiver() {
75            @Override
76            public void onReceive(Context context, Intent intent) {
77                switch (intent.getAction()) {
78                    case Intent.ACTION_USER_REMOVED:
79                        synchronized (mUserRemoveLock) {
80                            mUserRemoveLock.notifyAll();
81                        }
82                        break;
83                    case Intent.ACTION_USER_SWITCHED:
84                        synchronized (mUserSwitchLock) {
85                            mUserSwitchLock.notifyAll();
86                        }
87                        break;
88                }
89            }
90        }, filter);
91
92        removeExistingUsers();
93        usersToRemove = new ArrayList<>();
94    }
95
96    @Override
97    protected void tearDown() throws Exception {
98        for (Integer userId : usersToRemove) {
99            removeUser(userId);
100        }
101        super.tearDown();
102    }
103
104    private void removeExistingUsers() {
105        List<UserInfo> list = mUserManager.getUsers();
106        for (UserInfo user : list) {
107            // Keep system and primary user.
108            // We do not have to keep primary user, but in split system user mode, we need it
109            // until http://b/22976637 is fixed.  Right now in split system user mode, you need to
110            // switch to primary user and run tests under primary user.
111            if (user.id != UserHandle.USER_SYSTEM && !user.isPrimary()) {
112                removeUser(user.id);
113            }
114        }
115    }
116
117    @SmallTest
118    public void testHasSystemUser() throws Exception {
119        assertTrue(findUser(UserHandle.USER_SYSTEM));
120    }
121
122    @MediumTest
123    public void testAddUser() throws Exception {
124        UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST);
125        assertTrue(userInfo != null);
126
127        List<UserInfo> list = mUserManager.getUsers();
128        boolean found = false;
129        for (UserInfo user : list) {
130            if (user.id == userInfo.id && user.name.equals("Guest 1")
131                    && user.isGuest()
132                    && !user.isAdmin()
133                    && !user.isPrimary()) {
134                found = true;
135                Bundle restrictions = mUserManager.getUserRestrictions(user.getUserHandle());
136                assertTrue("Guest user should have DISALLOW_CONFIG_WIFI=true by default",
137                        restrictions.getBoolean(UserManager.DISALLOW_CONFIG_WIFI));
138            }
139        }
140        assertTrue(found);
141    }
142
143    @MediumTest
144    public void testAdd2Users() throws Exception {
145        UserInfo user1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
146        UserInfo user2 = createUser("User 2", UserInfo.FLAG_ADMIN);
147
148        assertTrue(user1 != null);
149        assertTrue(user2 != null);
150
151        assertTrue(findUser(0));
152        assertTrue(findUser(user1.id));
153        assertTrue(findUser(user2.id));
154    }
155
156    @MediumTest
157    public void testRemoveUser() throws Exception {
158        UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST);
159        removeUser(userInfo.id);
160
161        assertFalse(findUser(userInfo.id));
162    }
163
164    @MediumTest
165    public void testAddGuest() throws Exception {
166        UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST);
167        UserInfo userInfo2 = createUser("Guest 2", UserInfo.FLAG_GUEST);
168        assertNotNull(userInfo1);
169        assertNull(userInfo2);
170    }
171
172    @MediumTest
173    public void testGetProfileParent() throws Exception {
174        final int primaryUserId = mUserManager.getPrimaryUser().id;
175
176        UserInfo userInfo = createProfileForUser("Profile",
177                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
178        assertNotNull(userInfo);
179        assertNull(mUserManager.getProfileParent(primaryUserId));
180        UserInfo parentProfileInfo = mUserManager.getProfileParent(userInfo.id);
181        assertNotNull(parentProfileInfo);
182        assertEquals(parentProfileInfo.id, primaryUserId);
183        removeUser(userInfo.id);
184        assertNull(mUserManager.getProfileParent(primaryUserId));
185    }
186
187    // Make sure only one managed profile can be created
188    @MediumTest
189    public void testAddManagedProfile() throws Exception {
190        final int primaryUserId = mUserManager.getPrimaryUser().id;
191        UserInfo userInfo1 = createProfileForUser("Managed 1",
192                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
193        UserInfo userInfo2 = createProfileForUser("Managed 2",
194                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
195
196        assertNotNull(userInfo1);
197        assertNull(userInfo2);
198        // Verify that current user is not a managed profile
199        assertFalse(mUserManager.isManagedProfile());
200    }
201
202    // Verify that disallowed packages are not installed in the managed profile.
203    @MediumTest
204    public void testAddManagedProfile_withDisallowedPackages() throws Exception {
205        final int primaryUserId = mUserManager.getPrimaryUser().id;
206        UserInfo userInfo1 = createProfileForUser("Managed1",
207                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
208        // Verify that the packagesToVerify are installed by default.
209        for (String pkg : PACKAGES) {
210            assertTrue("Package should be installed in managed profile: " + pkg,
211                    isPackageInstalledForUser(pkg, userInfo1.id));
212        }
213        removeUser(userInfo1.id);
214
215        UserInfo userInfo2 = createProfileForUser("Managed2",
216                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES);
217        // Verify that the packagesToVerify are not installed by default.
218        for (String pkg : PACKAGES) {
219            assertFalse("Package should not be installed in managed profile when disallowed: "
220                    + pkg, isPackageInstalledForUser(pkg, userInfo2.id));
221        }
222    }
223
224    // Verify that if any packages are disallowed to install during creation of managed profile can
225    // still be installed later.
226    @MediumTest
227    public void testAddManagedProfile_disallowedPackagesInstalledLater() throws Exception {
228        final int primaryUserId = mUserManager.getPrimaryUser().id;
229        UserInfo userInfo = createProfileForUser("Managed",
230                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId, PACKAGES);
231        // Verify that the packagesToVerify are not installed by default.
232        for (String pkg : PACKAGES) {
233            assertFalse("Package should not be installed in managed profile when disallowed: "
234                    + pkg, isPackageInstalledForUser(pkg, userInfo.id));
235        }
236
237        // Verify that the disallowed packages during profile creation can be installed now.
238        for (String pkg : PACKAGES) {
239            assertEquals("Package could not be installed: " + pkg,
240                    PackageManager.INSTALL_SUCCEEDED,
241                    mPackageManager.installExistingPackageAsUser(pkg, userInfo.id));
242        }
243    }
244
245    // Make sure createUser would fail if we have DISALLOW_ADD_USER.
246    @MediumTest
247    public void testCreateUser_disallowAddUser() throws Exception {
248        final int primaryUserId = mUserManager.getPrimaryUser().id;
249        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
250        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
251        try {
252            UserInfo userInfo = createUser("SecondaryUser", /*flags=*/ 0);
253            assertNull(userInfo);
254        } finally {
255            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
256                    primaryUserHandle);
257        }
258    }
259
260    // Make sure createProfile would fail if we have DISALLOW_ADD_MANAGED_PROFILE.
261    @MediumTest
262    public void testCreateProfileForUser_disallowAddManagedProfile() throws Exception {
263        final int primaryUserId = mUserManager.getPrimaryUser().id;
264        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
265        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
266                primaryUserHandle);
267        try {
268            UserInfo userInfo = createProfileForUser("Managed",
269                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
270            assertNull(userInfo);
271        } finally {
272            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
273                    primaryUserHandle);
274        }
275    }
276
277    // Make sure createProfileEvenWhenDisallowedForUser bypass DISALLOW_ADD_MANAGED_PROFILE.
278    @MediumTest
279    public void testCreateProfileForUserEvenWhenDisallowed() throws Exception {
280        final int primaryUserId = mUserManager.getPrimaryUser().id;
281        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
282        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
283                primaryUserHandle);
284        try {
285            UserInfo userInfo = createProfileEvenWhenDisallowedForUser("Managed",
286                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
287            assertNotNull(userInfo);
288        } finally {
289            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
290                    primaryUserHandle);
291        }
292    }
293
294    // createProfile succeeds even if DISALLOW_ADD_USER is set
295    @MediumTest
296    public void testCreateProfileForUser_disallowAddUser() throws Exception {
297        final int primaryUserId = mUserManager.getPrimaryUser().id;
298        final UserHandle primaryUserHandle = new UserHandle(primaryUserId);
299        mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, true, primaryUserHandle);
300        try {
301            UserInfo userInfo = createProfileForUser("Managed",
302                    UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
303            assertNotNull(userInfo);
304        } finally {
305            mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false,
306                    primaryUserHandle);
307        }
308    }
309
310    @MediumTest
311    public void testAddRestrictedProfile() throws Exception {
312        UserInfo userInfo = createRestrictedProfile("Profile");
313        assertNotNull(userInfo);
314
315        Bundle restrictions = mUserManager.getUserRestrictions(UserHandle.of(userInfo.id));
316        assertTrue("Restricted profile should have DISALLOW_MODIFY_ACCOUNTS restriction by default",
317                restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS));
318        assertTrue("Restricted profile should have DISALLOW_SHARE_LOCATION restriction by default",
319                restrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION));
320
321        int locationMode = Settings.Secure.getIntForUser(getContext().getContentResolver(),
322                Settings.Secure.LOCATION_MODE,
323                Settings.Secure.LOCATION_MODE_HIGH_ACCURACY,
324                userInfo.id);
325        assertEquals("Restricted profile should have setting LOCATION_MODE set to "
326                + "LOCATION_MODE_OFF by default", locationMode, Settings.Secure.LOCATION_MODE_OFF);
327    }
328
329    @MediumTest
330    public void testGetUserCreationTime() throws Exception {
331        final int primaryUserId = mUserManager.getPrimaryUser().id;
332        final long startTime = System.currentTimeMillis();
333        UserInfo profile = createProfileForUser("Managed 1",
334                UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
335        final long endTime = System.currentTimeMillis();
336        assertNotNull(profile);
337        if (System.currentTimeMillis() > EPOCH_PLUS_30_YEARS) {
338            assertTrue("creationTime must be set when the profile is created",
339                    profile.creationTime >= startTime && profile.creationTime <= endTime);
340        } else {
341            assertTrue("creationTime must be 0 if the time is not > EPOCH_PLUS_30_years",
342                    profile.creationTime == 0);
343        }
344        assertEquals(profile.creationTime, mUserManager.getUserCreationTime(
345                new UserHandle(profile.id)));
346
347        long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime;
348        assertEquals(ownerCreationTime, mUserManager.getUserCreationTime(
349                new UserHandle(primaryUserId)));
350    }
351
352    @SmallTest
353    public void testGetUserCreationTime_nonExistentUser() throws Exception {
354        try {
355            int noSuchUserId = 100500;
356            mUserManager.getUserCreationTime(new UserHandle(noSuchUserId));
357            fail("SecurityException should be thrown for nonexistent user");
358        } catch (Exception e) {
359            assertTrue("SecurityException should be thrown for nonexistent user, but was: " + e,
360                    e instanceof SecurityException);
361        }
362    }
363
364    @SmallTest
365    public void testGetUserCreationTime_otherUser() throws Exception {
366        UserInfo user = createUser("User 1", 0);
367        try {
368            mUserManager.getUserCreationTime(new UserHandle(user.id));
369            fail("SecurityException should be thrown for other user");
370        } catch (Exception e) {
371            assertTrue("SecurityException should be thrown for other user, but was: " + e,
372                    e instanceof SecurityException);
373        }
374    }
375
376    private boolean findUser(int id) {
377        List<UserInfo> list = mUserManager.getUsers();
378
379        for (UserInfo user : list) {
380            if (user.id == id) {
381                return true;
382            }
383        }
384        return false;
385    }
386
387    @MediumTest
388    public void testSerialNumber() {
389        UserInfo user1 = createUser("User 1", 0);
390        int serialNumber1 = user1.serialNumber;
391        assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id));
392        assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1));
393        UserInfo user2 = createUser("User 2", 0);
394        int serialNumber2 = user2.serialNumber;
395        assertFalse(serialNumber1 == serialNumber2);
396        assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id));
397        assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2));
398    }
399
400    @MediumTest
401    public void testGetSerialNumbersOfUsers() {
402        UserInfo user1 = createUser("User 1", 0);
403        UserInfo user2 = createUser("User 2", 0);
404        long[] serialNumbersOfUsers = mUserManager.getSerialNumbersOfUsers(false);
405        String errMsg = "Array " + Arrays.toString(serialNumbersOfUsers) + " should contain ";
406        assertTrue(errMsg + user1.serialNumber,
407                ArrayUtils.contains(serialNumbersOfUsers, user1.serialNumber));
408        assertTrue(errMsg + user2.serialNumber,
409                ArrayUtils.contains(serialNumbersOfUsers, user2.serialNumber));
410    }
411
412    @MediumTest
413    public void testMaxUsers() {
414        int N = UserManager.getMaxSupportedUsers();
415        int count = mUserManager.getUsers().size();
416        // Create as many users as permitted and make sure creation passes
417        while (count < N) {
418            UserInfo ui = createUser("User " + count, 0);
419            assertNotNull(ui);
420            count++;
421        }
422        // Try to create one more user and make sure it fails
423        UserInfo extra = createUser("One more", 0);
424        assertNull(extra);
425    }
426
427    @MediumTest
428    public void testGetUserCount() {
429        int count = mUserManager.getUsers().size();
430        UserInfo user1 = createUser("User 1", 0);
431        assertNotNull(user1);
432        UserInfo user2 = createUser("User 2", 0);
433        assertNotNull(user2);
434        assertEquals(count + 2, mUserManager.getUserCount());
435    }
436
437    @MediumTest
438    public void testRestrictions() {
439        UserInfo testUser = createUser("User 1", 0);
440
441        mUserManager.setUserRestriction(
442                UserManager.DISALLOW_INSTALL_APPS, true, new UserHandle(testUser.id));
443        mUserManager.setUserRestriction(
444                UserManager.DISALLOW_CONFIG_WIFI, false, new UserHandle(testUser.id));
445
446        Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id));
447        // Note this will fail if DO already sets those restrictions.
448        assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false);
449        assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false);
450        assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true);
451    }
452
453    @MediumTest
454    public void testSetDefaultGuestRestrictions() {
455        final Bundle origGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
456        Bundle restrictions = new Bundle();
457        restrictions.putBoolean(UserManager.DISALLOW_FUN, true);
458        mUserManager.setDefaultGuestRestrictions(restrictions);
459
460        try {
461            UserInfo guest = createUser("Guest", UserInfo.FLAG_GUEST);
462            assertNotNull(guest);
463            assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_FUN,
464                    guest.getUserHandle()));
465        } finally {
466            mUserManager.setDefaultGuestRestrictions(origGuestRestrictions);
467        }
468    }
469
470    @LargeTest
471    public void testSwitchUser() {
472        ActivityManager am = getContext().getSystemService(ActivityManager.class);
473        final int startUser = am.getCurrentUser();
474        UserInfo user = createUser("User", 0);
475        assertNotNull(user);
476        // Switch to the user just created.
477        switchUser(user.id);
478        // Switch back to the starting user.
479        switchUser(startUser);
480    }
481
482    @MediumTest
483    public void testConcurrentUserCreate() throws Exception {
484        int userCount = mUserManager.getUserCount();
485        int maxSupportedUsers = UserManager.getMaxSupportedUsers();
486        int canBeCreatedCount = maxSupportedUsers - userCount;
487        // Test exceeding the limit while running in parallel
488        int createUsersCount = canBeCreatedCount + 5;
489        ExecutorService es = Executors.newCachedThreadPool();
490        AtomicInteger created = new AtomicInteger();
491        for (int i = 0; i < createUsersCount; i++) {
492            final String userName = "testConcUser" + i;
493            es.submit(() -> {
494                UserInfo user = mUserManager.createUser(userName, 0);
495                if (user != null) {
496                    created.incrementAndGet();
497                    synchronized (mUserRemoveLock) {
498                        usersToRemove.add(user.id);
499                    }
500                }
501            });
502        }
503        es.shutdown();
504        es.awaitTermination(20, TimeUnit.SECONDS);
505        assertEquals(maxSupportedUsers, mUserManager.getUserCount());
506        assertEquals(canBeCreatedCount, created.get());
507    }
508
509    private boolean isPackageInstalledForUser(String packageName, int userId) {
510        try {
511            return mPackageManager.getPackageInfoAsUser(packageName, 0, userId) != null;
512        } catch (PackageManager.NameNotFoundException e) {
513            return false;
514        }
515    }
516
517    private void switchUser(int userId) {
518        synchronized (mUserSwitchLock) {
519            ActivityManager am = getContext().getSystemService(ActivityManager.class);
520            am.switchUser(userId);
521            long time = System.currentTimeMillis();
522            try {
523                mUserSwitchLock.wait(SWITCH_USER_TIMEOUT_MILLIS);
524            } catch (InterruptedException ie) {
525                Thread.currentThread().interrupt();
526                return;
527            }
528            if (System.currentTimeMillis() - time > SWITCH_USER_TIMEOUT_MILLIS) {
529                fail("Timeout waiting for the user switch to u" + userId);
530            }
531        }
532    }
533
534    private void removeUser(int userId) {
535        synchronized (mUserRemoveLock) {
536            mUserManager.removeUser(userId);
537            long time = System.currentTimeMillis();
538            while (mUserManager.getUserInfo(userId) != null) {
539                try {
540                    mUserRemoveLock.wait(REMOVE_CHECK_INTERVAL_MILLIS);
541                } catch (InterruptedException ie) {
542                    Thread.currentThread().interrupt();
543                    return;
544                }
545                if (System.currentTimeMillis() - time > REMOVE_TIMEOUT_MILLIS) {
546                    fail("Timeout waiting for removeUser. userId = " + userId);
547                }
548            }
549        }
550    }
551
552    private UserInfo createUser(String name, int flags) {
553        UserInfo user = mUserManager.createUser(name, flags);
554        if (user != null) {
555            usersToRemove.add(user.id);
556        }
557        return user;
558    }
559
560    private UserInfo createProfileForUser(String name, int flags, int userHandle) {
561        return createProfileForUser(name, flags, userHandle, null);
562    }
563
564    private UserInfo createProfileForUser(String name, int flags, int userHandle,
565            String[] disallowedPackages) {
566        UserInfo profile = mUserManager.createProfileForUser(
567                name, flags, userHandle, disallowedPackages);
568        if (profile != null) {
569            usersToRemove.add(profile.id);
570        }
571        return profile;
572    }
573
574    private UserInfo createProfileEvenWhenDisallowedForUser(String name, int flags,
575            int userHandle) {
576        UserInfo profile = mUserManager.createProfileForUserEvenWhenDisallowed(
577                name, flags, userHandle, null);
578        if (profile != null) {
579            usersToRemove.add(profile.id);
580        }
581        return profile;
582    }
583
584    private UserInfo createRestrictedProfile(String name) {
585        UserInfo profile = mUserManager.createRestrictedProfile(name);
586        if (profile != null) {
587            usersToRemove.add(profile.id);
588        }
589        return profile;
590    }
591
592}
593