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 
17 package com.android.cts.deviceowner;
18 
19 import static com.google.common.truth.Truth.assertWithMessage;
20 
21 import static org.testng.Assert.expectThrows;
22 
23 import android.app.ActivityManager;
24 import android.app.Service;
25 import android.app.admin.DeviceAdminReceiver;
26 import android.app.admin.DevicePolicyManager;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.ServiceConnection;
31 import android.content.pm.PackageManager;
32 import android.os.IBinder;
33 import android.os.PersistableBundle;
34 import android.os.RemoteException;
35 import android.os.UserHandle;
36 import android.os.UserManager;
37 import android.provider.Settings;
38 import android.util.DebugUtils;
39 import android.util.Log;
40 
41 import com.android.compatibility.common.util.SystemUtil;
42 
43 import java.lang.reflect.InvocationTargetException;
44 import java.lang.reflect.Method;
45 import java.util.Collections;
46 import java.util.HashSet;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Set;
50 import java.util.concurrent.Semaphore;
51 import java.util.concurrent.TimeUnit;
52 import java.util.function.Predicate;
53 import java.util.stream.Collectors;
54 
55 /**
56  * Test {@link DevicePolicyManager#createAndManageUser}.
57  */
58 public class CreateAndManageUserTest extends BaseDeviceOwnerTest {
59     private static final String TAG = "CreateAndManageUserTest";
60 
61     private static final int BROADCAST_TIMEOUT = 300_000;
62 
63     private static final String AFFILIATION_ID = "affiliation.id";
64     private static final String EXTRA_AFFILIATION_ID = "affiliationIdExtra";
65     private static final String EXTRA_CURRENT_USER_PACKAGES = "currentUserPackages";
66     private static final String EXTRA_METHOD_NAME = "methodName";
67     private static final long ON_ENABLED_TIMEOUT_SECONDS = 120;
68 
69     @Override
tearDown()70     protected void tearDown() throws Exception {
71         mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
72         mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
73         super.tearDown();
74     }
75 
testCreateAndManageUser()76     public void testCreateAndManageUser() throws Exception {
77         UserHandle userHandle = createAndManageUser();
78 
79         assertWithMessage("New user").that(userHandle).isNotNull();
80     }
81 
testCreateAndManageUser_LowStorage()82     public void testCreateAndManageUser_LowStorage() throws Exception {
83         UserManager.UserOperationException e = expectThrows(
84                 UserManager.UserOperationException.class, () -> createAndManageUser());
85 
86         assertUserOperationResult(e.getUserOperationResult(),
87                 UserManager.USER_OPERATION_ERROR_LOW_STORAGE,
88                 "user creation on low storage");
89     }
90 
testCreateAndManageUser_MaxUsers()91     public void testCreateAndManageUser_MaxUsers() throws Exception {
92         UserManager.UserOperationException e = expectThrows(
93                 UserManager.UserOperationException.class, () -> createAndManageUser());
94 
95         assertUserOperationResult(e.getUserOperationResult(),
96                 UserManager.USER_OPERATION_ERROR_MAX_USERS,
97                 "user creation when max users is reached");
98     }
99 
100     @SuppressWarnings("unused")
assertSkipSetupWizard(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)101     private static void assertSkipSetupWizard(Context context,
102             DevicePolicyManager devicePolicyManager, ComponentName componentName) throws Exception {
103         assertWithMessage("user setup settings (%s)", Settings.Secure.USER_SETUP_COMPLETE)
104                 .that(Settings.Secure.getInt(context.getContentResolver(),
105                         Settings.Secure.USER_SETUP_COMPLETE))
106                 .isEqualTo(1);
107     }
108 
testCreateAndManageUser_SkipSetupWizard()109     public void testCreateAndManageUser_SkipSetupWizard() throws Exception {
110         runCrossUserVerification(DevicePolicyManager.SKIP_SETUP_WIZARD, "assertSkipSetupWizard");
111 
112         PrimaryUserService.assertCrossUserCallArrived();
113     }
114 
testCreateAndManageUser_GetSecondaryUsers()115     public void testCreateAndManageUser_GetSecondaryUsers() throws Exception {
116         UserHandle newUserHandle = createAndManageUser();
117 
118         List<UserHandle> secondaryUsers = mDevicePolicyManager.getSecondaryUsers(getWho());
119         if (isHeadlessSystemUserMode()) {
120             assertWithMessage("secondary users").that(secondaryUsers)
121                 .containsExactly(getCurrentUser(), newUserHandle);
122         } else {
123             assertWithMessage("secondary users").that(secondaryUsers)
124                     .containsExactly(newUserHandle);
125         }
126     }
127 
testCreateAndManageUser_SwitchUser()128     public void testCreateAndManageUser_SwitchUser() throws Exception {
129         UserHandle userHandle = createAndManageUser();
130 
131         List<UserHandle> usersOnBroadcasts = switchUserAndWaitForBroadcasts(userHandle);
132 
133         assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle,
134                 userHandle);
135     }
136 
testCreateAndManageUser_CannotStopCurrentUser()137     public void testCreateAndManageUser_CannotStopCurrentUser() throws Exception {
138         UserHandle userHandle = createAndManageUser();
139 
140         switchUserAndWaitForBroadcasts(userHandle);
141 
142         stopUserAndCheckResult(userHandle, UserManager.USER_OPERATION_ERROR_CURRENT_USER);
143     }
144 
testCreateAndManageUser_StartInBackground()145     public void testCreateAndManageUser_StartInBackground() throws Exception {
146         UserHandle userHandle = createAndManageUser();
147 
148         List<UserHandle> usersOnBroadcasts = startUserInBackgroundAndWaitForBroadcasts(userHandle);
149 
150         assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle);
151     }
152 
testCreateAndManageUser_StartInBackground_MaxRunningUsers()153     public void testCreateAndManageUser_StartInBackground_MaxRunningUsers() throws Exception {
154         UserHandle userHandle = createAndManageUser();
155 
156         // Start user in background and should receive max running users error
157         startUserInBackgroundAndCheckResult(userHandle,
158                 UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS);
159     }
160 
testCreateAndManageUser_StopUser()161     public void testCreateAndManageUser_StopUser() throws Exception {
162         UserHandle userHandle = createAndManageUser();
163         startUserInBackgroundAndWaitForBroadcasts(userHandle);
164 
165         List<UserHandle> usersOnBroadcasts = stopUserAndWaitForBroadcasts(userHandle);
166 
167         assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle);
168     }
169 
testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser()170     public void testCreateAndManageUser_StopEphemeralUser_DisallowRemoveUser() throws Exception {
171         // Set DISALLOW_REMOVE_USER restriction
172         mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
173 
174         UserHandle userHandle = createAndManageUser(DevicePolicyManager.MAKE_USER_EPHEMERAL);
175         startUserInBackgroundAndWaitForBroadcasts(userHandle);
176         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
177                 getContext(),
178                 BasicAdminReceiver.ACTION_USER_STOPPED, BasicAdminReceiver.ACTION_USER_REMOVED);
179 
180         callback.runAndUnregisterSelf(
181                 () -> stopUserAndCheckResult(userHandle, UserManager.USER_OPERATION_SUCCESS));
182 
183         // It's running just one operation (which issues a ACTION_USER_STOPPED), but as the
184         // user is ephemeral, it will be automatically removed (which issues a
185         // ACTION_USER_REMOVED).
186         assertWithMessage("user on broadcasts").that(callback.getUsersOnReceivedBroadcasts())
187                 .containsExactly(userHandle, userHandle);
188     }
189 
190     @SuppressWarnings("unused")
logoutUser(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)191     private static void logoutUser(Context context, DevicePolicyManager devicePolicyManager,
192             ComponentName componentName) {
193         assertUserOperationResult(devicePolicyManager.logoutUser(componentName),
194                 UserManager.USER_OPERATION_SUCCESS, "cannot logout user");
195     }
196 
testCreateAndManageUser_LogoutUser()197     public void testCreateAndManageUser_LogoutUser() throws Exception {
198         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
199                 getContext(),
200                 BasicAdminReceiver.ACTION_USER_STARTED, BasicAdminReceiver.ACTION_USER_STOPPED);
201 
202         UserHandle userHandle = runCrossUserVerification(callback,
203                 /* createAndManageUserFlags= */ 0, "logoutUser", /* currentUserPackages= */ null);
204 
205         assertWithMessage("user on broadcasts").that(callback.getUsersOnReceivedBroadcasts())
206                 .containsExactly(userHandle, userHandle);
207     }
208 
209     @SuppressWarnings("unused")
assertAffiliatedUser(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)210     private static void assertAffiliatedUser(Context context,
211             DevicePolicyManager devicePolicyManager, ComponentName componentName) {
212         assertWithMessage("affiliated user").that(devicePolicyManager.isAffiliatedUser()).isTrue();
213     }
214 
testCreateAndManageUser_Affiliated()215     public void testCreateAndManageUser_Affiliated() throws Exception {
216         runCrossUserVerification(/* createAndManageUserFlags= */ 0, "assertAffiliatedUser");
217         PrimaryUserService.assertCrossUserCallArrived();
218     }
219 
220     @SuppressWarnings("unused")
assertEphemeralUser(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName)221     private static void assertEphemeralUser(Context context,
222             DevicePolicyManager devicePolicyManager, ComponentName componentName) {
223         assertWithMessage("ephemeral user").that(devicePolicyManager.isEphemeralUser(componentName))
224                 .isTrue();
225     }
226 
testCreateAndManageUser_Ephemeral()227     public void testCreateAndManageUser_Ephemeral() throws Exception {
228         runCrossUserVerification(DevicePolicyManager.MAKE_USER_EPHEMERAL, "assertEphemeralUser");
229         PrimaryUserService.assertCrossUserCallArrived();
230     }
231 
232     @SuppressWarnings("unused")
assertAllSystemAppsInstalled(Context context, DevicePolicyManager devicePolicyManager, ComponentName componentName, Set<String> preInstalledSystemPackages)233     private static void assertAllSystemAppsInstalled(Context context,
234             DevicePolicyManager devicePolicyManager, ComponentName componentName,
235             Set<String> preInstalledSystemPackages) {
236         Log.d(TAG, "assertAllSystemAppsInstalled(): checking apps for user " + context.getUserId());
237 
238         PackageManager packageManager = context.getPackageManager();
239         // First get a set of installed package names
240         Set<String> installedPackageNames = packageManager
241                 .getInstalledApplications(/* flags= */ 0)
242                 .stream()
243                 .map(applicationInfo -> applicationInfo.packageName)
244                 .collect(Collectors.toSet());
245         // Then filter all package names by those that are not installed
246         Set<String> uninstalledPackageNames = packageManager
247                 .getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES)
248                 .stream()
249                 .map(applicationInfo -> applicationInfo.packageName)
250                 .filter(((Predicate<String>) installedPackageNames::contains).negate())
251                 .collect(Collectors.toSet());
252 
253         // Finally, filter out packages that are not pre-installed for the user
254         Iterator<String> iterator = uninstalledPackageNames.iterator();
255         while (iterator.hasNext()) {
256             String pkg = iterator.next();
257             if (!preInstalledSystemPackages.contains(pkg)) {
258                 Log.i(TAG, "assertAllSystemAppsInstalled(): ignoring package " + pkg
259                         + " as it's not pre-installed on current user");
260                 iterator.remove();
261             }
262         }
263 
264         // Assert that all expected apps are installed
265         assertWithMessage("uninstalled system apps").that(uninstalledPackageNames).isEmpty();
266     }
267 
testCreateAndManageUser_LeaveAllSystemApps()268     public void testCreateAndManageUser_LeaveAllSystemApps() throws Exception {
269         int currentUserId = ActivityManager.getCurrentUser();
270         // TODO: instead of hard-coding the user type, calling getPreInstallableSystemPackages(),
271         // and passing the packages to runCrossUserVerification() / assertAllSystemAppsInstalled(),
272         // ideally the later should call um.getPreInstallableSystemPackages(um.getUsertype())
273         // (where um is the UserManager with the context of the newly created user),
274         // but currently the list of pre-installed apps is passed to the new user in the bundle.
275         // Given that these tests will be refactored anyways, it's not worth to try to change it.
276         String newUserType = UserManager.USER_TYPE_FULL_SECONDARY;
277         Set<String> preInstalledSystemPackages = SystemUtil.callWithShellPermissionIdentity(
278                 () -> UserManager.get(mContext).getPreInstallableSystemPackages(newUserType));
279         if (preInstalledSystemPackages != null) {
280             Log.d(TAG, preInstalledSystemPackages.size() + " pre-installed system apps for "
281                     + "new user of type " + newUserType + ": " + preInstalledSystemPackages);
282         } else {
283             Log.d(TAG, "no pre-installed system apps allowlist for new user of type" + newUserType);
284         }
285 
286         runCrossUserVerification(/* callback= */ null,
287                 DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED, "assertAllSystemAppsInstalled",
288                 preInstalledSystemPackages);
289         PrimaryUserService.assertCrossUserCallArrived();
290     }
291 
runCrossUserVerification(int createAndManageUserFlags, String methodName)292     private UserHandle runCrossUserVerification(int createAndManageUserFlags, String methodName)
293             throws Exception {
294         return runCrossUserVerification(/* callback= */ null, createAndManageUserFlags, methodName,
295                 /* currentUserPackages= */ null);
296     }
297 
runCrossUserVerification(UserActionCallback callback, int createAndManageUserFlags, String methodName, Set<String> currentUserPackages)298     private UserHandle runCrossUserVerification(UserActionCallback callback,
299             int createAndManageUserFlags, String methodName,
300             Set<String> currentUserPackages) throws Exception {
301         Log.d(TAG, "runCrossUserVerification(): flags=" + createAndManageUserFlags
302                 + ", method=" + methodName);
303         String testUserName = "TestUser_" + System.currentTimeMillis();
304 
305         // Set affiliation id to allow communication.
306         mDevicePolicyManager.setAffiliationIds(getWho(), Collections.singleton(AFFILIATION_ID));
307 
308         ComponentName profileOwner = SecondaryUserAdminReceiver.getComponentName(getContext());
309 
310         // Pack the affiliation id in a bundle so the secondary user can get it.
311         PersistableBundle bundle = new PersistableBundle();
312         bundle.putString(EXTRA_AFFILIATION_ID, AFFILIATION_ID);
313         bundle.putString(EXTRA_METHOD_NAME, methodName);
314         if (currentUserPackages != null) {
315             String[] array = new String[currentUserPackages.size()];
316             currentUserPackages.toArray(array);
317             bundle.putStringArray(EXTRA_CURRENT_USER_PACKAGES, array);
318         }
319 
320         Log.d(TAG, "creating user with PO " + profileOwner);
321 
322         UserHandle userHandle = createAndManageUser(profileOwner, bundle, createAndManageUserFlags);
323         if (callback != null) {
324             startUserInBackgroundAndWaitForBroadcasts(callback, userHandle);
325         } else {
326             startUserInBackgroundAndWaitForBroadcasts(userHandle);
327         }
328         return userHandle;
329     }
330 
331     // createAndManageUser should circumvent the DISALLOW_ADD_USER restriction
testCreateAndManageUser_AddRestrictionSet()332     public void testCreateAndManageUser_AddRestrictionSet() throws Exception {
333         mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
334 
335         createAndManageUser();
336     }
337 
testCreateAndManageUser_RemoveRestrictionSet()338     public void testCreateAndManageUser_RemoveRestrictionSet() throws Exception {
339         mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
340 
341         UserHandle userHandle = createAndManageUser();
342 
343         // When the device owner itself has set the user restriction, it should still be allowed
344         // to remove a user.
345         List<UserHandle> usersOnBroadcasts = removeUserAndWaitForBroadcasts(userHandle);
346 
347         assertWithMessage("user on broadcasts").that(usersOnBroadcasts).containsExactly(userHandle);
348     }
349 
testUserAddedOrRemovedBroadcasts()350     public void testUserAddedOrRemovedBroadcasts() throws Exception {
351         UserHandle userHandle = createAndManageUser();
352 
353         List<UserHandle> userHandles = removeUserAndWaitForBroadcasts(userHandle);
354 
355         assertWithMessage("user on broadcasts").that(userHandles).containsExactly(userHandle);
356     }
357 
createAndManageUser()358     private UserHandle createAndManageUser() throws Exception {
359         return createAndManageUser(/* flags= */ 0);
360     }
361 
createAndManageUser(int flags)362     private UserHandle createAndManageUser(int flags) throws Exception {
363         return createAndManageUser(/* profileOwner= */ getWho(), /* adminExtras= */ null, flags);
364     }
365 
createAndManageUser(ComponentName profileOwner, PersistableBundle adminExtras, int flags)366     private UserHandle createAndManageUser(ComponentName profileOwner,
367             PersistableBundle adminExtras, int flags) throws Exception {
368         String testUserName = "TestUser_" + System.currentTimeMillis();
369 
370         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
371                 getContext(), BasicAdminReceiver.ACTION_USER_ADDED);
372 
373         UserHandle userHandle = callback.callAndUnregisterSelf(() ->
374                 mDevicePolicyManager.createAndManageUser(
375                         /* admin= */ getWho(),
376                         testUserName,
377                         profileOwner,
378                         adminExtras,
379                         flags));
380         Log.d(TAG, "User '" + testUserName + "' created: " + userHandle);
381         return userHandle;
382     }
383 
384     /**
385      * Switches to the given user, or fails if the user could not be switched or if the expected
386      * broadcasts were not received in time.
387      *
388      * @return users received in the broadcasts
389      */
switchUserAndWaitForBroadcasts(UserHandle userHandle)390     private List<UserHandle> switchUserAndWaitForBroadcasts(UserHandle userHandle)
391             throws Exception {
392         Log.d(TAG, "Switching to user " + userHandle);
393 
394         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
395                 getContext(),
396                 BasicAdminReceiver.ACTION_USER_STARTED, BasicAdminReceiver.ACTION_USER_SWITCHED);
397 
398         callback.runAndUnregisterSelf(() -> {
399             boolean switched = mDevicePolicyManager.switchUser(getWho(), userHandle);
400             assertWithMessage("switched to user %s", userHandle).that(switched).isTrue();
401         });
402         return callback.getUsersOnReceivedBroadcasts();
403     }
404 
405     /**
406      * Removes the given user, or fails if the user could not be removed or if the expected
407      * broadcasts were not received in time.
408      *
409      * @return users received in the broadcasts
410      */
removeUserAndWaitForBroadcasts(UserHandle userHandle)411     private List<UserHandle> removeUserAndWaitForBroadcasts(UserHandle userHandle)
412             throws Exception {
413         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
414                 getContext(), BasicAdminReceiver.ACTION_USER_REMOVED);
415 
416         callback.runAndUnregisterSelf(() -> {
417             boolean removed = mDevicePolicyManager.removeUser(getWho(), userHandle);
418             assertWithMessage("removed user %s", userHandle).that(removed).isTrue();
419         });
420 
421         return callback.getUsersOnReceivedBroadcasts();
422     }
423 
userOperationResultToString(int result)424     private static String userOperationResultToString(int result) {
425         return DebugUtils.constantToString(UserManager.class, "USER_OPERATION_", result);
426     }
427 
assertUserOperationResult(int actualResult, int expectedResult, String operationFormat, Object... operationArgs)428     private static void assertUserOperationResult(int actualResult, int expectedResult,
429             String operationFormat, Object... operationArgs) {
430         String operation = String.format(operationFormat, operationArgs);
431         assertWithMessage("result for %s (%s instead of %s)", operation,
432                 userOperationResultToString(actualResult),
433                 userOperationResultToString(expectedResult))
434                         .that(actualResult).isEqualTo(expectedResult);
435     }
436 
startUserInBackgroundAndCheckResult(UserHandle userHandle, int expectedResult)437     private void startUserInBackgroundAndCheckResult(UserHandle userHandle, int expectedResult) {
438         int actualResult = mDevicePolicyManager.startUserInBackground(getWho(), userHandle);
439         assertUserOperationResult(actualResult, expectedResult, "starting user %s in background",
440                 userHandle);
441     }
442 
443     /**
444      * Starts the given user in background, or fails if the user could not be started or if the
445      * expected broadcasts were not received in time.
446      *
447      * @return users received in the broadcasts
448      */
startUserInBackgroundAndWaitForBroadcasts(UserHandle userHandle)449     private List<UserHandle> startUserInBackgroundAndWaitForBroadcasts(UserHandle userHandle)
450             throws Exception {
451         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
452                 getContext(), BasicAdminReceiver.ACTION_USER_STARTED);
453         return startUserInBackgroundAndWaitForBroadcasts(callback, userHandle);
454     }
455 
startUserInBackgroundAndWaitForBroadcasts(UserActionCallback callback, UserHandle userHandle)456     private List<UserHandle> startUserInBackgroundAndWaitForBroadcasts(UserActionCallback callback,
457             UserHandle userHandle) throws Exception {
458         callback.runAndUnregisterSelf(() -> startUserInBackgroundAndCheckResult(userHandle,
459                 UserManager.USER_OPERATION_SUCCESS));
460         return callback.getUsersOnReceivedBroadcasts();
461     }
462 
stopUserAndCheckResult(UserHandle userHandle, int expectedResult)463     private void stopUserAndCheckResult(UserHandle userHandle, int expectedResult) {
464         int actualResult = mDevicePolicyManager.stopUser(getWho(), userHandle);
465         assertUserOperationResult(actualResult, expectedResult, "stopping user %s", userHandle);
466     }
467 
468     /**
469      * Stops the given user, or fails if the user could not be stop or if the expected broadcasts
470      * were not received in time.
471      *
472      * @return users received in the broadcasts
473      */
stopUserAndWaitForBroadcasts(UserHandle userHandle)474     private List<UserHandle> stopUserAndWaitForBroadcasts(UserHandle userHandle) throws Exception {
475         UserActionCallback callback = UserActionCallback.getCallbackForBroadcastActions(
476                 getContext(), BasicAdminReceiver.ACTION_USER_STOPPED);
477         callback.runAndUnregisterSelf(
478                 () -> stopUserAndCheckResult(userHandle, UserManager.USER_OPERATION_SUCCESS));
479         return callback.getUsersOnReceivedBroadcasts();
480     }
481 
482     public static final class PrimaryUserService extends Service {
483         private static final Semaphore sSemaphore = new Semaphore(0);
484         private static String sError = null;
485 
486         private final ICrossUserService.Stub mBinder = new ICrossUserService.Stub() {
487             public void onEnabledCalled(String error) {
488                 Log.d(TAG, "PrimaryUserService.onEnabledCalled() on user "
489                         + getApplicationContext().getUserId() + " with error " + error);
490                 sError = error;
491                 sSemaphore.release();
492             }
493         };
494 
495         @Override
onBind(Intent intent)496         public IBinder onBind(Intent intent) {
497             Log.d(TAG, "PrimaryUserService.onBind() on user "
498                     + getApplicationContext().getUserId() + ": " + intent);
499             return mBinder;
500         }
501 
assertCrossUserCallArrived()502         static void assertCrossUserCallArrived() throws Exception {
503             assertWithMessage("cross-user call arrived in %ss", ON_ENABLED_TIMEOUT_SECONDS)
504                     .that(sSemaphore.tryAcquire(ON_ENABLED_TIMEOUT_SECONDS, TimeUnit.SECONDS))
505                     .isTrue();
506             if (sError != null) {
507                 Log.e(TAG, "assertCrossUserCallArrived() had error: " + sError);
508                 throw new Exception(sError);
509             }
510         }
511     }
512 
513     public static final class SecondaryUserAdminReceiver extends DeviceAdminReceiver {
514 
515         @Override
onEnabled(Context context, Intent intent)516         public void onEnabled(Context context, Intent intent) {
517             Log.d(TAG, "SecondaryUserAdminReceiver.onEnabled() called on user "
518                     + context.getUserId());
519 
520             DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
521             ComponentName who = getComponentName(context);
522 
523             // Set affiliation ids
524             Set<String> ids = Collections.singleton(intent.getStringExtra(EXTRA_AFFILIATION_ID));
525             Log.d(TAG, "setting affiliation ids as " + ids);
526             dpm.setAffiliationIds(who, ids);
527 
528             String error = null;
529             try {
530                 Method method;
531                 if (intent.hasExtra(EXTRA_CURRENT_USER_PACKAGES)) {
532                     method = CreateAndManageUserTest.class.getDeclaredMethod(
533                             intent.getStringExtra(EXTRA_METHOD_NAME), Context.class,
534                             DevicePolicyManager.class, ComponentName.class, Set.class);
535                 } else {
536                     method = CreateAndManageUserTest.class.getDeclaredMethod(
537                             intent.getStringExtra(EXTRA_METHOD_NAME), Context.class,
538                             DevicePolicyManager.class, ComponentName.class);
539                 }
540                 method.setAccessible(true);
541                 Log.d(TAG, "Calling method " + method);
542                 if (intent.hasExtra(EXTRA_CURRENT_USER_PACKAGES)) {
543                     String[] pkgsArray = intent.getStringArrayExtra(EXTRA_CURRENT_USER_PACKAGES);
544                     Set<String> pkgs = new HashSet<>(pkgsArray.length);
545                     for (String pkg : pkgsArray) {
546                         pkgs.add(pkg);
547                     }
548                     method.invoke(null, context, dpm, who, pkgs);
549                 } else {
550                     method.invoke(null, context, dpm, who);
551                 }
552             } catch (NoSuchMethodException | IllegalAccessException e) {
553                 error = e.toString();
554             } catch (InvocationTargetException e) {
555                 error = e.getCause().toString();
556             }
557 
558             // Call all affiliated users
559             final List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(who);
560             assertWithMessage("target users").that(targetUsers).hasSize(1);
561 
562             pingTargetUser(context, dpm, targetUsers.get(0), error);
563         }
564 
pingTargetUser(Context context, DevicePolicyManager dpm, UserHandle target, String error)565         private void pingTargetUser(Context context, DevicePolicyManager dpm,
566                 UserHandle target, String error) {
567             Log.d(TAG, "Pinging target " + target + " with error " + error);
568             final ServiceConnection serviceConnection = new ServiceConnection() {
569                 @Override
570                 public void onServiceConnected(ComponentName name, IBinder service) {
571                     Log.d(TAG, "onServiceConnected() is called in " + Thread.currentThread());
572                     ICrossUserService crossUserService = ICrossUserService
573                             .Stub.asInterface(service);
574                     try {
575                         crossUserService.onEnabledCalled(error);
576                     } catch (RemoteException re) {
577                         Log.e(TAG, "Error when calling primary user", re);
578                         // Do nothing, primary user will time out
579                     }
580                 }
581 
582                 @Override
583                 public void onServiceDisconnected(ComponentName name) {
584                     Log.d(TAG, "onServiceDisconnected() is called");
585                 }
586             };
587             Intent serviceIntent = new Intent(context, PrimaryUserService.class);
588             boolean bound = dpm.bindDeviceAdminServiceAsUser(
589                     getComponentName(context),
590                     serviceIntent,
591                     serviceConnection,
592                     Context.BIND_AUTO_CREATE,
593                     target);
594             assertWithMessage("bound to user %s using intent %s", target, serviceIntent).that(bound)
595                     .isTrue();
596         }
597 
getComponentName(Context context)598         public static ComponentName getComponentName(Context context) {
599             return new ComponentName(context, SecondaryUserAdminReceiver.class);
600         }
601     }
602 }
603