Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 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 | |
| 17 | package com.android.server.pm; |
| 18 | |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 19 | import android.content.BroadcastReceiver; |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 20 | import android.content.Context; |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 21 | import android.content.Intent; |
| 22 | import android.content.IntentFilter; |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 23 | import android.content.pm.UserInfo; |
Amith Yamasani | e4cf734 | 2012-12-17 11:12:09 -0800 | [diff] [blame] | 24 | import android.os.Bundle; |
Amith Yamasani | 20949a7 | 2013-02-11 15:47:30 -0800 | [diff] [blame] | 25 | import android.os.UserHandle; |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 26 | import android.os.UserManager; |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 27 | import android.test.AndroidTestCase; |
| 28 | |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 29 | import java.util.ArrayList; |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 30 | import java.util.List; |
| 31 | |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 32 | /** Test {@link UserManager} functionality. */ |
Amith Yamasani | 0b28549 | 2011-04-14 17:35:23 -0700 | [diff] [blame] | 33 | public class UserManagerTest extends AndroidTestCase { |
Fyodor Kupolov | 9cbfc9e | 2015-10-07 15:52:33 -0700 | [diff] [blame^] | 34 | private static final int REMOVE_CHECK_INTERVAL = 500; |
| 35 | private static final int REMOVE_TIMEOUT = 60 * 1000; |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 36 | private UserManager mUserManager = null; |
| 37 | private final Object mUserLock = new Object(); |
| 38 | private List<Integer> usersToRemove; |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 39 | |
| 40 | @Override |
| 41 | public void setUp() throws Exception { |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 42 | super.setUp(); |
| 43 | mUserManager = UserManager.get(getContext()); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 44 | IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED); |
| 45 | getContext().registerReceiver(new BroadcastReceiver() { |
| 46 | @Override |
| 47 | public void onReceive(Context context, Intent intent) { |
| 48 | synchronized (mUserLock) { |
| 49 | mUserLock.notifyAll(); |
| 50 | } |
| 51 | } |
| 52 | }, filter); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 53 | |
| 54 | removeExistingUsers(); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 55 | usersToRemove = new ArrayList<>(); |
| 56 | } |
| 57 | |
| 58 | @Override |
| 59 | protected void tearDown() throws Exception { |
| 60 | for (Integer userId : usersToRemove) { |
| 61 | removeUser(userId); |
| 62 | } |
| 63 | super.tearDown(); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | private void removeExistingUsers() { |
| 67 | List<UserInfo> list = mUserManager.getUsers(); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 68 | for (UserInfo user : list) { |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 69 | // Keep system and primary user. |
| 70 | // We do not have to keep primary user, but in split system user mode, we need it |
| 71 | // until http://b/22976637 is fixed. Right now in split system user mode, you need to |
| 72 | // switch to primary user and run tests under primary user. |
| 73 | if (user.id != UserHandle.USER_SYSTEM && !user.isPrimary()) { |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 74 | removeUser(user.id); |
| 75 | } |
| 76 | } |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 77 | } |
| 78 | |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 79 | public void testHasSystemUser() throws Exception { |
| 80 | assertTrue(findUser(UserHandle.USER_SYSTEM)); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | public void testAddUser() throws Exception { |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 84 | UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 85 | assertTrue(userInfo != null); |
| 86 | |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 87 | List<UserInfo> list = mUserManager.getUsers(); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 88 | boolean found = false; |
| 89 | for (UserInfo user : list) { |
| 90 | if (user.id == userInfo.id && user.name.equals("Guest 1") |
| 91 | && user.isGuest() |
| 92 | && !user.isAdmin() |
| 93 | && !user.isPrimary()) { |
| 94 | found = true; |
Maggie Benthall | 6794458 | 2013-02-22 14:58:27 -0500 | [diff] [blame] | 95 | Bundle restrictions = mUserManager.getUserRestrictions(user.getUserHandle()); |
Amith Yamasani | 0519105 | 2013-03-26 15:32:29 -0700 | [diff] [blame] | 96 | assertFalse("New user should have DISALLOW_CONFIG_WIFI =false by default", |
| 97 | restrictions.getBoolean(UserManager.DISALLOW_CONFIG_WIFI)); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 98 | } |
| 99 | } |
| 100 | assertTrue(found); |
| 101 | } |
| 102 | |
| 103 | public void testAdd2Users() throws Exception { |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 104 | UserInfo user1 = createUser("Guest 1", UserInfo.FLAG_GUEST); |
| 105 | UserInfo user2 = createUser("User 2", UserInfo.FLAG_ADMIN); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 106 | |
| 107 | assertTrue(user1 != null); |
| 108 | assertTrue(user2 != null); |
| 109 | |
| 110 | assertTrue(findUser(0)); |
| 111 | assertTrue(findUser(user1.id)); |
| 112 | assertTrue(findUser(user2.id)); |
| 113 | } |
| 114 | |
| 115 | public void testRemoveUser() throws Exception { |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 116 | UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 117 | removeUser(userInfo.id); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 118 | |
| 119 | assertFalse(findUser(userInfo.id)); |
| 120 | } |
| 121 | |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 122 | public void testAddGuest() throws Exception { |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 123 | UserInfo userInfo1 = createUser("Guest 1", UserInfo.FLAG_GUEST); |
| 124 | UserInfo userInfo2 = createUser("Guest 2", UserInfo.FLAG_GUEST); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 125 | assertNotNull(userInfo1); |
| 126 | assertNull(userInfo2); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | // Make sure only one managed profile can be created |
| 130 | public void testAddManagedProfile() throws Exception { |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 131 | final int primaryUserId = mUserManager.getPrimaryUser().id; |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 132 | UserInfo userInfo1 = createProfileForUser("Managed 1", |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 133 | UserInfo.FLAG_MANAGED_PROFILE, primaryUserId); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 134 | UserInfo userInfo2 = createProfileForUser("Managed 2", |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 135 | UserInfo.FLAG_MANAGED_PROFILE, primaryUserId); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 136 | assertNotNull(userInfo1); |
| 137 | assertNull(userInfo2); |
Amith Yamasani | 0e8d7d6 | 2014-09-03 13:17:28 -0700 | [diff] [blame] | 138 | // Verify that current user is not a managed profile |
| 139 | assertFalse(mUserManager.isManagedProfile()); |
Amith Yamasani | 95ab784 | 2014-08-11 17:09:26 -0700 | [diff] [blame] | 140 | } |
| 141 | |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 142 | public void testGetUserCreationTime() throws Exception { |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 143 | final int primaryUserId = mUserManager.getPrimaryUser().id; |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 144 | UserInfo profile = createProfileForUser("Managed 1", |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 145 | UserInfo.FLAG_MANAGED_PROFILE, primaryUserId); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 146 | assertNotNull(profile); |
| 147 | assertTrue("creationTime must be set when the profile is created", |
| 148 | profile.creationTime > 0); |
Fyodor Kupolov | 385de62 | 2015-04-10 18:00:19 -0700 | [diff] [blame] | 149 | assertEquals(profile.creationTime, mUserManager.getUserCreationTime( |
| 150 | new UserHandle(profile.id))); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 151 | |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 152 | long ownerCreationTime = mUserManager.getUserInfo(primaryUserId).creationTime; |
Fyodor Kupolov | 385de62 | 2015-04-10 18:00:19 -0700 | [diff] [blame] | 153 | assertEquals(ownerCreationTime, mUserManager.getUserCreationTime( |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 154 | new UserHandle(primaryUserId))); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 155 | |
| 156 | try { |
| 157 | int noSuchUserId = 100500; |
Fyodor Kupolov | 385de62 | 2015-04-10 18:00:19 -0700 | [diff] [blame] | 158 | mUserManager.getUserCreationTime(new UserHandle(noSuchUserId)); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 159 | fail("SecurityException should be thrown for nonexistent user"); |
| 160 | } catch (Exception e) { |
| 161 | assertTrue("SecurityException should be thrown for nonexistent user, but was: " + e, |
| 162 | e instanceof SecurityException); |
| 163 | } |
| 164 | |
| 165 | UserInfo user = createUser("User 1", 0); |
| 166 | try { |
Fyodor Kupolov | 385de62 | 2015-04-10 18:00:19 -0700 | [diff] [blame] | 167 | mUserManager.getUserCreationTime(new UserHandle(user.id)); |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 168 | fail("SecurityException should be thrown for other user"); |
| 169 | } catch (Exception e) { |
| 170 | assertTrue("SecurityException should be thrown for other user, but was: " + e, |
| 171 | e instanceof SecurityException); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 176 | private boolean findUser(int id) { |
Amith Yamasani | 0b28549 | 2011-04-14 17:35:23 -0700 | [diff] [blame] | 177 | List<UserInfo> list = mUserManager.getUsers(); |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 178 | |
| 179 | for (UserInfo user : list) { |
| 180 | if (user.id == id) { |
| 181 | return true; |
| 182 | } |
| 183 | } |
| 184 | return false; |
| 185 | } |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 186 | |
| 187 | public void testSerialNumber() { |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 188 | UserInfo user1 = createUser("User 1", 0); |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 189 | int serialNumber1 = user1.serialNumber; |
| 190 | assertEquals(serialNumber1, mUserManager.getUserSerialNumber(user1.id)); |
| 191 | assertEquals(user1.id, mUserManager.getUserHandle(serialNumber1)); |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 192 | UserInfo user2 = createUser("User 2", 0); |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 193 | int serialNumber2 = user2.serialNumber; |
| 194 | assertFalse(serialNumber1 == serialNumber2); |
| 195 | assertEquals(serialNumber2, mUserManager.getUserSerialNumber(user2.id)); |
| 196 | assertEquals(user2.id, mUserManager.getUserHandle(serialNumber2)); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 197 | } |
| 198 | |
| 199 | public void testMaxUsers() { |
| 200 | int N = UserManager.getMaxSupportedUsers(); |
| 201 | int count = mUserManager.getUsers().size(); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 202 | // Create as many users as permitted and make sure creation passes |
| 203 | while (count < N) { |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 204 | UserInfo ui = createUser("User " + count, 0); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 205 | assertNotNull(ui); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 206 | count++; |
| 207 | } |
| 208 | // Try to create one more user and make sure it fails |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 209 | UserInfo extra = createUser("One more", 0); |
| 210 | assertNull(extra); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 211 | } |
| 212 | |
Amith Yamasani | e4cf734 | 2012-12-17 11:12:09 -0800 | [diff] [blame] | 213 | public void testRestrictions() { |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 214 | UserInfo testUser = createUser("User 1", 0); |
Makoto Onuki | 068c54a | 2015-10-13 14:34:03 -0700 | [diff] [blame] | 215 | |
| 216 | mUserManager.setUserRestriction( |
| 217 | UserManager.DISALLOW_INSTALL_APPS, true, new UserHandle(testUser.id)); |
| 218 | mUserManager.setUserRestriction( |
| 219 | UserManager.DISALLOW_CONFIG_WIFI, false, new UserHandle(testUser.id)); |
| 220 | |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 221 | Bundle stored = mUserManager.getUserRestrictions(new UserHandle(testUser.id)); |
Makoto Onuki | 068c54a | 2015-10-13 14:34:03 -0700 | [diff] [blame] | 222 | // Note this will fail if DO already sets those restrictions. |
Xiaohui Chen | 72d9c02 | 2015-08-21 09:23:23 -0700 | [diff] [blame] | 223 | assertEquals(stored.getBoolean(UserManager.DISALLOW_CONFIG_WIFI), false); |
| 224 | assertEquals(stored.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS), false); |
| 225 | assertEquals(stored.getBoolean(UserManager.DISALLOW_INSTALL_APPS), true); |
Amith Yamasani | e4cf734 | 2012-12-17 11:12:09 -0800 | [diff] [blame] | 226 | } |
| 227 | |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 228 | private void removeUser(int userId) { |
| 229 | synchronized (mUserLock) { |
| 230 | mUserManager.removeUser(userId); |
Fyodor Kupolov | 9cbfc9e | 2015-10-07 15:52:33 -0700 | [diff] [blame^] | 231 | long time = System.currentTimeMillis(); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 232 | while (mUserManager.getUserInfo(userId) != null) { |
| 233 | try { |
Fyodor Kupolov | 9cbfc9e | 2015-10-07 15:52:33 -0700 | [diff] [blame^] | 234 | mUserLock.wait(REMOVE_CHECK_INTERVAL); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 235 | } catch (InterruptedException ie) { |
Fyodor Kupolov | 9cbfc9e | 2015-10-07 15:52:33 -0700 | [diff] [blame^] | 236 | Thread.currentThread().interrupt(); |
| 237 | return; |
| 238 | } |
| 239 | if (System.currentTimeMillis() - time > REMOVE_TIMEOUT) { |
| 240 | fail("Timeout waiting for removeUser. userId = " + userId); |
Amith Yamasani | db6a14c | 2012-10-17 21:16:52 -0700 | [diff] [blame] | 241 | } |
| 242 | } |
| 243 | } |
Amith Yamasani | 2a00329 | 2012-08-14 18:25:45 -0700 | [diff] [blame] | 244 | } |
Amith Yamasani | e4cf734 | 2012-12-17 11:12:09 -0800 | [diff] [blame] | 245 | |
Fyodor Kupolov | ff7233e | 2015-04-08 11:28:52 -0700 | [diff] [blame] | 246 | private UserInfo createUser(String name, int flags) { |
| 247 | UserInfo user = mUserManager.createUser(name, flags); |
| 248 | if (user != null) { |
| 249 | usersToRemove.add(user.id); |
| 250 | } |
| 251 | return user; |
| 252 | } |
| 253 | |
| 254 | private UserInfo createProfileForUser(String name, int flags, int userHandle) { |
| 255 | UserInfo profile = mUserManager.createProfileForUser(name, flags, userHandle); |
| 256 | if (profile != null) { |
| 257 | usersToRemove.add(profile.id); |
| 258 | } |
| 259 | return profile; |
| 260 | } |
| 261 | |
Amith Yamasani | 4b2e934 | 2011-03-31 12:38:53 -0700 | [diff] [blame] | 262 | } |