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