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.runWithShellPermissionIdentity;
22 import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
23 import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObjectOrNull;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.junit.Assert.assertThrows;
28 import static org.junit.Assert.fail;
29 import static org.junit.Assume.assumeTrue;
30 
31 import android.app.Activity;
32 import android.app.Instrumentation;
33 import android.app.role.OnRoleHoldersChangedListener;
34 import android.app.role.RoleManager;
35 import android.content.ComponentName;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.pm.PackageManager;
39 import android.content.pm.PermissionInfo;
40 import android.os.Build;
41 import android.os.Process;
42 import android.os.UserHandle;
43 import android.provider.Settings;
44 import android.provider.Telephony;
45 import android.support.test.uiautomator.By;
46 import android.support.test.uiautomator.BySelector;
47 import android.support.test.uiautomator.UiObject2;
48 import android.support.test.uiautomator.UiObjectNotFoundException;
49 import android.util.Pair;
50 
51 import androidx.annotation.NonNull;
52 import androidx.annotation.Nullable;
53 import androidx.test.InstrumentationRegistry;
54 import androidx.test.filters.SdkSuppress;
55 import androidx.test.rule.ActivityTestRule;
56 import androidx.test.runner.AndroidJUnit4;
57 
58 import com.android.compatibility.common.util.DisableAnimationRule;
59 import com.android.compatibility.common.util.FreezeRotationRule;
60 import com.android.compatibility.common.util.TestUtils;
61 import com.android.compatibility.common.util.ThrowingRunnable;
62 import com.android.compatibility.common.util.UiAutomatorUtils;
63 
64 import org.junit.After;
65 import org.junit.Before;
66 import org.junit.Rule;
67 import org.junit.Test;
68 import org.junit.runner.RunWith;
69 
70 import java.io.IOException;
71 import java.util.Collections;
72 import java.util.List;
73 import java.util.Objects;
74 import java.util.concurrent.CompletableFuture;
75 import java.util.concurrent.TimeUnit;
76 import java.util.concurrent.TimeoutException;
77 import java.util.function.Consumer;
78 
79 /**
80  * Tests {@link RoleManager}.
81  */
82 @RunWith(AndroidJUnit4.class)
83 public class RoleManagerTest {
84 
85     private static final long TIMEOUT_MILLIS = 15 * 1000;
86 
87     private static final long UNEXPECTED_TIMEOUT_MILLIS = 1000;
88 
89     private static final String ROLE_NAME = RoleManager.ROLE_BROWSER;
90     private static final String ROLE_SHORT_LABEL = "Browser app";
91 
92     private static final String APP_APK_PATH = "/data/local/tmp/cts/role/CtsRoleTestApp.apk";
93     private static final String APP_PACKAGE_NAME = "android.app.role.cts.app";
94     private static final String APP_LABEL = "CtsRoleTestApp";
95     private static final String APP_IS_ROLE_HELD_ACTIVITY_NAME = APP_PACKAGE_NAME
96             + ".IsRoleHeldActivity";
97     private static final String APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD = APP_PACKAGE_NAME
98             + ".extra.IS_ROLE_HELD";
99     private static final String APP_REQUEST_ROLE_ACTIVITY_NAME = APP_PACKAGE_NAME
100             + ".RequestRoleActivity";
101     private static final String APP_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME = APP_PACKAGE_NAME
102             + ".ChangeDefaultDialerActivity";
103     private static final String APP_CHANGE_DEFAULT_SMS_ACTIVITY_NAME = APP_PACKAGE_NAME
104             + ".ChangeDefaultSmsActivity";
105 
106     private static final String APP_28_APK_PATH = "/data/local/tmp/cts/role/CtsRoleTestApp28.apk";
107     private static final String APP_28_PACKAGE_NAME = "android.app.role.cts.app28";
108     private static final String APP_28_LABEL = "CtsRoleTestApp28";
109     private static final String APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME = APP_28_PACKAGE_NAME
110             + ".ChangeDefaultDialerActivity";
111     private static final String APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME = APP_28_PACKAGE_NAME
112             + ".ChangeDefaultSmsActivity";
113 
114     private static final String PERMISSION_MANAGE_ROLES_FROM_CONTROLLER =
115             "com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER";
116 
117     private static final Instrumentation sInstrumentation =
118             InstrumentationRegistry.getInstrumentation();
119     private static final Context sContext = InstrumentationRegistry.getTargetContext();
120     private static final PackageManager sPackageManager = sContext.getPackageManager();
121     private static final RoleManager sRoleManager = sContext.getSystemService(RoleManager.class);
122 
123     @Rule
124     public DisableAnimationRule mDisableAnimationRule = new DisableAnimationRule();
125 
126     @Rule
127     public FreezeRotationRule mFreezeRotationRule = new FreezeRotationRule();
128 
129     @Rule
130     public ActivityTestRule<WaitForResultActivity> mActivityRule =
131             new ActivityTestRule<>(WaitForResultActivity.class);
132 
133     private String mRoleHolder;
134 
135     @Before
saveRoleHolder()136     public void saveRoleHolder() throws Exception {
137         List<String> roleHolders = getRoleHolders(ROLE_NAME);
138         mRoleHolder = !roleHolders.isEmpty() ? roleHolders.get(0) : null;
139 
140         if (Objects.equals(mRoleHolder, APP_PACKAGE_NAME)) {
141             removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
142             mRoleHolder = null;
143         }
144     }
145 
146     @After
restoreRoleHolder()147     public void restoreRoleHolder() throws Exception {
148         removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
149 
150         if (mRoleHolder != null) {
151             addRoleHolder(ROLE_NAME, mRoleHolder);
152         }
153 
154         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
155     }
156 
157     @Before
installApp()158     public void installApp() throws Exception {
159         installPackage(APP_APK_PATH);
160         installPackage(APP_28_APK_PATH);
161     }
162 
163     @After
uninstallApp()164     public void uninstallApp() throws Exception {
165         uninstallPackage(APP_PACKAGE_NAME);
166         uninstallPackage(APP_28_PACKAGE_NAME);
167     }
168 
169     @Before
wakeUpScreen()170     public void wakeUpScreen() throws IOException {
171         runShellCommand(sInstrumentation, "input keyevent KEYCODE_WAKEUP");
172     }
173 
174     @Before
closeNotificationShade()175     public void closeNotificationShade() {
176         sContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
177     }
178 
179     @Test
requestRoleIntentHasPermissionControllerPackage()180     public void requestRoleIntentHasPermissionControllerPackage() throws Exception {
181         Intent intent = sRoleManager.createRequestRoleIntent(ROLE_NAME);
182 
183         assertThat(intent.getPackage()).isEqualTo(
184                 sPackageManager.getPermissionControllerPackageName());
185     }
186 
187     @Test
requestRoleIntentHasExtraRoleName()188     public void requestRoleIntentHasExtraRoleName() throws Exception {
189         Intent intent = sRoleManager.createRequestRoleIntent(ROLE_NAME);
190 
191         assertThat(intent.getStringExtra(Intent.EXTRA_ROLE_NAME)).isEqualTo(ROLE_NAME);
192     }
193 
194     @Test
requestRoleAndDenyThenIsNotRoleHolder()195     public void requestRoleAndDenyThenIsNotRoleHolder() throws Exception {
196         requestRole(ROLE_NAME);
197         respondToRoleRequest(false);
198 
199         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
200     }
201 
202     @Test
requestRoleAndAllowThenIsRoleHolder()203     public void requestRoleAndAllowThenIsRoleHolder() throws Exception {
204         requestRole(ROLE_NAME);
205         respondToRoleRequest(true);
206 
207         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
208     }
209 
210     @Test
requestRoleFirstTimeNoDontAskAgain()211     public void requestRoleFirstTimeNoDontAskAgain() throws Exception {
212         requestRole(ROLE_NAME);
213         UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
214 
215         assertThat(dontAskAgainCheck).isNull();
216 
217         respondToRoleRequest(false);
218     }
219 
220     @Test
requestRoleAndDenyThenHasDontAskAgain()221     public void requestRoleAndDenyThenHasDontAskAgain() throws Exception {
222         requestRole(ROLE_NAME);
223         respondToRoleRequest(false);
224 
225         requestRole(ROLE_NAME);
226         UiObject2 dontAskAgainCheck = findDontAskAgainCheck();
227 
228         assertThat(dontAskAgainCheck).isNotNull();
229 
230         respondToRoleRequest(false);
231     }
232 
233     @Test
requestRoleAndDenyWithDontAskAgainReturnsCanceled()234     public void requestRoleAndDenyWithDontAskAgainReturnsCanceled() throws Exception {
235         requestRole(ROLE_NAME);
236         respondToRoleRequest(false);
237 
238         requestRole(ROLE_NAME);
239         findDontAskAgainCheck().click();
240         Pair<Integer, Intent> result = clickButtonAndWaitForResult(true);
241 
242         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
243     }
244 
245     @Test
requestRoleAndDenyWithDontAskAgainThenDeniedAutomatically()246     public void requestRoleAndDenyWithDontAskAgainThenDeniedAutomatically() throws Exception {
247         requestRole(ROLE_NAME);
248         respondToRoleRequest(false);
249 
250         requestRole(ROLE_NAME);
251         findDontAskAgainCheck().click();
252         clickButtonAndWaitForResult(true);
253 
254         requestRole(ROLE_NAME);
255         Pair<Integer, Intent> result = waitForResult();
256 
257         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
258     }
259 
260     @Test
requestRoleAndDenyWithDontAskAgainAndClearDataThenShowsUiWithoutDontAskAgain()261     public void requestRoleAndDenyWithDontAskAgainAndClearDataThenShowsUiWithoutDontAskAgain()
262             throws Exception {
263         requestRole(ROLE_NAME);
264         respondToRoleRequest(false);
265 
266         requestRole(ROLE_NAME);
267         findDontAskAgainCheck().click();
268         clickButtonAndWaitForResult(true);
269         // Wait for the RequestRoleActivity inside the test app to be removed from our task so that
270         // when the test app is force stopped, our task isn't force finished and our
271         // WaitForResultActivity can survive.
272         Thread.sleep(5000);
273 
274         clearPackageData(APP_PACKAGE_NAME);
275         // Wait for the don't ask again to be forgotten.
276         Thread.sleep(5000);
277 
278         TestUtils.waitUntil("Find and respond to request role UI", () -> {
279             requestRole(ROLE_NAME);
280             UiObject2 cancelButton = waitFindObjectOrNull(By.res("android:id/button2"));
281             if (cancelButton == null) {
282                 // Dialog not found, try again later.
283                 return false;
284             }
285             UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
286 
287             assertThat(dontAskAgainCheck).isNull();
288 
289             respondToRoleRequest(false);
290             return true;
291         });
292     }
293 
294     @Test
requestRoleAndDenyWithDontAskAgainAndReinstallThenShowsUiWithoutDontAskAgain()295     public void requestRoleAndDenyWithDontAskAgainAndReinstallThenShowsUiWithoutDontAskAgain()
296             throws Exception {
297         requestRole(ROLE_NAME);
298         respondToRoleRequest(false);
299 
300         requestRole(ROLE_NAME);
301         findDontAskAgainCheck().click();
302         clickButtonAndWaitForResult(true);
303         // Wait for the RequestRoleActivity inside the test app to be removed from our task so that
304         // when the test app is uninstalled, our task isn't force finished and our
305         // WaitForResultActivity can survive.
306         Thread.sleep(5000);
307 
308         uninstallPackage(APP_PACKAGE_NAME);
309         // Wait for the don't ask again to be forgotten.
310         Thread.sleep(5000);
311         installPackage(APP_APK_PATH);
312 
313         TestUtils.waitUntil("Find and respond to request role UI", () -> {
314             requestRole(ROLE_NAME);
315             UiObject2 cancelButton = waitFindObjectOrNull(By.res("android:id/button2"));
316             if (cancelButton == null) {
317                 // Dialog not found, try again later.
318                 return false;
319             }
320             UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
321 
322             assertThat(dontAskAgainCheck).isNull();
323 
324             respondToRoleRequest(false);
325             return true;
326         });
327     }
328 
329     @Test
requestInvalidRoleThenDeniedAutomatically()330     public void requestInvalidRoleThenDeniedAutomatically() throws Exception {
331         requestRole("invalid");
332         Pair<Integer, Intent> result = waitForResult();
333 
334         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
335     }
336 
337     @Test
requestUnqualifiedRoleThenDeniedAutomatically()338     public void requestUnqualifiedRoleThenDeniedAutomatically() throws Exception {
339         requestRole(RoleManager.ROLE_HOME);
340         Pair<Integer, Intent> result = waitForResult();
341 
342         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
343     }
344 
345     @Test
requestAssistantRoleThenDeniedAutomatically()346     public void requestAssistantRoleThenDeniedAutomatically() throws Exception {
347         requestRole(RoleManager.ROLE_ASSISTANT);
348         Pair<Integer, Intent> result = waitForResult();
349 
350         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
351     }
352 
353     @Test
requestHoldingRoleThenAllowedAutomatically()354     public void requestHoldingRoleThenAllowedAutomatically() throws Exception {
355         requestRole(ROLE_NAME);
356         respondToRoleRequest(true);
357 
358         requestRole(ROLE_NAME);
359         Pair<Integer, Intent> result = waitForResult();
360 
361         assertThat(result.first).isEqualTo(Activity.RESULT_OK);
362     }
363 
requestRole(@onNull String roleName)364     private void requestRole(@NonNull String roleName) {
365         Intent intent = new Intent()
366                 .setComponent(new ComponentName(APP_PACKAGE_NAME, APP_REQUEST_ROLE_ACTIVITY_NAME))
367                 .putExtra(Intent.EXTRA_ROLE_NAME, roleName);
368         mActivityRule.getActivity().startActivityToWaitForResult(intent);
369     }
370 
respondToRoleRequest(boolean allow)371     private void respondToRoleRequest(boolean allow)
372             throws InterruptedException, UiObjectNotFoundException {
373         if (allow) {
374             waitFindObject(By.text(APP_LABEL)).click();
375         }
376         Pair<Integer, Intent> result = clickButtonAndWaitForResult(allow);
377         int expectedResult = allow ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
378 
379         assertThat(result.first).isEqualTo(expectedResult);
380     }
381 
382     @Nullable
findDontAskAgainCheck(boolean expected)383     private UiObject2 findDontAskAgainCheck(boolean expected) throws UiObjectNotFoundException {
384         BySelector selector = By.res("com.android.permissioncontroller:id/dont_ask_again");
385         return expected
386                 ? waitFindObject(selector)
387                 : waitFindObjectOrNull(selector, UNEXPECTED_TIMEOUT_MILLIS);
388     }
389 
390     @Nullable
findDontAskAgainCheck()391     private UiObject2 findDontAskAgainCheck() throws UiObjectNotFoundException {
392         return findDontAskAgainCheck(true);
393     }
394 
395     @NonNull
clickButtonAndWaitForResult(boolean positive)396     private Pair<Integer, Intent> clickButtonAndWaitForResult(boolean positive)
397             throws InterruptedException, UiObjectNotFoundException {
398         waitFindObject(By.res(positive ? "android:id/button1" : "android:id/button2")).click();
399         return waitForResult();
400     }
401 
402     @NonNull
waitForResult()403     private Pair<Integer, Intent> waitForResult() throws InterruptedException {
404         return mActivityRule.getActivity().waitForActivityResult(TIMEOUT_MILLIS);
405     }
406 
clearPackageData(@onNull String packageName)407     private void clearPackageData(@NonNull String packageName) {
408         runShellCommand("pm clear --user " + Process.myUserHandle().getIdentifier() + " "
409                 + packageName);
410     }
411 
installPackage(@onNull String apkPath)412     private void installPackage(@NonNull String apkPath) {
413         runShellCommand("pm install -r --user " + Process.myUserHandle().getIdentifier() + " "
414                 + apkPath);
415     }
416 
uninstallPackage(@onNull String packageName)417     private void uninstallPackage(@NonNull String packageName) {
418         runShellCommand("pm uninstall --user " + Process.myUserHandle().getIdentifier() + " "
419                 + packageName);
420     }
421 
422     @Test
targetCurrentSdkAndChangeDefaultDialerThenDeniedAutomatically()423     public void targetCurrentSdkAndChangeDefaultDialerThenDeniedAutomatically() throws Exception {
424         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
425 
426         WaitForResultActivity activity = mActivityRule.getActivity();
427         activity.startActivityToWaitForResult(new Intent()
428                 .setComponent(new ComponentName(APP_PACKAGE_NAME,
429                         APP_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
430                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
431         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
432 
433         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
434     }
435 
436     @Test
targetCurrentSdkAndChangeDefaultSmsThenDeniedAutomatically()437     public void targetCurrentSdkAndChangeDefaultSmsThenDeniedAutomatically() throws Exception {
438         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
439 
440         WaitForResultActivity activity = mActivityRule.getActivity();
441         activity.startActivityToWaitForResult(new Intent()
442                 .setComponent(new ComponentName(APP_PACKAGE_NAME,
443                         APP_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
444                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
445         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
446 
447         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
448     }
449 
450     @Test
targetSdk28AndChangeDefaultDialerAndAllowThenIsDefaultDialer()451     public void targetSdk28AndChangeDefaultDialerAndAllowThenIsDefaultDialer() throws Exception {
452         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
453 
454         sContext.startActivity(new Intent()
455                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
456                         APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
457                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_28_PACKAGE_NAME)
458                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
459         waitFindObject(By.text(APP_28_LABEL)).click();
460         waitFindObject(By.res("android:id/button1")).click();
461 
462         // TODO(b/149037075): Use TelecomManager.getDefaultDialerPackage() once the bug is fixed.
463         //TelecomManager telecomManager = sContext.getSystemService(TelecomManager.class);
464         //TestUtils.waitUntil("App is not set as default dialer app", () -> Objects.equals(
465         //        telecomManager.getDefaultDialerPackage(), APP_28_PACKAGE_NAME));
466         TestUtils.waitUntil("App is not set as default dialer app", () ->
467                 getRoleHolders(RoleManager.ROLE_DIALER).contains(APP_28_PACKAGE_NAME));
468     }
469 
470     @Test
targetSdk28AndChangeDefaultSmsAndAllowThenIsDefaultSms()471     public void targetSdk28AndChangeDefaultSmsAndAllowThenIsDefaultSms() throws Exception {
472         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
473 
474         sContext.startActivity(new Intent()
475                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
476                         APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
477                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_28_PACKAGE_NAME)
478                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
479         waitFindObject(By.text(APP_28_LABEL)).click();
480         waitFindObject(By.res("android:id/button1")).click();
481 
482         TestUtils.waitUntil("App is not set as default sms app", () -> Objects.equals(
483                 Telephony.Sms.getDefaultSmsPackage(sContext), APP_28_PACKAGE_NAME));
484     }
485 
486     @Test
targetSdk28AndChangeDefaultDialerForAnotherAppThenDeniedAutomatically()487     public void targetSdk28AndChangeDefaultDialerForAnotherAppThenDeniedAutomatically()
488             throws Exception {
489         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
490 
491         WaitForResultActivity activity = mActivityRule.getActivity();
492         activity.startActivityToWaitForResult(new Intent()
493                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
494                         APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
495                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
496         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
497 
498         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
499     }
500 
501     @Test
targetSdk28AndChangeDefaultSmsForAnotherAppThenDeniedAutomatically()502     public void targetSdk28AndChangeDefaultSmsForAnotherAppThenDeniedAutomatically()
503             throws Exception {
504         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
505 
506         WaitForResultActivity activity = mActivityRule.getActivity();
507         activity.startActivityToWaitForResult(new Intent()
508                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
509                         APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
510                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
511         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
512 
513         assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
514     }
515 
516     @Test
517     public void
targetSdk28AndChangeDefaultDialerForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultDialer()518     targetSdk28AndChangeDefaultDialerForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultDialer()
519             throws Exception {
520         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
521 
522         addRoleHolder(RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME);
523         sContext.startActivity(new Intent()
524                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
525                         APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
526                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
527                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
528         waitFindObject(By.text(APP_LABEL)).click();
529         waitFindObject(By.res("android:id/button1")).click();
530 
531         // TODO(b/149037075): Use TelecomManager.getDefaultDialerPackage() once the bug is fixed.
532         //TelecomManager telecomManager = sContext.getSystemService(TelecomManager.class);
533         //TestUtils.waitUntil("App is not set as default dialer app", () -> Objects.equals(
534         //        telecomManager.getDefaultDialerPackage(), APP_PACKAGE_NAME));
535         TestUtils.waitUntil("App is not set as default dialer app", () ->
536                 getRoleHolders(RoleManager.ROLE_DIALER).contains(APP_PACKAGE_NAME));
537     }
538 
539     @Test
540     public void
targetSdk28AndChangeDefaultSmsForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultSms()541     targetSdk28AndChangeDefaultSmsForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultSms()
542             throws Exception {
543         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
544 
545         addRoleHolder(RoleManager.ROLE_SMS, APP_28_PACKAGE_NAME);
546         sContext.startActivity(new Intent()
547                 .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
548                         APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
549                 .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
550                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
551         waitFindObject(By.text(APP_LABEL)).click();
552         waitFindObject(By.res("android:id/button1")).click();
553 
554         TestUtils.waitUntil("App is not set as default sms app", () -> Objects.equals(
555                 Telephony.Sms.getDefaultSmsPackage(sContext), APP_PACKAGE_NAME));
556     }
557 
558     @Test
openDefaultAppDetailsThenIsNotDefaultApp()559     public void openDefaultAppDetailsThenIsNotDefaultApp() throws Exception {
560         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
561                 Intent.ACTION_MANAGE_DEFAULT_APP)
562                 .addCategory(Intent.CATEGORY_DEFAULT)
563                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
564                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
565                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
566 
567         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
568                 .hasDescendant(By.text(APP_LABEL)));
569 
570         pressBack();
571     }
572 
573     @Test
openDefaultAppDetailsAndSetDefaultAppThenIsDefaultApp()574     public void openDefaultAppDetailsAndSetDefaultAppThenIsDefaultApp() throws Exception {
575         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
576                 Intent.ACTION_MANAGE_DEFAULT_APP)
577                 .addCategory(Intent.CATEGORY_DEFAULT)
578                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
579                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
580                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
581         waitForIdle();
582         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
583                 .hasDescendant(By.text(APP_LABEL))).click();
584 
585         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
586                 .hasDescendant(By.text(APP_LABEL)));
587         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
588 
589         pressBack();
590     }
591 
592     @Test
openDefaultAppDetailsAndSetDefaultAppAndSetAnotherThenIsNotDefaultApp()593     public void openDefaultAppDetailsAndSetDefaultAppAndSetAnotherThenIsNotDefaultApp()
594             throws Exception {
595         runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
596                 Intent.ACTION_MANAGE_DEFAULT_APP)
597                 .addCategory(Intent.CATEGORY_DEFAULT)
598                 .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
599                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
600                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
601         waitForIdle();
602         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
603                 .hasDescendant(By.text(APP_LABEL))).click();
604         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
605                 .hasDescendant(By.text(APP_LABEL)));
606         waitForIdle();
607         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))).click();
608 
609         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
610                 .hasDescendant(By.text(APP_LABEL)));
611         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
612 
613         pressBack();
614     }
615 
616     @Test
openDefaultAppListThenHasDefaultApp()617     public void openDefaultAppListThenHasDefaultApp() throws Exception {
618         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
619                 .addCategory(Intent.CATEGORY_DEFAULT)
620                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
621 
622         waitFindObject(By.text(ROLE_SHORT_LABEL));
623 
624         pressBack();
625     }
626 
627     @Test
openDefaultAppListThenIsNotDefaultAppInList()628     public void openDefaultAppListThenIsNotDefaultAppInList() throws Exception {
629         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
630                 .addCategory(Intent.CATEGORY_DEFAULT)
631                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
632 
633         assertThat(waitFindObjectOrNull(By.text(APP_LABEL), UNEXPECTED_TIMEOUT_MILLIS))
634                 .isNull();
635 
636         pressBack();
637     }
638 
639     @Test
openDefaultAppListAndSetDefaultAppThenIsDefaultApp()640     public void openDefaultAppListAndSetDefaultAppThenIsDefaultApp() throws Exception {
641         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
642                 .addCategory(Intent.CATEGORY_DEFAULT)
643                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
644         waitForIdle();
645         waitFindObject(By.text(ROLE_SHORT_LABEL)).click();
646         waitForIdle();
647         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
648                 .hasDescendant(By.text(APP_LABEL))).click();
649 
650         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
651                 .hasDescendant(By.text(APP_LABEL)));
652         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
653 
654         pressBack();
655         pressBack();
656     }
657 
658     @Test
openDefaultAppListAndSetDefaultAppThenIsDefaultAppInList()659     public void openDefaultAppListAndSetDefaultAppThenIsDefaultAppInList() throws Exception {
660         sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
661                 .addCategory(Intent.CATEGORY_DEFAULT)
662                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
663         waitForIdle();
664         waitFindObject(By.text(ROLE_SHORT_LABEL)).click();
665         waitForIdle();
666         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
667                 .hasDescendant(By.text(APP_LABEL))).click();
668         waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
669                 .hasDescendant(By.text(APP_LABEL)));
670         pressBack();
671 
672         waitFindObject(By.text(APP_LABEL));
673 
674         pressBack();
675     }
676 
waitForIdle()677     private static void waitForIdle() {
678         UiAutomatorUtils.getUiDevice().waitForIdle();
679     }
680 
pressBack()681     private static void pressBack() {
682         UiAutomatorUtils.getUiDevice().pressBack();
683         waitForIdle();
684     }
685 
686     @Test
roleIsAvailable()687     public void roleIsAvailable() {
688         assertThat(sRoleManager.isRoleAvailable(ROLE_NAME)).isTrue();
689     }
690 
691     @Test
dontAddRoleHolderThenRoleIsNotHeld()692     public void dontAddRoleHolderThenRoleIsNotHeld() throws Exception {
693         assertRoleIsHeld(ROLE_NAME, false);
694     }
695 
696     @Test
addRoleHolderThenRoleIsHeld()697     public void addRoleHolderThenRoleIsHeld() throws Exception {
698         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
699 
700         assertRoleIsHeld(ROLE_NAME, true);
701     }
702 
703     @Test
addAndRemoveRoleHolderThenRoleIsNotHeld()704     public void addAndRemoveRoleHolderThenRoleIsNotHeld() throws Exception {
705         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
706         removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
707 
708         assertRoleIsHeld(ROLE_NAME, false);
709     }
710 
assertRoleIsHeld(@onNull String roleName, boolean isHeld)711     private void assertRoleIsHeld(@NonNull String roleName, boolean isHeld)
712             throws InterruptedException {
713         Intent intent = new Intent()
714                 .setComponent(new ComponentName(APP_PACKAGE_NAME, APP_IS_ROLE_HELD_ACTIVITY_NAME))
715                 .putExtra(Intent.EXTRA_ROLE_NAME, roleName);
716         WaitForResultActivity activity = mActivityRule.getActivity();
717         activity.startActivityToWaitForResult(intent);
718         Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
719 
720         assertThat(result.first).isEqualTo(Activity.RESULT_OK);
721         assertThat(result.second).isNotNull();
722         assertThat(result.second.hasExtra(APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD)).isTrue();
723         assertThat(result.second.getBooleanExtra(APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD, false))
724                 .isEqualTo(isHeld);
725     }
726 
727     @Test
dontAddRoleHolderThenIsNotRoleHolder()728     public void dontAddRoleHolderThenIsNotRoleHolder() throws Exception {
729         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
730     }
731 
732     @Test
addRoleHolderThenIsRoleHolder()733     public void addRoleHolderThenIsRoleHolder() throws Exception {
734         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
735 
736         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
737     }
738 
739     @Test
addAndRemoveRoleHolderThenIsNotRoleHolder()740     public void addAndRemoveRoleHolderThenIsNotRoleHolder() throws Exception {
741         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
742         removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
743 
744         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
745     }
746 
747     @Test
addAndClearRoleHoldersThenIsNotRoleHolder()748     public void addAndClearRoleHoldersThenIsNotRoleHolder() throws Exception {
749         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
750         clearRoleHolders(ROLE_NAME);
751 
752         assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
753     }
754 
755     @Test
addInvalidRoleHolderThenFails()756     public void addInvalidRoleHolderThenFails() throws Exception {
757         addRoleHolder("invalid", APP_PACKAGE_NAME, false);
758     }
759 
760     @Test
addUnqualifiedRoleHolderThenFails()761     public void addUnqualifiedRoleHolderThenFails() throws Exception {
762         addRoleHolder(RoleManager.ROLE_HOME, APP_PACKAGE_NAME, false);
763     }
764 
765     @Test
removeInvalidRoleHolderThenFails()766     public void removeInvalidRoleHolderThenFails() throws Exception {
767         removeRoleHolder("invalid", APP_PACKAGE_NAME, false);
768     }
769 
770     @Test
clearInvalidRoleHoldersThenFails()771     public void clearInvalidRoleHoldersThenFails() throws Exception {
772         clearRoleHolders("invalid", false);
773     }
774 
775     @Test
addOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotified()776     public void addOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotified() throws Exception {
777         assertOnRoleHoldersChangedListenerIsNotified(() -> addRoleHolder(ROLE_NAME,
778                 APP_PACKAGE_NAME));
779     }
780 
781     @Test
addOnRoleHoldersChangedListenerAndRemoveRoleHolderThenIsNotified()782     public void addOnRoleHoldersChangedListenerAndRemoveRoleHolderThenIsNotified()
783             throws Exception {
784         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
785 
786         assertOnRoleHoldersChangedListenerIsNotified(() -> removeRoleHolder(ROLE_NAME,
787                 APP_PACKAGE_NAME));
788     }
789 
790     @Test
addOnRoleHoldersChangedListenerAndClearRoleHoldersThenIsNotified()791     public void addOnRoleHoldersChangedListenerAndClearRoleHoldersThenIsNotified()
792             throws Exception {
793         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
794 
795         assertOnRoleHoldersChangedListenerIsNotified(() -> clearRoleHolders(ROLE_NAME));
796     }
797 
assertOnRoleHoldersChangedListenerIsNotified(@onNull ThrowingRunnable runnable)798     private void assertOnRoleHoldersChangedListenerIsNotified(@NonNull ThrowingRunnable runnable)
799             throws Exception {
800         ListenerFuture future = new ListenerFuture();
801         UserHandle user = Process.myUserHandle();
802         runWithShellPermissionIdentity(() -> sRoleManager.addOnRoleHoldersChangedListenerAsUser(
803                 sContext.getMainExecutor(), future, user));
804         Pair<String, UserHandle> result;
805         try {
806             runnable.run();
807             result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
808         } finally {
809             runWithShellPermissionIdentity(() ->
810                     sRoleManager.removeOnRoleHoldersChangedListenerAsUser(future, user));
811         }
812 
813         assertThat(result.first).isEqualTo(ROLE_NAME);
814         assertThat(result.second).isEqualTo(user);
815     }
816 
817     @Test
addAndRemoveOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotNotified()818     public void addAndRemoveOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotNotified()
819             throws Exception {
820         ListenerFuture future = new ListenerFuture();
821         UserHandle user = Process.myUserHandle();
822         runWithShellPermissionIdentity(() -> {
823             sRoleManager.addOnRoleHoldersChangedListenerAsUser(sContext.getMainExecutor(), future,
824                     user);
825             sRoleManager.removeOnRoleHoldersChangedListenerAsUser(future, user);
826         });
827         addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
828 
829         try {
830             future.get(UNEXPECTED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
831         } catch (TimeoutException e) {
832             // Expected
833             return;
834         }
835         throw new AssertionError("OnRoleHoldersChangedListener was notified after removal");
836     }
837 
838     @Test
setRoleNamesFromControllerShouldRequireManageRolesFromControllerPermission()839     public void setRoleNamesFromControllerShouldRequireManageRolesFromControllerPermission() {
840         assertRequiresManageRolesFromControllerPermission(
841                 () -> sRoleManager.setRoleNamesFromController(Collections.emptyList()),
842                 "setRoleNamesFromController");
843     }
844 
845     @Test
addRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission()846     public void addRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission() {
847         assertRequiresManageRolesFromControllerPermission(
848                 () -> sRoleManager.addRoleHolderFromController(ROLE_NAME, APP_PACKAGE_NAME),
849                 "addRoleHolderFromController");
850     }
851 
852     @Test
removeRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission()853     public void removeRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission() {
854         assertRequiresManageRolesFromControllerPermission(
855                 () -> sRoleManager.removeRoleHolderFromController(ROLE_NAME, APP_PACKAGE_NAME),
856                 "removeRoleHolderFromController");
857     }
858 
859     @Test
getHeldRolesFromControllerShouldRequireManageRolesFromControllerPermission()860     public void getHeldRolesFromControllerShouldRequireManageRolesFromControllerPermission() {
861         assertRequiresManageRolesFromControllerPermission(
862                 () -> sRoleManager.getHeldRolesFromController(APP_PACKAGE_NAME),
863                 "getHeldRolesFromController");
864     }
865 
assertRequiresManageRolesFromControllerPermission(@onNull Runnable runnable, @NonNull String methodName)866     private void assertRequiresManageRolesFromControllerPermission(@NonNull Runnable runnable,
867             @NonNull String methodName) {
868         try {
869             runnable.run();
870         } catch (SecurityException e) {
871             if (e.getMessage().contains(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)) {
872                 // Expected
873                 return;
874             }
875             throw e;
876         }
877         fail("RoleManager." + methodName + "() should require "
878                 + PERMISSION_MANAGE_ROLES_FROM_CONTROLLER);
879     }
880 
881     @Test
manageRolesFromControllerPermissionShouldBeDeclaredByPermissionController()882     public void manageRolesFromControllerPermissionShouldBeDeclaredByPermissionController()
883             throws PackageManager.NameNotFoundException {
884         PermissionInfo permissionInfo = sPackageManager.getPermissionInfo(
885                 PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 0);
886 
887         assertThat(permissionInfo.packageName).isEqualTo(
888                 sPackageManager.getPermissionControllerPackageName());
889         assertThat(permissionInfo.getProtection()).isEqualTo(PermissionInfo.PROTECTION_SIGNATURE);
890         assertThat(permissionInfo.getProtectionFlags()).isEqualTo(0);
891     }
892 
893     @Test
smsRoleHasHolder()894     public void smsRoleHasHolder() throws Exception {
895         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
896 
897         assertThat(getRoleHolders(RoleManager.ROLE_SMS)).isNotEmpty();
898     }
899 
900     @Test
addSmsRoleHolderThenPermissionIsGranted()901     public void addSmsRoleHolderThenPermissionIsGranted() throws Exception {
902         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
903 
904         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
905 
906         assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
907                 APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_GRANTED);
908     }
909 
910     @Test
removeSmsRoleHolderThenPermissionIsRevoked()911     public void removeSmsRoleHolderThenPermissionIsRevoked() throws Exception {
912         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
913 
914         String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
915         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
916         addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
917 
918         assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
919                 APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_DENIED);
920     }
921 
922     @Test
removeSmsRoleHolderThenDialerRolePermissionIsRetained()923     public void removeSmsRoleHolderThenDialerRolePermissionIsRetained() throws Exception {
924         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER)
925                 && sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
926 
927         addRoleHolder(RoleManager.ROLE_DIALER, APP_PACKAGE_NAME);
928         String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
929         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
930         addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
931 
932         assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
933                 APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_GRANTED);
934     }
935 
936     @Test
packageManagerGetDefaultBrowserBackedByRole()937     public void packageManagerGetDefaultBrowserBackedByRole() throws Exception {
938         addRoleHolder(RoleManager.ROLE_BROWSER, APP_PACKAGE_NAME);
939 
940         assertThat(sPackageManager.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId()))
941                 .isEqualTo(APP_PACKAGE_NAME);
942     }
943 
944     @Test
packageManagerSetDefaultBrowserBackedByRole()945     public void packageManagerSetDefaultBrowserBackedByRole() throws Exception {
946         callWithShellPermissionIdentity(() -> sPackageManager.setDefaultBrowserPackageNameAsUser(
947                 APP_PACKAGE_NAME, UserHandle.myUserId()));
948 
949         assertIsRoleHolder(RoleManager.ROLE_BROWSER, APP_PACKAGE_NAME, true);
950     }
951 
952     @Test
telephonySmsGetDefaultSmsPackageBackedByRole()953     public void telephonySmsGetDefaultSmsPackageBackedByRole() throws Exception {
954         assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
955 
956         addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
957 
958         assertThat(Telephony.Sms.getDefaultSmsPackage(sContext)).isEqualTo(APP_PACKAGE_NAME);
959     }
960 
961     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
962     @Test
cannotBypassRoleQualificationWithoutPermission()963     public void cannotBypassRoleQualificationWithoutPermission() throws Exception {
964         assertThrows(SecurityException.class, () ->
965                 sRoleManager.setBypassingRoleQualification(true));
966     }
967 
968     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
969     @Test
bypassRoleQualificationThenCanAddUnqualifiedRoleHolder()970     public void bypassRoleQualificationThenCanAddUnqualifiedRoleHolder() throws Exception {
971         assertThat(sRoleManager.isRoleAvailable(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))
972                 .isTrue();
973 
974         runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(true));
975         try {
976             assertThat(callWithShellPermissionIdentity(() ->
977                     sRoleManager.isBypassingRoleQualification())).isTrue();
978 
979             // The System Activity Recognizer role requires a system app, so this won't succeed
980             // without bypassing role qualification.
981             addRoleHolder(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, APP_PACKAGE_NAME);
982 
983             assertThat(getRoleHolders(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))
984                     .contains(APP_PACKAGE_NAME);
985         } finally {
986             runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(false));
987         }
988         assertThat(callWithShellPermissionIdentity(() ->
989                 sRoleManager.isBypassingRoleQualification())).isFalse();
990     }
991 
992     @NonNull
getRoleHolders(@onNull String roleName)993     private List<String> getRoleHolders(@NonNull String roleName) throws Exception {
994         return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName));
995     }
996 
assertIsRoleHolder(@onNull String roleName, @NonNull String packageName, boolean shouldBeRoleHolder)997     private void assertIsRoleHolder(@NonNull String roleName, @NonNull String packageName,
998             boolean shouldBeRoleHolder) throws Exception {
999         List<String> packageNames = getRoleHolders(roleName);
1000 
1001         if (shouldBeRoleHolder) {
1002             assertThat(packageNames).contains(packageName);
1003         } else {
1004             assertThat(packageNames).doesNotContain(packageName);
1005         }
1006      }
1007 
addRoleHolder(@onNull String roleName, @NonNull String packageName, boolean expectSuccess)1008     private void addRoleHolder(@NonNull String roleName, @NonNull String packageName,
1009             boolean expectSuccess) throws Exception {
1010         CallbackFuture future = new CallbackFuture();
1011         runWithShellPermissionIdentity(() -> sRoleManager.addRoleHolderAsUser(roleName,
1012                 packageName, 0, Process.myUserHandle(), sContext.getMainExecutor(), future));
1013         assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
1014     }
1015 
addRoleHolder(@onNull String roleName, @NonNull String packageName)1016     private void addRoleHolder(@NonNull String roleName, @NonNull String packageName)
1017             throws Exception {
1018         addRoleHolder(roleName, packageName, true);
1019     }
1020 
removeRoleHolder(@onNull String roleName, @NonNull String packageName, boolean expectSuccess)1021     private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName,
1022             boolean expectSuccess) throws Exception {
1023         CallbackFuture future = new CallbackFuture();
1024         runWithShellPermissionIdentity(() -> sRoleManager.removeRoleHolderAsUser(roleName,
1025                 packageName, 0, Process.myUserHandle(), sContext.getMainExecutor(), future));
1026         assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
1027     }
1028 
removeRoleHolder(@onNull String roleName, @NonNull String packageName)1029     private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName)
1030             throws Exception {
1031         removeRoleHolder(roleName, packageName, true);
1032     }
1033 
clearRoleHolders(@onNull String roleName, boolean expectSuccess)1034     private void clearRoleHolders(@NonNull String roleName, boolean expectSuccess)
1035             throws Exception {
1036         CallbackFuture future = new CallbackFuture();
1037         runWithShellPermissionIdentity(() -> sRoleManager.clearRoleHoldersAsUser(roleName, 0,
1038                 Process.myUserHandle(), sContext.getMainExecutor(), future));
1039         assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
1040     }
1041 
clearRoleHolders(@onNull String roleName)1042     private void clearRoleHolders(@NonNull String roleName) throws Exception {
1043         clearRoleHolders(roleName, true);
1044     }
1045 
1046     private static class ListenerFuture extends CompletableFuture<Pair<String, UserHandle>>
1047             implements OnRoleHoldersChangedListener {
1048 
1049         @Override
onRoleHoldersChanged(@onNull String roleName, @NonNull UserHandle user)1050         public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
1051             complete(new Pair<>(roleName, user));
1052         }
1053     }
1054 
1055     private static class CallbackFuture extends CompletableFuture<Boolean>
1056             implements Consumer<Boolean> {
1057 
1058         @Override
accept(Boolean successful)1059         public void accept(Boolean successful) {
1060             complete(successful);
1061         }
1062     }
1063 }
1064