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