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.telecom.cts; 18 19 import static android.telecom.cts.TestUtils.shouldTestTelecom; 20 import static android.telecom.cts.TestUtils.waitOnAllHandlers; 21 22 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 23 24 import android.Manifest; 25 import android.app.role.RoleManager; 26 import android.content.ComponentName; 27 import android.content.ContentResolver; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.ServiceConnection; 31 import android.content.pm.PackageManager; 32 import android.database.Cursor; 33 import android.net.Uri; 34 import android.os.Bundle; 35 import android.os.IBinder; 36 import android.os.Process; 37 import android.os.UserHandle; 38 39 import android.provider.CallLog; 40 import android.telecom.Call; 41 import android.telecom.CallScreeningService; 42 import android.telecom.TelecomManager; 43 import android.telecom.cts.screeningtestapp.CallScreeningServiceControl; 44 import android.telecom.cts.screeningtestapp.CtsCallScreeningService; 45 import android.telecom.cts.screeningtestapp.ICallScreeningControl; 46 import android.text.TextUtils; 47 48 import java.util.List; 49 import java.util.concurrent.CountDownLatch; 50 import java.util.concurrent.Executor; 51 import java.util.concurrent.LinkedBlockingQueue; 52 import java.util.concurrent.TimeUnit; 53 54 public class ThirdPartyCallScreeningServiceTest extends BaseTelecomTestWithMockServices { 55 public static final String EXTRA_NETWORK_IDENTIFIED_EMERGENCY_CALL = "identifiedEmergencyCall"; 56 private static final String TAG = ThirdPartyCallScreeningServiceTest.class.getSimpleName(); 57 private static final String TEST_APP_NAME = "CTSCSTest"; 58 private static final String TEST_APP_PACKAGE = "android.telecom.cts.screeningtestapp"; 59 private static final String TEST_APP_COMPONENT = 60 "android.telecom.cts.screeningtestapp/" 61 + "android.telecom.cts.screeningtestapp.CtsCallScreeningService"; 62 private static final int ASYNC_TIMEOUT = 10000; 63 private static final String ROLE_CALL_SCREENING = RoleManager.ROLE_CALL_SCREENING; 64 private static final Uri TEST_OUTGOING_NUMBER = Uri.fromParts("tel", "6505551212", null); 65 66 private ICallScreeningControl mCallScreeningControl; 67 private RoleManager mRoleManager; 68 private String mPreviousCallScreeningPackage; 69 private PackageManager mPackageManager; 70 private Uri mContactUri; 71 private ContentResolver mContentResolver; 72 73 @Override setUp()74 protected void setUp() throws Exception { 75 super.setUp(); 76 if (!mShouldTestTelecom) { 77 return; 78 } 79 mRoleManager = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE); 80 mPackageManager = mContext.getPackageManager(); 81 revokeReadContactPermission(); 82 setupControlBinder(); 83 setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE); 84 rememberPreviousCallScreeningApp(); 85 // Ensure CTS app holds the call screening role. 86 addRoleHolder(ROLE_CALL_SCREENING, 87 CtsCallScreeningService.class.getPackage().getName()); 88 mContentResolver = getInstrumentation().getTargetContext().getContentResolver(); 89 } 90 91 @Override tearDown()92 protected void tearDown() throws Exception { 93 super.tearDown(); 94 if (!mShouldTestTelecom) { 95 return; 96 } 97 98 if (mCallScreeningControl != null) { 99 mCallScreeningControl.reset(); 100 } 101 102 // Remove the test app from the screening role. 103 removeRoleHolder(ROLE_CALL_SCREENING, CtsCallScreeningService.class.getPackage().getName()); 104 105 if (!TextUtils.isEmpty(mPreviousCallScreeningPackage)) { 106 addRoleHolder(ROLE_CALL_SCREENING, mPreviousCallScreeningPackage); 107 } 108 } 109 110 /** 111 * Verifies that a {@link android.telecom.CallScreeningService} can reject an incoming call. 112 * Ensures that the system logs the blocked call to the call log. 113 * 114 * @throws Exception 115 */ testRejectCall()116 public void testRejectCall() throws Exception { 117 if (!shouldTestTelecom(mContext)) { 118 return; 119 } 120 121 // Tell the test app to block the call. 122 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 123 true /* shouldRejectCall */, false /* shouldSilenceCall */, 124 false /* shouldSkipCallLog */, true /* shouldSkipNotification */); 125 126 addIncomingAndVerifyBlocked(false /* addContact */); 127 } 128 129 /** 130 * Similar to {@link #testRejectCall()}, except the {@link android.telecom.CallScreeningService} 131 * tries to skip logging the call to the call log. We verify that Telecom still logs the call 132 * to the call log, retaining the API behavior documented in 133 * {@link android.telecom.CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)} 134 * @throws Exception 135 */ testRejectCallAndTryToSkipCallLog()136 public void testRejectCallAndTryToSkipCallLog() throws Exception { 137 if (!shouldTestTelecom(mContext)) { 138 return; 139 } 140 141 // Tell the test app to block the call; also try to skip logging the call. 142 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 143 true /* shouldRejectCall */, false /* shouldSilenceCall */, 144 true /* shouldSkipCallLog */, true /* shouldSkipNotification */); 145 146 addIncomingAndVerifyBlocked(false /* addContact */); 147 } 148 149 /** 150 * Verifies that a {@link android.telecom.CallScreeningService} set the extra to silence a call. 151 * @throws Exception 152 */ testIncomingCallHasSilenceExtra()153 public void testIncomingCallHasSilenceExtra() throws Exception { 154 if (!shouldTestTelecom(mContext)) { 155 return; 156 } 157 158 // Tell the test app to silence the call. 159 mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */, 160 false /* shouldRejectCall */, true /* shouldSilenceCall */, 161 false /* shouldSkipCallLog */, false /* shouldSkipNotification */); 162 163 addIncomingAndVerifyCallExtraForSilence(true); 164 } 165 166 /** 167 * Verifies that a {@link android.telecom.CallScreeningService} did not set the extra to silence an incoming call. 168 * @throws Exception 169 */ testIncomingCallDoesNotHaveHaveSilenceExtra()170 public void testIncomingCallDoesNotHaveHaveSilenceExtra() throws Exception { 171 if (!shouldTestTelecom(mContext)) { 172 return; 173 } 174 175 // Tell the test app to not silence the call. 176 mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */, 177 false /* shouldRejectCall */, false /* shouldSilenceCall */, 178 false /* shouldSkipCallLog */, false /* shouldSkipNotification */); 179 180 addIncomingAndVerifyCallExtraForSilence(false); 181 } 182 testHasPermissionAndNoContactIncoming()183 public void testHasPermissionAndNoContactIncoming() throws Exception { 184 if (!shouldTestTelecom(mContext)) { 185 return; 186 } 187 188 grantReadContactPermission(); 189 verifyPermission(true); 190 // Tell the test app to block the call. 191 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 192 true /* shouldRejectCall */, false /* shouldSilenceCall */, 193 false /* shouldSkipCallLog */, true /* shouldSkipNotification */); 194 addIncomingAndVerifyBlocked(false /* addContact */); 195 } 196 testNoPermissionAndNoContactIncoming()197 public void testNoPermissionAndNoContactIncoming() throws Exception { 198 if (!shouldTestTelecom(mContext)) { 199 return; 200 } 201 202 verifyPermission(false); 203 // Tell the test app to block the call. 204 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 205 true /* shouldRejectCall */, false /* shouldSilenceCall */, 206 false /* shouldSkipCallLog */, true /* shouldSkipNotification */); 207 addIncomingAndVerifyBlocked(false /* addContact */); 208 } 209 testHasPermissionAndHasContactIncoming()210 public void testHasPermissionAndHasContactIncoming() throws Exception { 211 if (!shouldTestTelecom(mContext)) { 212 return; 213 } 214 215 grantReadContactPermission(); 216 verifyPermission(true); 217 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 218 true /* shouldRejectCall */, false /* shouldSilenceCall */, 219 false /* shouldSkipCallLog */, true /* shouldSkipNotification */); 220 addIncomingAndVerifyBlocked(true /* addContact */); 221 } 222 testNoPermissionAndHasContactIncoming()223 public void testNoPermissionAndHasContactIncoming() throws Exception { 224 if (!shouldTestTelecom(mContext)) { 225 return; 226 } 227 228 verifyPermission(false); 229 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 230 true /* shouldRejectCall */, false /* shouldSilenceCall */, 231 false /* shouldSkipCallLog */, true /* shouldSkipNotification */); 232 addIncomingAndVerifyAllowed(true /* addContact */); 233 } 234 testHasPermissionAndNoContactOutgoing()235 public void testHasPermissionAndNoContactOutgoing() throws Exception { 236 if (!shouldTestTelecom(mContext)) { 237 return; 238 } 239 240 grantReadContactPermission(); 241 verifyPermission(true); 242 placeOutgoingCall(false /* addContact */); 243 assertTrue(mCallScreeningControl.waitForBind()); 244 } 245 testNoPermissionAndNoContactOutgoing()246 public void testNoPermissionAndNoContactOutgoing() throws Exception { 247 if (!shouldTestTelecom(mContext)) { 248 return; 249 } 250 251 verifyPermission(false); 252 placeOutgoingCall(false /* addContact */); 253 assertTrue(mCallScreeningControl.waitForBind()); 254 } 255 testHasPermissionAndHasContactOutgoing()256 public void testHasPermissionAndHasContactOutgoing() throws Exception { 257 if (!shouldTestTelecom(mContext)) { 258 return; 259 } 260 261 grantReadContactPermission(); 262 verifyPermission(true); 263 placeOutgoingCall(true /* addCountact */); 264 assertTrue(mCallScreeningControl.waitForBind()); 265 } 266 testNoPermissionAndHasContactOutgoing()267 public void testNoPermissionAndHasContactOutgoing() throws Exception { 268 if (!shouldTestTelecom(mContext)) { 269 return; 270 } 271 272 verifyPermission(false); 273 placeOutgoingCall(true /* addCountact */); 274 assertFalse(mCallScreeningControl.waitForBind()); 275 } 276 testNoPostCallActivityWithoutRole()277 public void testNoPostCallActivityWithoutRole() throws Exception { 278 if (!shouldTestTelecom(mContext)) { 279 return; 280 } 281 282 removeRoleHolder(ROLE_CALL_SCREENING, CtsCallScreeningService.class.getPackage().getName()); 283 addIncomingAndVerifyAllowed(false); 284 assertFalse(mCallScreeningControl.waitForActivity()); 285 } 286 testAllowCall()287 public void testAllowCall() throws Exception { 288 if (!mShouldTestTelecom) { 289 return; 290 } 291 292 mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */, 293 false /* shouldRejectCall */, false /* shouldSilenceCall */, 294 false /* shouldSkipCallLog */, false /* shouldSkipNotification */); 295 addIncomingAndVerifyAllowed(false /* addContact */); 296 assertTrue(mCallScreeningControl.waitForActivity()); 297 } 298 testNoPostCallActivityWhenBlocked()299 public void testNoPostCallActivityWhenBlocked() throws Exception { 300 if (!mShouldTestTelecom) { 301 return; 302 } 303 304 mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */, 305 true /* shouldRejectCall */, false /* shouldSilenceCall */, 306 false /* shouldSkipCallLog */, true /* shouldSkipNotification */); 307 addIncomingAndVerifyBlocked(false /* addContact */); 308 assertFalse(mCallScreeningControl.waitForActivity()); 309 } 310 testNoPostCallActivityWhenAudioProcessing()311 public void testNoPostCallActivityWhenAudioProcessing() throws Exception { 312 if (!shouldTestTelecom(mContext)) { 313 return; 314 } 315 316 mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */, 317 false /* shouldRejectCall */, false /* shouldSilenceCall */, 318 false /* shouldSkipCallLog */, false /* shouldSkipNotification */); 319 Uri testNumber = createRandomTestNumber(); 320 Bundle extras = new Bundle(); 321 extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, testNumber); 322 mTelecomManager.addNewIncomingCall(TestUtils.TEST_PHONE_ACCOUNT_HANDLE, extras); 323 324 // Wait until the new incoming call is processed. 325 waitOnAllHandlers(getInstrumentation()); 326 327 assertEquals(1, mInCallCallbacks.getService().getCallCount()); 328 Call call = mInCallCallbacks.getService().getLastCall(); 329 call.enterBackgroundAudioProcessing(); 330 331 waitOnAllHandlers(getInstrumentation()); 332 mInCallCallbacks.getService().disconnectAllCalls(); 333 assertFalse(mCallScreeningControl.waitForActivity()); 334 } 335 testNoPostCallActivityForOutgoingEmergencyCall()336 public void testNoPostCallActivityForOutgoingEmergencyCall() throws Exception { 337 if (!shouldTestTelecom(mContext)) { 338 return; 339 } 340 341 setupForEmergencyCalling(TEST_EMERGENCY_NUMBER); 342 Bundle extras = new Bundle(); 343 extras.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, TEST_EMERGENCY_URI); 344 placeAndVerifyCall(extras); 345 346 // Wait until the new incoming call is processed. 347 waitOnAllHandlers(getInstrumentation()); 348 mInCallCallbacks.getService().disconnectAllCalls(); 349 assertFalse(mCallScreeningControl.waitForActivity()); 350 } 351 testNoPostCallActivityForIncomingEmergencyCall()352 public void testNoPostCallActivityForIncomingEmergencyCall() throws Exception { 353 if (!shouldTestTelecom(mContext)) { 354 return; 355 } 356 setupForEmergencyCalling(TEST_EMERGENCY_NUMBER); 357 mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */, 358 false /* shouldRejectCall */, false /* shouldSilenceCall */, 359 false /* shouldSkipCallLog */, false /* shouldSkipNotification */); 360 Bundle extras = new Bundle(); 361 extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, TEST_EMERGENCY_URI); 362 extras.putBoolean(EXTRA_NETWORK_IDENTIFIED_EMERGENCY_CALL, true); 363 mTelecomManager.addNewIncomingCall(TestUtils.TEST_PHONE_ACCOUNT_HANDLE, extras); 364 365 // Wait until the new incoming call is processed. 366 waitOnAllHandlers(getInstrumentation()); 367 mInCallCallbacks.getService().disconnectAllCalls(); 368 369 assertFalse(mCallScreeningControl.waitForActivity()); 370 } 371 placeOutgoingCall(boolean addContact)372 private void placeOutgoingCall(boolean addContact) throws Exception { 373 // Setup content observer to notify us when we call log entry is added. 374 CountDownLatch callLogEntryLatch = getCallLogEntryLatch(); 375 376 Uri contactUri = null; 377 if (addContact) { 378 contactUri = TestUtils.insertContact(mContentResolver, 379 TEST_OUTGOING_NUMBER.getSchemeSpecificPart()); 380 } 381 382 try { 383 Bundle extras = new Bundle(); 384 extras.putParcelable(TestUtils.EXTRA_PHONE_NUMBER, TEST_OUTGOING_NUMBER); 385 // Create a new outgoing call. 386 placeAndVerifyCall(extras); 387 388 mInCallCallbacks.getService().disconnectAllCalls(); 389 assertNumCalls(mInCallCallbacks.getService(), 0); 390 391 // Wait for it to log. 392 callLogEntryLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 393 } finally { 394 if (addContact) { 395 assertEquals(1, TestUtils.deleteContact(mContentResolver, contactUri)); 396 } 397 } 398 } 399 addIncoming(boolean disconnectImmediately, boolean addContact)400 private Uri addIncoming(boolean disconnectImmediately, boolean addContact) throws Exception { 401 // Add call through TelecomManager; we can't use the test methods since they assume a call 402 // makes it through to the InCallService; this is blocked so it shouldn't. 403 Uri testNumber = createRandomTestNumber(); 404 if (addContact) { 405 mContactUri = TestUtils.insertContact(mContentResolver, 406 testNumber.getSchemeSpecificPart()); 407 } 408 409 // Setup content observer to notify us when we call log entry is added. 410 CountDownLatch callLogEntryLatch = getCallLogEntryLatch(); 411 412 Bundle extras = new Bundle(); 413 extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, testNumber); 414 mTelecomManager.addNewIncomingCall(TestUtils.TEST_PHONE_ACCOUNT_HANDLE, extras); 415 416 // Wait until the new incoming call is processed. 417 waitOnAllHandlers(getInstrumentation()); 418 419 if (disconnectImmediately) { 420 // Disconnect the call 421 mInCallCallbacks.getService().disconnectAllCalls(); 422 assertNumCalls(mInCallCallbacks.getService(), 0); 423 } 424 425 // Wait for the content observer to report that we have gotten a new call log entry. 426 callLogEntryLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 427 return testNumber; 428 } 429 addIncomingAndVerifyAllowed(boolean addContact)430 private void addIncomingAndVerifyAllowed(boolean addContact) throws Exception { 431 Uri testNumber = addIncoming(true, addContact); 432 433 // Query the latest entry into the call log. 434 Cursor callsCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, null, 435 null, null, CallLog.Calls._ID + " DESC limit 1;"); 436 int numberIndex = callsCursor.getColumnIndex(CallLog.Calls.NUMBER); 437 int callTypeIndex = callsCursor.getColumnIndex(CallLog.Calls.TYPE); 438 int blockReasonIndex = callsCursor.getColumnIndex(CallLog.Calls.BLOCK_REASON); 439 if (callsCursor.moveToNext()) { 440 String number = callsCursor.getString(numberIndex); 441 int callType = callsCursor.getInt(callTypeIndex); 442 int blockReason = callsCursor.getInt(blockReasonIndex); 443 assertEquals(testNumber.getSchemeSpecificPart(), number); 444 assertEquals(CallLog.Calls.INCOMING_TYPE, callType); 445 assertEquals(CallLog.Calls.BLOCK_REASON_NOT_BLOCKED, blockReason); 446 } else { 447 fail("Call not logged"); 448 } 449 450 if (addContact && mContactUri != null) { 451 assertEquals(1, TestUtils.deleteContact(mContentResolver, mContactUri)); 452 } 453 } 454 addIncomingAndVerifyBlocked(boolean addContact)455 private void addIncomingAndVerifyBlocked(boolean addContact) throws Exception { 456 Uri testNumber = addIncoming(false, addContact); 457 458 // Query the latest entry into the call log. 459 Cursor callsCursor = mContentResolver.query(CallLog.Calls.CONTENT_URI, null, 460 null, null, CallLog.Calls._ID + " DESC limit 1;"); 461 int numberIndex = callsCursor.getColumnIndex(CallLog.Calls.NUMBER); 462 int callTypeIndex = callsCursor.getColumnIndex(CallLog.Calls.TYPE); 463 int blockReasonIndex = callsCursor.getColumnIndex(CallLog.Calls.BLOCK_REASON); 464 int callScreeningAppNameIndex = callsCursor.getColumnIndex( 465 CallLog.Calls.CALL_SCREENING_APP_NAME); 466 int callScreeningCmpNameIndex = callsCursor.getColumnIndex( 467 CallLog.Calls.CALL_SCREENING_COMPONENT_NAME); 468 if (callsCursor.moveToNext()) { 469 String number = callsCursor.getString(numberIndex); 470 int callType = callsCursor.getInt(callTypeIndex); 471 int blockReason = callsCursor.getInt(blockReasonIndex); 472 String screeningAppName = callsCursor.getString(callScreeningAppNameIndex); 473 String screeningComponentName = callsCursor.getString(callScreeningCmpNameIndex); 474 assertEquals(testNumber.getSchemeSpecificPart(), number); 475 assertEquals(CallLog.Calls.BLOCKED_TYPE, callType); 476 assertEquals(CallLog.Calls.BLOCK_REASON_CALL_SCREENING_SERVICE, blockReason); 477 assertEquals(TEST_APP_NAME, screeningAppName); 478 assertEquals(TEST_APP_COMPONENT, screeningComponentName); 479 } else { 480 fail("Blocked call was not logged."); 481 } 482 483 if (addContact && mContactUri != null) { 484 assertEquals(1, TestUtils.deleteContact(mContentResolver, mContactUri)); 485 } 486 } 487 addIncomingAndVerifyCallExtraForSilence(boolean expectedIsSilentRingingExtraSet)488 private void addIncomingAndVerifyCallExtraForSilence(boolean expectedIsSilentRingingExtraSet) 489 throws Exception { 490 Uri testNumber = addIncoming(false, false); 491 492 waitUntilConditionIsTrueOrTimeout( 493 new Condition() { 494 @Override 495 public Object expected() { 496 return true; 497 } 498 499 @Override 500 public Object actual() { 501 // Verify that the call extra matches expectation 502 Call call = mInCallCallbacks.getService().getLastCall(); 503 return expectedIsSilentRingingExtraSet == 504 call.getDetails().getExtras().getBoolean( 505 Call.EXTRA_SILENT_RINGING_REQUESTED); 506 } 507 }, 508 TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS, 509 "Call extra - verification failed, expected the extra " + 510 "EXTRA_SILENT_RINGING_REQUESTED to be set:" + 511 expectedIsSilentRingingExtraSet); 512 } 513 514 /** 515 * Sets up a binder used to control the CallScreeningServiceCtsTestApp. 516 * This app is a standalone APK so that it can reside in a package name outside of the one the 517 * CTS test itself runs in (since that APK is where the CTS InCallService resides). 518 * @throws InterruptedException 519 */ setupControlBinder()520 private void setupControlBinder() throws InterruptedException { 521 Intent bindIntent = new Intent(CallScreeningServiceControl.CONTROL_INTERFACE_ACTION); 522 bindIntent.setComponent(CallScreeningServiceControl.CONTROL_INTERFACE_COMPONENT); 523 final CountDownLatch bindLatch = new CountDownLatch(1); 524 525 boolean success = mContext.bindService(bindIntent, new ServiceConnection() { 526 @Override 527 public void onServiceConnected(ComponentName name, IBinder service) { 528 mCallScreeningControl = ICallScreeningControl.Stub.asInterface(service); 529 bindLatch.countDown(); 530 } 531 532 @Override 533 public void onServiceDisconnected(ComponentName name) { 534 mCallScreeningControl = null; 535 } 536 }, Context.BIND_AUTO_CREATE); 537 if (!success) { 538 fail("Failed to get control interface -- bind error"); 539 } 540 bindLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 541 } 542 543 /** 544 * Use RoleManager to query the previous call screening app so we can restore it later. 545 */ rememberPreviousCallScreeningApp()546 private void rememberPreviousCallScreeningApp() { 547 runWithShellPermissionIdentity(() -> { 548 List<String> callScreeningApps = mRoleManager.getRoleHolders(ROLE_CALL_SCREENING); 549 if (!callScreeningApps.isEmpty()) { 550 mPreviousCallScreeningPackage = callScreeningApps.get(0); 551 } else { 552 mPreviousCallScreeningPackage = null; 553 } 554 }); 555 } 556 addRoleHolder(String roleName, String packageName)557 private void addRoleHolder(String roleName, String packageName) 558 throws Exception { 559 UserHandle user = Process.myUserHandle(); 560 Executor executor = mContext.getMainExecutor(); 561 LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue(1); 562 563 runWithShellPermissionIdentity(() -> mRoleManager.addRoleHolderAsUser(roleName, 564 packageName, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, executor, 565 successful -> { 566 try { 567 queue.put(successful); 568 } catch (InterruptedException e) { 569 e.printStackTrace(); 570 } 571 })); 572 boolean result = queue.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 573 assertTrue(result); 574 } 575 removeRoleHolder(String roleName, String packageName)576 private void removeRoleHolder(String roleName, String packageName) 577 throws Exception { 578 UserHandle user = Process.myUserHandle(); 579 Executor executor = mContext.getMainExecutor(); 580 LinkedBlockingQueue<Boolean> queue = new LinkedBlockingQueue(1); 581 582 runWithShellPermissionIdentity(() -> mRoleManager.removeRoleHolderAsUser(roleName, 583 packageName, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, executor, 584 successful -> { 585 try { 586 queue.put(successful); 587 } catch (InterruptedException e) { 588 e.printStackTrace(); 589 } 590 })); 591 boolean result = queue.poll(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS); 592 assertTrue(result); 593 } 594 grantReadContactPermission()595 private void grantReadContactPermission() { 596 runWithShellPermissionIdentity(() -> { 597 if (mPackageManager != null) { 598 mPackageManager.grantRuntimePermission(TEST_APP_PACKAGE, 599 Manifest.permission.READ_CONTACTS, mContext.getUser()); 600 }}); 601 } 602 revokeReadContactPermission()603 private void revokeReadContactPermission() { 604 runWithShellPermissionIdentity(() -> { 605 if (mPackageManager != null) { 606 mPackageManager.revokeRuntimePermission(TEST_APP_PACKAGE, 607 Manifest.permission.READ_CONTACTS, mContext.getUser()); 608 }}); 609 } 610 verifyPermission(boolean hasPermission)611 private void verifyPermission(boolean hasPermission) { 612 assertEquals(hasPermission, 613 mPackageManager.checkPermission 614 (Manifest.permission.READ_CONTACTS, TEST_APP_PACKAGE) 615 == PackageManager.PERMISSION_GRANTED); 616 } 617 } 618