1 /* 2 * Copyright (C) 2021 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.PhoneAccount.CAPABILITY_CALL_PROVIDER; 20 import static android.telecom.PhoneAccount.CAPABILITY_SELF_MANAGED; 21 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.ServiceConnection; 26 import android.net.Uri; 27 import android.os.IBinder; 28 import android.os.Process; 29 import android.os.RemoteException; 30 import android.os.UserHandle; 31 import android.os.UserManager; 32 import android.telecom.PhoneAccount; 33 import android.telecom.PhoneAccountHandle; 34 import android.telecom.TelecomManager; 35 import android.telecom.cts.carmodetestapp.ICtsCarModeInCallServiceControl; 36 import android.telecom.cts.carmodetestappselfmanaged.CtsCarModeInCallServiceControlSelfManaged; 37 import android.util.ArraySet; 38 import android.util.Log; 39 40 import com.android.compatibility.common.util.ApiTest; 41 import com.android.compatibility.common.util.ShellIdentityUtils; 42 import com.android.internal.telephony.flags.Flags; 43 44 import java.util.ArrayList; 45 import java.util.List; 46 import java.util.Random; 47 import java.util.concurrent.CountDownLatch; 48 import java.util.concurrent.TimeUnit; 49 50 public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices { 51 52 private static final String TAG = "PhoneAccountRegistrarTest"; 53 private static final long TIMEOUT = 3000L; 54 private static final int LARGE_ACCT_HANDLE_ID_MIN_SIZE = 50000; 55 private static final String RANDOM_CHAR_VALUE = "a"; 56 private static final String TEL_PREFIX = "tel:"; 57 private static final String TELECOM_CLEANUP_ACCTS_CMD = "telecom cleanup-orphan-phone-accounts"; 58 public static final long SEED = 52L; // random seed chosen 59 public static final int MAX_PHONE_ACCOUNT_REGISTRATIONS = 10; // mirrors constant in... 60 // PhoneAccountRegistrar called MAX_PHONE_ACCOUNT_REGISTRATIONS 61 62 // permissions 63 private static final String READ_PRIVILEGED_PHONE_STATE = 64 "android.permission.READ_PRIVILEGED_PHONE_STATE"; 65 private static final String MODIFY_PHONE_STATE_PERMISSION = 66 "android.permission.MODIFY_PHONE_STATE"; 67 private static final String REGISTER_SIM_SUBSCRIPTION_PERMISSION = 68 "android.permission.REGISTER_SIM_SUBSCRIPTION"; 69 private static final String INTERACT_ACROSS_PROFILES = 70 "android.permission.INTERACT_ACROSS_PROFILES"; 71 72 // telecom cts test package (default package that registers phoneAccounts) 73 private static final ComponentName TEST_COMPONENT_NAME = 74 new ComponentName(TestUtils.PACKAGE, TestUtils.COMPONENT); 75 76 // secondary test package (extra package that can be set up to register phoneAccounts) 77 private static final String SELF_MANAGED_CAR_PACKAGE = 78 CtsCarModeInCallServiceControlSelfManaged.class.getPackage().getName(); 79 private static final ComponentName SELF_MANAGED_CAR_RELATIVE_COMPONENT = ComponentName 80 .createRelative(SELF_MANAGED_CAR_PACKAGE, 81 CtsCarModeInCallServiceControlSelfManaged.class.getName()); 82 private static final ComponentName CAR_COMPONENT = new ComponentName(SELF_MANAGED_CAR_PACKAGE, 83 TestUtils.SELF_MANAGED_COMPONENT); 84 private static final String CAR_MODE_CONTROL = 85 "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL"; 86 // variables to interface with the second test package 87 TestServiceConnection mControl; 88 ICtsCarModeInCallServiceControl mSecondaryTestPackageControl; 89 90 @Override setUp()91 public void setUp() throws Exception { 92 // Sets up this package as default dialer in super. 93 super.setUp(); 94 NewOutgoingCallBroadcastReceiver.reset(); 95 if (!mShouldTestTelecom) return; 96 setupConnectionService(null, 0); 97 // cleanup any accounts registered to the test package before starting tests 98 cleanupPhoneAccounts(); 99 } 100 101 @Override tearDown()102 public void tearDown() throws Exception { 103 // cleanup any accounts registered to the test package after testing to avoid crashing other 104 // tests. 105 cleanupPhoneAccounts(); 106 super.tearDown(); 107 } 108 109 /** 110 * Test scenario where a single package can register MAX_PHONE_ACCOUNT_REGISTRATIONS via 111 * {@link android.telecom.TelecomManager#registerPhoneAccount(PhoneAccount)} without an 112 * exception being thrown. 113 */ testRegisterMaxPhoneAccountsWithoutException()114 public void testRegisterMaxPhoneAccountsWithoutException() { 115 if (!mShouldTestTelecom) return; 116 117 // ensure the test starts without any phone accounts registered to the test package 118 cleanupPhoneAccounts(); 119 120 // determine the number of phone accounts that can be registered before hitting limit 121 int numberOfAccountsThatCanBeRegistered = MAX_PHONE_ACCOUNT_REGISTRATIONS 122 - getNumberOfPhoneAccountsRegisteredToTestPackage(); 123 124 // create the remaining number of phone accounts via helper function 125 // in order to reach the upper bound MAX_PHONE_ACCOUNT_REGISTRATIONS 126 ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED, 127 numberOfAccountsThatCanBeRegistered, TestUtils.PACKAGE, TestUtils.COMPONENT); 128 try { 129 // register all accounts created 130 accounts.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a)); 131 // assert the maximum accounts that can be registered were registered successfully 132 assertEquals(MAX_PHONE_ACCOUNT_REGISTRATIONS, 133 getNumberOfPhoneAccountsRegisteredToTestPackage()); 134 } finally { 135 // cleanup accounts registered 136 accounts.stream().forEach( 137 d -> mTelecomManager.unregisterPhoneAccount(d.getAccountHandle())); 138 } 139 } 140 141 /** 142 * Tests a scenario where a PhoneAccount with more than MAX_PHONE_ACCOUNT_REGISTRATIONS 143 * PhoneAccountHandles set as a simultaneous calling restriction throws an 144 * {@link IllegalArgumentException}. 145 */ testExceptionThrownDueToInvalidSimultaneousCallRestriction_tooManyAccounts()146 public void testExceptionThrownDueToInvalidSimultaneousCallRestriction_tooManyAccounts() { 147 if (!mShouldTestTelecom || !Flags.simultaneousCallingIndications()) return; 148 149 // ensure the test starts without any phone accounts registered to the test package 150 cleanupPhoneAccounts(); 151 152 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function 153 ArrayList<PhoneAccountHandle> restrictionHandles = 154 TestUtils.generateRandomPhoneAccountHandles(SEED, 155 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE, TestUtils.COMPONENT); 156 PhoneAccountHandle acctHandle = TestUtils.makePhoneAccountHandle( 157 TestUtils.DEFAULT_TEST_ACCOUNT_1_ID); 158 PhoneAccount acct = TestUtils.buildSelfManagedPhoneAccount(acctHandle, 159 TestUtils.ACCOUNT_LABEL) 160 .setSimultaneousCallingRestriction(new ArraySet<>(restrictionHandles)).build(); 161 162 try { 163 // Try to register more phone accounts than allowed by the upper bound limit 164 // MAX_PHONE_ACCOUNT_REGISTRATIONS 165 mTelecomManager.registerPhoneAccount(acct); 166 // A successful test should never reach this line of execution. 167 // However, if it does, fail the test by throwing a fail(...) 168 fail("Test failed. The test did not throw an IllegalArgumentException when " 169 + "registering a phone account where the Set of PhoneAccountHandles in the " 170 + "simultaneous calling restriction is over the upper bound: " 171 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 172 } catch (IllegalArgumentException e) { 173 // Assert the IllegalArgumentException was thrown 174 assertNotNull(e.toString()); 175 } finally { 176 // Cleanup accounts registered 177 mTelecomManager.unregisterPhoneAccount(acctHandle); 178 } 179 } 180 181 /** 182 * Tests a scenario where a PhoneAccount contains a simultaneous calling restriction and the 183 * associated PhoneAccountHandle contains an ID where the field exceeds the maximum size. 184 */ testExceptionThrownDueToInvalidSimultaneousCallRestriction_invalidId()185 public void testExceptionThrownDueToInvalidSimultaneousCallRestriction_invalidId() { 186 if (!mShouldTestTelecom || !Flags.simultaneousCallingIndications()) return; 187 188 // ensure the test starts without any phone accounts registered to the test package 189 cleanupPhoneAccounts(); 190 191 // Exceed the field size for the ID 192 ArraySet<PhoneAccountHandle> invalidRestrictionHandles = new ArraySet<>(1); 193 invalidRestrictionHandles.add(TestUtils.makePhoneAccountHandle("a".repeat(257))); 194 PhoneAccountHandle acctHandle = TestUtils.makePhoneAccountHandle( 195 TestUtils.DEFAULT_TEST_ACCOUNT_1_ID); 196 PhoneAccount acct = TestUtils.buildSelfManagedPhoneAccount(acctHandle, 197 TestUtils.ACCOUNT_LABEL) 198 .setSimultaneousCallingRestriction(invalidRestrictionHandles).build(); 199 200 try { 201 // Try to register more phone accounts than allowed by the upper bound limit 202 // MAX_PHONE_ACCOUNT_REGISTRATIONS 203 mTelecomManager.registerPhoneAccount(acct); 204 // A successful test should never reach this line of execution. 205 // However, if it does, fail the test by throwing a fail(...) 206 fail("Test failed. The test did not throw an IllegalArgumentException when " 207 + "registering a phone account where the Set of PhoneAccountHandles in the " 208 + "simultaneous calling restriction is over the upper bound: " 209 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 210 } catch (IllegalArgumentException e) { 211 // Assert the IllegalArgumentException was thrown 212 assertNotNull(e.toString()); 213 } finally { 214 // Cleanup accounts registered 215 mTelecomManager.unregisterPhoneAccount(acctHandle); 216 } 217 } 218 219 /** 220 * Tests a scenario where a single package exceeds MAX_PHONE_ACCOUNT_REGISTRATIONS and 221 * an {@link IllegalArgumentException} is thrown. Will fail if no exception is thrown. 222 */ testExceptionThrownDueUserExceededMaxPhoneAccountRegistrations()223 public void testExceptionThrownDueUserExceededMaxPhoneAccountRegistrations() 224 throws IllegalArgumentException { 225 if (!mShouldTestTelecom) return; 226 227 // ensure the test starts without any phone accounts registered to the test package 228 cleanupPhoneAccounts(); 229 230 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function 231 ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED, 232 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE, 233 TestUtils.COMPONENT); 234 235 try { 236 // Try to register more phone accounts than allowed by the upper bound limit 237 // MAX_PHONE_ACCOUNT_REGISTRATIONS 238 accounts.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a)); 239 // A successful test should never reach this line of execution. 240 // However, if it does, fail the test by throwing a fail(...) 241 fail("Test failed. The test did not throw an IllegalArgumentException when " 242 + "registering phone accounts over the upper bound: " 243 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 244 } catch (IllegalArgumentException e) { 245 // Assert the IllegalArgumentException was thrown 246 assertNotNull(e.toString()); 247 } finally { 248 // Cleanup accounts registered 249 accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 250 d.getAccountHandle())); 251 } 252 } 253 254 /** 255 * Ensure an app does not register accounts over the upper bound limit by disabling them 256 */ testDisablingAccountsAfterRegStillThrowsException()257 public void testDisablingAccountsAfterRegStillThrowsException() throws Exception { 258 if (!mShouldTestTelecom) return; 259 260 // ensure the test starts without any phone accounts registered to the test package 261 cleanupPhoneAccounts(); 262 263 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function 264 ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED, 265 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE, 266 TestUtils.COMPONENT); 267 268 try { 269 // Try to register more phone accounts than allowed by the upper bound limit 270 for (PhoneAccount pa : accounts) { 271 mTelecomManager.registerPhoneAccount(pa); 272 TestUtils.disablePhoneAccount(getInstrumentation(), pa.getAccountHandle()); 273 // verify the account is both registered and disabled 274 verifyAccountIsDisabled(pa); 275 } 276 277 // A successful test should never reach this line of execution. 278 // However, if it does, fail the test by throwing a fail(...) 279 fail("Test failed. The test did not throw an IllegalArgumentException when " 280 + "registering phone accounts over the upper bound: " 281 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 282 } catch (IllegalArgumentException e) { 283 // Assert the IllegalArgumentException was thrown 284 assertNotNull(e.toString()); 285 } finally { 286 // Cleanup accounts registered 287 accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 288 d.getAccountHandle())); 289 } 290 } 291 292 /** 293 * Ensure an app does not register accounts that will be auto-disabled upon registered and 294 * bypass the limit. Note: CAPABILITY_CALL_PROVIDER will register the account as disabled. 295 */ testDisabledAccountsThrowsException()296 public void testDisabledAccountsThrowsException() throws Exception { 297 if (!mShouldTestTelecom) return; 298 299 // ensure the test starts without any phone accounts registered to the test package 300 cleanupPhoneAccounts(); 301 302 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 303 ArrayList<PhoneAccount> accounts = new ArrayList<>(); 304 for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS + 1; i++) { 305 accounts.add(new PhoneAccount.Builder( 306 TestUtils.makePhoneAccountHandle(Integer.toString(i)), 307 TestUtils.ACCOUNT_LABEL) 308 .setCapabilities(CAPABILITY_CALL_PROVIDER) 309 .build()); 310 } 311 312 try { 313 // Try to register more phone accounts than allowed by the upper bound limit 314 for (PhoneAccount pa : accounts) { 315 mTelecomManager.registerPhoneAccount(pa); 316 // verify the account is both registered and disabled 317 verifyAccountIsDisabled(pa); 318 } 319 // A successful test should never reach this line of execution. 320 // However, if it does, fail the test by throwing a fail(...) 321 fail("Test failed. The test did not throw an IllegalArgumentException when " 322 + "registering phone accounts over the upper bound: " 323 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 324 } catch (IllegalArgumentException e) { 325 // Assert the IllegalArgumentException was thrown 326 assertNotNull(e.toString()); 327 } finally { 328 // Cleanup accounts registered 329 accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 330 d.getAccountHandle())); 331 } 332 } 333 334 /** 335 * Test scenario where two distinct packages register MAX_PHONE_ACCOUNT_REGISTRATIONS via 336 * {@link 337 * android.telecom.TelecomManager#registerPhoneAccount(PhoneAccount)} without an exception being 338 * thrown. 339 * This ensures that PhoneAccountRegistrar is handling {@link PhoneAccount} registrations 340 * to distinct packages correctly. 341 */ testTwoPackagesRegisterMax()342 public void testTwoPackagesRegisterMax() throws Exception { 343 if (!mShouldTestTelecom) return; 344 345 // ensure the test starts without any phone accounts registered to the test package 346 cleanupPhoneAccounts(); 347 348 // determine the number of phone accounts that can be registered to package 1 349 int numberOfAccountsThatCanBeRegisteredToPackage1 = MAX_PHONE_ACCOUNT_REGISTRATIONS 350 - getNumberOfPhoneAccountsRegisteredToTestPackage(); 351 352 // Create MAX phone accounts for package 1 353 ArrayList<PhoneAccount> accountsPackage1 = TestUtils.generateRandomPhoneAccounts(SEED, 354 numberOfAccountsThatCanBeRegisteredToPackage1, TestUtils.PACKAGE, 355 TestUtils.COMPONENT); 356 357 // Constants for creating a second package to register phone accounts 358 final String carPkgSelfManaged = 359 CtsCarModeInCallServiceControlSelfManaged.class 360 .getPackage().getName(); 361 final ComponentName carComponentSelfManaged = ComponentName.createRelative( 362 carPkgSelfManaged, CtsCarModeInCallServiceControlSelfManaged.class.getName()); 363 final String carModeControl = 364 "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL"; 365 366 // Set up binding for second package. This is needed in order to bypass a SecurityException 367 // thrown by a second test package registering phone accounts. 368 TestServiceConnection control = setUpControl(carModeControl, 369 carComponentSelfManaged); 370 371 ICtsCarModeInCallServiceControl carModeIncallServiceControlSelfManaged = 372 ICtsCarModeInCallServiceControl.Stub 373 .asInterface(control.getService()); 374 375 carModeIncallServiceControlSelfManaged.reset(); //... done setting up binding 376 377 // Create MAX phone accounts for package 2 378 ArrayList<PhoneAccount> accountsPackage2 = TestUtils.generateRandomPhoneAccounts(SEED, 379 MAX_PHONE_ACCOUNT_REGISTRATIONS, carPkgSelfManaged, 380 TestUtils.SELF_MANAGED_COMPONENT); 381 382 try { 383 384 // register all accounts for package 1 385 accountsPackage1.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a)); 386 387 388 // register all phone accounts for package 2 389 for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS; i++) { 390 carModeIncallServiceControlSelfManaged.registerPhoneAccount( 391 accountsPackage2.get(i)); 392 } 393 394 } finally { 395 // cleanup all phone accounts registered. Note, unregisterPhoneAccount will not 396 // cause a runtime error if no phone account is found when trying to unregister. 397 398 accountsPackage1.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 399 d.getAccountHandle())); 400 401 for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS; i++) { 402 carModeIncallServiceControlSelfManaged.unregisterPhoneAccount( 403 accountsPackage2.get(i).getAccountHandle()); 404 } 405 } 406 // unbind from second package 407 mContext.unbindService(control); 408 } 409 410 /** 411 * Test the scenario where {@link android.telecom.TelecomManager 412 * #getCallCapablePhoneAccounts(boolean)} is called with a heavy payload 413 * that could cause a {@link android.os.TransactionTooLargeException}. Telecom is expected to 414 * handle this by splitting the parcels via {@link android.content.pm.ParceledListSlice}. 415 */ testGettingLargeCallCapablePhoneAccountHandlePayload()416 public void testGettingLargeCallCapablePhoneAccountHandlePayload() throws Exception { 417 if (!mShouldTestTelecom) return; 418 // ensure the test starts without any phone accounts registered to the test package 419 cleanupPhoneAccounts(); 420 421 // generate a large phoneAccountHandle id string to create a large payload 422 String largeAccountHandleId = generateLargeString( 423 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 424 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 425 426 // create handles for package 1 427 List<PhoneAccount> phoneAccountsForPackage1 = 428 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 429 numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_CALL_PROVIDER); 430 431 //create handles for package 2 432 List<PhoneAccount> phoneAccountsForPackage2 = 433 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 434 MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_CALL_PROVIDER); 435 try { 436 // register all accounts for package 1 437 phoneAccountsForPackage1.stream() 438 .forEach(a -> mTelecomManager.registerPhoneAccount(a)); 439 // verify all can be fetched 440 verifyCanFetchCallCapableAccounts(); 441 // register all accounts for package 2 442 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 443 // verify all can be fetched 444 verifyCanFetchCallCapableAccounts(); 445 } catch (IllegalArgumentException e) { 446 // allow test pass ... 447 Log.i(TAG, "testGettingLargeCallCapablePhoneAccountHandlePayload:" 448 + " illegal arg exception thrown."); 449 } finally { 450 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 451 cleanupPhoneAccounts(); 452 } 453 } 454 455 /** 456 * Test the scenario where {@link android.telecom.TelecomManager#getSelfManagedPhoneAccounts()} 457 * is called with a heavy payload that could cause a {@link 458 * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting 459 * the parcels via {@link android.content.pm.ParceledListSlice}. 460 */ testGettingLargeSelfManagedPhoneAccountHandlePayload()461 public void testGettingLargeSelfManagedPhoneAccountHandlePayload() throws Exception { 462 if (!mShouldTestTelecom) return; 463 // ensure the test starts without any phone accounts registered to the test package 464 cleanupPhoneAccounts(); 465 466 // generate a large phoneAccountHandle id string to create a large payload 467 String largeAccountHandleId = generateLargeString( 468 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 469 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 470 471 // create handles for package 1 472 List<PhoneAccount> phoneAccountsForPackage1 = 473 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 474 numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED); 475 476 //create handles for package 2 477 List<PhoneAccount> phoneAccountsForPackage2 = 478 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 479 MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED); 480 try { 481 // register all accounts for package 1 482 phoneAccountsForPackage1.stream() 483 .forEach(a -> mTelecomManager.registerPhoneAccount(a)); 484 // verify all can be fetched 485 verifyCanFetchSelfManagedPhoneAccounts(); 486 // register all accounts for package 2 487 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 488 // verify all can be fetched 489 verifyCanFetchSelfManagedPhoneAccounts(); 490 } catch (IllegalArgumentException e) { 491 // allow test pass ... 492 Log.i(TAG, "testGettingLargeSelfManagedPhoneAccountHandlePayload:" 493 + " illegal arg exception thrown."); 494 } finally { 495 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 496 cleanupPhoneAccounts(); 497 } 498 } 499 500 /** 501 * Test the scenario where {@link android.telecom.TelecomManager#getAllPhoneAccountHandles()} 502 * is called with a heavy payload that could cause a {@link 503 * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting 504 * the parcels via {@link android.content.pm.ParceledListSlice}. 505 */ testGettingAllPhoneAccountHandlesWithLargePayload()506 public void testGettingAllPhoneAccountHandlesWithLargePayload() throws Exception { 507 if (!mShouldTestTelecom) return; 508 509 // ensure the test starts without any phone accounts registered to the test package 510 cleanupPhoneAccounts(); 511 512 // generate a large phoneAccountHandle id string to create a large payload 513 String largeAccountHandleId = generateLargeString( 514 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 515 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 516 517 // create handles for package 1 518 List<PhoneAccount> phoneAccountsForPackage1 = 519 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 520 numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED); 521 522 //create handles for package 2 523 List<PhoneAccount> phoneAccountsForPackage2 = 524 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 525 MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED); 526 try { 527 // register all accounts for package 1 528 phoneAccountsForPackage1.stream() 529 .forEach(a -> mTelecomManager.registerPhoneAccount(a)); 530 // verify all can be fetched 531 verifyCanFetchAllPhoneAccountHandles(); 532 // register all accounts for package 2 533 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 534 // verify all can be fetched 535 verifyCanFetchAllPhoneAccountHandles(); 536 } catch (IllegalArgumentException e) { 537 // allow test pass ... 538 } finally { 539 540 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 541 cleanupPhoneAccounts(); 542 } 543 } 544 545 /** 546 * Test the scenario where {@link TelecomManager#getAllPhoneAccounts()} 547 * is called with a heavy payload that could cause a {@link 548 * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting 549 * the parcels via {@link android.content.pm.ParceledListSlice}. 550 */ testGetAllPhoneAccountsWithLargePayload()551 public void testGetAllPhoneAccountsWithLargePayload() throws Exception { 552 if (!mShouldTestTelecom) return; 553 554 // ensure the test starts without any phone accounts registered to the test package 555 cleanupPhoneAccounts(); 556 557 // generate a large phoneAccountHandle id string to create a large payload 558 String largeAccountHandleId = generateLargeString( 559 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 560 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 561 562 // create handles for package 1 563 List<PhoneAccount> phoneAccountsForPackage1 = 564 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 565 numberOfPhoneAccountsCtsPackageCanRegister(), 566 CAPABILITY_CALL_PROVIDER 567 | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 568 569 //create handles for package 2 570 List<PhoneAccount> phoneAccountsForPackage2 = 571 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 572 MAX_PHONE_ACCOUNT_REGISTRATIONS, 573 CAPABILITY_SELF_MANAGED); 574 try { 575 // register all accounts for package 1 576 for (PhoneAccount pa : phoneAccountsForPackage1) { 577 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelecomManager, 578 tm -> tm.registerPhoneAccount(pa), REGISTER_SIM_SUBSCRIPTION_PERMISSION); 579 } 580 // verify all can be fetched 581 verifyCanFetchAllPhoneAccounts(); 582 // register all accounts for package 2 583 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 584 // verify all can be fetched 585 verifyCanFetchAllPhoneAccounts(); 586 } catch (IllegalArgumentException e) { 587 // allow test pass ... 588 } finally { 589 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 590 cleanupPhoneAccounts(); 591 } 592 } 593 594 @ApiTest(apis = { 595 "android.telecom.TelecomManager#getCallCapablePhoneAccounts", 596 "android.telecom.TelecomManager#getCallCapablePhoneAccountsAcrossProfiles"}) testGetCallCapablePhoneAccountsAcrossProfiles()597 public void testGetCallCapablePhoneAccountsAcrossProfiles() throws Exception { 598 if (!mShouldTestTelecom || !Flags.workProfileApiSplit()) { 599 return; 600 } 601 602 // ensure the test starts without any phone accounts registered to the test package 603 cleanupPhoneAccounts(); 604 605 List<PhoneAccountHandle> handles = mTelecomManager.getCallCapablePhoneAccounts(); 606 List<PhoneAccountHandle> handlesAcrossProfiles = ShellIdentityUtils 607 .invokeMethodWithShellPermissions(mTelecomManager, 608 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(), 609 INTERACT_ACROSS_PROFILES); 610 611 assertEquals(handles.size(), handlesAcrossProfiles.size()); 612 613 Random random = new Random(SEED); 614 PhoneAccountHandle handle1 = TestUtils.createPhoneAccountHandle( 615 random, TestUtils.PACKAGE, TestUtils.REMOTE_COMPONENT, 616 Process.myUserHandle().getIdentifier()); 617 PhoneAccountHandle handle2 = TestUtils.createPhoneAccountHandle( 618 random, TestUtils.PACKAGE, TestUtils.REMOTE_COMPONENT, 619 Process.myUserHandle().getIdentifier()); 620 PhoneAccount account1 = new PhoneAccount.Builder( 621 handle1, this.getClass().getName()) 622 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 623 .build(); 624 PhoneAccount account2 = new PhoneAccount.Builder( 625 handle2, this.getClass().getName()) 626 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 627 .build(); 628 629 try { 630 mTelecomManager.registerPhoneAccount(account1); 631 mTelecomManager.registerPhoneAccount(account2); 632 TestUtils.enablePhoneAccount(getInstrumentation(), handle1); 633 TestUtils.enablePhoneAccount(getInstrumentation(), handle2); 634 635 handles = mTelecomManager.getCallCapablePhoneAccounts(); 636 handlesAcrossProfiles = ShellIdentityUtils 637 .invokeMethodWithShellPermissions(mTelecomManager, 638 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(), 639 INTERACT_ACROSS_PROFILES); 640 641 assertEquals(handles, handlesAcrossProfiles); 642 assertTrue(handles.contains(handle1)); 643 assertTrue(handles.contains(handle2)); 644 645 //test for disabled account 646 TestUtils.disablePhoneAccount(getInstrumentation(), handle2); 647 648 handles = mTelecomManager.getCallCapablePhoneAccounts(); 649 handlesAcrossProfiles = ShellIdentityUtils 650 .invokeMethodWithShellPermissions(mTelecomManager, 651 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(), 652 INTERACT_ACROSS_PROFILES); 653 List<PhoneAccountHandle> handlesAcrossProfilesWithDisabledAccount = ShellIdentityUtils 654 .invokeMethodWithShellPermissions(mTelecomManager, 655 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(true), 656 INTERACT_ACROSS_PROFILES); 657 658 assertEquals(handles, handlesAcrossProfiles); 659 assertEquals(handles.size() + 1, handlesAcrossProfilesWithDisabledAccount.size()); 660 assertTrue(handlesAcrossProfiles.containsAll(handles)); 661 assertTrue(handlesAcrossProfilesWithDisabledAccount.contains(handle2)); 662 } catch (IllegalArgumentException e) { 663 // allow test pass ... 664 } finally { 665 cleanupPhoneAccounts(); 666 } 667 } 668 669 @ApiTest(apis = { 670 "android.telecom.TelecomManager#getCallCapablePhoneAccounts", 671 "android.telecom.TelecomManager#getCallCapablePhoneAccountsAcrossProfiles"}) testGetCallCapablePhoneAccountsAcrossProfilesWithWorkProfile()672 public void testGetCallCapablePhoneAccountsAcrossProfilesWithWorkProfile() throws Exception { 673 if (!mShouldTestTelecom || !Flags.workProfileApiSplit() || !hasWorkProfile()) { 674 return; 675 } 676 677 // ensure the test starts without any phone accounts registered to the test package 678 cleanupPhoneAccounts(); 679 680 Random random = new Random(SEED); 681 PhoneAccountHandle currentHandle = TestUtils.createPhoneAccountHandle( 682 random, TestUtils.PACKAGE, TestUtils.REMOTE_COMPONENT, 683 Process.myUserHandle().getIdentifier()); 684 PhoneAccountHandle otherHandle = TestUtils.createPhoneAccountHandle( 685 random, TestUtils.PACKAGE, TestUtils.REMOTE_COMPONENT, 686 UserHandle.MIN_SECONDARY_USER_ID); 687 688 PhoneAccount currentAccount = new PhoneAccount.Builder( 689 currentHandle, this.getClass().getName()) 690 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 691 .build(); 692 PhoneAccount otherAccount = new PhoneAccount.Builder( 693 otherHandle, this.getClass().getName()) 694 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 695 .build(); 696 697 try { 698 mTelecomManager.registerPhoneAccount(currentAccount); 699 mTelecomManager.registerPhoneAccount(otherAccount); 700 701 TestUtils.enablePhoneAccount(getInstrumentation(), currentHandle); 702 TestUtils.enablePhoneAccount(getInstrumentation(), otherHandle); 703 704 List<PhoneAccountHandle> handlesCurrent = mTelecomManager.getCallCapablePhoneAccounts(); 705 List<PhoneAccountHandle> handlesAcrossProfiles = ShellIdentityUtils 706 .invokeMethodWithShellPermissions(mTelecomManager, 707 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(), 708 INTERACT_ACROSS_PROFILES); 709 710 assertEquals(handlesAcrossProfiles.size(), handlesCurrent.size() + 1); 711 assertTrue(handlesAcrossProfiles.containsAll(handlesCurrent)); 712 assertTrue(handlesAcrossProfiles.contains(otherHandle)); 713 714 //test for disabled account 715 TestUtils.disablePhoneAccount(getInstrumentation(), currentHandle); 716 717 handlesCurrent = mTelecomManager.getCallCapablePhoneAccounts(); 718 handlesAcrossProfiles = ShellIdentityUtils 719 .invokeMethodWithShellPermissions(mTelecomManager, 720 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(), 721 INTERACT_ACROSS_PROFILES); 722 List<PhoneAccountHandle> handlesAcrossProfilesWithDisabledAccount = ShellIdentityUtils 723 .invokeMethodWithShellPermissions(mTelecomManager, 724 (tm) -> tm.getCallCapablePhoneAccountsAcrossProfiles(true), 725 INTERACT_ACROSS_PROFILES); 726 727 assertEquals(handlesAcrossProfiles.size(), handlesCurrent.size() + 1); 728 assertEquals(handlesAcrossProfilesWithDisabledAccount.size(), 729 handlesAcrossProfiles.size() + 1); 730 assertTrue(handlesAcrossProfiles.containsAll(handlesCurrent)); 731 assertTrue(handlesAcrossProfilesWithDisabledAccount.containsAll(handlesAcrossProfiles)); 732 assertTrue(handlesAcrossProfilesWithDisabledAccount.contains(currentHandle)); 733 } catch (IllegalArgumentException e) { 734 // allow test pass ... 735 } finally { 736 cleanupPhoneAccounts(); 737 } 738 } 739 740 // -- The following are helper methods for this testing class. -- 741 generateLargeString(int size, String repeatStrValue)742 private String generateLargeString(int size, String repeatStrValue) { 743 StringBuilder sb = new StringBuilder(); 744 for (int i = 0; i < size; i++) { 745 sb.append(repeatStrValue); 746 } 747 return sb.toString(); 748 } 749 generatePhoneAccountsForPackage(ComponentName cn, String baseId, int numOfAccountsToRegister, int capabilities)750 private List<PhoneAccount> generatePhoneAccountsForPackage(ComponentName cn, String baseId, 751 int numOfAccountsToRegister, int capabilities) { 752 List<PhoneAccount> accounts = new ArrayList<>(); 753 754 for (int i = 0; i < numOfAccountsToRegister; i++) { 755 String id = baseId + i; 756 PhoneAccountHandle pah = new PhoneAccountHandle(cn, id); 757 // create phoneAccount 758 String number = TEL_PREFIX + i; 759 PhoneAccount pa = PhoneAccount.builder(pah, TestUtils.ACCOUNT_LABEL) 760 .setAddress(Uri.parse(number)) 761 .setSubscriptionAddress(Uri.parse(number)) 762 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 763 .setCapabilities(capabilities) 764 .build(); 765 accounts.add(pa); 766 } 767 return accounts; 768 } 769 bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts)770 public void bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts) 771 throws Exception { 772 bindToSecondTestPackage(); 773 registerAccountsToSecondTestPackage(accounts); 774 } 775 unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts)776 public void unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts) { 777 try { 778 mContext.unbindService(mControl); 779 unRegisterAccountsForSecondTestPackage(accounts); 780 } catch (Exception e) { 781 Log.d(TAG, 782 "exception thrown while trying to unbind and unregister accts for 2nd package"); 783 } 784 } 785 bindToSecondTestPackage()786 public void bindToSecondTestPackage() throws RemoteException { 787 // Set up binding for second package. This is needed in order to bypass a SecurityException 788 // thrown by a second test package registering phone accounts. 789 mControl = setUpControl(CAR_MODE_CONTROL, SELF_MANAGED_CAR_RELATIVE_COMPONENT); 790 mSecondaryTestPackageControl = 791 ICtsCarModeInCallServiceControl.Stub.asInterface(mControl.getService()); 792 // reset all package variables etc. 793 if (mSecondaryTestPackageControl != null) { 794 mSecondaryTestPackageControl.reset(); //... done setting up binding 795 } 796 } 797 registerAccountsToSecondTestPackage(List<PhoneAccount> accounts)798 public void registerAccountsToSecondTestPackage(List<PhoneAccount> accounts) 799 throws Exception { 800 if (mSecondaryTestPackageControl != null) { 801 for (PhoneAccount p : accounts) { 802 mSecondaryTestPackageControl.registerPhoneAccount(p); 803 TestUtils.enablePhoneAccount(getInstrumentation(), p.getAccountHandle()); 804 } 805 } 806 } 807 unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts)808 public void unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts) 809 throws RemoteException { 810 if (mSecondaryTestPackageControl != null) { 811 for (PhoneAccount p : accounts) { 812 mSecondaryTestPackageControl.unregisterPhoneAccount(p.getAccountHandle()); 813 } 814 } 815 } 816 verifyAccountIsDisabled(PhoneAccount account)817 public void verifyAccountIsDisabled(PhoneAccount account) { 818 PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(account.getAccountHandle()); 819 assertNotNull(phoneAccount); 820 assertFalse(phoneAccount.isEnabled()); 821 } 822 verifyCanFetchCallCapableAccounts()823 public void verifyCanFetchCallCapableAccounts() { 824 List<PhoneAccountHandle> res = 825 mTelecomManager.getCallCapablePhoneAccounts(true); 826 assertNotNull(res); 827 assertTrue(res.size() > 0); 828 } 829 verifyCanFetchAllPhoneAccountHandles()830 public void verifyCanFetchAllPhoneAccountHandles() { 831 List<PhoneAccountHandle> res = 832 ShellIdentityUtils.invokeMethodWithShellPermissions( 833 mTelecomManager, (tm) -> tm.getAllPhoneAccountHandles(), 834 MODIFY_PHONE_STATE_PERMISSION); 835 assertNotNull(res); 836 assertTrue(res.size() > 0); 837 } 838 verifyCanFetchAllPhoneAccounts()839 public void verifyCanFetchAllPhoneAccounts() { 840 List<PhoneAccount> res = 841 ShellIdentityUtils.invokeMethodWithShellPermissions( 842 mTelecomManager, (tm) -> tm.getAllPhoneAccounts(), 843 MODIFY_PHONE_STATE_PERMISSION); 844 assertNotNull(res); 845 assertTrue(res.size() > 0); 846 } 847 verifyCanFetchSelfManagedPhoneAccounts()848 public void verifyCanFetchSelfManagedPhoneAccounts() { 849 List<PhoneAccountHandle> res = 850 mTelecomManager.getSelfManagedPhoneAccounts(); 851 assertNotNull(res); 852 assertTrue(res.size() > 0); 853 } 854 numberOfPhoneAccountsCtsPackageCanRegister()855 private int numberOfPhoneAccountsCtsPackageCanRegister() { 856 return MAX_PHONE_ACCOUNT_REGISTRATIONS - getNumberOfPhoneAccountsRegisteredToTestPackage(); 857 } 858 setUpControl(String action, ComponentName componentName)859 private TestServiceConnection setUpControl(String action, ComponentName componentName) { 860 Intent bindIntent = new Intent(action); 861 bindIntent.setComponent(componentName); 862 863 TestServiceConnection 864 serviceConnection = new TestServiceConnection(); 865 mContext.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE); 866 if (!serviceConnection.waitBind()) { 867 fail("fail bind to service"); 868 } 869 return serviceConnection; 870 } 871 872 private class TestServiceConnection implements ServiceConnection { 873 private IBinder mService; 874 private CountDownLatch mLatch = new CountDownLatch(1); 875 private boolean mIsConnected; 876 877 @Override onServiceConnected(ComponentName componentName, IBinder service)878 public void onServiceConnected(ComponentName componentName, IBinder service) { 879 Log.i(TAG, "Service Connected: " + componentName); 880 mService = service; 881 mIsConnected = true; 882 mLatch.countDown(); 883 } 884 885 @Override onServiceDisconnected(ComponentName componentName)886 public void onServiceDisconnected(ComponentName componentName) { 887 mService = null; 888 } 889 getService()890 public IBinder getService() { 891 return mService; 892 } 893 waitBind()894 public boolean waitBind() { 895 try { 896 mLatch.await(TIMEOUT, TimeUnit.MILLISECONDS); 897 return mIsConnected; 898 } catch (InterruptedException e) { 899 return false; 900 } 901 } 902 } 903 904 /** 905 * Helper that cleans up any phone accounts registered to this testing package. Requires 906 * the permission READ_PRIVILEGED_PHONE_STATE in order to invoke the 907 * getPhoneAccountsForPackage() method. 908 */ cleanupPhoneAccounts()909 private void cleanupPhoneAccounts() { 910 try { 911 if (mTelecomManager != null) { 912 // Get all handles registered to the testing package 913 List<PhoneAccountHandle> handles = 914 ShellIdentityUtils.invokeMethodWithShellPermissions(mTelecomManager, 915 (tm) -> tm.getPhoneAccountsForPackage(), 916 READ_PRIVILEGED_PHONE_STATE); 917 918 // cleanup any extra phone accounts registered to the testing package 919 if (handles.size() > 0 && mTelecomManager != null) { 920 handles.stream().forEach( 921 d -> mTelecomManager.unregisterPhoneAccount(d)); 922 } 923 924 TestUtils.executeShellCommand(getInstrumentation(), TELECOM_CLEANUP_ACCTS_CMD); 925 } 926 } catch (Exception e) { 927 Log.d(TAG, "cleanupPhoneAccounts: hit exception while trying to clean"); 928 } 929 } 930 931 /** 932 * Helper that gets the number of phone accounts registered to the testing package. Requires 933 * the permission READ_PRIVILEGED_PHONE_STATE in order to invoke the 934 * getPhoneAccountsForPackage() method. 935 * @return number of phone accounts registered to the testing package. 936 */ getNumberOfPhoneAccountsRegisteredToTestPackage()937 private int getNumberOfPhoneAccountsRegisteredToTestPackage() { 938 if (mTelecomManager != null) { 939 return ShellIdentityUtils.invokeMethodWithShellPermissions(mTelecomManager, 940 (tm) -> tm.getPhoneAccountsForPackage(), 941 READ_PRIVILEGED_PHONE_STATE).size(); 942 } 943 return 0; 944 } 945 hasWorkProfile()946 private boolean hasWorkProfile() { 947 UserManager userManager = mContext.getSystemService(UserManager.class); 948 for (final UserHandle userHandle : userManager.getUserProfiles()) { 949 if (userManager.isManagedProfile(userHandle.getIdentifier())) { 950 return true; 951 } 952 } 953 954 return false; 955 } 956 } 957 958