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