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.RemoteException; 29 import android.telecom.PhoneAccount; 30 import android.telecom.PhoneAccountHandle; 31 import android.telecom.TelecomManager; 32 import android.telecom.cts.carmodetestapp.ICtsCarModeInCallServiceControl; 33 import android.telecom.cts.carmodetestappselfmanaged.CtsCarModeInCallServiceControlSelfManaged; 34 import android.util.Log; 35 36 import com.android.compatibility.common.util.ShellIdentityUtils; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 import java.util.concurrent.CountDownLatch; 41 import java.util.concurrent.TimeUnit; 42 43 public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices { 44 45 private static final String TAG = "PhoneAccountRegistrarTest"; 46 private static final long TIMEOUT = 3000L; 47 private static final int LARGE_ACCT_HANDLE_ID_MIN_SIZE = 50000; 48 private static final String RANDOM_CHAR_VALUE = "a"; 49 private static final String TEL_PREFIX = "tel:"; 50 private static final String TELECOM_CLEANUP_ACCTS_CMD = "telecom cleanup-orphan-phone-accounts"; 51 public static final long SEED = 52L; // random seed chosen 52 public static final int MAX_PHONE_ACCOUNT_REGISTRATIONS = 10; // mirrors constant in... 53 // PhoneAccountRegistrar called MAX_PHONE_ACCOUNT_REGISTRATIONS 54 55 // permissions 56 private static final String READ_PRIVILEGED_PHONE_STATE = 57 "android.permission.READ_PRIVILEGED_PHONE_STATE"; 58 private static final String MODIFY_PHONE_STATE_PERMISSION = 59 "android.permission.MODIFY_PHONE_STATE"; 60 private static final String REGISTER_SIM_SUBSCRIPTION_PERMISSION = 61 "android.permission.REGISTER_SIM_SUBSCRIPTION"; 62 63 // telecom cts test package (default package that registers phoneAccounts) 64 private static final ComponentName TEST_COMPONENT_NAME = 65 new ComponentName(TestUtils.PACKAGE, TestUtils.COMPONENT); 66 67 // secondary test package (extra package that can be set up to register phoneAccounts) 68 private static final String SELF_MANAGED_CAR_PACKAGE = 69 CtsCarModeInCallServiceControlSelfManaged.class.getPackage().getName(); 70 private static final ComponentName SELF_MANAGED_CAR_RELATIVE_COMPONENT = ComponentName 71 .createRelative(SELF_MANAGED_CAR_PACKAGE, 72 CtsCarModeInCallServiceControlSelfManaged.class.getName()); 73 private static final ComponentName CAR_COMPONENT = new ComponentName(SELF_MANAGED_CAR_PACKAGE, 74 TestUtils.SELF_MANAGED_COMPONENT); 75 private static final String CAR_MODE_CONTROL = 76 "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL"; 77 // variables to interface with the second test package 78 TestServiceConnection mControl; 79 ICtsCarModeInCallServiceControl mSecondaryTestPackageControl; 80 81 @Override setUp()82 public void setUp() throws Exception { 83 // Sets up this package as default dialer in super. 84 super.setUp(); 85 NewOutgoingCallBroadcastReceiver.reset(); 86 if (!mShouldTestTelecom) return; 87 setupConnectionService(null, 0); 88 // cleanup any accounts registered to the test package before starting tests 89 cleanupPhoneAccounts(); 90 } 91 92 @Override tearDown()93 public void tearDown() throws Exception { 94 // cleanup any accounts registered to the test package after testing to avoid crashing other 95 // tests. 96 cleanupPhoneAccounts(); 97 super.tearDown(); 98 } 99 100 /** 101 * Test scenario where a single package can register MAX_PHONE_ACCOUNT_REGISTRATIONS via 102 * {@link android.telecom.TelecomManager#registerPhoneAccount(PhoneAccount)} without an 103 * exception being thrown. 104 */ testRegisterMaxPhoneAccountsWithoutException()105 public void testRegisterMaxPhoneAccountsWithoutException() { 106 if (!mShouldTestTelecom) return; 107 108 // ensure the test starts without any phone accounts registered to the test package 109 cleanupPhoneAccounts(); 110 111 // determine the number of phone accounts that can be registered before hitting limit 112 int numberOfAccountsThatCanBeRegistered = MAX_PHONE_ACCOUNT_REGISTRATIONS 113 - getNumberOfPhoneAccountsRegisteredToTestPackage(); 114 115 // create the remaining number of phone accounts via helper function 116 // in order to reach the upper bound MAX_PHONE_ACCOUNT_REGISTRATIONS 117 ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED, 118 numberOfAccountsThatCanBeRegistered, TestUtils.PACKAGE, TestUtils.COMPONENT); 119 try { 120 // register all accounts created 121 accounts.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a)); 122 // assert the maximum accounts that can be registered were registered successfully 123 assertEquals(MAX_PHONE_ACCOUNT_REGISTRATIONS, 124 getNumberOfPhoneAccountsRegisteredToTestPackage()); 125 } finally { 126 // cleanup accounts registered 127 accounts.stream().forEach( 128 d -> mTelecomManager.unregisterPhoneAccount(d.getAccountHandle())); 129 } 130 } 131 132 /** 133 * Tests a scenario where a single package exceeds MAX_PHONE_ACCOUNT_REGISTRATIONS and 134 * an {@link IllegalArgumentException} is thrown. Will fail if no exception is thrown. 135 */ testExceptionThrownDueUserExceededMaxPhoneAccountRegistrations()136 public void testExceptionThrownDueUserExceededMaxPhoneAccountRegistrations() 137 throws IllegalArgumentException { 138 if (!mShouldTestTelecom) return; 139 140 // ensure the test starts without any phone accounts registered to the test package 141 cleanupPhoneAccounts(); 142 143 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function 144 ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED, 145 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE, 146 TestUtils.COMPONENT); 147 148 try { 149 // Try to register more phone accounts than allowed by the upper bound limit 150 // MAX_PHONE_ACCOUNT_REGISTRATIONS 151 accounts.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a)); 152 // A successful test should never reach this line of execution. 153 // However, if it does, fail the test by throwing a fail(...) 154 fail("Test failed. The test did not throw an IllegalArgumentException when " 155 + "registering phone accounts over the upper bound: " 156 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 157 } catch (IllegalArgumentException e) { 158 // Assert the IllegalArgumentException was thrown 159 assertNotNull(e.toString()); 160 } finally { 161 // Cleanup accounts registered 162 accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 163 d.getAccountHandle())); 164 } 165 } 166 167 /** 168 * Ensure an app does not register accounts over the upper bound limit by disabling them 169 */ testDisablingAccountsAfterRegStillThrowsException()170 public void testDisablingAccountsAfterRegStillThrowsException() throws Exception { 171 if (!mShouldTestTelecom) return; 172 173 // ensure the test starts without any phone accounts registered to the test package 174 cleanupPhoneAccounts(); 175 176 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function 177 ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED, 178 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE, 179 TestUtils.COMPONENT); 180 181 try { 182 // Try to register more phone accounts than allowed by the upper bound limit 183 for (PhoneAccount pa : accounts) { 184 mTelecomManager.registerPhoneAccount(pa); 185 TestUtils.disablePhoneAccount(getInstrumentation(), pa.getAccountHandle()); 186 // verify the account is both registered and disabled 187 verifyAccountIsDisabled(pa); 188 } 189 190 // A successful test should never reach this line of execution. 191 // However, if it does, fail the test by throwing a fail(...) 192 fail("Test failed. The test did not throw an IllegalArgumentException when " 193 + "registering phone accounts over the upper bound: " 194 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 195 } catch (IllegalArgumentException e) { 196 // Assert the IllegalArgumentException was thrown 197 assertNotNull(e.toString()); 198 } finally { 199 // Cleanup accounts registered 200 accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 201 d.getAccountHandle())); 202 } 203 } 204 205 /** 206 * Ensure an app does not register accounts that will be auto-disabled upon registered and 207 * bypass the limit. Note: CAPABILITY_CALL_PROVIDER will register the account as disabled. 208 */ testDisabledAccountsThrowsException()209 public void testDisabledAccountsThrowsException() throws Exception { 210 if (!mShouldTestTelecom) return; 211 212 // ensure the test starts without any phone accounts registered to the test package 213 cleanupPhoneAccounts(); 214 215 // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 216 ArrayList<PhoneAccount> accounts = new ArrayList<>(); 217 for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS + 1; i++) { 218 accounts.add(new PhoneAccount.Builder( 219 TestUtils.makePhoneAccountHandle(Integer.toString(i)), 220 TestUtils.ACCOUNT_LABEL) 221 .setCapabilities(CAPABILITY_CALL_PROVIDER) 222 .build()); 223 } 224 225 try { 226 // Try to register more phone accounts than allowed by the upper bound limit 227 for (PhoneAccount pa : accounts) { 228 mTelecomManager.registerPhoneAccount(pa); 229 // verify the account is both registered and disabled 230 verifyAccountIsDisabled(pa); 231 } 232 // A successful test should never reach this line of execution. 233 // However, if it does, fail the test by throwing a fail(...) 234 fail("Test failed. The test did not throw an IllegalArgumentException when " 235 + "registering phone accounts over the upper bound: " 236 + "MAX_PHONE_ACCOUNT_REGISTRATIONS"); 237 } catch (IllegalArgumentException e) { 238 // Assert the IllegalArgumentException was thrown 239 assertNotNull(e.toString()); 240 } finally { 241 // Cleanup accounts registered 242 accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 243 d.getAccountHandle())); 244 } 245 } 246 247 /** 248 * Test scenario where two distinct packages register MAX_PHONE_ACCOUNT_REGISTRATIONS via 249 * {@link 250 * android.telecom.TelecomManager#registerPhoneAccount(PhoneAccount)} without an exception being 251 * thrown. 252 * This ensures that PhoneAccountRegistrar is handling {@link PhoneAccount} registrations 253 * to distinct packages correctly. 254 */ testTwoPackagesRegisterMax()255 public void testTwoPackagesRegisterMax() throws Exception { 256 if (!mShouldTestTelecom) return; 257 258 // ensure the test starts without any phone accounts registered to the test package 259 cleanupPhoneAccounts(); 260 261 // determine the number of phone accounts that can be registered to package 1 262 int numberOfAccountsThatCanBeRegisteredToPackage1 = MAX_PHONE_ACCOUNT_REGISTRATIONS 263 - getNumberOfPhoneAccountsRegisteredToTestPackage(); 264 265 // Create MAX phone accounts for package 1 266 ArrayList<PhoneAccount> accountsPackage1 = TestUtils.generateRandomPhoneAccounts(SEED, 267 numberOfAccountsThatCanBeRegisteredToPackage1, TestUtils.PACKAGE, 268 TestUtils.COMPONENT); 269 270 // Constants for creating a second package to register phone accounts 271 final String carPkgSelfManaged = 272 CtsCarModeInCallServiceControlSelfManaged.class 273 .getPackage().getName(); 274 final ComponentName carComponentSelfManaged = ComponentName.createRelative( 275 carPkgSelfManaged, CtsCarModeInCallServiceControlSelfManaged.class.getName()); 276 final String carModeControl = 277 "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL"; 278 279 // Set up binding for second package. This is needed in order to bypass a SecurityException 280 // thrown by a second test package registering phone accounts. 281 TestServiceConnection control = setUpControl(carModeControl, 282 carComponentSelfManaged); 283 284 ICtsCarModeInCallServiceControl carModeIncallServiceControlSelfManaged = 285 ICtsCarModeInCallServiceControl.Stub 286 .asInterface(control.getService()); 287 288 carModeIncallServiceControlSelfManaged.reset(); //... done setting up binding 289 290 // Create MAX phone accounts for package 2 291 ArrayList<PhoneAccount> accountsPackage2 = TestUtils.generateRandomPhoneAccounts(SEED, 292 MAX_PHONE_ACCOUNT_REGISTRATIONS, carPkgSelfManaged, 293 TestUtils.SELF_MANAGED_COMPONENT); 294 295 try { 296 297 // register all accounts for package 1 298 accountsPackage1.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a)); 299 300 301 // register all phone accounts for package 2 302 for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS; i++) { 303 carModeIncallServiceControlSelfManaged.registerPhoneAccount( 304 accountsPackage2.get(i)); 305 } 306 307 } finally { 308 // cleanup all phone accounts registered. Note, unregisterPhoneAccount will not 309 // cause a runtime error if no phone account is found when trying to unregister. 310 311 accountsPackage1.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount( 312 d.getAccountHandle())); 313 314 for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS; i++) { 315 carModeIncallServiceControlSelfManaged.unregisterPhoneAccount( 316 accountsPackage2.get(i).getAccountHandle()); 317 } 318 } 319 // unbind from second package 320 mContext.unbindService(control); 321 } 322 323 /** 324 * Test the scenario where {@link android.telecom.TelecomManager 325 * #getCallCapablePhoneAccounts(boolean)} is called with a heavy payload 326 * that could cause a {@link android.os.TransactionTooLargeException}. Telecom is expected to 327 * handle this by splitting the parcels via {@link android.content.pm.ParceledListSlice}. 328 */ testGettingLargeCallCapablePhoneAccountHandlePayload()329 public void testGettingLargeCallCapablePhoneAccountHandlePayload() throws Exception { 330 if (!mShouldTestTelecom) return; 331 // ensure the test starts without any phone accounts registered to the test package 332 cleanupPhoneAccounts(); 333 334 // generate a large phoneAccountHandle id string to create a large payload 335 String largeAccountHandleId = generateLargeString( 336 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 337 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 338 339 // create handles for package 1 340 List<PhoneAccount> phoneAccountsForPackage1 = 341 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 342 numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_CALL_PROVIDER); 343 344 //create handles for package 2 345 List<PhoneAccount> phoneAccountsForPackage2 = 346 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 347 MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_CALL_PROVIDER); 348 try { 349 // register all accounts for package 1 350 phoneAccountsForPackage1.stream() 351 .forEach(a -> mTelecomManager.registerPhoneAccount(a)); 352 // verify all can be fetched 353 verifyCanFetchCallCapableAccounts(); 354 // register all accounts for package 2 355 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 356 // verify all can be fetched 357 verifyCanFetchCallCapableAccounts(); 358 } catch (IllegalArgumentException e) { 359 // allow test pass ... 360 Log.i(TAG, "testGettingLargeCallCapablePhoneAccountHandlePayload:" 361 + " illegal arg exception thrown."); 362 } finally { 363 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 364 cleanupPhoneAccounts(); 365 } 366 } 367 368 /** 369 * Test the scenario where {@link android.telecom.TelecomManager#getSelfManagedPhoneAccounts()} 370 * is called with a heavy payload that could cause a {@link 371 * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting 372 * the parcels via {@link android.content.pm.ParceledListSlice}. 373 */ testGettingLargeSelfManagedPhoneAccountHandlePayload()374 public void testGettingLargeSelfManagedPhoneAccountHandlePayload() throws Exception { 375 if (!mShouldTestTelecom) return; 376 // ensure the test starts without any phone accounts registered to the test package 377 cleanupPhoneAccounts(); 378 379 // generate a large phoneAccountHandle id string to create a large payload 380 String largeAccountHandleId = generateLargeString( 381 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 382 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 383 384 // create handles for package 1 385 List<PhoneAccount> phoneAccountsForPackage1 = 386 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 387 numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED); 388 389 //create handles for package 2 390 List<PhoneAccount> phoneAccountsForPackage2 = 391 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 392 MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED); 393 try { 394 // register all accounts for package 1 395 phoneAccountsForPackage1.stream() 396 .forEach(a -> mTelecomManager.registerPhoneAccount(a)); 397 // verify all can be fetched 398 verifyCanFetchSelfManagedPhoneAccounts(); 399 // register all accounts for package 2 400 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 401 // verify all can be fetched 402 verifyCanFetchSelfManagedPhoneAccounts(); 403 } catch (IllegalArgumentException e) { 404 // allow test pass ... 405 Log.i(TAG, "testGettingLargeSelfManagedPhoneAccountHandlePayload:" 406 + " illegal arg exception thrown."); 407 } finally { 408 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 409 cleanupPhoneAccounts(); 410 } 411 } 412 413 /** 414 * Test the scenario where {@link android.telecom.TelecomManager#getAllPhoneAccountHandles()} 415 * is called with a heavy payload that could cause a {@link 416 * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting 417 * the parcels via {@link android.content.pm.ParceledListSlice}. 418 */ testGettingAllPhoneAccountHandlesWithLargePayload()419 public void testGettingAllPhoneAccountHandlesWithLargePayload() throws Exception { 420 if (!mShouldTestTelecom) return; 421 422 // ensure the test starts without any phone accounts registered to the test package 423 cleanupPhoneAccounts(); 424 425 // generate a large phoneAccountHandle id string to create a large payload 426 String largeAccountHandleId = generateLargeString( 427 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 428 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 429 430 // create handles for package 1 431 List<PhoneAccount> phoneAccountsForPackage1 = 432 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 433 numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED); 434 435 //create handles for package 2 436 List<PhoneAccount> phoneAccountsForPackage2 = 437 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 438 MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED); 439 try { 440 // register all accounts for package 1 441 phoneAccountsForPackage1.stream() 442 .forEach(a -> mTelecomManager.registerPhoneAccount(a)); 443 // verify all can be fetched 444 verifyCanFetchAllPhoneAccountHandles(); 445 // register all accounts for package 2 446 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 447 // verify all can be fetched 448 verifyCanFetchAllPhoneAccountHandles(); 449 } catch (IllegalArgumentException e) { 450 // allow test pass ... 451 } finally { 452 453 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 454 cleanupPhoneAccounts(); 455 } 456 } 457 458 /** 459 * Test the scenario where {@link TelecomManager#getAllPhoneAccounts()} 460 * is called with a heavy payload that could cause a {@link 461 * android.os.TransactionTooLargeException}. Telecom is expected to handle this by splitting 462 * the parcels via {@link android.content.pm.ParceledListSlice}. 463 */ testGetAllPhoneAccountsWithLargePayload()464 public void testGetAllPhoneAccountsWithLargePayload() throws Exception { 465 if (!mShouldTestTelecom) return; 466 467 // ensure the test starts without any phone accounts registered to the test package 468 cleanupPhoneAccounts(); 469 470 // generate a large phoneAccountHandle id string to create a large payload 471 String largeAccountHandleId = generateLargeString( 472 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE); 473 assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length()); 474 475 // create handles for package 1 476 List<PhoneAccount> phoneAccountsForPackage1 = 477 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId, 478 numberOfPhoneAccountsCtsPackageCanRegister(), 479 CAPABILITY_CALL_PROVIDER 480 | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION); 481 482 //create handles for package 2 483 List<PhoneAccount> phoneAccountsForPackage2 = 484 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId, 485 MAX_PHONE_ACCOUNT_REGISTRATIONS, 486 CAPABILITY_SELF_MANAGED); 487 try { 488 // register all accounts for package 1 489 for (PhoneAccount pa : phoneAccountsForPackage1) { 490 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelecomManager, 491 tm -> tm.registerPhoneAccount(pa), REGISTER_SIM_SUBSCRIPTION_PERMISSION); 492 } 493 // verify all can be fetched 494 verifyCanFetchAllPhoneAccounts(); 495 // register all accounts for package 2 496 bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2); 497 // verify all can be fetched 498 verifyCanFetchAllPhoneAccounts(); 499 } catch (IllegalArgumentException e) { 500 // allow test pass ... 501 } finally { 502 unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2); 503 cleanupPhoneAccounts(); 504 } 505 } 506 507 // -- The following are helper methods for this testing class. -- 508 generateLargeString(int size, String repeatStrValue)509 private String generateLargeString(int size, String repeatStrValue) { 510 StringBuilder sb = new StringBuilder(); 511 for (int i = 0; i < size; i++) { 512 sb.append(repeatStrValue); 513 } 514 return sb.toString(); 515 } 516 generatePhoneAccountsForPackage(ComponentName cn, String baseId, int numOfAccountsToRegister, int capabilities)517 private List<PhoneAccount> generatePhoneAccountsForPackage(ComponentName cn, String baseId, 518 int numOfAccountsToRegister, int capabilities) { 519 List<PhoneAccount> accounts = new ArrayList<>(); 520 521 for (int i = 0; i < numOfAccountsToRegister; i++) { 522 String id = baseId + i; 523 PhoneAccountHandle pah = new PhoneAccountHandle(cn, id); 524 // create phoneAccount 525 String number = TEL_PREFIX + i; 526 PhoneAccount pa = PhoneAccount.builder(pah, TestUtils.ACCOUNT_LABEL) 527 .setAddress(Uri.parse(number)) 528 .setSubscriptionAddress(Uri.parse(number)) 529 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 530 .setCapabilities(capabilities) 531 .build(); 532 accounts.add(pa); 533 } 534 return accounts; 535 } 536 bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts)537 public void bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts) 538 throws Exception { 539 bindToSecondTestPackage(); 540 registerAccountsToSecondTestPackage(accounts); 541 } 542 unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts)543 public void unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts) { 544 try { 545 mContext.unbindService(mControl); 546 unRegisterAccountsForSecondTestPackage(accounts); 547 } catch (Exception e) { 548 Log.d(TAG, 549 "exception thrown while trying to unbind and unregister accts for 2nd package"); 550 } 551 } 552 bindToSecondTestPackage()553 public void bindToSecondTestPackage() throws RemoteException { 554 // Set up binding for second package. This is needed in order to bypass a SecurityException 555 // thrown by a second test package registering phone accounts. 556 mControl = setUpControl(CAR_MODE_CONTROL, SELF_MANAGED_CAR_RELATIVE_COMPONENT); 557 mSecondaryTestPackageControl = 558 ICtsCarModeInCallServiceControl.Stub.asInterface(mControl.getService()); 559 // reset all package variables etc. 560 if (mSecondaryTestPackageControl != null) { 561 mSecondaryTestPackageControl.reset(); //... done setting up binding 562 } 563 } 564 registerAccountsToSecondTestPackage(List<PhoneAccount> accounts)565 public void registerAccountsToSecondTestPackage(List<PhoneAccount> accounts) 566 throws Exception { 567 if (mSecondaryTestPackageControl != null) { 568 for (PhoneAccount p : accounts) { 569 mSecondaryTestPackageControl.registerPhoneAccount(p); 570 TestUtils.enablePhoneAccount(getInstrumentation(), p.getAccountHandle()); 571 } 572 } 573 } 574 unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts)575 public void unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts) 576 throws RemoteException { 577 if (mSecondaryTestPackageControl != null) { 578 for (PhoneAccount p : accounts) { 579 mSecondaryTestPackageControl.unregisterPhoneAccount(p.getAccountHandle()); 580 } 581 } 582 } 583 verifyAccountIsDisabled(PhoneAccount account)584 public void verifyAccountIsDisabled(PhoneAccount account) { 585 PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(account.getAccountHandle()); 586 assertNotNull(phoneAccount); 587 assertFalse(phoneAccount.isEnabled()); 588 } 589 verifyCanFetchCallCapableAccounts()590 public void verifyCanFetchCallCapableAccounts() { 591 List<PhoneAccountHandle> res = 592 mTelecomManager.getCallCapablePhoneAccounts(true); 593 assertNotNull(res); 594 assertTrue(res.size() > 0); 595 } 596 verifyCanFetchAllPhoneAccountHandles()597 public void verifyCanFetchAllPhoneAccountHandles() { 598 List<PhoneAccountHandle> res = 599 ShellIdentityUtils.invokeMethodWithShellPermissions( 600 mTelecomManager, (tm) -> tm.getAllPhoneAccountHandles(), 601 MODIFY_PHONE_STATE_PERMISSION); 602 assertNotNull(res); 603 assertTrue(res.size() > 0); 604 } 605 verifyCanFetchAllPhoneAccounts()606 public void verifyCanFetchAllPhoneAccounts() { 607 List<PhoneAccount> res = 608 ShellIdentityUtils.invokeMethodWithShellPermissions( 609 mTelecomManager, (tm) -> tm.getAllPhoneAccounts(), 610 MODIFY_PHONE_STATE_PERMISSION); 611 assertNotNull(res); 612 assertTrue(res.size() > 0); 613 } 614 verifyCanFetchSelfManagedPhoneAccounts()615 public void verifyCanFetchSelfManagedPhoneAccounts() { 616 List<PhoneAccountHandle> res = 617 mTelecomManager.getSelfManagedPhoneAccounts(); 618 assertNotNull(res); 619 assertTrue(res.size() > 0); 620 } 621 numberOfPhoneAccountsCtsPackageCanRegister()622 private int numberOfPhoneAccountsCtsPackageCanRegister() { 623 return MAX_PHONE_ACCOUNT_REGISTRATIONS - getNumberOfPhoneAccountsRegisteredToTestPackage(); 624 } 625 setUpControl(String action, ComponentName componentName)626 private TestServiceConnection setUpControl(String action, ComponentName componentName) { 627 Intent bindIntent = new Intent(action); 628 bindIntent.setComponent(componentName); 629 630 TestServiceConnection 631 serviceConnection = new TestServiceConnection(); 632 mContext.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE); 633 if (!serviceConnection.waitBind()) { 634 fail("fail bind to service"); 635 } 636 return serviceConnection; 637 } 638 639 private class TestServiceConnection implements ServiceConnection { 640 private IBinder mService; 641 private CountDownLatch mLatch = new CountDownLatch(1); 642 private boolean mIsConnected; 643 644 @Override onServiceConnected(ComponentName componentName, IBinder service)645 public void onServiceConnected(ComponentName componentName, IBinder service) { 646 Log.i(TAG, "Service Connected: " + componentName); 647 mService = service; 648 mIsConnected = true; 649 mLatch.countDown(); 650 } 651 652 @Override onServiceDisconnected(ComponentName componentName)653 public void onServiceDisconnected(ComponentName componentName) { 654 mService = null; 655 } 656 getService()657 public IBinder getService() { 658 return mService; 659 } 660 waitBind()661 public boolean waitBind() { 662 try { 663 mLatch.await(TIMEOUT, TimeUnit.MILLISECONDS); 664 return mIsConnected; 665 } catch (InterruptedException e) { 666 return false; 667 } 668 } 669 } 670 671 /** 672 * Helper that cleans up any phone accounts registered to this testing package. Requires 673 * the permission READ_PRIVILEGED_PHONE_STATE in order to invoke the 674 * getPhoneAccountsForPackage() method. 675 */ cleanupPhoneAccounts()676 private void cleanupPhoneAccounts() { 677 try { 678 if (mTelecomManager != null) { 679 // Get all handles registered to the testing package 680 List<PhoneAccountHandle> handles = 681 ShellIdentityUtils.invokeMethodWithShellPermissions(mTelecomManager, 682 (tm) -> tm.getPhoneAccountsForPackage(), 683 READ_PRIVILEGED_PHONE_STATE); 684 685 // cleanup any extra phone accounts registered to the testing package 686 if (handles.size() > 0 && mTelecomManager != null) { 687 handles.stream().forEach( 688 d -> mTelecomManager.unregisterPhoneAccount(d)); 689 } 690 691 TestUtils.executeShellCommand(getInstrumentation(), TELECOM_CLEANUP_ACCTS_CMD); 692 } 693 } catch (Exception e) { 694 Log.d(TAG, "cleanupPhoneAccounts: hit exception while trying to clean"); 695 } 696 } 697 698 /** 699 * Helper that gets the number of phone accounts registered to the testing package. Requires 700 * the permission READ_PRIVILEGED_PHONE_STATE in order to invoke the 701 * getPhoneAccountsForPackage() method. 702 * @return number of phone accounts registered to the testing package. 703 */ getNumberOfPhoneAccountsRegisteredToTestPackage()704 private int getNumberOfPhoneAccountsRegisteredToTestPackage() { 705 if (mTelecomManager != null) { 706 return ShellIdentityUtils.invokeMethodWithShellPermissions(mTelecomManager, 707 (tm) -> tm.getPhoneAccountsForPackage(), 708 READ_PRIVILEGED_PHONE_STATE).size(); 709 } 710 return 0; 711 } 712 } 713 714