1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.usepermission; 18 19 import static junit.framework.Assert.assertEquals; 20 21 import static org.junit.Assert.fail; 22 23 import android.Manifest; 24 import android.content.ContentValues; 25 import android.content.Context; 26 import android.content.pm.PackageManager; 27 import android.database.Cursor; 28 import android.net.Uri; 29 import android.os.Build; 30 import android.provider.CalendarContract; 31 32 import androidx.test.InstrumentationRegistry; 33 34 import org.junit.Before; 35 import org.junit.Test; 36 37 import java.util.ArrayList; 38 import java.util.Arrays; 39 40 /** 41 * Runtime permission behavior tests for apps targeting API 23 42 */ 43 public class UsePermissionTest23 extends BasePermissionsTest { 44 private static final int REQUEST_CODE_PERMISSIONS = 42; 45 46 private final Context mContext = getInstrumentation().getContext(); 47 48 private boolean mLeanback; 49 private boolean mWatch; 50 51 @Before initialize()52 public void initialize() { 53 PackageManager pm = getInstrumentation().getContext().getPackageManager(); 54 mLeanback = pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); 55 mWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH); 56 } 57 58 @Test testFail()59 public void testFail() throws Exception { 60 fail("Expected"); 61 } 62 63 @Test testKill()64 public void testKill() throws Exception { 65 android.os.Process.killProcess(android.os.Process.myPid()); 66 } 67 68 @Test testDefault()69 public void testDefault() throws Exception { 70 // New permission model is denied by default 71 assertAllPermissionsRevoked(); 72 } 73 74 @Test testGranted()75 public void testGranted() throws Exception { 76 grantPermission(Manifest.permission.READ_CALENDAR); 77 78 // Read/write access should be allowed 79 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 80 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 81 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 82 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 83 final Uri uri = insertCalendarItem(); 84 try (Cursor c = mContext.getContentResolver().query(uri, null, null, null)) { 85 assertEquals(1, c.getCount()); 86 } 87 } 88 89 @Test testInteractiveGrant()90 public void testInteractiveGrant() throws Exception { 91 // Start out without permission 92 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 93 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 94 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 95 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 96 try { 97 insertCalendarItem(); 98 fail(); 99 } catch (SecurityException expected) { 100 } 101 try (Cursor c = mContext.getContentResolver().query( 102 CalendarContract.Calendars.CONTENT_URI, null, null, null)) { 103 fail(); 104 } catch (SecurityException expected) { 105 } 106 107 // Go through normal grant flow 108 BasePermissionActivity.Result result = requestPermissions(new String[] { 109 Manifest.permission.READ_CALENDAR, 110 Manifest.permission.WRITE_CALENDAR}, 111 REQUEST_CODE_PERMISSIONS, 112 BasePermissionActivity.class, 113 () -> { 114 try { 115 clickAllowButton(); 116 getUiDevice().waitForIdle(); 117 } catch (Exception e) { 118 throw new RuntimeException(e); 119 } 120 }); 121 122 assertEquals(REQUEST_CODE_PERMISSIONS, result.requestCode); 123 assertEquals(Manifest.permission.READ_CALENDAR, result.permissions[0]); 124 assertEquals(Manifest.permission.WRITE_CALENDAR, result.permissions[1]); 125 assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[0]); 126 assertEquals(PackageManager.PERMISSION_GRANTED, result.grantResults[1]); 127 128 // We should have permission now! 129 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 130 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 131 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 132 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 133 final Uri uri = insertCalendarItem(); 134 try (Cursor c = mContext.getContentResolver().query(uri, null, null, null)) { 135 assertEquals(1, c.getCount()); 136 } 137 } 138 139 @Test testRuntimeGroupGrantSpecificity()140 public void testRuntimeGroupGrantSpecificity() throws Exception { 141 // Start out without permission 142 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 143 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 144 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 145 .checkSelfPermission(Manifest.permission.READ_CONTACTS)); 146 147 String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS}; 148 149 // request only one permission from the 'contacts' permission group 150 BasePermissionActivity.Result result = requestPermissions(permissions, 151 REQUEST_CODE_PERMISSIONS, 152 BasePermissionActivity.class, 153 () -> { 154 try { 155 clickAllowButton(); 156 getUiDevice().waitForIdle(); 157 } catch (Exception e) { 158 throw new RuntimeException(e); 159 } 160 }); 161 162 // Expect the permission is granted 163 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 164 permissions, new boolean[] {true}); 165 166 // Make sure no undeclared as used permissions are granted 167 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 168 .checkSelfPermission(Manifest.permission.READ_CONTACTS)); 169 } 170 171 @Test testRuntimeGroupGrantExpansion()172 public void testRuntimeGroupGrantExpansion() throws Exception { 173 // Start out without permission 174 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 175 .checkSelfPermission(Manifest.permission.RECEIVE_SMS)); 176 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 177 .checkSelfPermission(Manifest.permission.SEND_SMS)); 178 179 String[] permissions = new String[] {Manifest.permission.RECEIVE_SMS}; 180 181 // request only one permission from the 'SMS' permission group at runtime, 182 // but two from this group are <uses-permission> in the manifest 183 // request only one permission from the 'contacts' permission group 184 BasePermissionActivity.Result result = requestPermissions(permissions, 185 REQUEST_CODE_PERMISSIONS, 186 BasePermissionActivity.class, 187 () -> { 188 try { 189 clickAllowButton(); 190 getUiDevice().waitForIdle(); 191 } catch (Exception e) { 192 throw new RuntimeException(e); 193 } 194 }); 195 196 // Expect the permission is granted 197 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 198 permissions, new boolean[] {true}); 199 200 // We should now have been granted both of the permissions from this group. 201 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 202 .checkSelfPermission(Manifest.permission.SEND_SMS)); 203 } 204 205 @Test testCancelledPermissionRequest()206 public void testCancelledPermissionRequest() throws Exception { 207 // Make sure we don't have the permission 208 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 209 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 210 211 String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS}; 212 213 // Request the permission and cancel the request 214 BasePermissionActivity.Result result = requestPermissions(permissions, 215 REQUEST_CODE_PERMISSIONS, 216 BasePermissionActivity.class, 217 () -> { 218 try { 219 clickDenyButton(); 220 getUiDevice().waitForIdle(); 221 } catch (Exception e) { 222 throw new RuntimeException(e); 223 } 224 }); 225 226 // Expect the permission is not granted 227 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 228 permissions, new boolean[] {false}); 229 } 230 231 @Test testRequestGrantedPermission()232 public void testRequestGrantedPermission() throws Exception { 233 // Make sure we don't have the permission 234 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 235 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 236 237 String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS}; 238 239 // Request the permission and allow it 240 BasePermissionActivity.Result firstResult = requestPermissions(permissions, 241 REQUEST_CODE_PERMISSIONS, 242 BasePermissionActivity.class, () -> { 243 try { 244 clickAllowButton(); 245 getUiDevice().waitForIdle(); 246 } catch (Exception e) { 247 throw new RuntimeException(e); 248 } 249 }); 250 251 // Expect the permission is granted 252 assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS, 253 permissions, new boolean[] {true}); 254 255 // Request the permission and do nothing 256 BasePermissionActivity.Result secondResult = requestPermissions(new String[] { 257 Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 1, 258 BasePermissionActivity.class, null); 259 260 // Expect the permission is granted 261 assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1, 262 permissions, new boolean[] {true}); 263 } 264 265 @Test testDenialWithPrejudice()266 public void testDenialWithPrejudice() throws Exception { 267 // Make sure we don't have the permission 268 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 269 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 270 271 String[] permissions = new String[] {Manifest.permission.WRITE_CONTACTS}; 272 273 // Request the permission and deny it 274 BasePermissionActivity.Result firstResult = requestPermissions( 275 permissions, REQUEST_CODE_PERMISSIONS, 276 BasePermissionActivity.class, () -> { 277 try { 278 clickDenyButton(); 279 getUiDevice().waitForIdle(); 280 } catch (Exception e) { 281 throw new RuntimeException(e); 282 } 283 }); 284 285 // Expect the permission is not granted 286 assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS, 287 permissions, new boolean[] {false}); 288 289 // Request the permission and choose don't ask again 290 BasePermissionActivity.Result secondResult = requestPermissions(new String[] { 291 Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 1, 292 BasePermissionActivity.class, () -> { 293 try { 294 denyWithPrejudice(); 295 getUiDevice().waitForIdle(); 296 } catch (Exception e) { 297 throw new RuntimeException(e); 298 } 299 }); 300 301 // Expect the permission is not granted 302 assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1, 303 permissions, new boolean[] {false}); 304 305 // Request the permission and do nothing 306 BasePermissionActivity.Result thirdResult = requestPermissions(new String[] { 307 Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_PERMISSIONS + 2, 308 BasePermissionActivity.class, null); 309 310 // Expect the permission is not granted 311 assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS + 2, 312 permissions, new boolean[] {false}); 313 } 314 315 @Test testRevokeAffectsWholeGroup_part1()316 public void testRevokeAffectsWholeGroup_part1() throws Exception { 317 // Grant the group 318 grantPermission(Manifest.permission.READ_CALENDAR); 319 320 // Make sure we have the permissions 321 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 322 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 323 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 324 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 325 326 // Revoke the group 327 revokePermission(Manifest.permission.READ_CALENDAR); 328 329 // We just committed a suicide by revoking the permission. See part2 below... 330 } 331 332 @Test testRevokeAffectsWholeGroup_part2()333 public void testRevokeAffectsWholeGroup_part2() throws Exception { 334 // Make sure we don't have the permissions 335 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 336 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 337 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 338 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 339 } 340 341 @Test testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1()342 public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1() throws Exception { 343 // Make sure we don't have the permission 344 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 345 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 346 347 String[] permissions = new String[] {Manifest.permission.READ_CALENDAR}; 348 349 // Request the permission and deny it 350 BasePermissionActivity.Result firstResult = requestPermissions( 351 permissions, REQUEST_CODE_PERMISSIONS, 352 BasePermissionActivity.class, () -> { 353 try { 354 clickDenyButton(); 355 getUiDevice().waitForIdle(); 356 } catch (Exception e) { 357 throw new RuntimeException(e); 358 } 359 }); 360 361 // Expect the permission is not granted 362 assertPermissionRequestResult(firstResult, REQUEST_CODE_PERMISSIONS, 363 permissions, new boolean[] {false}); 364 365 // Request the permission and choose don't ask again 366 BasePermissionActivity.Result secondResult = requestPermissions(new String[] { 367 Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS + 1, 368 BasePermissionActivity.class, () -> { 369 try { 370 denyWithPrejudice(); 371 getUiDevice().waitForIdle(); 372 } catch (Exception e) { 373 throw new RuntimeException(e); 374 } 375 }); 376 377 // Expect the permission is not granted 378 assertPermissionRequestResult(secondResult, REQUEST_CODE_PERMISSIONS + 1, 379 permissions, new boolean[] {false}); 380 381 // Clear the denial with prejudice 382 grantPermission(Manifest.permission.READ_CALENDAR); 383 revokePermission(Manifest.permission.READ_CALENDAR); 384 385 // We just committed a suicide by revoking the permission. See part2 below... 386 } 387 388 @Test testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2()389 public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2() throws Exception { 390 // Make sure we don't have the permission 391 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 392 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 393 394 // Request the permission and allow it 395 BasePermissionActivity.Result thirdResult = requestPermissions(new String[] { 396 Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS + 2, 397 BasePermissionActivity.class, () -> { 398 try { 399 clickAllowButton(); 400 getUiDevice().waitForIdle(); 401 } catch (Exception e) { 402 throw new RuntimeException(e); 403 } 404 }); 405 406 // Make sure the permission is granted 407 assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS + 2, 408 new String[] {Manifest.permission.READ_CALENDAR}, new boolean[] {true}); 409 } 410 411 @Test testRequestNonRuntimePermission()412 public void testRequestNonRuntimePermission() throws Exception { 413 // Make sure we don't have the permission 414 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 415 .checkSelfPermission(Manifest.permission.BIND_PRINT_SERVICE)); 416 417 String[] permissions = new String[] {Manifest.permission.BIND_PRINT_SERVICE}; 418 419 // Request the permission and do nothing 420 BasePermissionActivity.Result result = requestPermissions(permissions, 421 REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, null); 422 423 // Expect the permission is not granted 424 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 425 permissions, new boolean[] {false}); 426 } 427 428 @Test testRequestNonExistentPermission()429 public void testRequestNonExistentPermission() throws Exception { 430 // Make sure we don't have the permission 431 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 432 .checkSelfPermission("permission.does.not.exist")); 433 434 String[] permissions = new String[] {"permission.does.not.exist"}; 435 436 // Request the permission and do nothing 437 BasePermissionActivity.Result result = requestPermissions(permissions, 438 REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, null); 439 440 // Expect the permission is not granted 441 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 442 permissions, new boolean[] {false}); 443 } 444 445 @Test testRequestPermissionFromTwoGroups()446 public void testRequestPermissionFromTwoGroups() throws Exception { 447 // Make sure we don't have the permissions 448 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 449 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 450 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 451 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 452 453 String[] permissions = new String[] { 454 Manifest.permission.WRITE_CONTACTS, 455 Manifest.permission.WRITE_CALENDAR 456 }; 457 458 // Request the permission and allow it 459 BasePermissionActivity.Result result = requestPermissions(permissions, 460 REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, () -> { 461 try { 462 clickAllowButton(); 463 getUiDevice().waitForIdle(); 464 clickAllowButton(); 465 getUiDevice().waitForIdle(); 466 } catch (Exception e) { 467 throw new RuntimeException(e); 468 } 469 }); 470 471 // Expect the permission are reported as granted 472 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 473 permissions, new boolean[] {true, true}); 474 475 // The permissions are granted 476 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 477 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 478 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 479 .checkSelfPermission(Manifest.permission.WRITE_CALENDAR)); 480 481 // In API < N_MR1 all permissions of a group are granted. I.e. the grant was "expanded" 482 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 483 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 484 485 // Even the contacts group was expanded, the read-calendar permission is not in the 486 // manifest, hence not granted. 487 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 488 .checkSelfPermission(Manifest.permission.READ_CONTACTS)); 489 } 490 491 @Test testNoResidualPermissionsOnUninstall_part1()492 public void testNoResidualPermissionsOnUninstall_part1() throws Exception { 493 ArrayList<String> perms = new ArrayList<>(Arrays.asList( 494 Manifest.permission.WRITE_CALENDAR, 495 Manifest.permission.WRITE_CONTACTS, 496 Manifest.permission.READ_SMS, 497 Manifest.permission.CALL_PHONE, 498 Manifest.permission.RECORD_AUDIO, 499 Manifest.permission.BODY_SENSORS, 500 Manifest.permission.CAMERA 501 )); 502 503 perms.add(Manifest.permission.READ_EXTERNAL_STORAGE); 504 505 // Grant all permissions 506 grantPermissions(perms.toArray(new String[perms.size()])); 507 508 // Don't use UI for granting location permission as this shows another dialog 509 String packageName = InstrumentationRegistry.getTargetContext().getPackageName(); 510 getInstrumentation().getUiAutomation().grantRuntimePermission(packageName, 511 Manifest.permission.ACCESS_FINE_LOCATION); 512 getInstrumentation().getUiAutomation().grantRuntimePermission(packageName, 513 Manifest.permission.ACCESS_COARSE_LOCATION); 514 getInstrumentation().getUiAutomation().grantRuntimePermission(packageName, 515 Manifest.permission.ACCESS_BACKGROUND_LOCATION); 516 } 517 518 @Test testNoResidualPermissionsOnUninstall_part2()519 public void testNoResidualPermissionsOnUninstall_part2() throws Exception { 520 // Make no permissions are granted after uninstalling and installing the app 521 assertAllPermissionsRevoked(); 522 } 523 524 @Test testRevokePropagatedOnUpgradeOldToNewModel_part2()525 public void testRevokePropagatedOnUpgradeOldToNewModel_part2() throws Exception { 526 assertPermissionsGrantState(new String[] {Manifest.permission.WRITE_CALENDAR}, 527 PackageManager.PERMISSION_DENIED); 528 } 529 530 @Test testRevokePropagatedOnUpgradeNewToNewModel_part1()531 public void testRevokePropagatedOnUpgradeNewToNewModel_part1() throws Exception { 532 // Make sure we don't have the permission 533 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 534 .checkSelfPermission(Manifest.permission.READ_CALENDAR)); 535 536 // Request the permission and allow it 537 BasePermissionActivity.Result thirdResult = requestPermissions(new String[] { 538 Manifest.permission.READ_CALENDAR}, REQUEST_CODE_PERMISSIONS, 539 BasePermissionActivity.class, () -> { 540 try { 541 clickAllowButton(); 542 getUiDevice().waitForIdle(); 543 } catch (Exception e) { 544 throw new RuntimeException(e); 545 } 546 }); 547 548 // Make sure the permission is granted 549 assertPermissionRequestResult(thirdResult, REQUEST_CODE_PERMISSIONS, 550 new String[] {Manifest.permission.READ_CALENDAR}, new boolean[] {true}); 551 } 552 553 @Test testRevokePropagatedOnUpgradeNewToNewModel_part2()554 public void testRevokePropagatedOnUpgradeNewToNewModel_part2() throws Exception { 555 // Make sure the permission is still granted after the upgrade 556 assertPermissionsGrantState(new String[] {Manifest.permission.READ_CALENDAR}, 557 PackageManager.PERMISSION_GRANTED); 558 // Also make sure one of the not granted permissions is still not granted 559 assertPermissionsGrantState(new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, 560 PackageManager.PERMISSION_DENIED); 561 } 562 563 @Test testAllPermissionsGrantedOnUpgrade()564 public void testAllPermissionsGrantedOnUpgrade() throws Exception { 565 assertAllPermissionsGrantState(PackageManager.PERMISSION_GRANTED); 566 } 567 568 @Test testNullPermissionRequest()569 public void testNullPermissionRequest() throws Exception { 570 String[] permissions = new String[] {null}; 571 572 // Go through normal grant flow 573 BasePermissionActivity.Result result = requestPermissions(permissions, 574 REQUEST_CODE_PERMISSIONS, 575 BasePermissionActivity.class, 576 () -> { /* empty */ }); 577 578 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 579 permissions, new boolean[] {false}); 580 } 581 582 @Test testNullAndRealPermission()583 public void testNullAndRealPermission() throws Exception { 584 // Make sure we don't have the permissions 585 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 586 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 587 assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext() 588 .checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)); 589 590 String[] permissions = new String[] { 591 null, 592 Manifest.permission.WRITE_CONTACTS, 593 null, 594 Manifest.permission.RECORD_AUDIO 595 }; 596 597 // Request the permission and allow it 598 BasePermissionActivity.Result result = requestPermissions(permissions, 599 REQUEST_CODE_PERMISSIONS, BasePermissionActivity.class, () -> { 600 try { 601 clickAllowButton(); 602 getUiDevice().waitForIdle(); 603 clickAllowButton(); 604 getUiDevice().waitForIdle(); 605 } catch (Exception e) { 606 throw new RuntimeException(e); 607 } 608 }); 609 610 // Expect the permission are reported as granted 611 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 612 permissions, new boolean[] {false, true, false, true}); 613 614 // The permissions are granted 615 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 616 .checkSelfPermission(Manifest.permission.WRITE_CONTACTS)); 617 assertEquals(PackageManager.PERMISSION_GRANTED, getInstrumentation().getContext() 618 .checkSelfPermission(Manifest.permission.RECORD_AUDIO)); 619 } 620 621 @Test testInvalidPermission()622 public void testInvalidPermission() throws Exception { 623 String[] permissions = new String[] { 624 getInstrumentation().getContext().getPackageName() + ".abadname" 625 }; 626 627 // Request the permission and allow it 628 BasePermissionActivity.Result result = requestPermissions(permissions, 629 REQUEST_CODE_PERMISSIONS, 630 BasePermissionActivity.class, 631 () -> { /* empty */ }); 632 633 // Expect the permissions is not granted 634 assertPermissionRequestResult(result, REQUEST_CODE_PERMISSIONS, 635 permissions, new boolean[] {false}); 636 } 637 assertAllPermissionsRevoked()638 private void assertAllPermissionsRevoked() { 639 assertAllPermissionsGrantState(PackageManager.PERMISSION_DENIED); 640 } 641 assertAllPermissionsGrantState(int grantState)642 private void assertAllPermissionsGrantState(int grantState) { 643 ArrayList<String> perms = new ArrayList<>(Arrays.asList( 644 Manifest.permission.SEND_SMS, 645 Manifest.permission.RECEIVE_SMS, 646 Manifest.permission.RECEIVE_WAP_PUSH, 647 Manifest.permission.RECEIVE_MMS, 648 Manifest.permission.READ_CALENDAR, 649 Manifest.permission.WRITE_CALENDAR, 650 Manifest.permission.WRITE_CONTACTS, 651 Manifest.permission.READ_SMS, 652 Manifest.permission.READ_PHONE_STATE, 653 Manifest.permission.READ_CALL_LOG, 654 Manifest.permission.WRITE_CALL_LOG, 655 Manifest.permission.ADD_VOICEMAIL, 656 Manifest.permission.CALL_PHONE, 657 Manifest.permission.USE_SIP, 658 Manifest.permission.PROCESS_OUTGOING_CALLS, 659 Manifest.permission.RECORD_AUDIO, 660 Manifest.permission.ACCESS_FINE_LOCATION, 661 Manifest.permission.ACCESS_COARSE_LOCATION, 662 Manifest.permission.CAMERA, 663 Manifest.permission.BODY_SENSORS, 664 Manifest.permission.READ_CELL_BROADCASTS, 665 666 // Split permissions 667 Manifest.permission.ACCESS_BACKGROUND_LOCATION 668 )); 669 670 perms.add(Manifest.permission.READ_EXTERNAL_STORAGE); 671 perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); 672 assertPermissionsGrantState(perms.toArray(new String[perms.size()]), grantState); 673 } 674 assertPermissionsGrantState(String[] permissions, int grantState)675 private void assertPermissionsGrantState(String[] permissions, int grantState) { 676 for (String permission : permissions) { 677 assertEquals(grantState, getInstrumentation().getContext() 678 .checkSelfPermission(permission)); 679 } 680 } 681 denyWithPrejudice()682 private void denyWithPrejudice() throws Exception { 683 if (mLeanback || mWatch) { 684 clickDontAskAgainButton(); 685 } else { 686 clickDenyAndDontAskAgainButton(); 687 } 688 } 689 690 /** 691 * Attempt to insert a new unique calendar item; this might be ignored if 692 * this legacy app has its permission revoked. 693 */ insertCalendarItem()694 private Uri insertCalendarItem() { 695 final ContentValues values = new ContentValues(); 696 values.put(CalendarContract.Calendars.NAME, "cts" + System.nanoTime()); 697 values.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "cts"); 698 values.put(CalendarContract.Calendars.CALENDAR_COLOR, 0xffff0000); 699 return mContext.getContentResolver().insert(CalendarContract.Calendars.CONTENT_URI, values); 700 } 701 } 702