1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.telecom.tests; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.ArgumentMatchers.anyBoolean; 27 import static org.mockito.ArgumentMatchers.anyInt; 28 import static org.mockito.ArgumentMatchers.anyString; 29 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.Mockito.clearInvocations; 31 import static org.mockito.Mockito.doReturn; 32 import static org.mockito.Mockito.doThrow; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.annotation.Nullable; 40 import android.content.ComponentName; 41 import android.content.Context; 42 import android.content.pm.PackageInfo; 43 import android.content.pm.PackageManager; 44 import android.graphics.BitmapFactory; 45 import android.graphics.Rect; 46 import android.graphics.drawable.Icon; 47 import android.net.Uri; 48 import android.os.Bundle; 49 import android.os.Parcel; 50 import android.os.PersistableBundle; 51 import android.os.Process; 52 import android.os.UserHandle; 53 import android.os.UserManager; 54 import android.telecom.Log; 55 import android.telecom.PhoneAccount; 56 import android.telecom.PhoneAccountHandle; 57 import android.telecom.TelecomManager; 58 import android.telephony.CarrierConfigManager; 59 import android.telephony.SubscriptionInfo; 60 import android.telephony.SubscriptionManager; 61 import android.util.Xml; 62 63 import androidx.test.InstrumentationRegistry; 64 import androidx.test.filters.MediumTest; 65 import androidx.test.filters.SmallTest; 66 67 import com.android.internal.telecom.IConnectionService; 68 import com.android.internal.telephony.flags.FeatureFlags; 69 import com.android.internal.util.FastXmlSerializer; 70 import com.android.server.telecom.AppLabelProxy; 71 import com.android.server.telecom.DefaultDialerCache; 72 import com.android.server.telecom.PhoneAccountRegistrar; 73 import com.android.server.telecom.PhoneAccountRegistrar.DefaultPhoneAccountHandle; 74 import com.android.server.telecom.TelecomSystem; 75 76 import org.junit.After; 77 import org.junit.Before; 78 import org.junit.Test; 79 import org.junit.runner.RunWith; 80 import org.junit.runners.JUnit4; 81 import org.mockito.Mock; 82 import org.mockito.Mockito; 83 import org.mockito.MockitoAnnotations; 84 import org.xmlpull.v1.XmlPullParser; 85 import org.xmlpull.v1.XmlSerializer; 86 87 import java.io.BufferedInputStream; 88 import java.io.BufferedOutputStream; 89 import java.io.ByteArrayInputStream; 90 import java.io.ByteArrayOutputStream; 91 import java.io.File; 92 import java.io.IOException; 93 import java.io.OutputStream; 94 import java.util.ArrayList; 95 import java.util.Arrays; 96 import java.util.Collection; 97 import java.util.HashSet; 98 import java.util.List; 99 import java.util.Map; 100 import java.util.Set; 101 import java.util.UUID; 102 103 @RunWith(JUnit4.class) 104 public class PhoneAccountRegistrarTest extends TelecomTestCase { 105 106 private static final int MAX_VERSION = Integer.MAX_VALUE; 107 private static final int INVALID_CHAR_LIMIT_COUNT = 108 PhoneAccountRegistrar.MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT + 1; 109 private static final String INVALID_STR = "a".repeat(INVALID_CHAR_LIMIT_COUNT); 110 private static final String FILE_NAME = "phone-account-registrar-test-1223.xml"; 111 private static final String TEST_LABEL = "right"; 112 private static final String TEST_ID = "123"; 113 private final String PACKAGE_1 = "PACKAGE_1"; 114 private final String PACKAGE_2 = "PACKAGE_2"; 115 private final String COMPONENT_NAME = "com.android.server.telecom.tests.MockConnectionService"; 116 private final UserHandle USER_HANDLE_10 = new UserHandle(10); 117 private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; 118 private PhoneAccountRegistrar mRegistrar; 119 @Mock private SubscriptionManager mSubscriptionManager; 120 @Mock private TelecomManager mTelecomManager; 121 @Mock private DefaultDialerCache mDefaultDialerCache; 122 @Mock private AppLabelProxy mAppLabelProxy; 123 @Mock private FeatureFlags mTelephonyFeatureFlags; 124 125 @Override 126 @Before setUp()127 public void setUp() throws Exception { 128 super.setUp(); 129 MockitoAnnotations.initMocks(this); 130 mComponentContextFixture.setTelecomManager(mTelecomManager); 131 mComponentContextFixture.setSubscriptionManager(mSubscriptionManager); 132 new File( 133 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(), 134 FILE_NAME) 135 .delete(); 136 when(mDefaultDialerCache.getDefaultDialerApplication(anyInt())) 137 .thenReturn("com.android.dialer"); 138 when(mAppLabelProxy.getAppLabel(anyString())) 139 .thenReturn(TEST_LABEL); 140 mRegistrar = new PhoneAccountRegistrar( 141 mComponentContextFixture.getTestDouble().getApplicationContext(), mLock, FILE_NAME, 142 mDefaultDialerCache, mAppLabelProxy, mTelephonyFeatureFlags, mFeatureFlags); 143 when(mFeatureFlags.onlyUpdateTelephonyOnValidSubIds()).thenReturn(false); 144 when(mFeatureFlags.unregisterUnresolvableAccounts()).thenReturn(true); 145 when(mTelephonyFeatureFlags.workProfileApiSplit()).thenReturn(false); 146 } 147 148 @Override 149 @After tearDown()150 public void tearDown() throws Exception { 151 mRegistrar = null; 152 new File( 153 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(), 154 FILE_NAME) 155 .delete(); 156 super.tearDown(); 157 } 158 159 @MediumTest 160 @Test testPhoneAccountHandle()161 public void testPhoneAccountHandle() throws Exception { 162 PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0"); 163 PhoneAccountHandle result = roundTripXml(this, input, 164 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext, 165 mTelephonyFeatureFlags, mFeatureFlags); 166 assertPhoneAccountHandleEquals(input, result); 167 168 PhoneAccountHandle inputN = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), null); 169 PhoneAccountHandle resultN = roundTripXml(this, inputN, 170 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext, 171 mTelephonyFeatureFlags, mFeatureFlags); 172 Log.i(this, "inputN = %s, resultN = %s", inputN, resultN); 173 assertPhoneAccountHandleEquals(inputN, resultN); 174 } 175 176 @MediumTest 177 @Test testPhoneAccount()178 public void testPhoneAccount() throws Exception { 179 Bundle testBundle = new Bundle(); 180 testBundle.putInt("EXTRA_INT_1", 1); 181 testBundle.putInt("EXTRA_INT_100", 100); 182 testBundle.putBoolean("EXTRA_BOOL_TRUE", true); 183 testBundle.putBoolean("EXTRA_BOOL_FALSE", false); 184 testBundle.putString("EXTRA_STR1", "Hello"); 185 testBundle.putString("EXTRA_STR2", "There"); 186 187 PhoneAccount input = makeQuickAccountBuilder("id0", 0, null) 188 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 189 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 190 .setExtras(testBundle) 191 .setIsEnabled(true) 192 .build(); 193 PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml, 194 mContext, mTelephonyFeatureFlags, mFeatureFlags); 195 196 assertPhoneAccountEquals(input, result); 197 } 198 199 @MediumTest 200 @Test testPhoneAccountParsing_simultaneousCallingRestriction()201 public void testPhoneAccountParsing_simultaneousCallingRestriction() throws Exception { 202 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 203 // workaround: UserManager converts the user to a serial and back, we need to mock this 204 // behavior, unfortunately: USER_HANDLE_10 <-> 10L 205 UserManager userManager = mContext.getSystemService(UserManager.class); 206 doReturn(10L).when(userManager).getSerialNumberForUser(eq(USER_HANDLE_10)); 207 doReturn(USER_HANDLE_10).when(userManager).getUserForSerialNumber(eq(10L)); 208 Bundle testBundle = new Bundle(); 209 testBundle.putInt("EXTRA_INT_1", 1); 210 testBundle.putInt("EXTRA_INT_100", 100); 211 testBundle.putBoolean("EXTRA_BOOL_TRUE", true); 212 testBundle.putBoolean("EXTRA_BOOL_FALSE", false); 213 testBundle.putString("EXTRA_STR1", "Hello"); 214 testBundle.putString("EXTRA_STR2", "There"); 215 216 Set<PhoneAccountHandle> restriction = new HashSet<>(10); 217 for (int i = 0; i < 10; i++) { 218 restriction.add(makeQuickAccountHandleForUser("id" + i, USER_HANDLE_10)); 219 } 220 221 PhoneAccount input = makeQuickAccountBuilder("id0", 0, USER_HANDLE_10) 222 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 223 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 224 .setExtras(testBundle) 225 .setIsEnabled(true) 226 .setSimultaneousCallingRestriction(restriction) 227 .build(); 228 PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml, 229 mContext, mTelephonyFeatureFlags, mFeatureFlags); 230 231 assertPhoneAccountEquals(input, result); 232 } 233 234 @MediumTest 235 @Test testPhoneAccountParsing_simultaneousCallingRestrictionOnOffFlag()236 public void testPhoneAccountParsing_simultaneousCallingRestrictionOnOffFlag() throws Exception { 237 // Start the test with the flag on 238 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 239 // workaround: UserManager converts the user to a serial and back, we need to mock this 240 // behavior, unfortunately: USER_HANDLE_10 <-> 10L 241 UserManager userManager = mContext.getSystemService(UserManager.class); 242 doReturn(10L).when(userManager).getSerialNumberForUser(eq(USER_HANDLE_10)); 243 doReturn(USER_HANDLE_10).when(userManager).getUserForSerialNumber(eq(10L)); 244 Bundle testBundle = new Bundle(); 245 testBundle.putInt("EXTRA_INT_1", 1); 246 testBundle.putInt("EXTRA_INT_100", 100); 247 testBundle.putBoolean("EXTRA_BOOL_TRUE", true); 248 testBundle.putBoolean("EXTRA_BOOL_FALSE", false); 249 testBundle.putString("EXTRA_STR1", "Hello"); 250 testBundle.putString("EXTRA_STR2", "There"); 251 252 Set<PhoneAccountHandle> restriction = new HashSet<>(10); 253 for (int i = 0; i < 10; i++) { 254 restriction.add(makeQuickAccountHandleForUser("id" + i, USER_HANDLE_10)); 255 } 256 257 PhoneAccount input = makeQuickAccountBuilder("id0", 0, USER_HANDLE_10) 258 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 259 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 260 .setExtras(testBundle) 261 .setIsEnabled(true) 262 .setSimultaneousCallingRestriction(restriction) 263 .build(); 264 byte[] xmlData = toXml(input, PhoneAccountRegistrar.sPhoneAccountXml, mContext, 265 mTelephonyFeatureFlags); 266 // Simulate turning off the flag after reboot 267 doReturn(false).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 268 PhoneAccount result = fromXml(xmlData, PhoneAccountRegistrar.sPhoneAccountXml, mContext, 269 mTelephonyFeatureFlags, mFeatureFlags); 270 271 assertNotNull(result); 272 assertFalse(result.hasSimultaneousCallingRestriction()); 273 } 274 275 @MediumTest 276 @Test testPhoneAccountParsing_simultaneousCallingRestrictionOffOnFlag()277 public void testPhoneAccountParsing_simultaneousCallingRestrictionOffOnFlag() throws Exception { 278 // Start the test with the flag on 279 doReturn(false).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 280 Bundle testBundle = new Bundle(); 281 testBundle.putInt("EXTRA_INT_1", 1); 282 testBundle.putInt("EXTRA_INT_100", 100); 283 testBundle.putBoolean("EXTRA_BOOL_TRUE", true); 284 testBundle.putBoolean("EXTRA_BOOL_FALSE", false); 285 testBundle.putString("EXTRA_STR1", "Hello"); 286 testBundle.putString("EXTRA_STR2", "There"); 287 288 PhoneAccount input = makeQuickAccountBuilder("id0", 0, USER_HANDLE_10) 289 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 290 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 291 .setExtras(testBundle) 292 .setIsEnabled(true) 293 .build(); 294 byte[] xmlData = toXml(input, PhoneAccountRegistrar.sPhoneAccountXml, mContext, 295 mTelephonyFeatureFlags); 296 // Simulate turning on the flag after reboot 297 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 298 PhoneAccount result = fromXml(xmlData, PhoneAccountRegistrar.sPhoneAccountXml, mContext, 299 mTelephonyFeatureFlags, mFeatureFlags); 300 301 assertPhoneAccountEquals(input, result); 302 } 303 304 @SmallTest 305 @Test testFilterPhoneAccountForTest()306 public void testFilterPhoneAccountForTest() throws Exception { 307 ComponentName componentA = new ComponentName("a", "a"); 308 ComponentName componentB1 = new ComponentName("b", "b1"); 309 ComponentName componentB2 = new ComponentName("b", "b2"); 310 ComponentName componentC = new ComponentName("c", "c"); 311 312 PhoneAccount simAccountA = new PhoneAccount.Builder( 313 makeQuickAccountHandle(componentA, "1"), "1") 314 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 315 .setIsEnabled(true) 316 .build(); 317 318 List<PhoneAccount> accountAList = new ArrayList<>(); 319 accountAList.add(simAccountA); 320 321 PhoneAccount simAccountB1 = new PhoneAccount.Builder( 322 makeQuickAccountHandle(componentB1, "2"), "2") 323 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 324 .setIsEnabled(true) 325 .build(); 326 327 PhoneAccount simAccountB2 = new PhoneAccount.Builder( 328 makeQuickAccountHandle(componentB2, "3"), "3") 329 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 330 .setIsEnabled(true) 331 .build(); 332 333 List<PhoneAccount> accountBList = new ArrayList<>(); 334 accountBList.add(simAccountB1); 335 accountBList.add(simAccountB2); 336 337 PhoneAccount simAccountC = new PhoneAccount.Builder( 338 makeQuickAccountHandle(componentC, "4"), "4") 339 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 340 .setIsEnabled(true) 341 .build(); 342 343 List<PhoneAccount> accountCList = new ArrayList<>(); 344 accountCList.add(simAccountC); 345 346 List<PhoneAccount> allAccounts = new ArrayList<>(); 347 allAccounts.addAll(accountAList); 348 allAccounts.addAll(accountBList); 349 allAccounts.addAll(accountCList); 350 351 assertEquals(allAccounts, mRegistrar.filterRestrictedPhoneAccounts(allAccounts)); 352 353 mRegistrar.setTestPhoneAccountPackageNameFilter(componentA.getPackageName()); 354 assertEquals(accountAList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts)); 355 356 mRegistrar.setTestPhoneAccountPackageNameFilter(componentB1.getPackageName()); 357 assertEquals(accountBList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts)); 358 359 mRegistrar.setTestPhoneAccountPackageNameFilter(componentC.getPackageName()); 360 assertEquals(accountCList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts)); 361 362 mRegistrar.setTestPhoneAccountPackageNameFilter(null); 363 assertEquals(allAccounts, mRegistrar.filterRestrictedPhoneAccounts(allAccounts)); 364 } 365 366 @MediumTest 367 @Test testDefaultPhoneAccountHandleEmptyGroup()368 public void testDefaultPhoneAccountHandleEmptyGroup() throws Exception { 369 DefaultPhoneAccountHandle input = new DefaultPhoneAccountHandle(Process.myUserHandle(), 370 makeQuickAccountHandle("i1"), ""); 371 UserManager userManager = mContext.getSystemService(UserManager.class); 372 when(userManager.getSerialNumberForUser(input.userHandle)) 373 .thenReturn(0L); 374 when(userManager.getUserForSerialNumber(0L)) 375 .thenReturn(input.userHandle); 376 DefaultPhoneAccountHandle result = roundTripXml(this, input, 377 PhoneAccountRegistrar.sDefaultPhoneAccountHandleXml, mContext, 378 mTelephonyFeatureFlags, mFeatureFlags); 379 380 assertDefaultPhoneAccountHandleEquals(input, result); 381 } 382 383 /** 384 * Test to ensure non-supported values 385 * @throws Exception 386 */ 387 @MediumTest 388 @Test testPhoneAccountExtrasEdge()389 public void testPhoneAccountExtrasEdge() throws Exception { 390 Bundle testBundle = new Bundle(); 391 // Ensure null values for string are not persisted. 392 testBundle.putString("EXTRA_STR2", null); 393 // 394 395 // Ensure unsupported data types are not persisted. 396 testBundle.putShort("EXTRA_SHORT", (short) 2); 397 testBundle.putByte("EXTRA_BYTE", (byte) 1); 398 testBundle.putParcelable("EXTRA_PARC", new Rect(1, 1, 1, 1)); 399 // Put in something valid so the bundle exists. 400 testBundle.putString("EXTRA_OK", "OK"); 401 402 PhoneAccount input = makeQuickAccountBuilder("id0", 0, null) 403 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 404 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 405 .setExtras(testBundle) 406 .build(); 407 PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml, 408 mContext, mTelephonyFeatureFlags, mFeatureFlags); 409 410 Bundle extras = result.getExtras(); 411 assertFalse(extras.keySet().contains("EXTRA_STR2")); 412 assertFalse(extras.keySet().contains("EXTRA_SHORT")); 413 assertFalse(extras.keySet().contains("EXTRA_BYTE")); 414 assertFalse(extras.keySet().contains("EXTRA_PARC")); 415 } 416 417 @MediumTest 418 @Test testState()419 public void testState() throws Exception { 420 PhoneAccountRegistrar.State input = makeQuickState(); 421 PhoneAccountRegistrar.State result = roundTripXml(this, input, 422 PhoneAccountRegistrar.sStateXml, mContext, mTelephonyFeatureFlags, mFeatureFlags); 423 assertStateEquals(input, result); 424 } 425 registerAndEnableAccount(PhoneAccount account)426 private void registerAndEnableAccount(PhoneAccount account) { 427 mRegistrar.registerPhoneAccount(account); 428 mRegistrar.enablePhoneAccount(account.getAccountHandle(), true); 429 } 430 431 @MediumTest 432 @Test testAccounts()433 public void testAccounts() throws Exception { 434 int i = 0; 435 436 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 437 Mockito.mock(IConnectionService.class)); 438 439 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null) 440 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 441 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 442 .build()); 443 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null) 444 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 445 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 446 .build()); 447 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null) 448 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 449 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 450 .build()); 451 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, null) 452 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 453 .build()); 454 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, USER_HANDLE_10) 455 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 456 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 457 .build()); 458 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++, USER_HANDLE_10) 459 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 460 .build()); 461 462 assertEquals(6, mRegistrar. 463 getAllPhoneAccounts(null, true).size()); 464 assertEquals(4, mRegistrar.getCallCapablePhoneAccounts(null, false, 465 null, true).size()); 466 assertEquals(null, mRegistrar.getSimCallManagerOfCurrentUser()); 467 assertEquals(null, mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 468 PhoneAccount.SCHEME_TEL)); 469 } 470 471 /** 472 * Verify when a {@link android.telecom.ConnectionService} is disabled or cannot be resolved, 473 * all phone accounts are unregistered when calling 474 * {@link PhoneAccountRegistrar#cleanupAndGetVerifiedAccounts(PhoneAccount)}. 475 */ 476 @Test testCannotResolveServiceUnregistersAccounts()477 public void testCannotResolveServiceUnregistersAccounts() throws Exception { 478 ComponentName componentName = makeQuickConnectionServiceComponentName(); 479 PhoneAccount account = makeQuickAccountBuilder("0", 0, USER_HANDLE_10) 480 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 481 | PhoneAccount.CAPABILITY_CALL_PROVIDER).build(); 482 // add the ConnectionService and register a single phone account for it 483 mComponentContextFixture.addConnectionService(componentName, 484 Mockito.mock(IConnectionService.class)); 485 registerAndEnableAccount(account); 486 // verify the start state 487 assertEquals(1, 488 mRegistrar.getRegisteredAccountsForPackageName(componentName.getPackageName(), 489 USER_HANDLE_10).size()); 490 // remove the ConnectionService so that the account cannot be resolved anymore 491 mComponentContextFixture.removeConnectionService(componentName, 492 Mockito.mock(IConnectionService.class)); 493 // verify the account is unregistered when fetching the phone accounts for the package 494 assertEquals(1, 495 mRegistrar.getRegisteredAccountsForPackageName(componentName.getPackageName(), 496 USER_HANDLE_10).size()); 497 assertEquals(0, 498 mRegistrar.cleanupAndGetVerifiedAccounts(account).size()); 499 assertEquals(0, 500 mRegistrar.getRegisteredAccountsForPackageName(componentName.getPackageName(), 501 USER_HANDLE_10).size()); 502 } 503 504 /** 505 * Verify that if a client adds both the {@link 506 * PhoneAccount#CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS} capability AND is backed by a 507 * {@link android.telecom.ConnectionService}, a {@link IllegalArgumentException} is thrown. 508 */ 509 @Test testConnectionServiceAndTransactionalAccount()510 public void testConnectionServiceAndTransactionalAccount() throws Exception { 511 PhoneAccount account = makeQuickAccountBuilder("0", 0, USER_HANDLE_10) 512 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED 513 | PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS).build(); 514 mComponentContextFixture.addConnectionService( 515 makeQuickConnectionServiceComponentName(), 516 Mockito.mock(IConnectionService.class)); 517 try { 518 registerAndEnableAccount(account); 519 fail("failed to throw IllegalArgumentException"); 520 } catch (IllegalArgumentException e) { 521 // test passed, ignore Exception. 522 } 523 } 524 525 @MediumTest 526 @Test testSimCallManager()527 public void testSimCallManager() throws Exception { 528 // TODO 529 } 530 531 @MediumTest 532 @Test testDefaultOutgoing()533 public void testDefaultOutgoing() throws Exception { 534 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 535 Mockito.mock(IConnectionService.class)); 536 537 // By default, there is no default outgoing account (nothing has been registered) 538 assertNull( 539 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 540 541 // Register one tel: account 542 PhoneAccountHandle telAccount = makeQuickAccountHandle("tel_acct"); 543 registerAndEnableAccount(new PhoneAccount.Builder(telAccount, "tel_acct") 544 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 545 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 546 .build()); 547 PhoneAccountHandle defaultAccount = 548 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 549 assertEquals(telAccount, defaultAccount); 550 551 // Add a SIP account, make sure tel: doesn't change 552 PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct"); 553 registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct") 554 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 555 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP) 556 .build()); 557 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 558 PhoneAccount.SCHEME_SIP); 559 assertEquals(sipAccount, defaultAccount); 560 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 561 PhoneAccount.SCHEME_TEL); 562 assertEquals(telAccount, defaultAccount); 563 564 // Add a connection manager, make sure tel: doesn't change 565 PhoneAccountHandle connectionManager = makeQuickAccountHandle("mgr_acct"); 566 registerAndEnableAccount(new PhoneAccount.Builder(connectionManager, "mgr_acct") 567 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 568 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 569 .build()); 570 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 571 PhoneAccount.SCHEME_TEL); 572 assertEquals(telAccount, defaultAccount); 573 574 // Unregister the tel: account, make sure there is no tel: default now. 575 mRegistrar.unregisterPhoneAccount(telAccount); 576 assertNull( 577 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 578 } 579 580 @MediumTest 581 @Test testReplacePhoneAccountByGroup()582 public void testReplacePhoneAccountByGroup() throws Exception { 583 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 584 Mockito.mock(IConnectionService.class)); 585 586 // By default, there is no default outgoing account (nothing has been registered) 587 assertNull( 588 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 589 590 // Register one tel: account 591 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 592 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 593 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 594 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 595 .setGroupId("testGroup") 596 .build()); 597 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 598 PhoneAccountHandle defaultAccount = 599 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 600 assertEquals(telAccount1, defaultAccount); 601 602 // Add call capable SIP account, make sure tel: doesn't change 603 PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct"); 604 registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct") 605 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 606 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 607 .build()); 608 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 609 PhoneAccount.SCHEME_TEL); 610 assertEquals(telAccount1, defaultAccount); 611 612 // Replace tel: account with another in the same Group 613 PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2"); 614 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 615 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 616 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 617 .setGroupId("testGroup") 618 .build()); 619 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 620 PhoneAccount.SCHEME_TEL); 621 assertEquals(telAccount2, defaultAccount); 622 assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 623 } 624 625 @MediumTest 626 @Test testAddSameDefault()627 public void testAddSameDefault() throws Exception { 628 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 629 Mockito.mock(IConnectionService.class)); 630 631 // By default, there is no default outgoing account (nothing has been registered) 632 assertNull( 633 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 634 635 // Register one tel: account 636 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 637 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 638 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 639 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 640 .setGroupId("testGroup") 641 .build()); 642 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 643 PhoneAccountHandle defaultAccount = 644 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 645 assertEquals(telAccount1, defaultAccount); 646 mRegistrar.unregisterPhoneAccount(telAccount1); 647 648 // Register Emergency Account and unregister 649 PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct"); 650 registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct") 651 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 652 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 653 .build()); 654 defaultAccount = 655 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 656 assertNull(defaultAccount); 657 mRegistrar.unregisterPhoneAccount(emerAccount); 658 659 // Re-register the same account and make sure the default is in place 660 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 661 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 662 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 663 .setGroupId("testGroup") 664 .build()); 665 defaultAccount = 666 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 667 assertEquals(telAccount1, defaultAccount); 668 } 669 670 @MediumTest 671 @Test testAddSameGroup()672 public void testAddSameGroup() throws Exception { 673 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 674 Mockito.mock(IConnectionService.class)); 675 676 // By default, there is no default outgoing account (nothing has been registered) 677 assertNull( 678 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 679 680 // Register one tel: account 681 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 682 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 683 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 684 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 685 .setGroupId("testGroup") 686 .build()); 687 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 688 PhoneAccountHandle defaultAccount = 689 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 690 assertEquals(telAccount1, defaultAccount); 691 mRegistrar.unregisterPhoneAccount(telAccount1); 692 693 // Register Emergency Account and unregister 694 PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct"); 695 registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct") 696 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 697 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 698 .build()); 699 defaultAccount = 700 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 701 assertNull(defaultAccount); 702 mRegistrar.unregisterPhoneAccount(emerAccount); 703 704 // Re-register a new account with the same group 705 PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2"); 706 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 707 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 708 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 709 .setGroupId("testGroup") 710 .build()); 711 defaultAccount = 712 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 713 assertEquals(telAccount2, defaultAccount); 714 } 715 716 @MediumTest 717 @Test testAddSameGroupButDifferentComponent()718 public void testAddSameGroupButDifferentComponent() throws Exception { 719 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 720 Mockito.mock(IConnectionService.class)); 721 722 // By default, there is no default outgoing account (nothing has been registered) 723 assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 724 PhoneAccount.SCHEME_TEL)); 725 726 // Register one tel: account 727 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 728 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 729 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 730 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 731 .setGroupId("testGroup") 732 .build()); 733 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 734 PhoneAccountHandle defaultAccount = 735 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 736 assertEquals(telAccount1, defaultAccount); 737 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 738 739 // Register a new account with the same group, but different Component, so don't replace 740 // Default 741 PhoneAccountHandle telAccount2 = makeQuickAccountHandle( 742 new ComponentName("other1", "other2"), "tel_acct2"); 743 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 744 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 745 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 746 .setGroupId("testGroup") 747 .build()); 748 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount2)); 749 750 defaultAccount = 751 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 752 assertEquals(telAccount1, defaultAccount); 753 } 754 755 @MediumTest 756 @Test testAddSameGroupButDifferentComponent2()757 public void testAddSameGroupButDifferentComponent2() throws Exception { 758 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 759 Mockito.mock(IConnectionService.class)); 760 761 // By default, there is no default outgoing account (nothing has been registered) 762 assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 763 PhoneAccount.SCHEME_TEL)); 764 765 // Register first tel: account 766 PhoneAccountHandle telAccount1 = makeQuickAccountHandle( 767 new ComponentName("other1", "other2"), "tel_acct1"); 768 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 769 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 770 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 771 .setGroupId("testGroup") 772 .build()); 773 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 774 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 775 776 // Register second account with the same group, but a second Component, so don't replace 777 // Default 778 PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2"); 779 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 780 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 781 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 782 .setGroupId("testGroup") 783 .build()); 784 785 PhoneAccountHandle defaultAccount = 786 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 787 assertEquals(telAccount1, defaultAccount); 788 789 // Register third account with the second component name, but same group id 790 PhoneAccountHandle telAccount3 = makeQuickAccountHandle("tel_acct3"); 791 registerAndEnableAccount(new PhoneAccount.Builder(telAccount3, "tel_acct3") 792 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 793 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 794 .setGroupId("testGroup") 795 .build()); 796 797 // Make sure that the default account is still the original PhoneAccount and that the 798 // second PhoneAccount with the second ComponentName was replaced by the third PhoneAccount 799 defaultAccount = 800 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 801 assertEquals(telAccount1, defaultAccount); 802 803 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 804 assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount2)); 805 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount3)); 806 } 807 808 @MediumTest 809 @Test testPhoneAccountParceling()810 public void testPhoneAccountParceling() throws Exception { 811 PhoneAccountHandle handle = makeQuickAccountHandle("foo"); 812 roundTripPhoneAccount(new PhoneAccount.Builder(handle, null).build()); 813 roundTripPhoneAccount(new PhoneAccount.Builder(handle, "foo").build()); 814 roundTripPhoneAccount( 815 new PhoneAccount.Builder(handle, "foo") 816 .setAddress(Uri.parse("tel:123456")) 817 .setCapabilities(23) 818 .setHighlightColor(0xf0f0f0) 819 .setIcon(Icon.createWithResource( 820 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)) 821 // TODO: set icon tint (0xfefefe) 822 .setShortDescription("short description") 823 .setSubscriptionAddress(Uri.parse("tel:2345678")) 824 .setSupportedUriSchemes(Arrays.asList("tel", "sip")) 825 .setGroupId("testGroup") 826 .build()); 827 roundTripPhoneAccount( 828 new PhoneAccount.Builder(handle, "foo") 829 .setAddress(Uri.parse("tel:123456")) 830 .setCapabilities(23) 831 .setHighlightColor(0xf0f0f0) 832 .setIcon(Icon.createWithBitmap( 833 BitmapFactory.decodeResource( 834 InstrumentationRegistry.getContext().getResources(), 835 R.drawable.stat_sys_phone_call))) 836 .setShortDescription("short description") 837 .setSubscriptionAddress(Uri.parse("tel:2345678")) 838 .setSupportedUriSchemes(Arrays.asList("tel", "sip")) 839 .setGroupId("testGroup") 840 .build()); 841 } 842 843 /** 844 * Tests ability to register a self-managed PhoneAccount; verifies that the user defined label 845 * is overridden. 846 * @throws Exception 847 */ 848 @MediumTest 849 @Test testSelfManagedPhoneAccount()850 public void testSelfManagedPhoneAccount() throws Exception { 851 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 852 Mockito.mock(IConnectionService.class)); 853 854 PhoneAccountHandle selfManagedHandle = makeQuickAccountHandle( 855 new ComponentName("self", "managed"), "selfie1"); 856 857 PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, "Wrong") 858 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) 859 .build(); 860 861 mRegistrar.registerPhoneAccount(selfManagedAccount); 862 863 PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle); 864 assertEquals(TEST_LABEL, registeredAccount.getLabel()); 865 } 866 867 @MediumTest 868 @Test testSecurityExceptionIsThrownWhenSelfManagedLacksPermissions()869 public void testSecurityExceptionIsThrownWhenSelfManagedLacksPermissions() { 870 PhoneAccountHandle handle = makeQuickAccountHandle( 871 new ComponentName("self", "managed"), "selfie1"); 872 873 PhoneAccount accountWithoutCapability = new PhoneAccount.Builder(handle, "label") 874 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) 875 .build(); 876 877 assertFalse(mRegistrar.hasTransactionalCallCapabilities(accountWithoutCapability)); 878 879 try { 880 mRegistrar.registerPhoneAccount(accountWithoutCapability); 881 fail("should not be able to register account"); 882 } catch (SecurityException securityException) { 883 // test pass 884 } finally { 885 mRegistrar.unregisterPhoneAccount(handle); 886 } 887 } 888 889 @MediumTest 890 @Test testSelfManagedPhoneAccountWithTransactionalOperations()891 public void testSelfManagedPhoneAccountWithTransactionalOperations() { 892 PhoneAccountHandle handle = makeQuickAccountHandle( 893 new ComponentName("self", "managed"), "selfie1"); 894 895 PhoneAccount accountWithCapability = new PhoneAccount.Builder(handle, "label") 896 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED | 897 PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS) 898 .build(); 899 900 assertTrue(mRegistrar.hasTransactionalCallCapabilities(accountWithCapability)); 901 902 try { 903 mRegistrar.registerPhoneAccount(accountWithCapability); 904 PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(handle); 905 assertEquals(TEST_LABEL, registeredAccount.getLabel().toString()); 906 } finally { 907 mRegistrar.unregisterPhoneAccount(handle); 908 } 909 } 910 911 @MediumTest 912 @Test testRegisterPhoneAccountAmendsSelfManagedCapabilityInternally()913 public void testRegisterPhoneAccountAmendsSelfManagedCapabilityInternally() { 914 // GIVEN 915 PhoneAccountHandle handle = makeQuickAccountHandle( 916 new ComponentName("self", "managed"), "selfie1"); 917 PhoneAccount accountWithCapability = new PhoneAccount.Builder(handle, "label") 918 .setCapabilities( 919 PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS) 920 .build(); 921 922 assertTrue(mRegistrar.hasTransactionalCallCapabilities(accountWithCapability)); 923 924 try { 925 // WHEN 926 mRegistrar.registerPhoneAccount(accountWithCapability); 927 PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(handle); 928 // THEN 929 assertEquals(PhoneAccount.CAPABILITY_SELF_MANAGED, (registeredAccount.getCapabilities() 930 & PhoneAccount.CAPABILITY_SELF_MANAGED)); 931 } finally { 932 mRegistrar.unregisterPhoneAccount(handle); 933 } 934 } 935 936 /** 937 * Tests to ensure that when registering a self-managed PhoneAccount, it cannot also be defined 938 * as a call provider, connection manager, or sim subscription. 939 * @throws Exception 940 */ 941 @MediumTest 942 @Test testSelfManagedCapabilityOverride()943 public void testSelfManagedCapabilityOverride() throws Exception { 944 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 945 Mockito.mock(IConnectionService.class)); 946 947 PhoneAccountHandle selfManagedHandle = makeQuickAccountHandle( 948 new ComponentName("self", "managed"), "selfie1"); 949 950 PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, TEST_LABEL) 951 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED | 952 PhoneAccount.CAPABILITY_CALL_PROVIDER | 953 PhoneAccount.CAPABILITY_CONNECTION_MANAGER | 954 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 955 .build(); 956 957 mRegistrar.registerPhoneAccount(selfManagedAccount); 958 959 PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle); 960 assertEquals(PhoneAccount.CAPABILITY_SELF_MANAGED, registeredAccount.getCapabilities()); 961 } 962 963 @MediumTest 964 @Test testSortSimFirst()965 public void testSortSimFirst() throws Exception { 966 ComponentName componentA = new ComponentName("a", "a"); 967 ComponentName componentB = new ComponentName("b", "b"); 968 mComponentContextFixture.addConnectionService(componentA, 969 Mockito.mock(IConnectionService.class)); 970 mComponentContextFixture.addConnectionService(componentB, 971 Mockito.mock(IConnectionService.class)); 972 973 PhoneAccount simAccount = new PhoneAccount.Builder( 974 makeQuickAccountHandle(componentB, "2"), "2") 975 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 976 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 977 .setIsEnabled(true) 978 .build(); 979 980 PhoneAccount nonSimAccount = new PhoneAccount.Builder( 981 makeQuickAccountHandle(componentA, "1"), "1") 982 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 983 .setIsEnabled(true) 984 .build(); 985 986 registerAndEnableAccount(nonSimAccount); 987 registerAndEnableAccount(simAccount); 988 989 List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false); 990 assertTrue(accounts.get(0).getLabel().toString().equals("2")); 991 assertTrue(accounts.get(1).getLabel().toString().equals("1")); 992 } 993 994 @MediumTest 995 @Test testSortBySortOrder()996 public void testSortBySortOrder() throws Exception { 997 ComponentName componentA = new ComponentName("a", "a"); 998 ComponentName componentB = new ComponentName("b", "b"); 999 ComponentName componentC = new ComponentName("c", "c"); 1000 mComponentContextFixture.addConnectionService(componentA, 1001 Mockito.mock(IConnectionService.class)); 1002 mComponentContextFixture.addConnectionService(componentB, 1003 Mockito.mock(IConnectionService.class)); 1004 mComponentContextFixture.addConnectionService(componentC, 1005 Mockito.mock(IConnectionService.class)); 1006 1007 Bundle account1Extras = new Bundle(); 1008 account1Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 1); 1009 PhoneAccount account1 = new PhoneAccount.Builder( 1010 makeQuickAccountHandle(componentA, "c"), "c") 1011 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1012 .setExtras(account1Extras) 1013 .build(); 1014 1015 Bundle account2Extras = new Bundle(); 1016 account2Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 2); 1017 PhoneAccount account2 = new PhoneAccount.Builder( 1018 makeQuickAccountHandle(componentB, "b"), "b") 1019 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1020 .setExtras(account2Extras) 1021 .build(); 1022 1023 PhoneAccount account3 = new PhoneAccount.Builder( 1024 makeQuickAccountHandle(componentC, "c"), "a") 1025 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1026 .build(); 1027 1028 registerAndEnableAccount(account3); 1029 registerAndEnableAccount(account2); 1030 registerAndEnableAccount(account1); 1031 1032 List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false); 1033 assertTrue(accounts.get(0).getLabel().toString().equals("c")); 1034 assertTrue(accounts.get(1).getLabel().toString().equals("b")); 1035 assertTrue(accounts.get(2).getLabel().toString().equals("a")); 1036 } 1037 1038 @MediumTest 1039 @Test testSortByLabel()1040 public void testSortByLabel() throws Exception { 1041 ComponentName componentA = new ComponentName("a", "a"); 1042 ComponentName componentB = new ComponentName("b", "b"); 1043 ComponentName componentC = new ComponentName("c", "c"); 1044 mComponentContextFixture.addConnectionService(componentA, 1045 Mockito.mock(IConnectionService.class)); 1046 mComponentContextFixture.addConnectionService(componentB, 1047 Mockito.mock(IConnectionService.class)); 1048 mComponentContextFixture.addConnectionService(componentC, 1049 Mockito.mock(IConnectionService.class)); 1050 1051 PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(componentA, "c"), 1052 "c") 1053 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1054 .build(); 1055 1056 PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(componentB, "b"), 1057 "b") 1058 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1059 .build(); 1060 1061 PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(componentC, "a"), 1062 "a") 1063 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1064 .build(); 1065 1066 registerAndEnableAccount(account1); 1067 registerAndEnableAccount(account2); 1068 registerAndEnableAccount(account3); 1069 1070 List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false); 1071 assertTrue(accounts.get(0).getLabel().toString().equals("a")); 1072 assertTrue(accounts.get(1).getLabel().toString().equals("b")); 1073 assertTrue(accounts.get(2).getLabel().toString().equals("c")); 1074 } 1075 1076 @MediumTest 1077 @Test testSortAll()1078 public void testSortAll() throws Exception { 1079 ComponentName componentA = new ComponentName("a", "a"); 1080 ComponentName componentB = new ComponentName("b", "b"); 1081 ComponentName componentC = new ComponentName("c", "c"); 1082 ComponentName componentW = new ComponentName("w", "w"); 1083 ComponentName componentX = new ComponentName("x", "x"); 1084 ComponentName componentY = new ComponentName("y", "y"); 1085 ComponentName componentZ = new ComponentName("z", "z"); 1086 mComponentContextFixture.addConnectionService(componentA, 1087 Mockito.mock(IConnectionService.class)); 1088 mComponentContextFixture.addConnectionService(componentB, 1089 Mockito.mock(IConnectionService.class)); 1090 mComponentContextFixture.addConnectionService(componentC, 1091 Mockito.mock(IConnectionService.class)); 1092 mComponentContextFixture.addConnectionService(componentW, 1093 Mockito.mock(IConnectionService.class)); 1094 mComponentContextFixture.addConnectionService(componentX, 1095 Mockito.mock(IConnectionService.class)); 1096 mComponentContextFixture.addConnectionService(componentY, 1097 Mockito.mock(IConnectionService.class)); 1098 mComponentContextFixture.addConnectionService(componentZ, 1099 Mockito.mock(IConnectionService.class)); 1100 1101 Bundle account1Extras = new Bundle(); 1102 account1Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 2); 1103 PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle( 1104 makeQuickConnectionServiceComponentName(), "y"), "y") 1105 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 1106 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 1107 .setExtras(account1Extras) 1108 .build(); 1109 1110 Bundle account2Extras = new Bundle(); 1111 account2Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 1); 1112 PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle( 1113 makeQuickConnectionServiceComponentName(), "z"), "z") 1114 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 1115 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 1116 .setExtras(account2Extras) 1117 .build(); 1118 1119 PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle( 1120 makeQuickConnectionServiceComponentName(), "x"), "x") 1121 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 1122 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 1123 .build(); 1124 1125 PhoneAccount account4 = new PhoneAccount.Builder(makeQuickAccountHandle( 1126 makeQuickConnectionServiceComponentName(), "w"), "w") 1127 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER | 1128 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 1129 .build(); 1130 1131 PhoneAccount account5 = new PhoneAccount.Builder(makeQuickAccountHandle( 1132 makeQuickConnectionServiceComponentName(), "b"), "b") 1133 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1134 .build(); 1135 1136 PhoneAccount account6 = new PhoneAccount.Builder(makeQuickAccountHandle( 1137 makeQuickConnectionServiceComponentName(), "c"), "a") 1138 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1139 .build(); 1140 1141 registerAndEnableAccount(account1); 1142 registerAndEnableAccount(account2); 1143 registerAndEnableAccount(account3); 1144 registerAndEnableAccount(account4); 1145 registerAndEnableAccount(account5); 1146 registerAndEnableAccount(account6); 1147 1148 List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle(), false); 1149 // Sim accts ordered by sort order first 1150 assertTrue(accounts.get(0).getLabel().toString().equals("z")); 1151 assertTrue(accounts.get(1).getLabel().toString().equals("y")); 1152 1153 // Sim accts with no sort order next 1154 assertTrue(accounts.get(2).getLabel().toString().equals("w")); 1155 assertTrue(accounts.get(3).getLabel().toString().equals("x")); 1156 1157 // Other accts sorted by label next 1158 assertTrue(accounts.get(4).getLabel().toString().equals("a")); 1159 assertTrue(accounts.get(5).getLabel().toString().equals("b")); 1160 } 1161 1162 /** 1163 * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle)} 1164 * to ensure disabled accounts are filtered out of results when requested. 1165 * @throws Exception 1166 */ 1167 @MediumTest 1168 @Test testGetByEnabledState()1169 public void testGetByEnabledState() throws Exception { 1170 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1171 Mockito.mock(IConnectionService.class)); 1172 mRegistrar.registerPhoneAccount(makeQuickAccountBuilder("id1", 1, null) 1173 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1174 .build()); 1175 1176 assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL, 1177 false /* includeDisabled */, Process.myUserHandle(), false).size()); 1178 assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL, 1179 true /* includeDisabled */, Process.myUserHandle(), false).size()); 1180 } 1181 1182 /** 1183 * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle)} 1184 * to ensure scheme filtering operates. 1185 * @throws Exception 1186 */ 1187 @MediumTest 1188 @Test testGetByScheme()1189 public void testGetByScheme() throws Exception { 1190 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1191 Mockito.mock(IConnectionService.class)); 1192 registerAndEnableAccount(makeQuickAccountBuilder("id1", 1, null) 1193 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1194 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP)) 1195 .build()); 1196 registerAndEnableAccount(makeQuickAccountBuilder("id2", 2, null) 1197 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1198 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL)) 1199 .build()); 1200 1201 assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP, 1202 false /* includeDisabled */, Process.myUserHandle(), false).size()); 1203 assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL, 1204 false /* includeDisabled */, Process.myUserHandle(), false).size()); 1205 assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(null, false /* includeDisabled */, 1206 Process.myUserHandle(), false).size()); 1207 } 1208 1209 /** 1210 * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle, 1211 * int)} to ensure capability filtering operates. 1212 * @throws Exception 1213 */ 1214 @MediumTest 1215 @Test testGetByCapability()1216 public void testGetByCapability() throws Exception { 1217 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1218 Mockito.mock(IConnectionService.class)); 1219 registerAndEnableAccount(makeQuickAccountBuilder("id1", 1, null) 1220 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER 1221 | PhoneAccount.CAPABILITY_VIDEO_CALLING) 1222 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP)) 1223 .build()); 1224 registerAndEnableAccount(makeQuickAccountBuilder("id2", 2, null) 1225 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 1226 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP)) 1227 .build()); 1228 1229 assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP, 1230 false /* includeDisabled */, Process.myUserHandle(), false).size(), 1231 PhoneAccount.CAPABILITY_VIDEO_CALLING); 1232 assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP, 1233 false /* includeDisabled */, Process.myUserHandle(), false) 1234 .size(), 0 /* none extra */); 1235 assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP, 1236 false /* includeDisabled */, Process.myUserHandle(), false).size(), 1237 PhoneAccount.CAPABILITY_RTT); 1238 } 1239 1240 /** 1241 * Tests {@link PhoneAccount#equals(Object)} operator. 1242 * @throws Exception 1243 */ 1244 @MediumTest 1245 @Test testPhoneAccountEquality()1246 public void testPhoneAccountEquality() throws Exception { 1247 PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName("foo", "bar"), "id"); 1248 PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, "label"); 1249 builder.addSupportedUriScheme("tel"); 1250 builder.setAddress(Uri.fromParts("tel", "6505551212", null)); 1251 builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER); 1252 Bundle extras = new Bundle(); 1253 extras.putInt("INT", 1); 1254 extras.putString("STR", "str"); 1255 builder.setExtras(extras); 1256 builder.setGroupId("group"); 1257 builder.setHighlightColor(1); 1258 builder.setShortDescription("short"); 1259 builder.setSubscriptionAddress(Uri.fromParts("tel", "6505551213", null)); 1260 builder.setSupportedAudioRoutes(2); 1261 1262 PhoneAccount account1 = builder.build(); 1263 PhoneAccount account2 = builder.build(); 1264 assertEquals(account1, account2); 1265 } 1266 1267 /** 1268 * Tests {@link PhoneAccountHandle#areFromSamePackage(PhoneAccountHandle, 1269 * PhoneAccountHandle)} comparison. 1270 */ 1271 @SmallTest 1272 @Test testSamePhoneAccountHandlePackage()1273 public void testSamePhoneAccountHandlePackage() { 1274 PhoneAccountHandle a = new PhoneAccountHandle(new ComponentName("packageA", "class1"), 1275 "id1"); 1276 PhoneAccountHandle b = new PhoneAccountHandle(new ComponentName("packageA", "class2"), 1277 "id2"); 1278 PhoneAccountHandle c = new PhoneAccountHandle(new ComponentName("packageA", "class1"), 1279 "id3"); 1280 PhoneAccountHandle d = new PhoneAccountHandle(new ComponentName("packageB", "class1"), 1281 "id1"); 1282 1283 assertTrue(PhoneAccountHandle.areFromSamePackage(null, null)); 1284 assertTrue(PhoneAccountHandle.areFromSamePackage(a, b)); 1285 assertTrue(PhoneAccountHandle.areFromSamePackage(a, c)); 1286 assertTrue(PhoneAccountHandle.areFromSamePackage(b, c)); 1287 assertFalse(PhoneAccountHandle.areFromSamePackage(a, d)); 1288 assertFalse(PhoneAccountHandle.areFromSamePackage(b, d)); 1289 assertFalse(PhoneAccountHandle.areFromSamePackage(c, d)); 1290 assertFalse(PhoneAccountHandle.areFromSamePackage(a, null)); 1291 assertFalse(PhoneAccountHandle.areFromSamePackage(b, null)); 1292 assertFalse(PhoneAccountHandle.areFromSamePackage(c, null)); 1293 assertFalse(PhoneAccountHandle.areFromSamePackage(null, d)); 1294 assertFalse(PhoneAccountHandle.areFromSamePackage(null, d)); 1295 assertFalse(PhoneAccountHandle.areFromSamePackage(null, d)); 1296 } 1297 1298 /** 1299 * Tests {@link PhoneAccountRegistrar#cleanupOrphanedPhoneAccounts } cleans up / deletes an 1300 * orphan account. 1301 */ 1302 @Test testCleanUpOrphanAccounts()1303 public void testCleanUpOrphanAccounts() throws Exception { 1304 // GIVEN 1305 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1306 Mockito.mock(IConnectionService.class)); 1307 UserManager userManager = mContext.getSystemService(UserManager.class); 1308 1309 List<UserHandle> users = Arrays.asList(new UserHandle(0), 1310 new UserHandle(1000)); 1311 1312 PhoneAccount pa1 = new PhoneAccount.Builder( 1313 new PhoneAccountHandle(new ComponentName(PACKAGE_1, COMPONENT_NAME), "1234", 1314 users.get(0)), "l1").build(); 1315 PhoneAccount pa2 = new PhoneAccount.Builder( 1316 new PhoneAccountHandle(new ComponentName(PACKAGE_2, COMPONENT_NAME), "5678", 1317 users.get(1)), "l2").build(); 1318 1319 1320 registerAndEnableAccount(pa1); 1321 registerAndEnableAccount(pa2); 1322 1323 assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(0), false).size()); 1324 assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(1), false).size()); 1325 1326 1327 // WHEN 1328 when(mContext.getPackageManager().getPackageInfo(PACKAGE_1, 0)) 1329 .thenReturn(new PackageInfo()); 1330 1331 when(mContext.getPackageManager().getPackageInfo(PACKAGE_2, 0)) 1332 .thenThrow(new PackageManager.NameNotFoundException()); 1333 1334 when(userManager.getSerialNumberForUser(users.get(0))) 1335 .thenReturn(0L); 1336 1337 when(userManager.getSerialNumberForUser(users.get(1))) 1338 .thenReturn(-1L); 1339 1340 // THEN 1341 int deletedAccounts = mRegistrar.cleanupOrphanedPhoneAccounts(); 1342 assertEquals(1, deletedAccounts); 1343 } 1344 1345 @Test testGetSimPhoneAccountsFromSimCallManager()1346 public void testGetSimPhoneAccountsFromSimCallManager() throws Exception { 1347 // Register the SIM PhoneAccounts 1348 mComponentContextFixture.addConnectionService( 1349 makeQuickConnectionServiceComponentName(), Mockito.mock(IConnectionService.class)); 1350 PhoneAccount sim1Account = makeQuickSimAccount(1); 1351 PhoneAccountHandle sim1Handle = sim1Account.getAccountHandle(); 1352 registerAndEnableAccount(sim1Account); 1353 PhoneAccount sim2Account = makeQuickSimAccount(2); 1354 PhoneAccountHandle sim2Handle = sim2Account.getAccountHandle(); 1355 registerAndEnableAccount(sim2Account); 1356 1357 assertEquals( 1358 List.of(sim1Handle, sim2Handle), mRegistrar.getSimPhoneAccountsOfCurrentUser()); 1359 1360 // Set up the SIM call manager app + carrier configs 1361 ComponentName simCallManagerComponent = 1362 new ComponentName("com.carrier.app", "CarrierConnectionService"); 1363 PhoneAccountHandle simCallManagerHandle = 1364 makeQuickAccountHandle(simCallManagerComponent, "sim-call-manager"); 1365 setSimCallManagerCarrierConfig( 1366 1, new ComponentName("com.other.carrier", "OtherConnectionService")); 1367 setSimCallManagerCarrierConfig(2, simCallManagerComponent); 1368 1369 // Since SIM 1 names another app, so we only get the handle for SIM 2 1370 assertEquals( 1371 List.of(sim2Handle), 1372 mRegistrar.getSimPhoneAccountsFromSimCallManager(simCallManagerHandle)); 1373 // We do exact component matching, not just package name matching 1374 assertEquals( 1375 List.of(), 1376 mRegistrar.getSimPhoneAccountsFromSimCallManager( 1377 makeQuickAccountHandle( 1378 new ComponentName("com.carrier.app", "SomeOtherUnrelatedService"), 1379 "same-pkg-but-diff-svc"))); 1380 1381 // Results are identical after we register the PhoneAccount 1382 mComponentContextFixture.addConnectionService( 1383 simCallManagerComponent, Mockito.mock(IConnectionService.class)); 1384 PhoneAccount simCallManagerAccount = 1385 new PhoneAccount.Builder(simCallManagerHandle, "SIM call manager") 1386 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 1387 .build(); 1388 mRegistrar.registerPhoneAccount(simCallManagerAccount); 1389 assertEquals( 1390 List.of(sim2Handle), 1391 mRegistrar.getSimPhoneAccountsFromSimCallManager(simCallManagerHandle)); 1392 } 1393 1394 @Test testMaybeNotifyTelephonyForVoiceServiceState()1395 public void testMaybeNotifyTelephonyForVoiceServiceState() throws Exception { 1396 // Register the SIM PhoneAccounts 1397 mComponentContextFixture.addConnectionService( 1398 makeQuickConnectionServiceComponentName(), Mockito.mock(IConnectionService.class)); 1399 PhoneAccount sim1Account = makeQuickSimAccount(1); 1400 registerAndEnableAccount(sim1Account); 1401 PhoneAccount sim2Account = makeQuickSimAccount(2); 1402 registerAndEnableAccount(sim2Account); 1403 // Telephony is notified by default when new SIM accounts are registered 1404 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1405 .setVoiceServiceStateOverride(false); 1406 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1407 1408 // Set up the SIM call manager app + carrier configs 1409 ComponentName simCallManagerComponent = 1410 new ComponentName("com.carrier.app", "CarrierConnectionService"); 1411 PhoneAccountHandle simCallManagerHandle = 1412 makeQuickAccountHandle(simCallManagerComponent, "sim-call-manager"); 1413 mComponentContextFixture.addConnectionService( 1414 simCallManagerComponent, Mockito.mock(IConnectionService.class)); 1415 setSimCallManagerCarrierConfig(1, simCallManagerComponent); 1416 setSimCallManagerCarrierConfig(2, simCallManagerComponent); 1417 1418 // When the SIM call manager is registered without the SUPPORTS capability, telephony is 1419 // still notified for consistency (e.g. runtime capability removal + re-registration). 1420 PhoneAccount simCallManagerAccount = 1421 new PhoneAccount.Builder(simCallManagerHandle, "SIM call manager") 1422 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 1423 .build(); 1424 mRegistrar.registerPhoneAccount(simCallManagerAccount); 1425 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1426 .setVoiceServiceStateOverride(false); 1427 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1428 1429 // Adding the SUPPORTS capability causes the SIMs to get notified with false again for 1430 // consistency purposes 1431 simCallManagerAccount = 1432 copyPhoneAccountAndAddCapabilities( 1433 simCallManagerAccount, 1434 PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS); 1435 mRegistrar.registerPhoneAccount(simCallManagerAccount); 1436 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1437 .setVoiceServiceStateOverride(false); 1438 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1439 1440 // Adding the AVAILABLE capability updates the SIMs again, this time with hasService = true 1441 simCallManagerAccount = 1442 copyPhoneAccountAndAddCapabilities( 1443 simCallManagerAccount, PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE); 1444 mRegistrar.registerPhoneAccount(simCallManagerAccount); 1445 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1446 .setVoiceServiceStateOverride(true); 1447 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1448 1449 // Removing a SIM account does nothing, regardless of SIM call manager capabilities 1450 mRegistrar.unregisterPhoneAccount(sim1Account.getAccountHandle()); 1451 verify(mComponentContextFixture.getTelephonyManager(), never()) 1452 .setVoiceServiceStateOverride(anyBoolean()); 1453 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1454 1455 // Adding a SIM account while a SIM call manager with both capabilities is registered causes 1456 // a call to telephony with hasService = true 1457 mRegistrar.registerPhoneAccount(sim1Account); 1458 verify(mComponentContextFixture.getTelephonyManager(), times(1)) 1459 .setVoiceServiceStateOverride(true); 1460 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1461 1462 // Removing the SIM call manager while it has both capabilities causes a call to telephony 1463 // with hasService = false 1464 mRegistrar.unregisterPhoneAccount(simCallManagerHandle); 1465 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1466 .setVoiceServiceStateOverride(false); 1467 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1468 1469 // Removing the SIM call manager while it has the SUPPORTS capability but not AVAILABLE 1470 // still causes a call to telephony with hasService = false for consistency 1471 simCallManagerAccount = 1472 copyPhoneAccountAndRemoveCapabilities( 1473 simCallManagerAccount, PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE); 1474 mRegistrar.registerPhoneAccount(simCallManagerAccount); 1475 clearInvocations(mComponentContextFixture.getTelephonyManager()); // from re-registration 1476 mRegistrar.unregisterPhoneAccount(simCallManagerHandle); 1477 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1478 .setVoiceServiceStateOverride(false); 1479 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1480 1481 // Finally, removing the SIM call manager while it has neither capability still causes a 1482 // call to telephony with hasService = false for consistency 1483 simCallManagerAccount = 1484 copyPhoneAccountAndRemoveCapabilities( 1485 simCallManagerAccount, 1486 PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS); 1487 mRegistrar.registerPhoneAccount(simCallManagerAccount); 1488 clearInvocations(mComponentContextFixture.getTelephonyManager()); // from re-registration 1489 mRegistrar.unregisterPhoneAccount(simCallManagerHandle); 1490 verify(mComponentContextFixture.getTelephonyManager(), times(2)) 1491 .setVoiceServiceStateOverride(false); 1492 clearInvocations(mComponentContextFixture.getTelephonyManager()); 1493 } 1494 1495 /** 1496 * Test PhoneAccountHandle Migration Logic. 1497 */ 1498 @Test testPhoneAccountMigration()1499 public void testPhoneAccountMigration() throws Exception { 1500 PhoneAccountRegistrar.State testState = makeQuickStateWithTelephonyPhoneAccountHandle(); 1501 final int mTestPhoneAccountHandleSubIdInt = 123; 1502 // Mock SubscriptionManager 1503 SubscriptionInfo subscriptionInfo = new SubscriptionInfo( 1504 mTestPhoneAccountHandleSubIdInt, "id0", 1, "a", "b", 1, 1, "test", 1505 1, null, null, null, null, false, null, null); 1506 List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>(); 1507 subscriptionInfoList.add(subscriptionInfo); 1508 when(mSubscriptionManager.getAllSubscriptionInfoList()).thenReturn(subscriptionInfoList); 1509 mRegistrar.migratePhoneAccountHandle(testState); 1510 Collection<DefaultPhoneAccountHandle> defaultPhoneAccountHandles 1511 = testState.defaultOutgoingAccountHandles.values(); 1512 DefaultPhoneAccountHandle defaultPhoneAccountHandle 1513 = defaultPhoneAccountHandles.iterator().next(); 1514 assertEquals(Integer.toString(mTestPhoneAccountHandleSubIdInt), 1515 defaultPhoneAccountHandle.phoneAccountHandle.getId()); 1516 } 1517 1518 /** 1519 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1520 * {@link PhoneAccountHandle} with a { PhoneAccountHandle#packageName} that is over the 1521 * character limit set 1522 */ 1523 @Test testInvalidPhoneAccountHandlePackageNameThrowsException()1524 public void testInvalidPhoneAccountHandlePackageNameThrowsException() { 1525 // GIVEN 1526 String invalidPackageName = INVALID_STR; 1527 PhoneAccountHandle handle = makeQuickAccountHandle( 1528 new ComponentName(invalidPackageName, this.getClass().getName()), TEST_ID); 1529 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle); 1530 1531 // THEN 1532 try { 1533 PhoneAccount account = builder.build(); 1534 assertEquals(invalidPackageName, 1535 account.getAccountHandle().getComponentName().getPackageName()); 1536 mRegistrar.registerPhoneAccount(account); 1537 fail("failed to throw IllegalArgumentException"); 1538 } catch (IllegalArgumentException e) { 1539 // pass test 1540 } finally { 1541 mRegistrar.unregisterPhoneAccount(handle); 1542 } 1543 } 1544 1545 /** 1546 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1547 * {@link PhoneAccountHandle} with a { PhoneAccountHandle#className} that is over the 1548 * character limit set 1549 */ 1550 @Test testInvalidPhoneAccountHandleClassNameThrowsException()1551 public void testInvalidPhoneAccountHandleClassNameThrowsException() { 1552 // GIVEN 1553 String invalidClassName = INVALID_STR; 1554 PhoneAccountHandle handle = makeQuickAccountHandle( 1555 new ComponentName(this.getClass().getPackageName(), invalidClassName), TEST_ID); 1556 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle); 1557 1558 // THEN 1559 try { 1560 PhoneAccount account = builder.build(); 1561 assertEquals(invalidClassName, 1562 account.getAccountHandle().getComponentName().getClassName()); 1563 mRegistrar.registerPhoneAccount(account); 1564 fail("failed to throw IllegalArgumentException"); 1565 } catch (IllegalArgumentException e) { 1566 // pass test 1567 } finally { 1568 mRegistrar.unregisterPhoneAccount(handle); 1569 } 1570 } 1571 1572 /** 1573 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1574 * {@link PhoneAccountHandle} with a { PhoneAccount#mId} that is over the character limit set 1575 */ 1576 @Test testInvalidPhoneAccountHandleIdThrowsException()1577 public void testInvalidPhoneAccountHandleIdThrowsException() { 1578 // GIVEN 1579 String invalidId = INVALID_STR; 1580 PhoneAccountHandle handle = makeQuickAccountHandle(invalidId); 1581 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle); 1582 1583 // THEN 1584 try { 1585 PhoneAccount account = builder.build(); 1586 assertEquals(invalidId, account.getAccountHandle().getId()); 1587 mRegistrar.registerPhoneAccount(account); 1588 fail("failed to throw IllegalArgumentException"); 1589 } catch (IllegalArgumentException e) { 1590 // pass test 1591 } finally { 1592 mRegistrar.unregisterPhoneAccount(handle); 1593 } 1594 } 1595 1596 /** 1597 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1598 * {@link PhoneAccount} with a { PhoneAccount#mLabel} that is over the character limit set 1599 */ 1600 @Test testInvalidLabelThrowsException()1601 public void testInvalidLabelThrowsException() { 1602 // GIVEN 1603 String invalidLabel = INVALID_STR; 1604 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1605 PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, invalidLabel) 1606 .setCapabilities(PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS); 1607 1608 // WHEN 1609 when(mAppLabelProxy.getAppLabel(anyString())).thenReturn(invalidLabel); 1610 1611 // THEN 1612 try { 1613 PhoneAccount account = builder.build(); 1614 assertEquals(invalidLabel, account.getLabel()); 1615 mRegistrar.registerPhoneAccount(account); 1616 fail("failed to throw IllegalArgumentException"); 1617 } catch (IllegalArgumentException e) { 1618 // pass test 1619 } finally { 1620 mRegistrar.unregisterPhoneAccount(handle); 1621 } 1622 } 1623 1624 /** 1625 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1626 * {@link PhoneAccount} with a {PhoneAccount#mShortDescription} that is over the character 1627 * limit set 1628 */ 1629 @Test testInvalidShortDescriptionThrowsException()1630 public void testInvalidShortDescriptionThrowsException() { 1631 // GIVEN 1632 String invalidShortDescription = INVALID_STR; 1633 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1634 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle) 1635 .setShortDescription(invalidShortDescription); 1636 1637 // THEN 1638 try { 1639 PhoneAccount account = builder.build(); 1640 assertEquals(invalidShortDescription, account.getShortDescription()); 1641 mRegistrar.registerPhoneAccount(account); 1642 fail("failed to throw IllegalArgumentException"); 1643 } catch (IllegalArgumentException e) { 1644 // pass test 1645 } finally { 1646 mRegistrar.unregisterPhoneAccount(handle); 1647 } 1648 } 1649 1650 /** 1651 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1652 * {@link PhoneAccount} with a {PhoneAccount#mGroupId} that is over the character limit set 1653 */ 1654 @Test testInvalidGroupIdThrowsException()1655 public void testInvalidGroupIdThrowsException() { 1656 // GIVEN 1657 String invalidGroupId = INVALID_STR; 1658 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1659 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle) 1660 .setGroupId(invalidGroupId); 1661 1662 // THEN 1663 try { 1664 PhoneAccount account = builder.build(); 1665 assertEquals(invalidGroupId, account.getGroupId()); 1666 mRegistrar.registerPhoneAccount(account); 1667 fail("failed to throw IllegalArgumentException"); 1668 } catch (IllegalArgumentException e) { 1669 // pass test 1670 } finally { 1671 mRegistrar.unregisterPhoneAccount(handle); 1672 } 1673 } 1674 1675 /** 1676 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1677 * {@link PhoneAccount} with a {PhoneAccount#mExtras} that is over the character limit set 1678 */ 1679 @Test testInvalidExtraStringKeyThrowsException()1680 public void testInvalidExtraStringKeyThrowsException() { 1681 // GIVEN 1682 String invalidBundleKey = INVALID_STR; 1683 String keyValue = "value"; 1684 Bundle extras = new Bundle(); 1685 extras.putString(invalidBundleKey, keyValue); 1686 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1687 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle) 1688 .setExtras(extras); 1689 1690 // THEN 1691 try { 1692 PhoneAccount account = builder.build(); 1693 assertEquals(keyValue, account.getExtras().getString(invalidBundleKey)); 1694 mRegistrar.registerPhoneAccount(account); 1695 fail("failed to throw IllegalArgumentException"); 1696 } catch (IllegalArgumentException e) { 1697 // pass test 1698 } finally { 1699 mRegistrar.unregisterPhoneAccount(handle); 1700 } 1701 } 1702 1703 /** 1704 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1705 * {@link PhoneAccount} with a {PhoneAccount#mExtras} that is over the character limit set 1706 */ 1707 @Test testInvalidExtraStringValueThrowsException()1708 public void testInvalidExtraStringValueThrowsException() { 1709 // GIVEN 1710 String extrasKey = "ExtrasStringKey"; 1711 String invalidBundleValue = INVALID_STR; 1712 Bundle extras = new Bundle(); 1713 extras.putString(extrasKey, invalidBundleValue); 1714 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1715 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle) 1716 .setExtras(extras); 1717 1718 // THEN 1719 try { 1720 PhoneAccount account = builder.build(); 1721 assertEquals(invalidBundleValue, account.getExtras().getString(extrasKey)); 1722 mRegistrar.registerPhoneAccount(account); 1723 fail("failed to throw IllegalArgumentException"); 1724 } catch (IllegalArgumentException e) { 1725 // pass test 1726 } finally { 1727 mRegistrar.unregisterPhoneAccount(handle); 1728 } 1729 } 1730 1731 /** 1732 * Test that an {@link IllegalArgumentException} is thrown when a package registers a 1733 * {@link PhoneAccount} with a {PhoneAccount#mExtras} that is over the (key,value) pair limit 1734 */ 1735 @Test testInvalidExtraElementsExceedsLimitAndThrowsException()1736 public void testInvalidExtraElementsExceedsLimitAndThrowsException() { 1737 // GIVEN 1738 int invalidBundleExtrasLimit = 1739 PhoneAccountRegistrar.MAX_PHONE_ACCOUNT_EXTRAS_KEY_PAIR_LIMIT + 1; 1740 Bundle extras = new Bundle(); 1741 for (int i = 0; i < invalidBundleExtrasLimit; i++) { 1742 extras.putString(UUID.randomUUID().toString(), "value"); 1743 } 1744 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1745 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle) 1746 .setExtras(extras); 1747 // THEN 1748 try { 1749 PhoneAccount account = builder.build(); 1750 assertEquals(invalidBundleExtrasLimit, account.getExtras().size()); 1751 mRegistrar.registerPhoneAccount(account); 1752 fail("failed to throw IllegalArgumentException"); 1753 } catch (IllegalArgumentException e) { 1754 // Test Pass 1755 } finally { 1756 mRegistrar.unregisterPhoneAccount(handle); 1757 } 1758 } 1759 1760 /** 1761 * Ensure an IllegalArgumentException is thrown when adding more than 10 schemes for a single 1762 * account 1763 */ 1764 @Test testLimitOnSchemeCount()1765 public void testLimitOnSchemeCount() { 1766 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1767 PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, TEST_LABEL); 1768 for (int i = 0; i < PhoneAccountRegistrar.MAX_PHONE_ACCOUNT_REGISTRATIONS + 1; i++) { 1769 builder.addSupportedUriScheme(Integer.toString(i)); 1770 } 1771 try { 1772 mRegistrar.enforceLimitsOnSchemes(builder.build()); 1773 fail("should have hit exception in enforceLimitOnSchemes"); 1774 } catch (IllegalArgumentException e) { 1775 // pass test 1776 } 1777 } 1778 1779 /** 1780 * Ensure an IllegalArgumentException is thrown when adding more 256 chars for a single 1781 * account 1782 */ 1783 @Test testLimitOnSchemeLength()1784 public void testLimitOnSchemeLength() { 1785 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1786 PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, TEST_LABEL); 1787 builder.addSupportedUriScheme(INVALID_STR); 1788 try { 1789 mRegistrar.enforceLimitsOnSchemes(builder.build()); 1790 fail("should have hit exception in enforceLimitOnSchemes"); 1791 } catch (IllegalArgumentException e) { 1792 // pass test 1793 } 1794 } 1795 1796 /** 1797 * Ensure an IllegalArgumentException is thrown when adding too many PhoneAccountHandles to 1798 * a PhoneAccount. 1799 */ 1800 @Test testLimitOnSimultaneousCallingRestriction_tooManyElements()1801 public void testLimitOnSimultaneousCallingRestriction_tooManyElements() throws Exception { 1802 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 1803 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1804 Mockito.mock(IConnectionService.class)); 1805 Set<PhoneAccountHandle> tooManyElements = new HashSet<>(11); 1806 for (int i = 0; i < 11; i++) { 1807 tooManyElements.add(makeQuickAccountHandle(TEST_ID + i)); 1808 } 1809 PhoneAccount tooManyRestrictionsPA = new PhoneAccount.Builder( 1810 makeQuickAccountHandle(TEST_ID), TEST_LABEL) 1811 .setSimultaneousCallingRestriction(tooManyElements) 1812 .build(); 1813 try { 1814 mRegistrar.registerPhoneAccount(tooManyRestrictionsPA); 1815 fail("should have hit registrations exception in " 1816 + "enforceSimultaneousCallingRestrictionLimit"); 1817 } catch (IllegalArgumentException e) { 1818 // pass test 1819 } 1820 } 1821 1822 /** 1823 * Ensure an IllegalArgumentException is thrown when adding a PhoneAccountHandle where the 1824 * package name field is too large. 1825 */ 1826 @Test testLimitOnSimultaneousCallingRestriction_InvalidPackageName()1827 public void testLimitOnSimultaneousCallingRestriction_InvalidPackageName() throws Exception { 1828 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 1829 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1830 Mockito.mock(IConnectionService.class)); 1831 Set<PhoneAccountHandle> invalidElement = new HashSet<>(1); 1832 invalidElement.add(new PhoneAccountHandle(new ComponentName(INVALID_STR, "Class"), 1833 TEST_ID)); 1834 PhoneAccount invalidRestrictionPA = new PhoneAccount.Builder( 1835 makeQuickAccountHandle(TEST_ID), TEST_LABEL) 1836 .setSimultaneousCallingRestriction(invalidElement) 1837 .build(); 1838 try { 1839 mRegistrar.registerPhoneAccount(invalidRestrictionPA); 1840 fail("should have hit package name size limit exception in " 1841 + "enforceSimultaneousCallingRestrictionLimit"); 1842 } catch (IllegalArgumentException e) { 1843 // pass test 1844 } 1845 } 1846 1847 /** 1848 * Ensure an IllegalArgumentException is thrown when adding a PhoneAccountHandle where the 1849 * class name field is too large. 1850 */ 1851 @Test testLimitOnSimultaneousCallingRestriction_InvalidClassName()1852 public void testLimitOnSimultaneousCallingRestriction_InvalidClassName() throws Exception { 1853 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 1854 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1855 Mockito.mock(IConnectionService.class)); 1856 Set<PhoneAccountHandle> invalidElement = new HashSet<>(1); 1857 invalidElement.add(new PhoneAccountHandle(new ComponentName("pkg", INVALID_STR), 1858 TEST_ID)); 1859 PhoneAccount invalidRestrictionPA = new PhoneAccount.Builder( 1860 makeQuickAccountHandle(TEST_ID), TEST_LABEL) 1861 .setSimultaneousCallingRestriction(invalidElement) 1862 .build(); 1863 try { 1864 mRegistrar.registerPhoneAccount(invalidRestrictionPA); 1865 fail("should have hit class name size limit exception in " 1866 + "enforceSimultaneousCallingRestrictionLimit"); 1867 } catch (IllegalArgumentException e) { 1868 // pass test 1869 } 1870 } 1871 1872 /** 1873 * Ensure an IllegalArgumentException is thrown when adding a PhoneAccountHandle where the 1874 * ID field is too large. 1875 */ 1876 @Test testLimitOnSimultaneousCallingRestriction_InvalidIdSize()1877 public void testLimitOnSimultaneousCallingRestriction_InvalidIdSize() throws Exception { 1878 doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications(); 1879 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1880 Mockito.mock(IConnectionService.class)); 1881 Set<PhoneAccountHandle> invalidIdElement = new HashSet<>(1); 1882 invalidIdElement.add(new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), 1883 INVALID_STR)); 1884 PhoneAccount invalidRestrictionPA = new PhoneAccount.Builder( 1885 makeQuickAccountHandle(TEST_ID), TEST_LABEL) 1886 .setSimultaneousCallingRestriction(invalidIdElement) 1887 .build(); 1888 try { 1889 mRegistrar.registerPhoneAccount(invalidRestrictionPA); 1890 fail("should have hit ID size limit exception in " 1891 + "enforceSimultaneousCallingRestrictionLimit"); 1892 } catch (IllegalArgumentException e) { 1893 // pass test 1894 } 1895 } 1896 1897 /** 1898 * Ensure an IllegalArgumentException is thrown when adding an address over the limit 1899 */ 1900 @Test testLimitOnAddress()1901 public void testLimitOnAddress() { 1902 String text = "a".repeat(100); 1903 PhoneAccountHandle handle = makeQuickAccountHandle(TEST_ID); 1904 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities(handle) 1905 .setAddress(Uri.fromParts(text, text, text)); 1906 try { 1907 mRegistrar.registerPhoneAccount(builder.build()); 1908 fail("failed to throw IllegalArgumentException"); 1909 } catch (IllegalArgumentException e) { 1910 // pass test 1911 } 1912 finally { 1913 mRegistrar.unregisterPhoneAccount(handle); 1914 } 1915 } 1916 1917 /** 1918 * Ensure an IllegalArgumentException is thrown when an Icon that throws an IOException is given 1919 */ 1920 @Test testLimitOnIcon()1921 public void testLimitOnIcon() throws Exception { 1922 Icon mockIcon = mock(Icon.class); 1923 // GIVEN 1924 PhoneAccount.Builder builder = makeBuilderWithBindCapabilities( 1925 makeQuickAccountHandle(TEST_ID)).setIcon(mockIcon); 1926 try { 1927 // WHEN 1928 doThrow(new IOException()) 1929 .when(mockIcon).writeToStream(any(OutputStream.class)); 1930 //THEN 1931 mRegistrar.enforceIconSizeLimit(builder.build()); 1932 fail("failed to throw IllegalArgumentException"); 1933 } catch (IllegalArgumentException e) { 1934 // pass test 1935 assertTrue(e.getMessage().contains(PhoneAccountRegistrar.ICON_ERROR_MSG)); 1936 } 1937 } 1938 1939 /** 1940 * Ensure an IllegalArgumentException is thrown when providing a SubscriptionAddress that 1941 * exceeds the PhoneAccountRegistrar limit. 1942 */ 1943 @Test testLimitOnSubscriptionAddress()1944 public void testLimitOnSubscriptionAddress() throws Exception { 1945 String text = "a".repeat(100); 1946 PhoneAccount.Builder builder = new PhoneAccount.Builder(makeQuickAccountHandle(TEST_ID), 1947 TEST_LABEL).setSubscriptionAddress(Uri.fromParts(text, text, text)); 1948 try { 1949 mRegistrar.enforceCharacterLimit(builder.build()); 1950 fail("failed to throw IllegalArgumentException"); 1951 } catch (IllegalArgumentException e) { 1952 // pass test 1953 } 1954 } 1955 1956 /** 1957 * PhoneAccounts with CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS do not require a 1958 * ConnectionService. Ensure that such an account can be registered and fetched. 1959 */ 1960 @Test testFetchingTransactionalAccounts()1961 public void testFetchingTransactionalAccounts() { 1962 PhoneAccount account = makeBuilderWithBindCapabilities( 1963 makeQuickAccountHandle(TEST_ID)).build(); 1964 1965 try { 1966 assertEquals(0, mRegistrar.getAllPhoneAccounts(null, true).size()); 1967 registerAndEnableAccount(account); 1968 assertEquals(1, mRegistrar.getAllPhoneAccounts(null, true).size()); 1969 } finally { 1970 mRegistrar.unregisterPhoneAccount(account.getAccountHandle()); 1971 } 1972 } 1973 1974 @Test testGetPhoneAccountAcrossUsers()1975 public void testGetPhoneAccountAcrossUsers() throws Exception { 1976 when(mTelephonyFeatureFlags.workProfileApiSplit()).thenReturn(true); 1977 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 1978 Mockito.mock(IConnectionService.class)); 1979 1980 PhoneAccount accountForCurrent = makeQuickAccountBuilder("id_0", 0, UserHandle.CURRENT) 1981 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 1982 | PhoneAccount.CAPABILITY_CALL_PROVIDER).build(); 1983 PhoneAccount accountForAll = makeQuickAccountBuilder("id_0", 0, UserHandle.ALL) 1984 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 1985 | PhoneAccount.CAPABILITY_CALL_PROVIDER 1986 | PhoneAccount.CAPABILITY_MULTI_USER).build(); 1987 PhoneAccount accountForWorkProfile = makeQuickAccountBuilder("id_1", 1, USER_HANDLE_10) 1988 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 1989 | PhoneAccount.CAPABILITY_CALL_PROVIDER).build(); 1990 1991 registerAndEnableAccount(accountForCurrent); 1992 registerAndEnableAccount(accountForAll); 1993 registerAndEnableAccount(accountForWorkProfile); 1994 1995 List<PhoneAccount> accountsForUser = mRegistrar.getPhoneAccounts(0, 0, 1996 null, null, false, USER_HANDLE_10, false, false); 1997 List<PhoneAccount> accountsVisibleUser = mRegistrar.getPhoneAccounts(0, 0, 1998 null, null, false, USER_HANDLE_10, false, true); 1999 List<PhoneAccount> accountsAcrossUser = mRegistrar.getPhoneAccounts(0, 0, 2000 null, null, false, USER_HANDLE_10, true, false); 2001 2002 // Return the account exactly matching the user if it exists 2003 assertEquals(1, accountsForUser.size()); 2004 assertTrue(accountsForUser.contains(accountForWorkProfile)); 2005 // The accounts visible to the user without across user permission 2006 assertEquals(2, accountsVisibleUser.size()); 2007 assertTrue(accountsVisibleUser.containsAll(accountsForUser)); 2008 assertTrue(accountsVisibleUser.contains(accountForAll)); 2009 // The accounts visible to the user with across user permission 2010 assertEquals(3, accountsAcrossUser.size()); 2011 assertTrue(accountsAcrossUser.containsAll(accountsVisibleUser)); 2012 assertTrue(accountsAcrossUser.contains(accountForCurrent)); 2013 2014 mRegistrar.unregisterPhoneAccount(accountForWorkProfile.getAccountHandle()); 2015 2016 accountsForUser = mRegistrar.getPhoneAccounts(0, 0, 2017 null, null, false, USER_HANDLE_10, false, false); 2018 2019 // Return the account visible for the user if no account exactly matches the user 2020 assertEquals(1, accountsForUser.size()); 2021 assertTrue(accountsForUser.contains(accountForAll)); 2022 } 2023 2024 @SmallTest 2025 @Test testGetSubscriptionIdForPhoneAccountWhenNoTelephony()2026 public void testGetSubscriptionIdForPhoneAccountWhenNoTelephony() throws Exception { 2027 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 2028 Mockito.mock(IConnectionService.class)); 2029 2030 PhoneAccount simAccount = 2031 makeQuickAccountBuilder("simzor", 1, null) 2032 .setCapabilities( 2033 PhoneAccount.CAPABILITY_CALL_PROVIDER 2034 | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 2035 .setIsEnabled(true) 2036 .build(); 2037 registerAndEnableAccount(simAccount); 2038 when(mComponentContextFixture.getTelephonyManager() 2039 .getSubscriptionId(any(PhoneAccountHandle.class))) 2040 .thenThrow(new UnsupportedOperationException("Bee-boop")); 2041 assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 2042 mRegistrar.getSubscriptionIdForPhoneAccount(simAccount.getAccountHandle())); 2043 2044 // One more thing; we'll test 2045 doThrow(new UnsupportedOperationException("Bee boop!")) 2046 .when(mComponentContextFixture.getSubscriptionManager()) 2047 .setDefaultVoiceSubscriptionId(anyInt()); 2048 mRegistrar.setUserSelectedOutgoingPhoneAccount(simAccount.getAccountHandle(), 2049 simAccount.getAccountHandle().getUserHandle()); 2050 2051 // There is nothing to verify, we just want to ensure that we didn't crash. 2052 } 2053 makeBuilderWithBindCapabilities(PhoneAccountHandle handle)2054 private static PhoneAccount.Builder makeBuilderWithBindCapabilities(PhoneAccountHandle handle) { 2055 return new PhoneAccount.Builder(handle, TEST_LABEL) 2056 .setCapabilities(PhoneAccount.CAPABILITY_SUPPORTS_TRANSACTIONAL_OPERATIONS); 2057 } 2058 makeQuickConnectionServiceComponentName()2059 private static ComponentName makeQuickConnectionServiceComponentName() { 2060 return new ComponentName( 2061 "com.android.server.telecom.tests", 2062 "com.android.server.telecom.tests.MockConnectionService"); 2063 } 2064 makeQuickAccountHandle(String id)2065 private static PhoneAccountHandle makeQuickAccountHandle(String id) { 2066 return makeQuickAccountHandle(makeQuickConnectionServiceComponentName(), id); 2067 } 2068 makeQuickAccountHandle(ComponentName name, String id)2069 private static PhoneAccountHandle makeQuickAccountHandle(ComponentName name, String id) { 2070 return new PhoneAccountHandle(name, id, Process.myUserHandle()); 2071 } 2072 makeQuickAccountHandleForUser( String id, UserHandle userHandle)2073 private static PhoneAccountHandle makeQuickAccountHandleForUser( 2074 String id, UserHandle userHandle) { 2075 return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id, userHandle); 2076 } 2077 makeQuickAccountBuilder( String id, int idx, UserHandle userHandle)2078 private PhoneAccount.Builder makeQuickAccountBuilder( 2079 String id, int idx, UserHandle userHandle) { 2080 return new PhoneAccount.Builder( 2081 userHandle == null 2082 ? makeQuickAccountHandle(id) 2083 : makeQuickAccountHandleForUser(id, userHandle), 2084 "label" + idx); 2085 } 2086 copyPhoneAccountAndOverrideCapabilities( PhoneAccount base, int newCapabilities)2087 private static PhoneAccount copyPhoneAccountAndOverrideCapabilities( 2088 PhoneAccount base, int newCapabilities) { 2089 return base.toBuilder().setCapabilities(newCapabilities).build(); 2090 } 2091 copyPhoneAccountAndAddCapabilities( PhoneAccount base, int capabilitiesToAdd)2092 private static PhoneAccount copyPhoneAccountAndAddCapabilities( 2093 PhoneAccount base, int capabilitiesToAdd) { 2094 return copyPhoneAccountAndOverrideCapabilities( 2095 base, base.getCapabilities() | capabilitiesToAdd); 2096 } 2097 copyPhoneAccountAndRemoveCapabilities( PhoneAccount base, int capabilitiesToRemove)2098 private static PhoneAccount copyPhoneAccountAndRemoveCapabilities( 2099 PhoneAccount base, int capabilitiesToRemove) { 2100 return copyPhoneAccountAndOverrideCapabilities( 2101 base, base.getCapabilities() & ~capabilitiesToRemove); 2102 } 2103 makeQuickAccount(String id, int idx)2104 private PhoneAccount makeQuickAccount(String id, int idx) { 2105 return makeQuickAccountBuilder(id, idx, null) 2106 .setAddress(Uri.parse("http://foo.com/" + idx)) 2107 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx)) 2108 .setCapabilities(idx) 2109 .setIcon(Icon.createWithResource( 2110 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)) 2111 .setShortDescription("desc" + idx) 2112 .setIsEnabled(true) 2113 .build(); 2114 } 2115 2116 /** 2117 * Similar to {@link #makeQuickAccount}, but also hooks up {@code TelephonyManager} so that it 2118 * returns {@code simId} as the account's subscriptionId. 2119 */ makeQuickSimAccount(int simId)2120 private PhoneAccount makeQuickSimAccount(int simId) { 2121 PhoneAccount simAccount = 2122 makeQuickAccountBuilder("sim" + simId, simId, null) 2123 .setCapabilities( 2124 PhoneAccount.CAPABILITY_CALL_PROVIDER 2125 | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 2126 .setIsEnabled(true) 2127 .build(); 2128 when(mComponentContextFixture 2129 .getTelephonyManager() 2130 .getSubscriptionId(simAccount.getAccountHandle())) 2131 .thenReturn(simId); 2132 // mComponentContextFixture already sets up the createForSubscriptionId self-reference 2133 when(mComponentContextFixture 2134 .getTelephonyManager() 2135 .createForPhoneAccountHandle(simAccount.getAccountHandle())) 2136 .thenReturn(mComponentContextFixture.getTelephonyManager()); 2137 return simAccount; 2138 } 2139 2140 /** 2141 * Hooks up carrier config to point to {@code simCallManagerComponent} for the given {@code 2142 * subscriptionId}. 2143 */ setSimCallManagerCarrierConfig( int subscriptionId, @Nullable ComponentName simCallManagerComponent)2144 private void setSimCallManagerCarrierConfig( 2145 int subscriptionId, @Nullable ComponentName simCallManagerComponent) { 2146 PersistableBundle config = new PersistableBundle(); 2147 config.putString( 2148 CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING, 2149 simCallManagerComponent != null ? simCallManagerComponent.flattenToString() : null); 2150 when(mComponentContextFixture.getCarrierConfigManager().getConfigForSubId(subscriptionId)) 2151 .thenReturn(config); 2152 } 2153 roundTripPhoneAccount(PhoneAccount original)2154 private static void roundTripPhoneAccount(PhoneAccount original) throws Exception { 2155 PhoneAccount copy = null; 2156 2157 { 2158 Parcel parcel = Parcel.obtain(); 2159 parcel.writeParcelable(original, 0); 2160 parcel.setDataPosition(0); 2161 copy = parcel.readParcelable(PhoneAccountRegistrarTest.class.getClassLoader()); 2162 parcel.recycle(); 2163 } 2164 2165 assertPhoneAccountEquals(original, copy); 2166 } 2167 roundTripXml( Object self, T input, PhoneAccountRegistrar.XmlSerialization<T> xml, Context context, FeatureFlags telephonyFeatureFlags, com.android.server.telecom.flags.FeatureFlags telecomFeatureFlags)2168 private static <T> T roundTripXml( 2169 Object self, 2170 T input, 2171 PhoneAccountRegistrar.XmlSerialization<T> xml, 2172 Context context, 2173 FeatureFlags telephonyFeatureFlags, 2174 com.android.server.telecom.flags.FeatureFlags telecomFeatureFlags) 2175 throws Exception { 2176 Log.d(self, "Input = %s", input); 2177 2178 byte[] data = toXml(input, xml, context, telephonyFeatureFlags); 2179 2180 Log.i(self, "====== XML data ======\n%s", new String(data)); 2181 2182 T result = fromXml(data, xml, context, telephonyFeatureFlags, telecomFeatureFlags); 2183 2184 Log.i(self, "result = " + result); 2185 2186 return result; 2187 } 2188 toXml(T input, PhoneAccountRegistrar.XmlSerialization<T> xml, Context context, FeatureFlags telephonyFeatureFlags)2189 private static <T> byte[] toXml(T input, PhoneAccountRegistrar.XmlSerialization<T> xml, 2190 Context context, FeatureFlags telephonyFeatureFlags) throws Exception { 2191 XmlSerializer serializer = new FastXmlSerializer(); 2192 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2193 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 2194 xml.writeToXml(input, serializer, context, telephonyFeatureFlags); 2195 serializer.flush(); 2196 return baos.toByteArray(); 2197 } 2198 fromXml(byte[] data, PhoneAccountRegistrar.XmlSerialization<T> xml, Context context, FeatureFlags telephonyFeatureFlags, com.android.server.telecom.flags.FeatureFlags telecomFeatureFlags)2199 private static <T> T fromXml(byte[] data, PhoneAccountRegistrar.XmlSerialization<T> xml, 2200 Context context, FeatureFlags telephonyFeatureFlags, 2201 com.android.server.telecom.flags.FeatureFlags telecomFeatureFlags) throws Exception { 2202 XmlPullParser parser = Xml.newPullParser(); 2203 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null); 2204 parser.nextTag(); 2205 return xml.readFromXml(parser, MAX_VERSION, context, 2206 telephonyFeatureFlags, telecomFeatureFlags); 2207 2208 } 2209 assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b)2210 private static void assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b) { 2211 if (a != b) { 2212 assertEquals( 2213 a.getComponentName().getPackageName(), 2214 b.getComponentName().getPackageName()); 2215 assertEquals( 2216 a.getComponentName().getClassName(), 2217 b.getComponentName().getClassName()); 2218 assertEquals(a.getId(), b.getId()); 2219 } 2220 } 2221 assertIconEquals(Icon a, Icon b)2222 private static void assertIconEquals(Icon a, Icon b) { 2223 if (a != b) { 2224 if (a != null && b != null) { 2225 assertEquals(a.toString(), b.toString()); 2226 } else { 2227 fail("Icons not equal: " + a + ", " + b); 2228 } 2229 } 2230 } 2231 assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a, DefaultPhoneAccountHandle b)2232 private static void assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a, 2233 DefaultPhoneAccountHandle b) { 2234 if (a != b) { 2235 if (a!= null && b != null) { 2236 assertEquals(a.userHandle, b.userHandle); 2237 assertPhoneAccountHandleEquals(a.phoneAccountHandle, b.phoneAccountHandle); 2238 } else { 2239 fail("Default phone account handles are not equal: " + a + ", " + b); 2240 } 2241 } 2242 } 2243 assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b)2244 private static void assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b) { 2245 if (a != b) { 2246 if (a != null && b != null) { 2247 assertPhoneAccountHandleEquals(a.getAccountHandle(), b.getAccountHandle()); 2248 assertEquals(a.getAddress(), b.getAddress()); 2249 assertEquals(a.getSubscriptionAddress(), b.getSubscriptionAddress()); 2250 assertEquals(a.getCapabilities(), b.getCapabilities()); 2251 assertIconEquals(a.getIcon(), b.getIcon()); 2252 assertEquals(a.getHighlightColor(), b.getHighlightColor()); 2253 assertEquals(a.getLabel(), b.getLabel()); 2254 assertEquals(a.getShortDescription(), b.getShortDescription()); 2255 assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes()); 2256 assertBundlesEqual(a.getExtras(), b.getExtras()); 2257 assertEquals(a.isEnabled(), b.isEnabled()); 2258 assertEquals(a.hasSimultaneousCallingRestriction(), 2259 b.hasSimultaneousCallingRestriction()); 2260 if (a.hasSimultaneousCallingRestriction()) { 2261 assertEquals(a.getSimultaneousCallingRestriction(), 2262 b.getSimultaneousCallingRestriction()); 2263 } 2264 } else { 2265 fail("Phone accounts not equal: " + a + ", " + b); 2266 } 2267 } 2268 } 2269 assertBundlesEqual(Bundle a, Bundle b)2270 private static void assertBundlesEqual(Bundle a, Bundle b) { 2271 if (a == null && b == null) { 2272 return; 2273 } 2274 2275 assertNotNull(a); 2276 assertNotNull(b); 2277 Set<String> keySetA = a.keySet(); 2278 Set<String> keySetB = b.keySet(); 2279 2280 assertTrue("Bundle keys not the same", keySetA.containsAll(keySetB)); 2281 assertTrue("Bundle keys not the same", keySetB.containsAll(keySetA)); 2282 2283 for (String keyA : keySetA) { 2284 assertEquals("Bundle value not the same", a.get(keyA), b.get(keyA)); 2285 } 2286 } 2287 assertStateEquals( PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b)2288 private static void assertStateEquals( 2289 PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) { 2290 assertEquals(a.defaultOutgoingAccountHandles.size(), 2291 b.defaultOutgoingAccountHandles.size()); 2292 for (Map.Entry<UserHandle, DefaultPhoneAccountHandle> e : 2293 a.defaultOutgoingAccountHandles.entrySet()) { 2294 assertDefaultPhoneAccountHandleEquals(e.getValue(), 2295 b.defaultOutgoingAccountHandles.get(e.getKey())); 2296 } 2297 assertEquals(a.accounts.size(), b.accounts.size()); 2298 for (int i = 0; i < a.accounts.size(); i++) { 2299 assertPhoneAccountEquals(a.accounts.get(i), b.accounts.get(i)); 2300 } 2301 } 2302 makeQuickStateWithTelephonyPhoneAccountHandle()2303 private PhoneAccountRegistrar.State makeQuickStateWithTelephonyPhoneAccountHandle() { 2304 UserManager userManager = mContext.getSystemService(UserManager.class); 2305 PhoneAccountRegistrar.State s = new PhoneAccountRegistrar.State(); 2306 s.accounts.add(makeQuickAccount("id0", 0)); 2307 s.accounts.add(makeQuickAccount("id1", 1)); 2308 s.accounts.add(makeQuickAccount("id2", 2)); 2309 PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(new ComponentName( 2310 "com.android.phone", 2311 "com.android.services.telephony.TelephonyConnectionService"), "id0"); 2312 UserHandle userHandle = phoneAccountHandle.getUserHandle(); 2313 when(userManager.getSerialNumberForUser(userHandle)) 2314 .thenReturn(0L); 2315 when(userManager.getUserForSerialNumber(0L)) 2316 .thenReturn(userHandle); 2317 s.defaultOutgoingAccountHandles 2318 .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle, 2319 "testGroup")); 2320 return s; 2321 } 2322 makeQuickState()2323 private PhoneAccountRegistrar.State makeQuickState() { 2324 UserManager userManager = mContext.getSystemService(UserManager.class); 2325 PhoneAccountRegistrar.State s = new PhoneAccountRegistrar.State(); 2326 s.accounts.add(makeQuickAccount("id0", 0)); 2327 s.accounts.add(makeQuickAccount("id1", 1)); 2328 s.accounts.add(makeQuickAccount("id2", 2)); 2329 PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle( 2330 new ComponentName("pkg0", "cls0"), "id0"); 2331 UserHandle userHandle = phoneAccountHandle.getUserHandle(); 2332 when(userManager.getSerialNumberForUser(userHandle)) 2333 .thenReturn(0L); 2334 when(userManager.getUserForSerialNumber(0L)) 2335 .thenReturn(userHandle); 2336 s.defaultOutgoingAccountHandles 2337 .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle, 2338 "testGroup")); 2339 return s; 2340 } 2341 } 2342