1 /*
2  * Copyright (C) 2018 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.app.role.cts;
18 
19 import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
20 import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
21 import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
22 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
23 import static com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject;
24 import static com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull;
25 
26 import static com.google.common.truth.Truth.assertThat;
27 
28 import static org.junit.Assert.assertThrows;
29 import static org.junit.Assert.fail;
30 import static org.junit.Assume.assumeFalse;
31 import static org.junit.Assume.assumeTrue;
32 
33 import android.app.Activity;
34 import android.app.AppOpsManager;
35 import android.app.Instrumentation;
36 import android.app.role.OnRoleHoldersChangedListener;
37 import android.app.role.RoleManager;
38 import android.content.ComponentName;
39 import android.content.Context;
40 import android.content.Intent;
41 import android.content.pm.PackageManager;
42 import android.content.pm.PermissionInfo;
43 import android.os.Build;
44 import android.os.Process;
45 import android.os.UserHandle;
46 import android.permission.flags.Flags;
47 import android.platform.test.annotations.RequiresFlagsEnabled;
48 import android.platform.test.flag.junit.CheckFlagsRule;
49 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
50 import android.provider.Settings;
51 import android.provider.Telephony;
52 import android.telephony.TelephonyManager;
53 import android.util.Pair;
54 
55 import androidx.annotation.NonNull;
56 import androidx.annotation.Nullable;
57 import androidx.test.InstrumentationRegistry;
58 import androidx.test.filters.FlakyTest;
59 import androidx.test.filters.SdkSuppress;
60 import androidx.test.rule.ActivityTestRule;
61 import androidx.test.uiautomator.By;
62 import androidx.test.uiautomator.BySelector;
63 import androidx.test.uiautomator.UiObject2;
64 import androidx.test.uiautomator.UiObjectNotFoundException;
65 import androidx.test.uiautomator.Until;
66 
67 import com.android.bedstead.harrier.BedsteadJUnit4;
68 import com.android.bedstead.harrier.DeviceState;
69 import com.android.bedstead.harrier.annotations.EnsureHasPrivateProfile;
70 import com.android.bedstead.nene.types.OptionalBoolean;
71 import com.android.compatibility.common.util.DisableAnimationRule;
72 import com.android.compatibility.common.util.FreezeRotationRule;
73 import com.android.compatibility.common.util.TestUtils;
74 import com.android.compatibility.common.util.ThrowingRunnable;
75 import com.android.compatibility.common.util.UiAutomatorUtils;
76 
77 import org.junit.After;
78 import org.junit.Before;
79 import org.junit.ClassRule;
80 import org.junit.Rule;
81 import org.junit.Test;
82 import org.junit.runner.RunWith;
83 
84 import java.io.IOException;
85 import java.util.Collections;
86 import java.util.List;
87 import java.util.Objects;
88 import java.util.concurrent.CompletableFuture;
89 import java.util.concurrent.TimeUnit;
90 import java.util.concurrent.TimeoutException;
91 import java.util.function.Consumer;
92 
93 /**
94  * Tests {@link RoleManager}.
95  */
96 @RunWith(BedsteadJUnit4.class)
97 public class RoleManagerTest {
98 
99     private static final long TIMEOUT_MILLIS = 15 * 1000;
100 
101     private static final long UNEXPECTED_TIMEOUT_MILLIS = 1000;
102 
103     private static final String ROLE_NAME = RoleManager.ROLE_BROWSER;
104     private static final String ROLE_PHONE_NAME = RoleManager.ROLE_DIALER;
105     private static final String ROLE_SMS_NAME = RoleManager.ROLE_SMS;
106     private static final String ROLE_SHORT_LABEL = "Browser app";
107 
108     private static final String APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk";
109     private static final String APP_PACKAGE_NAME = "android.app.role.cts.app";
110     private static final String APP_LABEL = "CtsRoleTestApp";
111     private static final String APP_FOR_PROFILE_APK_PATH =
112             "/data/local/tmp/cts-role/CtsRoleTestAppForProfile.apk";
113     private static final String APP_FOR_PROFILE_PACKAGE_NAME = "android.app.role.cts.appForProfile";
114     private static final String APP_FOR_PROFILE = "CtsRoleTestAppForProfile";
115     private static final String APP_IS_ROLE_HELD_ACTIVITY_NAME = APP_PACKAGE_NAME
116             + ".IsRoleHeldActivity";
117     private static final String APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD = APP_PACKAGE_NAME
118             + ".extra.IS_ROLE_HELD";
119     private static final String APP_REQUEST_ROLE_ACTIVITY_NAME = APP_PACKAGE_NAME
120             + ".RequestRoleActivity";
121     private static final String APP_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME = APP_PACKAGE_NAME
122             + ".ChangeDefaultDialerActivity";
123     private static final String APP_CHANGE_DEFAULT_SMS_ACTIVITY_NAME = APP_PACKAGE_NAME
124             + ".ChangeDefaultSmsActivity";
125 
126     private static final String APP_28_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp28.apk";
127     private static final String APP_28_PACKAGE_NAME = "android.app.role.cts.app28";
128     private static final String APP_28_LABEL = "CtsRoleTestApp28";
129     private static final String APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME = APP_28_PACKAGE_NAME
130             + ".ChangeDefaultDialerActivity";
131     private static final String APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME = APP_28_PACKAGE_NAME
132             + ".ChangeDefaultSmsActivity";
133 
134     private static final String APP_33_WITHOUT_INCALLSERVICE_APK_PATH =
135             "/data/local/tmp/cts-role/CtsRoleTestApp33WithoutInCallService.apk";
136     private static final String APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME =
137             "android.app.role.cts.app33WithoutInCallService";
138 
139     private static final String PERMISSION_MANAGE_ROLES_FROM_CONTROLLER =
140             "com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER";
141 
142     private static final Instrumentation sInstrumentation =
143             InstrumentationRegistry.getInstrumentation();
144     private static final Context sContext = InstrumentationRegistry.getTargetContext();
145     private static final PackageManager sPackageManager = sContext.getPackageManager();
146     private static final RoleManager sRoleManager = sContext.getSystemService(RoleManager.class);
147     private static final boolean sIsAutomotive = sPackageManager.hasSystemFeature(
148             PackageManager.FEATURE_AUTOMOTIVE);
149     private static final boolean sIsTelevision = sPackageManager.hasSystemFeature(
150             PackageManager.FEATURE_TELEVISION);
151     private static final boolean sIsWatch = sPackageManager.hasSystemFeature(
152             PackageManager.FEATURE_WATCH);
153 
154     private static final BySelector ENHANCED_CONFIRMATION_DIALOG_SELECTOR =
155             By.res("com.android.permissioncontroller:id/enhanced_confirmation_dialog_title");
156     // TODO(b/327528959): consider using resource selectors for Wear too, once the underlying
157     // issue is handled.
158     private static final BySelector NEGATIVE_BUTTON_SELECTOR =
159             sIsWatch ? By.text("Cancel") : By.res("android:id/button2");
160     private static final BySelector POSITIVE_BUTTON_SELECTOR =
161             sIsWatch ? By.text("Set as default") : By.res("android:id/button1");
162     private static final BySelector DONT_ASK_AGAIN_TOGGLE_SELECTOR =
163             sIsWatch
164                     ? By.text("Don\u2019t ask again")
165                     : By.res("com.android.permissioncontroller:id/dont_ask_again");
166 
167     @Rule
168     public CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
169     @Rule
170     public DisableAnimationRule mDisableAnimationRule = new DisableAnimationRule();
171 
172     @Rule
173     public FreezeRotationRule mFreezeRotationRule = new FreezeRotationRule();
174 
175     @Rule
176     public ActivityTestRule<WaitForResultActivity> mActivityRule =
177             new ActivityTestRule<>(WaitForResultActivity.class);
178 
179     @ClassRule
180     @Rule
181     public static final DeviceState sDeviceState = new DeviceState();
182 
183     private String mRoleHolder;
184 
185     @Before
saveRoleHolder()186     public void saveRoleHolder() throws Exception {
187         List<String> roleHolders = getRoleHolders(ROLE_NAME);
188         mRoleHolder = !roleHolders.isEmpty() ? roleHolders.get(0) : null;
189 
190         if (Objects.equals(mRoleHolder, APP_PACKAGE_NAME)) {
191             removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
192             mRoleHolder = null;
193         }
194     }
195 
196     @After
restoreRoleHolder()197     public void restoreRoleHolder() throws Exception {
198         removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
199 
200         if (mRoleHolder != null) {
201             addRoleHolder(ROLE_NAME, mRoleHolder);
202         }
203 
204         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
205     }
206 
207     @Before
installApp()208     public void installApp() throws Exception {
209         installPackage(APP_APK_PATH);
210         installPackage(APP_28_APK_PATH);
211         installPackage(APP_33_WITHOUT_INCALLSERVICE_APK_PATH);
212     }
213 
214     @After
uninstallApp()215     public void uninstallApp() throws Exception {
216         uninstallPackage(APP_PACKAGE_NAME);
217         uninstallPackage(APP_28_PACKAGE_NAME);
218         uninstallPackage(APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME);
219     }
220 
221     @Before
wakeUpScreen()222     public void wakeUpScreen() throws IOException {
223         runShellCommand(sInstrumentation, "input keyevent KEYCODE_WAKEUP");
224     }
225 
226     @Before
closeNotificationShade()227     public void closeNotificationShade() {
228         sContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
229     }
230 
231     @Test
requestRoleIntentHasPermissionControllerPackage()232     public void requestRoleIntentHasPermissionControllerPackage() throws Exception {
233         Intent intent = sRoleManager.createRequestRoleIntent(ROLE_NAME);
234 
235         assertThat(intent.getPackage()).isEqualTo(
236                 sPackageManager.getPermissionControllerPackageName());
237     }
238 
239     @Test
requestRoleIntentHasExtraRoleName()240     public void requestRoleIntentHasExtraRoleName() throws Exception {
241         Intent intent = sRoleManager.createRequestRoleIntent(ROLE_NAME);
242 
243         assertThat(intent.getStringExtra(Intent.EXTRA_ROLE_NAME)).isEqualTo(ROLE_NAME);
244     }
245 
246     @Test
247     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
requestRoleAndDenyThenIsNotRoleHolder()248     public void requestRoleAndDenyThenIsNotRoleHolder() throws Exception {
249         requestRole(ROLE_NAME);
250         respondToRoleRequest(false);
251 
252         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
253     }
254 
255     @Test
256     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
requestRoleAndAllowThenIsRoleHolder()257     public void requestRoleAndAllowThenIsRoleHolder() throws Exception {
258         requestRole(ROLE_NAME);
259         respondToRoleRequest(true);
260 
261         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
262     }
263 
264     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
265             "VanillaIceCream")
266     @Test
267     @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
268     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
requestRoleThenBlockRequestRoleDialogByRestrictedSettingDialog()269     public void requestRoleThenBlockRequestRoleDialogByRestrictedSettingDialog() throws Exception {
270         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
271         assumeFalse(sIsWatch || sIsAutomotive || sIsTelevision);
272         runWithShellPermissionIdentity(
273                 () -> setEnhancedConfirmationRestrictedAppOpMode(sContext, APP_PACKAGE_NAME,
274                         AppOpsManager.MODE_ERRORED));
275 
276         requestRole(ROLE_SMS_NAME);
277         waitFindObject(ENHANCED_CONFIRMATION_DIALOG_SELECTOR, TIMEOUT_MILLIS);
278 
279         pressBack();
280     }
281 
282     @Test
283     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
requestRoleFirstTimeNoDontAskAgain()284     public void requestRoleFirstTimeNoDontAskAgain() throws Exception {
285         requestRole(ROLE_NAME);
286         UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
287 
288         assertThat(dontAskAgainCheck).isNull();
289 
290         respondToRoleRequest(false);
291     }
292 
293     @Test
294     @FlakyTest
requestRoleAndDenyThenHasDontAskAgain()295     public void requestRoleAndDenyThenHasDontAskAgain() throws Exception {
296         requestRole(ROLE_NAME);
297         respondToRoleRequest(false);
298 
299         requestRole(ROLE_NAME);
300         UiObject2 dontAskAgainCheck = findDontAskAgainCheck();
301 
302         assertThat(dontAskAgainCheck).isNotNull();
303 
304         respondToRoleRequest(false);
305     }
306 
307     @Test
308     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
requestRoleAndDenyWithDontAskAgainReturnsCanceled()309     public void requestRoleAndDenyWithDontAskAgainReturnsCanceled() throws Exception {
310         requestRole(ROLE_NAME);
311         respondToRoleRequest(false);
312 
313         requestRole(ROLE_NAME);
314         findDontAskAgainCheck().click();
315         Pair<Integer, Intent> result = clickButtonAndWaitForResult(true);
316 
317         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
318     }
319 
320     @Test
321     @FlakyTest
requestRoleAndDenyWithDontAskAgainThenDeniedAutomatically()322     public void requestRoleAndDenyWithDontAskAgainThenDeniedAutomatically() throws Exception {
323         requestRole(ROLE_NAME);
324         respondToRoleRequest(false);
325 
326         requestRole(ROLE_NAME);
327         findDontAskAgainCheck().click();
328         clickButtonAndWaitForResult(true);
329 
330         requestRole(ROLE_NAME);
331         Pair<Integer, Intent> result = waitForResult();
332 
333         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
334     }
335 
336     @Test
337     @FlakyTest
requestRoleAndDenyWithDontAskAgainAndClearDataThenShowsUiWithoutDontAskAgain()338     public void requestRoleAndDenyWithDontAskAgainAndClearDataThenShowsUiWithoutDontAskAgain()
339             throws Exception {
340         requestRole(ROLE_NAME);
341         respondToRoleRequest(false);
342 
343         requestRole(ROLE_NAME);
344         findDontAskAgainCheck().click();
345         clickButtonAndWaitForResult(true);
346         // Wait for the RequestRoleActivity inside the test app to be removed from our task so that
347         // when the test app is force stopped, our task isn't force finished and our
348         // WaitForResultActivity can survive.
349         Thread.sleep(5000);
350 
351         clearPackageData(APP_PACKAGE_NAME);
352         // Wait for the don't ask again to be forgotten.
353         Thread.sleep(10000);
354 
355         TestUtils.waitUntil("Find and respond to request role UI", () -> {
356             requestRole(ROLE_NAME);
357             UiObject2 cancelButton = waitFindObjectOrNull(NEGATIVE_BUTTON_SELECTOR);
358             if (cancelButton == null) {
359                 // Dialog not found, try again later.
360                 return false;
361             }
362             UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
363 
364             assertThat(dontAskAgainCheck).isNull();
365 
366             respondToRoleRequest(false);
367             return true;
368         });
369     }
370 
371     @Test
372     @FlakyTest
requestRoleAndDenyWithDontAskAgainAndReinstallThenShowsUiWithoutDontAskAgain()373     public void requestRoleAndDenyWithDontAskAgainAndReinstallThenShowsUiWithoutDontAskAgain()
374             throws Exception {
375         requestRole(ROLE_NAME);
376         respondToRoleRequest(false);
377 
378         requestRole(ROLE_NAME);
379         findDontAskAgainCheck().click();
380         clickButtonAndWaitForResult(true);
381         // Wait for the RequestRoleActivity inside the test app to be removed from our task so that
382         // when the test app is uninstalled, our task isn't force finished and our
383         // WaitForResultActivity can survive.
384         Thread.sleep(5000);
385 
386         uninstallPackage(APP_PACKAGE_NAME);
387         // Wait for the don't ask again to be forgotten.
388         Thread.sleep(10000);
389         installPackage(APP_APK_PATH);
390 
391         TestUtils.waitUntil("Find and respond to request role UI", () -> {
392             requestRole(ROLE_NAME);
393             UiObject2 cancelButton = waitFindObjectOrNull(NEGATIVE_BUTTON_SELECTOR);
394             if (cancelButton == null) {
395                 // Dialog not found, try again later.
396                 return false;
397             }
398             UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
399 
400             assertThat(dontAskAgainCheck).isNull();
401 
402             respondToRoleRequest(false);
403             return true;
404         });
405     }
406 
407     @Test
requestInvalidRoleThenDeniedAutomatically()408     public void requestInvalidRoleThenDeniedAutomatically() throws Exception {
409         requestRole("invalid");
410         Pair<Integer, Intent> result = waitForResult();
411 
412         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
413     }
414 
415     @Test
requestUnqualifiedRoleThenDeniedAutomatically()416     public void requestUnqualifiedRoleThenDeniedAutomatically() throws Exception {
417         requestRole(RoleManager.ROLE_HOME);
418         Pair<Integer, Intent> result = waitForResult();
419 
420         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
421     }
422 
423     @Test
requestAssistantRoleThenDeniedAutomatically()424     public void requestAssistantRoleThenDeniedAutomatically() throws Exception {
425         requestRole(RoleManager.ROLE_ASSISTANT);
426         Pair<Integer, Intent> result = waitForResult();
427 
428         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
429     }
430 
431     @Test
432     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
requestHoldingRoleThenAllowedAutomatically()433     public void requestHoldingRoleThenAllowedAutomatically() throws Exception {
434         requestRole(ROLE_NAME);
435         respondToRoleRequest(true);
436 
437         requestRole(ROLE_NAME);
438         Pair<Integer, Intent> result = waitForResult();
439 
440         assertThat(result.first).isEqualTo(Activity.RESULT_OK);
441     }
442 
requestRole(@onNull String roleName)443     private void requestRole(@NonNull String roleName) {
444         Intent intent = new Intent()
445                 .setComponent(new ComponentName(APP_PACKAGE_NAME, APP_REQUEST_ROLE_ACTIVITY_NAME))
446                 .putExtra(Intent.EXTRA_ROLE_NAME, roleName);
447         mActivityRule.getActivity().startActivityToWaitForResult(intent);
448     }
449 
respondToRoleRequest(boolean allow)450     private void respondToRoleRequest(boolean allow)
451             throws InterruptedException, UiObjectNotFoundException {
452         if (allow) {
453             waitFindObject(By.text(APP_LABEL)).click();
454         }
455         Pair<Integer, Intent> result = clickButtonAndWaitForResult(allow);
456         int expectedResult = allow ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
457 
458         assertThat(result.first).isEqualTo(expectedResult);
459     }
460 
461     @Nullable
findDontAskAgainCheck(boolean expected)462     private UiObject2 findDontAskAgainCheck(boolean expected) throws UiObjectNotFoundException {
463         return expected
464                 ? waitFindObject(DONT_ASK_AGAIN_TOGGLE_SELECTOR)
465                 : waitFindObjectOrNull(DONT_ASK_AGAIN_TOGGLE_SELECTOR, UNEXPECTED_TIMEOUT_MILLIS);
466     }
467 
468     @Nullable
findDontAskAgainCheck()469     private UiObject2 findDontAskAgainCheck() throws UiObjectNotFoundException {
470         return findDontAskAgainCheck(true);
471     }
472 
473     @NonNull
clickButtonAndWaitForResult(boolean positive)474     private Pair<Integer, Intent> clickButtonAndWaitForResult(boolean positive)
475             throws InterruptedException, UiObjectNotFoundException {
476         waitFindObject(positive ? POSITIVE_BUTTON_SELECTOR : NEGATIVE_BUTTON_SELECTOR).click();
477         return waitForResult();
478     }
479 
480     @NonNull
waitForResult()481     private Pair<Integer, Intent> waitForResult() throws InterruptedException {
482         return mActivityRule.getActivity().waitForActivityResult(TIMEOUT_MILLIS);
483     }
484 
clearPackageData(@onNull String packageName)485     private void clearPackageData(@NonNull String packageName) {
486         runShellCommand("pm clear --user " + Process.myUserHandle().getIdentifier() + " "
487                 + packageName);
488     }
489 
installPackage(@onNull String apkPath)490     private void installPackage(@NonNull String apkPath) {
491         installPackage(apkPath, Process.myUserHandle());
492     }
493 
installPackage(@onNull String apkPath, UserHandle user)494     private void installPackage(@NonNull String apkPath, UserHandle user) {
495         runShellCommandOrThrow("pm install -r --user " + user.getIdentifier() + " " + apkPath);
496     }
497 
uninstallPackage(@onNull String packageName)498     private void uninstallPackage(@NonNull String packageName) {
499         uninstallPackage(packageName, Process.myUserHandle());
500     }
501 
uninstallPackage(@onNull String packageName, UserHandle user)502     private void uninstallPackage(@NonNull String packageName, UserHandle user) {
503         runShellCommand("pm uninstall --user " + user.getIdentifier() + " " + packageName);
504     }
505 
506     @Test
targetCurrentSdkAndChangeDefaultDialerThenDeniedAutomatically()507     public void targetCurrentSdkAndChangeDefaultDialerThenDeniedAutomatically() throws Exception {
508         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
509 
510         WaitForResultActivity activity = mActivityRule.getActivity();
511         activity.startActivityToWaitForResult(new Intent()
512                 .setComponent(new ComponentName(APP_PACKAGE_NAME,
513                         APP_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
514                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
515         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
516 
517         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
518     }
519 
520     @Test
targetCurrentSdkAndChangeDefaultSmsThenDeniedAutomatically()521     public void targetCurrentSdkAndChangeDefaultSmsThenDeniedAutomatically() throws Exception {
522         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
523 
524         WaitForResultActivity activity = mActivityRule.getActivity();
525         activity.startActivityToWaitForResult(new Intent()
526                 .setComponent(new ComponentName(APP_PACKAGE_NAME,
527                         APP_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
528                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
529         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
530 
531         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
532     }
533 
534     @Test
535     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
targetSdk28AndChangeDefaultDialerAndAllowThenIsDefaultDialer()536     public void targetSdk28AndChangeDefaultDialerAndAllowThenIsDefaultDialer() throws Exception {
537         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
538 
539         sContext.startActivity(new Intent()
540                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
541                         APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
542                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_28_PACKAGE_NAME)
543                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
544         waitFindObject(By.text(APP_28_LABEL)).click();
545         waitFindObject(POSITIVE_BUTTON_SELECTOR).click();
546 
547         // TODO(b/149037075): Use TelecomManager.getDefaultDialerPackage() once the bug is fixed.
548         //TelecomManager telecomManager = sContext.getSystemService(TelecomManager.class);
549         //TestUtils.waitUntil("App is not set as default dialer app", () -> Objects.equals(
550         //        telecomManager.getDefaultDialerPackage(), APP_28_PACKAGE_NAME));
551         TestUtils.waitUntil("App is not set as default dialer app", () ->
552                 getRoleHolders(RoleManager.ROLE_DIALER).contains(APP_28_PACKAGE_NAME));
553     }
554 
555     @Test
556     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
targetSdk28AndChangeDefaultSmsAndAllowThenIsDefaultSms()557     public void targetSdk28AndChangeDefaultSmsAndAllowThenIsDefaultSms() throws Exception {
558         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
559 
560         sContext.startActivity(new Intent()
561                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
562                         APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
563                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_28_PACKAGE_NAME)
564                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
565         waitFindObject(By.text(APP_28_LABEL)).click();
566         waitFindObject(POSITIVE_BUTTON_SELECTOR).click();
567 
568         TestUtils.waitUntil("App is not set as default sms app", () -> Objects.equals(
569                 Telephony.Sms.getDefaultSmsPackage(sContext), APP_28_PACKAGE_NAME));
570     }
571 
572     @Test
573     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
targetSdk28AndChangeDefaultDialerForAnotherAppThenDeniedAutomatically()574     public void targetSdk28AndChangeDefaultDialerForAnotherAppThenDeniedAutomatically()
575             throws Exception {
576         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
577 
578         WaitForResultActivity activity = mActivityRule.getActivity();
579         activity.startActivityToWaitForResult(new Intent()
580                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
581                         APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
582                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
583         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
584 
585         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
586     }
587 
588     @Test
589     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
targetSdk28AndChangeDefaultSmsForAnotherAppThenDeniedAutomatically()590     public void targetSdk28AndChangeDefaultSmsForAnotherAppThenDeniedAutomatically()
591             throws Exception {
592         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
593 
594         WaitForResultActivity activity = mActivityRule.getActivity();
595         activity.startActivityToWaitForResult(new Intent()
596                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
597                         APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
598                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
599         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
600 
601         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
602     }
603 
604     @Test
605     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
606     public void
targetSdk28AndChangeDefaultDialerForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultDialer()607     targetSdk28AndChangeDefaultDialerForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultDialer()
608             throws Exception {
609         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
610 
611         addRoleHolder(RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME);
612         sContext.startActivity(new Intent()
613                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
614                         APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
615                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
616                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
617         waitFindObject(By.text(APP_LABEL)).click();
618         waitFindObject(POSITIVE_BUTTON_SELECTOR).click();
619 
620         // TODO(b/149037075): Use TelecomManager.getDefaultDialerPackage() once the bug is fixed.
621         //TelecomManager telecomManager = sContext.getSystemService(TelecomManager.class);
622         //TestUtils.waitUntil("App is not set as default dialer app", () -> Objects.equals(
623         //        telecomManager.getDefaultDialerPackage(), APP_PACKAGE_NAME));
624         TestUtils.waitUntil("App is not set as default dialer app", () ->
625                 getRoleHolders(RoleManager.ROLE_DIALER).contains(APP_PACKAGE_NAME));
626     }
627 
628     @Test
629     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
testHoldDialerRoleRequirementWithInCallServiceAndSdk()630     public void testHoldDialerRoleRequirementWithInCallServiceAndSdk()
631             throws Exception {
632         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
633         // target below sdk 33 without InCallService component can hold dialer role
634         addRoleHolder(
635                 RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME, true);
636         assertIsRoleHolder(
637                 RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME, true);
638         // target sdk 33 without InCallService component cannot hold dialer role
639         addRoleHolder(
640                 RoleManager.ROLE_DIALER, APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME, false);
641         assertIsRoleHolder(
642                 RoleManager.ROLE_DIALER, APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME, false);
643         // target sdk 33 with InCallService component can hold dialer role
644         addRoleHolder(
645                 RoleManager.ROLE_DIALER, APP_PACKAGE_NAME, true);
646         assertIsRoleHolder(
647                 RoleManager.ROLE_DIALER, APP_PACKAGE_NAME, true);
648     }
649 
650     @Test
651     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
652     public void
targetSdk28AndChangeDefaultSmsForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultSms()653     targetSdk28AndChangeDefaultSmsForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultSms()
654             throws Exception {
655         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
656 
657         addRoleHolder(RoleManager.ROLE_SMS, APP_28_PACKAGE_NAME);
658         sContext.startActivity(new Intent()
659                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
660                         APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
661                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
662                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
663         waitFindObject(By.text(APP_LABEL)).click();
664         waitFindObject(POSITIVE_BUTTON_SELECTOR).click();
665 
666         TestUtils.waitUntil("App is not set as default sms app", () -> Objects.equals(
667                 Telephony.Sms.getDefaultSmsPackage(sContext), APP_PACKAGE_NAME));
668     }
669 
670     @Test
671     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppDetailsThenIsNotDefaultApp()672     public void openDefaultAppDetailsThenIsNotDefaultApp() throws Exception {
673         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
674                 Intent.ACTION_MANAGE_DEFAULT_APP)
675                 .addCategory(Intent.CATEGORY_DEFAULT)
676                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
677                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
678                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
679 
680         if (sIsWatch) {
681             waitFindObject(By.clickable(true).checked(false).hasDescendant(By.text(APP_LABEL)));
682         } else {
683             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
684                     .hasDescendant(By.text(APP_LABEL)));
685         }
686 
687         pressBack();
688     }
689 
690     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
691             "VanillaIceCream")
692     @Test
693     @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
694     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppDetailsOnHandHeldThenRestrictedAppIsNotSelectableAsDefaultApp()695     public void openDefaultAppDetailsOnHandHeldThenRestrictedAppIsNotSelectableAsDefaultApp()
696             throws Exception {
697         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
698         assumeFalse(sIsWatch || sIsAutomotive || sIsTelevision);
699         runWithShellPermissionIdentity(
700                 () -> setEnhancedConfirmationRestrictedAppOpMode(sContext, APP_PACKAGE_NAME,
701                         AppOpsManager.MODE_ERRORED));
702 
703         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
704                 Intent.ACTION_MANAGE_DEFAULT_APP)
705                 .addCategory(Intent.CATEGORY_DEFAULT)
706                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_PHONE_NAME)
707                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
708                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
709 
710         waitFindObject(By.text(APP_LABEL).enabled(false)).clickAndWait(Until.newWindow(),
711                 TIMEOUT_MILLIS);
712 
713         waitFindObject(ENHANCED_CONFIRMATION_DIALOG_SELECTOR, TIMEOUT_MILLIS);
714         pressBack();
715 
716         pressBack();
717     }
718 
719     @Test
720     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppDetailsAndSetDefaultAppThenIsDefaultApp()721     public void openDefaultAppDetailsAndSetDefaultAppThenIsDefaultApp() throws Exception {
722         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
723                 Intent.ACTION_MANAGE_DEFAULT_APP)
724                 .addCategory(Intent.CATEGORY_DEFAULT)
725                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
726                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
727                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
728         waitForIdle();
729         if (sIsWatch) {
730             waitFindObject(By.clickable(true).checked(false).hasDescendant(
731                     By.text(APP_LABEL))).click();
732         } else {
733             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
734                     .hasDescendant(By.text(APP_LABEL))).click();
735         }
736 
737         if (sIsWatch) {
738             waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
739         } else {
740             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
741                     .hasDescendant(By.text(APP_LABEL)));
742         }
743         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
744 
745         pressBack();
746     }
747 
748     @Test
749     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppDetailsAndSetDefaultAppAndSetAnotherThenIsNotDefaultApp()750     public void openDefaultAppDetailsAndSetDefaultAppAndSetAnotherThenIsNotDefaultApp()
751             throws Exception {
752         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
753                 Intent.ACTION_MANAGE_DEFAULT_APP)
754                 .addCategory(Intent.CATEGORY_DEFAULT)
755                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
756                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
757                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
758         waitForIdle();
759         if (sIsWatch) {
760             waitFindObject(By.clickable(true).checked(false).hasDescendant(
761                     By.text(APP_LABEL))).click();
762             waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
763         } else {
764             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
765                     .hasDescendant(By.text(APP_LABEL))).click();
766             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
767                     .hasDescendant(By.text(APP_LABEL)));
768         }
769         waitForIdle();
770         if (sIsWatch) {
771             waitFindObject(By.clickable(true).checked(false)).click();
772         } else {
773             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).enabled(true)
774                     .checked(false))).click();
775         }
776 
777         if (sIsWatch) {
778             waitFindObject(By.clickable(true).checked(false).hasDescendant(By.text(APP_LABEL)));
779         } else {
780             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
781                     .hasDescendant(By.text(APP_LABEL)));
782         }
783         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
784 
785         pressBack();
786     }
787 
788     @Test
789     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppListThenHasDefaultApp()790     public void openDefaultAppListThenHasDefaultApp() throws Exception {
791         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
792                 .addCategory(Intent.CATEGORY_DEFAULT)
793                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
794 
795         waitFindObject(By.text(ROLE_SHORT_LABEL));
796 
797         pressBack();
798     }
799 
800     @FlakyTest
801     @Test
openDefaultAppListThenIsNotDefaultAppInList()802     public void openDefaultAppListThenIsNotDefaultAppInList() throws Exception {
803         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
804                 .addCategory(Intent.CATEGORY_DEFAULT)
805                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
806 
807         assertThat(waitFindObjectOrNull(By.text(APP_LABEL), UNEXPECTED_TIMEOUT_MILLIS))
808                 .isNull();
809 
810         pressBack();
811     }
812 
813     @Test
814     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppListAndSetDefaultAppThenIsDefaultApp()815     public void openDefaultAppListAndSetDefaultAppThenIsDefaultApp() throws Exception {
816         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
817                 .addCategory(Intent.CATEGORY_DEFAULT)
818                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
819         waitForIdle();
820         waitFindObject(By.text(ROLE_SHORT_LABEL)).click();
821         waitForIdle();
822         if (sIsWatch) {
823             waitFindObject(By.clickable(true).checked(false).hasDescendant(
824                     By.text(APP_LABEL))).click();
825         } else {
826             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
827                     .hasDescendant(By.text(APP_LABEL))).click();
828         }
829 
830         if (sIsWatch) {
831             waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
832         } else {
833             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
834                     .hasDescendant(By.text(APP_LABEL)));
835         }
836         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
837 
838         pressBack();
839         pressBack();
840     }
841 
842     @Test
843     @RequiresFlagsEnabled(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE)
844     @EnsureHasPrivateProfile(installInstrumentedApp = OptionalBoolean.TRUE)
845     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
846             codeName = "VanillaIceCream")
847     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppListAndSetDefaultAppThenIsDefaultAppForPrivateSpace()848     public void openDefaultAppListAndSetDefaultAppThenIsDefaultAppForPrivateSpace()
849             throws Exception {
850         // Private space is not supported on Watch right now and there are no existing plans yet.
851         if (sIsWatch) {
852             return;
853         }
854 
855         UserHandle privateProfile = sDeviceState.privateProfile().userHandle();
856         assertThat(privateProfile).isNotNull();
857         installPackage(APP_APK_PATH, privateProfile);
858         installPackage(APP_FOR_PROFILE_APK_PATH, privateProfile);
859         addRoleHolderAsUser(ROLE_NAME, APP_FOR_PROFILE_PACKAGE_NAME, privateProfile);
860 
861         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
862                 .addCategory(Intent.CATEGORY_DEFAULT)
863                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
864         waitForIdle();
865 
866         waitFindObject(By.hasDescendant(By.text(APP_FOR_PROFILE))).click();
867 
868         waitForIdle();
869         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
870                     .hasDescendant(By.text(APP_LABEL))).click();
871         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
872                     .hasDescendant(By.text(APP_LABEL)));
873 
874         assertIsRoleHolderAsUser(ROLE_NAME, APP_PACKAGE_NAME, true, privateProfile);
875 
876         pressBack();
877         pressBack();
878 
879         uninstallPackage(APP_PACKAGE_NAME, privateProfile);
880         uninstallPackage(APP_FOR_PROFILE_APK_PATH, privateProfile);
881     }
882 
883     @Test
884     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
openDefaultAppListAndSetDefaultAppThenIsDefaultAppInList()885     public void openDefaultAppListAndSetDefaultAppThenIsDefaultAppInList() throws Exception {
886         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
887                 .addCategory(Intent.CATEGORY_DEFAULT)
888                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
889         waitForIdle();
890         waitFindObject(By.text(ROLE_SHORT_LABEL)).click();
891         waitForIdle();
892         if (sIsWatch) {
893             waitFindObject(By.clickable(true).checked(false).hasDescendant(
894                     By.text(APP_LABEL))).click();
895             waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
896         } else {
897             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
898                     .hasDescendant(By.text(APP_LABEL))).click();
899             waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
900                     .hasDescendant(By.text(APP_LABEL)));
901         }
902         pressBack();
903 
904         waitFindObject(By.text(APP_LABEL));
905 
906         pressBack();
907     }
908 
setEnhancedConfirmationRestrictedAppOpMode(@onNull Context context, @NonNull String packageName, int mode)909     private void setEnhancedConfirmationRestrictedAppOpMode(@NonNull Context context,
910             @NonNull String packageName, int mode)
911             throws PackageManager.NameNotFoundException {
912         AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
913         appOpsManager.setMode(AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS,
914                 context.getPackageManager().getApplicationInfo(packageName, 0).uid,
915                 packageName, mode);
916     }
917 
waitForIdle()918     private static void waitForIdle() {
919         UiAutomatorUtils.getUiDevice().waitForIdle();
920     }
921 
pressBack()922     private static void pressBack() {
923         UiAutomatorUtils.getUiDevice().pressBack();
924         waitForIdle();
925     }
926 
927     @Test
roleIsAvailable()928     public void roleIsAvailable() {
929         assertThat(sRoleManager.isRoleAvailable(ROLE_NAME)).isTrue();
930     }
931 
932     @Test
dontAddRoleHolderThenRoleIsNotHeld()933     public void dontAddRoleHolderThenRoleIsNotHeld() throws Exception {
934         assertRoleIsHeld(ROLE_NAME, false);
935     }
936 
937     @Test
addRoleHolderThenRoleIsHeld()938     public void addRoleHolderThenRoleIsHeld() throws Exception {
939         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
940 
941         assertRoleIsHeld(ROLE_NAME, true);
942     }
943 
944     @Test
addAndRemoveRoleHolderThenRoleIsNotHeld()945     public void addAndRemoveRoleHolderThenRoleIsNotHeld() throws Exception {
946         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
947         removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
948 
949         assertRoleIsHeld(ROLE_NAME, false);
950     }
951 
assertRoleIsHeld(@onNull String roleName, boolean isHeld)952     private void assertRoleIsHeld(@NonNull String roleName, boolean isHeld)
953             throws InterruptedException {
954         Intent intent = new Intent()
955                 .setComponent(new ComponentName(APP_PACKAGE_NAME, APP_IS_ROLE_HELD_ACTIVITY_NAME))
956                 .putExtra(Intent.EXTRA_ROLE_NAME, roleName);
957         WaitForResultActivity activity = mActivityRule.getActivity();
958         activity.startActivityToWaitForResult(intent);
959         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
960 
961         assertThat(result.first).isEqualTo(Activity.RESULT_OK);
962         assertThat(result.second).isNotNull();
963         assertThat(result.second.hasExtra(APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD)).isTrue();
964         assertThat(result.second.getBooleanExtra(APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD, false))
965                 .isEqualTo(isHeld);
966     }
967 
968     @Test
dontAddRoleHolderThenIsNotRoleHolder()969     public void dontAddRoleHolderThenIsNotRoleHolder() throws Exception {
970         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
971     }
972 
973     @Test
addRoleHolderThenIsRoleHolder()974     public void addRoleHolderThenIsRoleHolder() throws Exception {
975         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
976 
977         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
978     }
979 
980     @Test
addAndRemoveRoleHolderThenIsNotRoleHolder()981     public void addAndRemoveRoleHolderThenIsNotRoleHolder() throws Exception {
982         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
983         removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
984 
985         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
986     }
987 
988     @Test
addAndClearRoleHoldersThenIsNotRoleHolder()989     public void addAndClearRoleHoldersThenIsNotRoleHolder() throws Exception {
990         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
991         clearRoleHolders(ROLE_NAME);
992 
993         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
994     }
995 
996     @Test
addInvalidRoleHolderThenFails()997     public void addInvalidRoleHolderThenFails() throws Exception {
998         addRoleHolder("invalid", APP_PACKAGE_NAME, false);
999     }
1000 
1001     @Test
addUnqualifiedRoleHolderThenFails()1002     public void addUnqualifiedRoleHolderThenFails() throws Exception {
1003         addRoleHolder(RoleManager.ROLE_HOME, APP_PACKAGE_NAME, false);
1004     }
1005 
1006     @Test
removeInvalidRoleHolderThenFails()1007     public void removeInvalidRoleHolderThenFails() throws Exception {
1008         removeRoleHolder("invalid", APP_PACKAGE_NAME, false);
1009     }
1010 
1011     @Test
clearInvalidRoleHoldersThenFails()1012     public void clearInvalidRoleHoldersThenFails() throws Exception {
1013         clearRoleHolders("invalid", false);
1014     }
1015 
1016     @Test
addOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotified()1017     public void addOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotified() throws Exception {
1018         assertOnRoleHoldersChangedListenerIsNotified(() -> addRoleHolder(ROLE_NAME,
1019                 APP_PACKAGE_NAME));
1020     }
1021 
1022     @Test
addOnRoleHoldersChangedListenerAndRemoveRoleHolderThenIsNotified()1023     public void addOnRoleHoldersChangedListenerAndRemoveRoleHolderThenIsNotified()
1024             throws Exception {
1025         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
1026 
1027         assertOnRoleHoldersChangedListenerIsNotified(() -> removeRoleHolder(ROLE_NAME,
1028                 APP_PACKAGE_NAME));
1029     }
1030 
1031     @Test
addOnRoleHoldersChangedListenerAndClearRoleHoldersThenIsNotified()1032     public void addOnRoleHoldersChangedListenerAndClearRoleHoldersThenIsNotified()
1033             throws Exception {
1034         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
1035 
1036         assertOnRoleHoldersChangedListenerIsNotified(() -> clearRoleHolders(ROLE_NAME));
1037     }
1038 
assertOnRoleHoldersChangedListenerIsNotified(@onNull ThrowingRunnable runnable)1039     private void assertOnRoleHoldersChangedListenerIsNotified(@NonNull ThrowingRunnable runnable)
1040             throws Exception {
1041         ListenerFuture future = new ListenerFuture();
1042         UserHandle user = Process.myUserHandle();
1043         runWithShellPermissionIdentity(() -> sRoleManager.addOnRoleHoldersChangedListenerAsUser(
1044                 sContext.getMainExecutor(), future, user));
1045         Pair<String, UserHandle> result;
1046         try {
1047             runnable.run();
1048             result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
1049         } finally {
1050             runWithShellPermissionIdentity(() ->
1051                     sRoleManager.removeOnRoleHoldersChangedListenerAsUser(future, user));
1052         }
1053 
1054         assertThat(result.first).isEqualTo(ROLE_NAME);
1055         assertThat(result.second).isEqualTo(user);
1056     }
1057 
1058     @Test
addAndRemoveOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotNotified()1059     public void addAndRemoveOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotNotified()
1060             throws Exception {
1061         ListenerFuture future = new ListenerFuture();
1062         UserHandle user = Process.myUserHandle();
1063         runWithShellPermissionIdentity(() -> {
1064             sRoleManager.addOnRoleHoldersChangedListenerAsUser(sContext.getMainExecutor(), future,
1065                     user);
1066             sRoleManager.removeOnRoleHoldersChangedListenerAsUser(future, user);
1067         });
1068         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
1069 
1070         try {
1071             future.get(UNEXPECTED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
1072         } catch (TimeoutException e) {
1073             // Expected
1074             return;
1075         }
1076         throw new AssertionError("OnRoleHoldersChangedListener was notified after removal");
1077     }
1078 
1079     @Test
setRoleNamesFromControllerShouldRequireManageRolesFromControllerPermission()1080     public void setRoleNamesFromControllerShouldRequireManageRolesFromControllerPermission() {
1081         assertRequiresManageRolesFromControllerPermission(
1082                 () -> sRoleManager.setRoleNamesFromController(Collections.emptyList()),
1083                 "setRoleNamesFromController");
1084     }
1085 
1086     @Test
addRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission()1087     public void addRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission() {
1088         assertRequiresManageRolesFromControllerPermission(
1089                 () -> sRoleManager.addRoleHolderFromController(ROLE_NAME, APP_PACKAGE_NAME),
1090                 "addRoleHolderFromController");
1091     }
1092 
1093     @Test
removeRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission()1094     public void removeRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission() {
1095         assertRequiresManageRolesFromControllerPermission(
1096                 () -> sRoleManager.removeRoleHolderFromController(ROLE_NAME, APP_PACKAGE_NAME),
1097                 "removeRoleHolderFromController");
1098     }
1099 
1100     @Test
getHeldRolesFromControllerShouldRequireManageRolesFromControllerPermission()1101     public void getHeldRolesFromControllerShouldRequireManageRolesFromControllerPermission() {
1102         assertRequiresManageRolesFromControllerPermission(
1103                 () -> sRoleManager.getHeldRolesFromController(APP_PACKAGE_NAME),
1104                 "getHeldRolesFromController");
1105     }
1106 
assertRequiresManageRolesFromControllerPermission(@onNull Runnable runnable, @NonNull String methodName)1107     private void assertRequiresManageRolesFromControllerPermission(@NonNull Runnable runnable,
1108             @NonNull String methodName) {
1109         try {
1110             runnable.run();
1111         } catch (SecurityException e) {
1112             if (e.getMessage().contains(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)) {
1113                 // Expected
1114                 return;
1115             }
1116             throw e;
1117         }
1118         fail("RoleManager." + methodName + "() should require "
1119                 + PERMISSION_MANAGE_ROLES_FROM_CONTROLLER);
1120     }
1121 
1122     @Test
manageRolesFromControllerPermissionShouldBeDeclaredByPermissionController()1123     public void manageRolesFromControllerPermissionShouldBeDeclaredByPermissionController()
1124             throws PackageManager.NameNotFoundException {
1125         PermissionInfo permissionInfo = sPackageManager.getPermissionInfo(
1126                 PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 0);
1127 
1128         assertThat(permissionInfo.packageName).isEqualTo(
1129                 sPackageManager.getPermissionControllerPackageName());
1130         assertThat(permissionInfo.getProtection()).isEqualTo(PermissionInfo.PROTECTION_SIGNATURE);
1131         assertThat(permissionInfo.getProtectionFlags()).isEqualTo(0);
1132     }
1133 
1134     @Test
smsRoleHasHolder()1135     public void smsRoleHasHolder() throws Exception {
1136         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1137 
1138         assertThat(getRoleHolders(RoleManager.ROLE_SMS)).isNotEmpty();
1139     }
1140 
1141     @Test
addSmsRoleHolderThenPermissionIsGranted()1142     public void addSmsRoleHolderThenPermissionIsGranted() throws Exception {
1143         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1144 
1145         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
1146 
1147         assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
1148                 APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_GRANTED);
1149     }
1150 
1151     @Test
removeSmsRoleHolderThenPermissionIsRevoked()1152     public void removeSmsRoleHolderThenPermissionIsRevoked() throws Exception {
1153         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1154 
1155         String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
1156         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
1157         addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
1158 
1159         assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
1160                 APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_DENIED);
1161     }
1162 
1163     @Test
removeSmsRoleHolderThenDialerRolePermissionIsRetained()1164     public void removeSmsRoleHolderThenDialerRolePermissionIsRetained() throws Exception {
1165         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER)
1166                 && sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1167 
1168         addRoleHolder(RoleManager.ROLE_DIALER, APP_PACKAGE_NAME);
1169         String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
1170         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
1171         addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
1172 
1173         assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
1174                 APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_GRANTED);
1175     }
1176 
1177     @Test
packageManagerGetDefaultBrowserBackedByRole()1178     public void packageManagerGetDefaultBrowserBackedByRole() throws Exception {
1179         addRoleHolder(RoleManager.ROLE_BROWSER, APP_PACKAGE_NAME);
1180 
1181         assertThat(sPackageManager.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId()))
1182                 .isEqualTo(APP_PACKAGE_NAME);
1183     }
1184 
1185     @Test
1186     @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
packageManagerSetDefaultBrowserBackedByRole()1187     public void packageManagerSetDefaultBrowserBackedByRole() throws Exception {
1188         callWithShellPermissionIdentity(() -> sPackageManager.setDefaultBrowserPackageNameAsUser(
1189                 APP_PACKAGE_NAME, UserHandle.myUserId()));
1190 
1191         assertIsRoleHolder(RoleManager.ROLE_BROWSER, APP_PACKAGE_NAME, true);
1192     }
1193 
1194     @Test
telephonySmsGetDefaultSmsPackageBackedByRole()1195     public void telephonySmsGetDefaultSmsPackageBackedByRole() throws Exception {
1196         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1197 
1198         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
1199 
1200         assertThat(Telephony.Sms.getDefaultSmsPackage(sContext)).isEqualTo(APP_PACKAGE_NAME);
1201     }
1202 
1203     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
1204             codeName = "VanillaIceCream")
1205     @Test
1206     @RequiresFlagsEnabled(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED)
telephonyManagerGetEmergencyAssistancePackageNameBackedByRole()1207     public void telephonyManagerGetEmergencyAssistancePackageNameBackedByRole() throws Exception {
1208         TelephonyManager telephonyManager = sContext.getSystemService(TelephonyManager.class);
1209         List<String> emergencyRoleHolders = getRoleHolders(RoleManager.ROLE_EMERGENCY);
1210 
1211         if (telephonyManager.isVoiceCapable()
1212                 && callWithShellPermissionIdentity(() ->
1213                 telephonyManager.isEmergencyAssistanceEnabled())) {
1214             String emergencyAssistancePackageName = callWithShellPermissionIdentity(() ->
1215                     telephonyManager.getEmergencyAssistancePackageName());
1216             if (emergencyRoleHolders.isEmpty()) {
1217                 assertThat(emergencyAssistancePackageName).isNull();
1218             } else {
1219                 assertThat(emergencyRoleHolders).hasSize(1);
1220                 assertThat(emergencyAssistancePackageName).isEqualTo(emergencyRoleHolders.get(0));
1221             }
1222         } else {
1223             assertThrows(IllegalStateException.class, () ->
1224                     callWithShellPermissionIdentity(() ->
1225                             telephonyManager.getEmergencyAssistancePackageName()));
1226         }
1227     }
1228 
1229     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
1230     @Test
cannotBypassRoleQualificationWithoutPermission()1231     public void cannotBypassRoleQualificationWithoutPermission() throws Exception {
1232         assertThrows(SecurityException.class, () ->
1233                 sRoleManager.setBypassingRoleQualification(true));
1234     }
1235 
1236     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
1237     @Test
bypassRoleQualificationThenCanAddUnqualifiedRoleHolder()1238     public void bypassRoleQualificationThenCanAddUnqualifiedRoleHolder() throws Exception {
1239         assertThat(sRoleManager.isRoleAvailable(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))
1240                 .isTrue();
1241 
1242         runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(true));
1243         try {
1244             assertThat(callWithShellPermissionIdentity(() ->
1245                     sRoleManager.isBypassingRoleQualification())).isTrue();
1246 
1247             // The System Activity Recognizer role requires a system app, so this won't succeed
1248             // without bypassing role qualification.
1249             addRoleHolder(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, APP_PACKAGE_NAME);
1250 
1251             assertThat(getRoleHolders(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))
1252                     .contains(APP_PACKAGE_NAME);
1253         } finally {
1254             runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(false));
1255         }
1256         assertThat(callWithShellPermissionIdentity(() ->
1257                 sRoleManager.isBypassingRoleQualification())).isFalse();
1258     }
1259 
1260     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
1261     @Test
cannotGetDefaultApplicationWithoutPermission()1262     public void cannotGetDefaultApplicationWithoutPermission() throws Exception {
1263         assertThrows(SecurityException.class, ()->
1264                 sRoleManager.getDefaultApplication(
1265                         RoleManager.ROLE_SMS));
1266     }
1267 
1268     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
1269     @Test
getDefaultApplicationChecksRoles()1270     public void getDefaultApplicationChecksRoles() throws Exception {
1271         runWithShellPermissionIdentity(() ->
1272                 assertThrows(IllegalArgumentException.class, () ->
1273                         sRoleManager.getDefaultApplication(
1274                                 RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER)));
1275     }
1276 
1277     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
1278     @Test
getDefaultApplicationReadsRole()1279     public void getDefaultApplicationReadsRole() throws Exception {
1280         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1281 
1282         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
1283         runWithShellPermissionIdentity(() -> {
1284             assertThat(sRoleManager.getDefaultApplication(RoleManager.ROLE_SMS))
1285                     .isEqualTo(APP_PACKAGE_NAME);
1286         });
1287     }
1288 
1289     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
1290     @Test
cannotSetDefaultApplicationWithoutPermission()1291     public void cannotSetDefaultApplicationWithoutPermission() throws Exception {
1292         CallbackFuture future = new CallbackFuture();
1293         assertThrows(SecurityException.class, ()->
1294                 sRoleManager.setDefaultApplication(
1295                         RoleManager.ROLE_SMS, APP_PACKAGE_NAME, 0,
1296                         sContext.getMainExecutor(), future));
1297     }
1298 
1299     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
1300     @Test
setDefaultApplicationChecksRoles()1301     public void setDefaultApplicationChecksRoles() throws Exception {
1302         CallbackFuture future = new CallbackFuture();
1303         runWithShellPermissionIdentity(() ->
1304                 assertThrows(IllegalArgumentException.class, () ->
1305                           sRoleManager.setDefaultApplication(
1306                                 RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, APP_PACKAGE_NAME, 0,
1307                                 sContext.getMainExecutor(), future)));
1308     }
1309 
1310     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
1311     @Test
setDefaultApplicationSetsRole()1312     public void setDefaultApplicationSetsRole() throws Exception {
1313         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1314 
1315         CallbackFuture future = new CallbackFuture();
1316         runWithShellPermissionIdentity(() -> {
1317             sRoleManager.setDefaultApplication(
1318                     RoleManager.ROLE_SMS, APP_PACKAGE_NAME, 0,
1319                     sContext.getMainExecutor(), future);
1320             assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
1321             assertThat(sRoleManager.getRoleHolders(RoleManager.ROLE_SMS))
1322                     .containsExactly(APP_PACKAGE_NAME);
1323         });
1324     }
1325 
1326     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
1327             codeName = "VanillaIceCream")
1328     @Test
testSetAndGetRoleFallbackEnabled()1329     public void testSetAndGetRoleFallbackEnabled() {
1330         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
1331 
1332         runWithShellPermissionIdentity(() -> {
1333             sRoleManager.setRoleFallbackEnabled(RoleManager.ROLE_SMS, true);
1334             assertThat(sRoleManager.isRoleFallbackEnabled(RoleManager.ROLE_SMS)).isTrue();
1335         });
1336     }
1337 
1338     @NonNull
getRoleHolders(@onNull String roleName)1339     private List<String> getRoleHolders(@NonNull String roleName) throws Exception {
1340         return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName));
1341     }
1342 
1343     @NonNull
getRoleHoldersAsUser(@onNull String roleName, UserHandle userHandle)1344     private List<String> getRoleHoldersAsUser(@NonNull String roleName, UserHandle userHandle)
1345             throws Exception {
1346         return callWithShellPermissionIdentity(
1347                 () -> sRoleManager.getRoleHoldersAsUser(roleName, userHandle));
1348     }
1349 
assertIsRoleHolder(@onNull String roleName, @NonNull String packageName, boolean shouldBeRoleHolder)1350     private void assertIsRoleHolder(@NonNull String roleName, @NonNull String packageName,
1351             boolean shouldBeRoleHolder) throws Exception {
1352         List<String> packageNames = getRoleHolders(roleName);
1353 
1354         if (shouldBeRoleHolder) {
1355             assertThat(packageNames).contains(packageName);
1356         } else {
1357             assertThat(packageNames).doesNotContain(packageName);
1358         }
1359      }
1360 
assertIsRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, boolean shouldBeRoleHolder, UserHandle userHandle)1361     private void assertIsRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
1362             boolean shouldBeRoleHolder, UserHandle userHandle) throws Exception {
1363         List<String> packageNames = getRoleHoldersAsUser(roleName, userHandle);
1364 
1365         if (shouldBeRoleHolder) {
1366             assertThat(packageNames).contains(packageName);
1367         } else {
1368             assertThat(packageNames).doesNotContain(packageName);
1369         }
1370     }
1371 
addRoleHolder(@onNull String roleName, @NonNull String packageName, boolean expectSuccess)1372     private void addRoleHolder(@NonNull String roleName, @NonNull String packageName,
1373             boolean expectSuccess) throws Exception {
1374         addRoleHolderAsUser(roleName, packageName, Process.myUserHandle(), expectSuccess);
1375     }
1376 
addRoleHolder(@onNull String roleName, @NonNull String packageName)1377     private void addRoleHolder(@NonNull String roleName, @NonNull String packageName)
1378             throws Exception {
1379         addRoleHolder(roleName, packageName, true);
1380     }
1381 
addRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, UserHandle userHandle, boolean expectSuccess)1382     private void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
1383             UserHandle userHandle, boolean expectSuccess) throws Exception {
1384         CallbackFuture future = new CallbackFuture();
1385         runWithShellPermissionIdentity(() -> sRoleManager.addRoleHolderAsUser(roleName,
1386                 packageName, 0, userHandle, sContext.getMainExecutor(), future));
1387         assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
1388     }
1389 
addRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, UserHandle userHandle)1390     private void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
1391             UserHandle userHandle) throws Exception {
1392         addRoleHolderAsUser(roleName, packageName, userHandle, true);
1393     }
1394 
removeRoleHolder(@onNull String roleName, @NonNull String packageName, boolean expectSuccess)1395     private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName,
1396             boolean expectSuccess) throws Exception {
1397         CallbackFuture future = new CallbackFuture();
1398         runWithShellPermissionIdentity(() -> sRoleManager.removeRoleHolderAsUser(roleName,
1399                 packageName, 0, Process.myUserHandle(), sContext.getMainExecutor(), future));
1400         assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
1401     }
1402 
removeRoleHolder(@onNull String roleName, @NonNull String packageName)1403     private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName)
1404             throws Exception {
1405         removeRoleHolder(roleName, packageName, true);
1406     }
1407 
clearRoleHolders(@onNull String roleName, boolean expectSuccess)1408     private void clearRoleHolders(@NonNull String roleName, boolean expectSuccess)
1409             throws Exception {
1410         CallbackFuture future = new CallbackFuture();
1411         runWithShellPermissionIdentity(() -> sRoleManager.clearRoleHoldersAsUser(roleName, 0,
1412                 Process.myUserHandle(), sContext.getMainExecutor(), future));
1413         assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
1414     }
1415 
clearRoleHolders(@onNull String roleName)1416     private void clearRoleHolders(@NonNull String roleName) throws Exception {
1417         clearRoleHolders(roleName, true);
1418     }
1419 
1420     private static class ListenerFuture extends CompletableFuture<Pair<String, UserHandle>>
1421             implements OnRoleHoldersChangedListener {
1422 
1423         @Override
onRoleHoldersChanged(@onNull String roleName, @NonNull UserHandle user)1424         public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
1425             complete(new Pair<>(roleName, user));
1426         }
1427     }
1428 
1429     private static class CallbackFuture extends CompletableFuture<Boolean>
1430             implements Consumer<Boolean> {
1431 
1432         @Override
accept(Boolean successful)1433         public void accept(Boolean successful) {
1434             complete(successful);
1435         }
1436     }
1437 }
1438