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