• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.multiuser.cts;
18 
19 import static android.Manifest.permission.CREATE_USERS;
20 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
21 import static android.Manifest.permission.QUERY_USERS;
22 import static android.content.pm.PackageManager.FEATURE_MANAGED_USERS;
23 import static android.multiuser.cts.PermissionHelper.adoptShellPermissionIdentity;
24 import static android.multiuser.cts.TestingUtils.getBooleanProperty;
25 import static android.os.UserManager.USER_OPERATION_SUCCESS;
26 import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
27 import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
28 
29 import static com.google.common.truth.Truth.assertThat;
30 import static com.google.common.truth.Truth.assertWithMessage;
31 
32 import static org.junit.Assume.assumeNoException;
33 import static org.junit.Assume.assumeTrue;
34 
35 import android.app.Instrumentation;
36 import android.content.Context;
37 import android.content.pm.PackageManager;
38 import android.content.pm.UserInfo;
39 import android.graphics.Bitmap;
40 import android.os.Build;
41 import android.os.NewUserRequest;
42 import android.os.NewUserResponse;
43 import android.os.PersistableBundle;
44 import android.os.UserHandle;
45 import android.os.UserManager;
46 import android.platform.test.annotations.AppModeFull;
47 import android.platform.test.annotations.SystemUserOnly;
48 
49 import androidx.test.platform.app.InstrumentationRegistry;
50 
51 import com.android.bedstead.harrier.BedsteadJUnit4;
52 import com.android.bedstead.harrier.DeviceState;
53 import com.android.bedstead.harrier.annotations.EnsureHasPermission;
54 import com.android.bedstead.harrier.annotations.RequireFeature;
55 import com.android.bedstead.nene.TestApis;
56 import com.android.bedstead.nene.users.UserReference;
57 import com.android.bedstead.nene.users.UserType;
58 
59 import org.junit.Before;
60 import org.junit.ClassRule;
61 import org.junit.Rule;
62 import org.junit.Test;
63 import org.junit.runner.RunWith;
64 
65 import java.util.ArrayDeque;
66 import java.util.HashSet;
67 import java.util.List;
68 import java.util.Set;
69 import java.util.stream.Collectors;
70 
71 @RunWith(BedsteadJUnit4.class)
72 public final class UserManagerTest {
73 
74     @ClassRule
75     @Rule
76     public static final DeviceState sDeviceState = new DeviceState();
77 
78     private static final Context sContext = TestApis.context().instrumentedContext();
79 
80     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
81     private UserManager mUserManager;
82 
83     private final String mAccountName = "test_account_name";
84     private final String mAccountType = "test_account_type";
85 
86     @Before
setUp()87     public void setUp() {
88         mUserManager = sContext.getSystemService(UserManager.class);
89         assertWithMessage("UserManager service").that(mUserManager).isNotNull();
90     }
91 
removeUser(UserHandle userHandle)92     private void removeUser(UserHandle userHandle) {
93         if (userHandle == null) {
94             return;
95         }
96 
97         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
98             assertThat(mUserManager.removeUser(userHandle)).isTrue();
99         }
100     }
101 
102     /**
103      * Verify that the isUserAGoat() method always returns false for API level 30. This is
104      * because apps targeting R no longer have access to package queries by default.
105      */
106     @Test
testUserGoat_api30()107     public void testUserGoat_api30() {
108         assertWithMessage("isUserAGoat()").that(mUserManager.isUserAGoat()).isFalse();
109     }
110 
111     @Test
testIsRemoveResultSuccessful()112     public void testIsRemoveResultSuccessful() {
113         assertThat(UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_REMOVED))
114                 .isTrue();
115         assertThat(UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_DEFERRED))
116                 .isTrue();
117         assertThat(UserManager
118                 .isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED))
119                         .isTrue();
120         assertThat(UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_UNKNOWN))
121                 .isFalse();
122         assertThat(UserManager
123                 .isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_USER_RESTRICTION))
124                         .isFalse();
125         assertThat(UserManager
126                 .isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_USER_NOT_FOUND))
127                         .isFalse();
128         assertThat(
129                 UserManager.isRemoveResultSuccessful(UserManager.REMOVE_RESULT_ERROR_SYSTEM_USER))
130                         .isFalse();
131     }
132 
133     @Test
testIsHeadlessSystemUserMode()134     public void testIsHeadlessSystemUserMode() throws Exception {
135         boolean expected = getBooleanProperty(mInstrumentation,
136                 "ro.fw.mu.headless_system_user");
137         assertWithMessage("isHeadlessSystemUserMode()")
138                 .that(UserManager.isHeadlessSystemUserMode()).isEqualTo(expected);
139     }
140 
141     @Test
testIsUserForeground_currentUser()142     public void testIsUserForeground_currentUser() throws Exception {
143         assertWithMessage("isUserForeground() for current user")
144                 .that(mUserManager.isUserForeground()).isTrue();
145     }
146     // TODO(b/173541467): add testIsUserForeground_backgroundUser()
147     // TODO(b/179163496): add testIsUserForeground_ tests for profile users
148 
149     @Test
testCloneProfile()150     public void testCloneProfile() throws Exception {
151         UserHandle userHandle = null;
152 
153         // Need CREATE_USERS permission to create user in test
154         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
155             try {
156                 userHandle = mUserManager.createProfile(
157                     "Clone profile", UserManager.USER_TYPE_PROFILE_CLONE, new HashSet<>());
158             } catch (UserManager.UserOperationException e) {
159                 // Not all devices and user types support these profiles; skip if this one doesn't.
160                 assumeNoException("Couldn't create clone profile", e);
161                 return;
162             }
163             assertThat(userHandle).isNotNull();
164 
165             final Context userContext = sContext.createPackageContextAsUser("system", 0,
166                     userHandle);
167             final UserManager cloneUserManager = userContext.getSystemService(UserManager.class);
168             assertThat(cloneUserManager.isMediaSharedWithParent()).isTrue();
169             assertThat(cloneUserManager.isCredentialSharableWithParent()).isTrue();
170             assertThat(cloneUserManager.isCloneProfile()).isTrue();
171             assertThat(cloneUserManager.isProfile()).isTrue();
172             assertThat(cloneUserManager.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)).isTrue();
173 
174             final List<UserInfo> list = mUserManager.getUsers(true, true, true);
175             final UserHandle finalUserHandle = userHandle;
176             final List<UserInfo> cloneUsers = list.stream().filter(
177                     user -> (user.id == finalUserHandle.getIdentifier()
178                             && user.isCloneProfile()))
179                     .collect(Collectors.toList());
180             assertThat(cloneUsers.size()).isEqualTo(1);
181         } finally {
182             removeUser(userHandle);
183         }
184     }
185 
186     @Test
187     @RequireFeature(FEATURE_MANAGED_USERS)
188     @EnsureHasPermission({CREATE_USERS, QUERY_USERS})
testManagedProfile()189     public void testManagedProfile() throws Exception {
190         UserHandle userHandle = null;
191 
192         try {
193             try {
194                 userHandle = mUserManager.createProfile(
195                     "Managed profile", UserManager.USER_TYPE_PROFILE_MANAGED, new HashSet<>());
196             } catch (UserManager.UserOperationException e) {
197                 // Not all devices and user types support these profiles; skip if this one doesn't.
198                 assumeNoException("Couldn't create managed profile", e);
199                 return;
200             }
201             assertThat(userHandle).isNotNull();
202 
203             final UserManager umOfProfile = sContext
204                     .createPackageContextAsUser("android", 0, userHandle)
205                     .getSystemService(UserManager.class);
206 
207             // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump.
208             if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
209                 assertThat(umOfProfile.isManagedProfile()).isTrue();
210             }
211             assertThat(umOfProfile.isManagedProfile(userHandle.getIdentifier())).isTrue();
212             assertThat(umOfProfile.isProfile()).isTrue();
213             assertThat(umOfProfile.isUserOfType(UserManager.USER_TYPE_PROFILE_MANAGED)).isTrue();
214         } finally {
215             removeUser(userHandle);
216         }
217     }
218 
219     @Test
220     @EnsureHasPermission({QUERY_USERS})
testSystemUser()221     public void testSystemUser() throws Exception {
222         final UserManager umOfSys = sContext
223                 .createPackageContextAsUser("android", 0, UserHandle.SYSTEM)
224                 .getSystemService(UserManager.class);
225 
226         // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump.
227         if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
228             assertThat(umOfSys.isSystemUser()).isTrue();
229         }
230 
231         // We cannot demand what type of user SYSTEM is, but we can say some things it isn't.
232         assertThat(umOfSys.isUserOfType(UserManager.USER_TYPE_PROFILE_CLONE)).isFalse();
233         assertThat(umOfSys.isUserOfType(UserManager.USER_TYPE_PROFILE_MANAGED)).isFalse();
234         assertThat(umOfSys.isUserOfType(UserManager.USER_TYPE_FULL_GUEST)).isFalse();
235 
236         assertThat(umOfSys.isProfile()).isFalse();
237         assertThat(umOfSys.isManagedProfile()).isFalse();
238         assertThat(umOfSys.isManagedProfile(UserHandle.USER_SYSTEM)).isFalse();
239         assertThat(umOfSys.isCloneProfile()).isFalse();
240     }
241 
242     @Test
243     @SystemUserOnly(reason = "Restricted users are only supported on system user.")
testRestrictedUser()244     public void testRestrictedUser() throws Exception {
245         UserHandle user = null;
246         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
247             // Check that the SYSTEM user is not restricted.
248             assertThat(mUserManager.isRestrictedProfile()).isFalse();
249             assertThat(mUserManager.isRestrictedProfile(UserHandle.SYSTEM)).isFalse();
250             assertThat(mUserManager.getRestrictedProfileParent()).isNull();
251 
252             final UserInfo info = mUserManager.createRestrictedProfile("Restricted user");
253 
254             // If the device supports Restricted users, it must report it correctly.
255             assumeTrue("Couldn't create a restricted profile", info != null);
256 
257             user = UserHandle.of(info.id);
258             assertThat(mUserManager.isRestrictedProfile(user)).isTrue();
259 
260             final Context userContext = sContext.createPackageContextAsUser("system", 0, user);
261             final UserManager userUm = userContext.getSystemService(UserManager.class);
262             // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump.
263             if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
264                 assertThat(userUm.isRestrictedProfile()).isTrue();
265             }
266             assertThat(userUm.getRestrictedProfileParent().isSystem()).isTrue();
267         } finally {
268             removeUser(user);
269         }
270     }
271 
newUserRequest()272     private NewUserRequest newUserRequest() {
273         final PersistableBundle accountOptions = new PersistableBundle();
274         accountOptions.putString("test_account_option_key", "test_account_option_value");
275 
276         return new NewUserRequest.Builder()
277                 .setName("test_user")
278                 .setUserType(USER_TYPE_FULL_SECONDARY)
279                 .setUserIcon(Bitmap.createBitmap(32, 32, Bitmap.Config.RGB_565))
280                 .setAccountName(mAccountName)
281                 .setAccountType(mAccountType)
282                 .setAccountOptions(accountOptions)
283                 .build();
284     }
285 
286     @Test
testSomeUserHasAccount()287     public void testSomeUserHasAccount() {
288         // TODO: (b/233197356): Replace with bedstead annotation.
289         assumeTrue(mUserManager.supportsMultipleUsers());
290         UserHandle user = null;
291 
292         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
293             assertThat(mUserManager.someUserHasAccount(mAccountName, mAccountType)).isFalse();
294             user = mUserManager.createUser(newUserRequest()).getUser();
295             assertThat(mUserManager.someUserHasAccount(mAccountName, mAccountType)).isTrue();
296         } finally {
297             removeUser(user);
298         }
299     }
300 
301     @Test
testSomeUserHasAccount_shouldIgnoreToBeRemovedUsers()302     public void testSomeUserHasAccount_shouldIgnoreToBeRemovedUsers() {
303         // TODO: (b/233197356): Replace with bedstead annotation.
304         assumeTrue(mUserManager.supportsMultipleUsers());
305         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
306             final NewUserResponse response = mUserManager.createUser(newUserRequest());
307             assertThat(response.getOperationResult()).isEqualTo(USER_OPERATION_SUCCESS);
308             mUserManager.removeUser(response.getUser());
309             assertThat(mUserManager.someUserHasAccount(mAccountName, mAccountType)).isFalse();
310         }
311     }
312 
313     @Test
testCreateUser_withNewUserRequest_shouldCreateUserWithCorrectProperties()314     public void testCreateUser_withNewUserRequest_shouldCreateUserWithCorrectProperties()
315             throws PackageManager.NameNotFoundException {
316         // TODO: (b/233197356): Replace with bedstead annotation.
317         assumeTrue(mUserManager.supportsMultipleUsers());
318         UserHandle user = null;
319 
320         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
321             final NewUserRequest request = newUserRequest();
322             final NewUserResponse response = mUserManager.createUser(request);
323             user = response.getUser();
324 
325             assertThat(response.getOperationResult()).isEqualTo(USER_OPERATION_SUCCESS);
326             assertThat(response.isSuccessful()).isTrue();
327             assertThat(user).isNotNull();
328 
329             UserManager userManagerOfNewUser = sContext
330                     .createPackageContextAsUser("android", 0, user)
331                     .getSystemService(UserManager.class);
332 
333             assertThat(userManagerOfNewUser.getUserName()).isEqualTo(request.getName());
334             // TODO(b/222584163): Remove the if{} clause after v33 Sdk bump.
335             if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
336                 assertThat(userManagerOfNewUser.isUserNameSet()).isTrue();
337             }
338             assertThat(userManagerOfNewUser.getUserType()).isEqualTo(request.getUserType());
339             assertThat(userManagerOfNewUser.isUserOfType(request.getUserType())).isEqualTo(true);
340             // We can not test userIcon and accountOptions,
341             // because getters require MANAGE_USERS permission.
342             // And we are already testing accountName and accountType
343             // are set correctly in testSomeUserHasAccount method.
344         } finally {
345             removeUser(user);
346         }
347     }
348 
349     @Test
testCreateUser_withNewUserRequest_shouldNotAllowDuplicateUserAccounts()350     public void testCreateUser_withNewUserRequest_shouldNotAllowDuplicateUserAccounts() {
351         // TODO: (b/233197356): Replace with bedstead annotation.
352         assumeTrue(mUserManager.supportsMultipleUsers());
353         UserHandle user1 = null;
354         UserHandle user2 = null;
355 
356         try (PermissionHelper ph = adoptShellPermissionIdentity(mInstrumentation, CREATE_USERS)) {
357             final NewUserResponse response1 = mUserManager.createUser(newUserRequest());
358             user1 = response1.getUser();
359 
360             assertThat(response1.getOperationResult()).isEqualTo(USER_OPERATION_SUCCESS);
361             assertThat(response1.isSuccessful()).isTrue();
362             assertThat(user1).isNotNull();
363 
364             final NewUserResponse response2 = mUserManager.createUser(newUserRequest());
365             user2 = response2.getUser();
366 
367             assertThat(response2.getOperationResult()).isEqualTo(
368                     UserManager.USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS);
369             assertThat(response2.isSuccessful()).isFalse();
370             assertThat(user2).isNull();
371         } finally {
372             removeUser(user1);
373             removeUser(user2);
374         }
375     }
376 
377     @Test
378     @AppModeFull
379     @RequireFeature(FEATURE_MANAGED_USERS)
380     @EnsureHasPermission(INTERACT_ACROSS_USERS)
getProfileParent_withNewlyCreatedProfile()381     public void getProfileParent_withNewlyCreatedProfile() {
382         final UserReference parent = TestApis.users().instrumented();
383         try (UserReference profile = TestApis.users().createUser()
384                 .parent(parent)
385                 .type(TestApis.users().supportedType(UserType.MANAGED_PROFILE_TYPE_NAME))
386                 .createAndStart()) {
387             assertThat(mUserManager.getProfileParent(profile.userHandle()))
388                     .isEqualTo(parent.userHandle());
389         }
390     }
391 
392     @Test
393     @AppModeFull
394     @EnsureHasPermission(INTERACT_ACROSS_USERS)
getProfileParent_returnsNullForNonProfile()395     public void getProfileParent_returnsNullForNonProfile() {
396         assertThat(mUserManager.getProfileParent(TestApis.users().system().userHandle())).isNull();
397     }
398 
399     @Test
400     @EnsureHasPermission({CREATE_USERS, QUERY_USERS})
testGetRemainingCreatableUserCount()401     public void testGetRemainingCreatableUserCount() {
402         final int maxAllowedIterations = 15;
403         final String userType = USER_TYPE_FULL_SECONDARY;
404         final NewUserRequest request = new NewUserRequest.Builder().build();
405         final ArrayDeque<UserHandle> usersCreated = new ArrayDeque<>();
406 
407         try {
408             final int initialRemainingCount = mUserManager.getRemainingCreatableUserCount(userType);
409             assertThat(initialRemainingCount).isAtLeast(0);
410 
411             final int numUsersToAdd = Math.min(maxAllowedIterations, initialRemainingCount);
412 
413             for (int i = 0; i < numUsersToAdd; i++) {
414                 usersCreated.push(mUserManager.createUser(request).getUser());
415                 assertThat(mUserManager.getRemainingCreatableUserCount(userType))
416                         .isEqualTo(initialRemainingCount - usersCreated.size());
417             }
418             for (int i = 0; i < numUsersToAdd; i++) {
419                 mUserManager.removeUser(usersCreated.pop());
420                 assertThat(mUserManager.getRemainingCreatableUserCount(userType))
421                         .isEqualTo(initialRemainingCount - usersCreated.size());
422             }
423         } finally {
424             usersCreated.forEach(this::removeUser);
425         }
426     }
427 
428     @Test
429     @EnsureHasPermission({CREATE_USERS, QUERY_USERS})
testGetRemainingCreatableProfileCount()430     public void testGetRemainingCreatableProfileCount() {
431         final int maxAllowedIterations = 15;
432         final String type = USER_TYPE_PROFILE_MANAGED;
433         final ArrayDeque<UserHandle> profilesCreated = new ArrayDeque<>();
434         final Set<String> disallowedPackages = new HashSet<>();
435         try {
436             final int initialRemainingCount =
437                     mUserManager.getRemainingCreatableProfileCount(type);
438             assertThat(initialRemainingCount).isAtLeast(0);
439 
440             final int numUsersToAdd = Math.min(maxAllowedIterations, initialRemainingCount);
441 
442             for (int i = 0; i < numUsersToAdd; i++) {
443                 profilesCreated.push(mUserManager.createProfile(null, type, disallowedPackages));
444                 assertThat(mUserManager.getRemainingCreatableProfileCount(type))
445                         .isEqualTo(initialRemainingCount - profilesCreated.size());
446             }
447             for (int i = 0; i < numUsersToAdd; i++) {
448                 mUserManager.removeUser(profilesCreated.pop());
449                 assertThat(mUserManager.getRemainingCreatableProfileCount(type))
450                         .isEqualTo(initialRemainingCount - profilesCreated.size());
451             }
452         } finally {
453             profilesCreated.forEach(this::removeUser);
454         }
455     }
456 }
457