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 17package com.android.server.telecom.tests; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.graphics.BitmapFactory; 22import android.graphics.Rect; 23import android.graphics.drawable.Icon; 24import android.net.Uri; 25import android.os.Bundle; 26import android.os.Parcel; 27import android.os.Process; 28import android.os.UserHandle; 29import android.telecom.Log; 30import android.telecom.PhoneAccount; 31import android.telecom.PhoneAccountHandle; 32import android.telecom.TelecomManager; 33import android.test.suitebuilder.annotation.MediumTest; 34import android.util.Xml; 35 36import com.android.internal.telecom.IConnectionService; 37import com.android.internal.util.FastXmlSerializer; 38import com.android.server.telecom.DefaultDialerCache; 39import com.android.server.telecom.PhoneAccountRegistrar; 40import com.android.server.telecom.PhoneAccountRegistrar.DefaultPhoneAccountHandle; 41 42import org.mockito.Mock; 43import org.mockito.Mockito; 44import org.mockito.MockitoAnnotations; 45import org.xmlpull.v1.XmlPullParser; 46import org.xmlpull.v1.XmlSerializer; 47 48import java.io.BufferedInputStream; 49import java.io.BufferedOutputStream; 50import java.io.ByteArrayInputStream; 51import java.io.ByteArrayOutputStream; 52import java.io.File; 53import java.util.Arrays; 54import java.util.Set; 55 56import static org.mockito.Matchers.anyInt; 57import static org.mockito.Matchers.anyString; 58import static org.mockito.Mockito.when; 59 60public class PhoneAccountRegistrarTest extends TelecomTestCase { 61 62 private static final int MAX_VERSION = Integer.MAX_VALUE; 63 private static final String FILE_NAME = "phone-account-registrar-test-1223.xml"; 64 private static final String TEST_LABEL = "right"; 65 private PhoneAccountRegistrar mRegistrar; 66 @Mock private TelecomManager mTelecomManager; 67 @Mock private DefaultDialerCache mDefaultDialerCache; 68 @Mock private PhoneAccountRegistrar.AppLabelProxy mAppLabelProxy; 69 70 @Override 71 public void setUp() throws Exception { 72 super.setUp(); 73 MockitoAnnotations.initMocks(this); 74 mComponentContextFixture.setTelecomManager(mTelecomManager); 75 new File( 76 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(), 77 FILE_NAME) 78 .delete(); 79 when(mDefaultDialerCache.getDefaultDialerApplication(anyInt())) 80 .thenReturn("com.android.dialer"); 81 when(mAppLabelProxy.getAppLabel(anyString())) 82 .thenReturn(TEST_LABEL); 83 mRegistrar = new PhoneAccountRegistrar( 84 mComponentContextFixture.getTestDouble().getApplicationContext(), 85 FILE_NAME, mDefaultDialerCache, mAppLabelProxy); 86 } 87 88 @Override 89 public void tearDown() throws Exception { 90 mRegistrar = null; 91 new File( 92 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(), 93 FILE_NAME) 94 .delete(); 95 super.tearDown(); 96 } 97 98 @MediumTest 99 public void testPhoneAccountHandle() throws Exception { 100 PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0"); 101 PhoneAccountHandle result = roundTripXml(this, input, 102 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext); 103 assertPhoneAccountHandleEquals(input, result); 104 105 PhoneAccountHandle inputN = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), null); 106 PhoneAccountHandle resultN = roundTripXml(this, inputN, 107 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext); 108 Log.i(this, "inputN = %s, resultN = %s", inputN, resultN); 109 assertPhoneAccountHandleEquals(inputN, resultN); 110 } 111 112 @MediumTest 113 public void testPhoneAccount() throws Exception { 114 Bundle testBundle = new Bundle(); 115 testBundle.putInt("EXTRA_INT_1", 1); 116 testBundle.putInt("EXTRA_INT_100", 100); 117 testBundle.putBoolean("EXTRA_BOOL_TRUE", true); 118 testBundle.putBoolean("EXTRA_BOOL_FALSE", false); 119 testBundle.putString("EXTRA_STR1", "Hello"); 120 testBundle.putString("EXTRA_STR2", "There"); 121 122 PhoneAccount input = makeQuickAccountBuilder("id0", 0) 123 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 124 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 125 .setExtras(testBundle) 126 .setIsEnabled(true) 127 .build(); 128 PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml, 129 mContext); 130 131 assertPhoneAccountEquals(input, result); 132 } 133 134 @MediumTest 135 public void testDefaultPhoneAccountHandleEmptyGroup() throws Exception { 136 DefaultPhoneAccountHandle input = new DefaultPhoneAccountHandle(Process.myUserHandle(), 137 makeQuickAccountHandle("i1"), ""); 138 DefaultPhoneAccountHandle result = roundTripXml(this, input, 139 PhoneAccountRegistrar.sDefaultPhoneAcountHandleXml, mContext); 140 141 assertDefaultPhoneAccountHandleEquals(input, result); 142 } 143 144 /** 145 * Test to ensure non-supported values 146 * @throws Exception 147 */ 148 @MediumTest 149 public void testPhoneAccountExtrasEdge() throws Exception { 150 Bundle testBundle = new Bundle(); 151 // Ensure null values for string are not persisted. 152 testBundle.putString("EXTRA_STR2", null); 153 // 154 155 // Ensure unsupported data types are not persisted. 156 testBundle.putShort("EXTRA_SHORT", (short) 2); 157 testBundle.putByte("EXTRA_BYTE", (byte) 1); 158 testBundle.putParcelable("EXTRA_PARC", new Rect(1, 1, 1, 1)); 159 // Put in something valid so the bundle exists. 160 testBundle.putString("EXTRA_OK", "OK"); 161 162 PhoneAccount input = makeQuickAccountBuilder("id0", 0) 163 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 164 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL) 165 .setExtras(testBundle) 166 .build(); 167 PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml, 168 mContext); 169 170 Bundle extras = result.getExtras(); 171 assertFalse(extras.keySet().contains("EXTRA_STR2")); 172 assertFalse(extras.keySet().contains("EXTRA_SHORT")); 173 assertFalse(extras.keySet().contains("EXTRA_BYTE")); 174 assertFalse(extras.keySet().contains("EXTRA_PARC")); 175 } 176 177 @MediumTest 178 public void testState() throws Exception { 179 PhoneAccountRegistrar.State input = makeQuickState(); 180 PhoneAccountRegistrar.State result = roundTripXml(this, input, 181 PhoneAccountRegistrar.sStateXml, 182 mContext); 183 assertStateEquals(input, result); 184 } 185 186 private void registerAndEnableAccount(PhoneAccount account) { 187 mRegistrar.registerPhoneAccount(account); 188 mRegistrar.enablePhoneAccount(account.getAccountHandle(), true); 189 } 190 191 @MediumTest 192 public void testAccounts() throws Exception { 193 int i = 0; 194 195 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 196 Mockito.mock(IConnectionService.class)); 197 198 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++) 199 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 200 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 201 .build()); 202 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++) 203 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 204 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 205 .build()); 206 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++) 207 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER 208 | PhoneAccount.CAPABILITY_CALL_PROVIDER) 209 .build()); 210 registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++) 211 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 212 .build()); 213 214 assertEquals(4, mRegistrar.getAllPhoneAccountsOfCurrentUser().size()); 215 assertEquals(3, mRegistrar.getCallCapablePhoneAccountsOfCurrentUser(null, false).size()); 216 assertEquals(null, mRegistrar.getSimCallManagerOfCurrentUser()); 217 assertEquals(null, mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 218 PhoneAccount.SCHEME_TEL)); 219 } 220 221 @MediumTest 222 public void testSimCallManager() throws Exception { 223 // TODO 224 } 225 226 @MediumTest 227 public void testDefaultOutgoing() throws Exception { 228 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 229 Mockito.mock(IConnectionService.class)); 230 231 // By default, there is no default outgoing account (nothing has been registered) 232 assertNull( 233 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 234 235 // Register one tel: account 236 PhoneAccountHandle telAccount = makeQuickAccountHandle("tel_acct"); 237 registerAndEnableAccount(new PhoneAccount.Builder(telAccount, "tel_acct") 238 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 239 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 240 .build()); 241 PhoneAccountHandle defaultAccount = 242 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 243 assertEquals(telAccount, defaultAccount); 244 245 // Add a SIP account, make sure tel: doesn't change 246 PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct"); 247 registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct") 248 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 249 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP) 250 .build()); 251 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 252 PhoneAccount.SCHEME_SIP); 253 assertEquals(sipAccount, defaultAccount); 254 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 255 PhoneAccount.SCHEME_TEL); 256 assertEquals(telAccount, defaultAccount); 257 258 // Add a connection manager, make sure tel: doesn't change 259 PhoneAccountHandle connectionManager = makeQuickAccountHandle("mgr_acct"); 260 registerAndEnableAccount(new PhoneAccount.Builder(connectionManager, "mgr_acct") 261 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER) 262 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 263 .build()); 264 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 265 PhoneAccount.SCHEME_TEL); 266 assertEquals(telAccount, defaultAccount); 267 268 // Unregister the tel: account, make sure there is no tel: default now. 269 mRegistrar.unregisterPhoneAccount(telAccount); 270 assertNull( 271 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 272 } 273 274 @MediumTest 275 public void testReplacePhoneAccountByGroup() throws Exception { 276 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 277 Mockito.mock(IConnectionService.class)); 278 279 // By default, there is no default outgoing account (nothing has been registered) 280 assertNull( 281 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 282 283 // Register one tel: account 284 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 285 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 286 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 287 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 288 .setGroupId("testGroup") 289 .build()); 290 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 291 PhoneAccountHandle defaultAccount = 292 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 293 assertEquals(telAccount1, defaultAccount); 294 295 // Add call capable SIP account, make sure tel: doesn't change 296 PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct"); 297 registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct") 298 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 299 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 300 .build()); 301 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 302 PhoneAccount.SCHEME_TEL); 303 assertEquals(telAccount1, defaultAccount); 304 305 // Replace tel: account with another in the same Group 306 PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2"); 307 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 308 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 309 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 310 .setGroupId("testGroup") 311 .build()); 312 defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 313 PhoneAccount.SCHEME_TEL); 314 assertEquals(telAccount2, defaultAccount); 315 assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 316 } 317 318 @MediumTest 319 public void testAddSameDefault() throws Exception { 320 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 321 Mockito.mock(IConnectionService.class)); 322 323 // By default, there is no default outgoing account (nothing has been registered) 324 assertNull( 325 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 326 327 // Register one tel: account 328 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 329 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 330 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 331 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 332 .setGroupId("testGroup") 333 .build()); 334 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 335 PhoneAccountHandle defaultAccount = 336 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 337 assertEquals(telAccount1, defaultAccount); 338 mRegistrar.unregisterPhoneAccount(telAccount1); 339 340 // Register Emergency Account and unregister 341 PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct"); 342 registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct") 343 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 344 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 345 .build()); 346 defaultAccount = 347 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 348 assertNull(defaultAccount); 349 mRegistrar.unregisterPhoneAccount(emerAccount); 350 351 // Re-register the same account and make sure the default is in place 352 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 353 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 354 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 355 .setGroupId("testGroup") 356 .build()); 357 defaultAccount = 358 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 359 assertEquals(telAccount1, defaultAccount); 360 } 361 362 @MediumTest 363 public void testAddSameGroup() throws Exception { 364 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 365 Mockito.mock(IConnectionService.class)); 366 367 // By default, there is no default outgoing account (nothing has been registered) 368 assertNull( 369 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL)); 370 371 // Register one tel: account 372 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 373 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 374 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 375 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 376 .setGroupId("testGroup") 377 .build()); 378 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 379 PhoneAccountHandle defaultAccount = 380 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 381 assertEquals(telAccount1, defaultAccount); 382 mRegistrar.unregisterPhoneAccount(telAccount1); 383 384 // Register Emergency Account and unregister 385 PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct"); 386 registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct") 387 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 388 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 389 .build()); 390 defaultAccount = 391 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 392 assertNull(defaultAccount); 393 mRegistrar.unregisterPhoneAccount(emerAccount); 394 395 // Re-register a new account with the same group 396 PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2"); 397 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 398 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 399 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 400 .setGroupId("testGroup") 401 .build()); 402 defaultAccount = 403 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 404 assertEquals(telAccount2, defaultAccount); 405 } 406 407 @MediumTest 408 public void testAddSameGroupButDifferentComponent() throws Exception { 409 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 410 Mockito.mock(IConnectionService.class)); 411 412 // By default, there is no default outgoing account (nothing has been registered) 413 assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 414 PhoneAccount.SCHEME_TEL)); 415 416 // Register one tel: account 417 PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1"); 418 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 419 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 420 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 421 .setGroupId("testGroup") 422 .build()); 423 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 424 PhoneAccountHandle defaultAccount = 425 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 426 assertEquals(telAccount1, defaultAccount); 427 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 428 429 // Register a new account with the same group, but different Component, so don't replace 430 // Default 431 PhoneAccountHandle telAccount2 = makeQuickAccountHandle( 432 new ComponentName("other1", "other2"), "tel_acct2"); 433 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 434 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 435 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 436 .setGroupId("testGroup") 437 .build()); 438 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount2)); 439 440 defaultAccount = 441 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle()); 442 assertEquals(telAccount1, defaultAccount); 443 } 444 445 @MediumTest 446 public void testAddSameGroupButDifferentComponent2() throws Exception { 447 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 448 Mockito.mock(IConnectionService.class)); 449 450 // By default, there is no default outgoing account (nothing has been registered) 451 assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser( 452 PhoneAccount.SCHEME_TEL)); 453 454 // Register first tel: account 455 PhoneAccountHandle telAccount1 = makeQuickAccountHandle( 456 new ComponentName("other1", "other2"), "tel_acct1"); 457 registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1") 458 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 459 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 460 .setGroupId("testGroup") 461 .build()); 462 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 463 mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle()); 464 465 // Register second account with the same group, but a second Component, so don't replace 466 // Default 467 PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2"); 468 registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2") 469 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 470 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 471 .setGroupId("testGroup") 472 .build()); 473 474 PhoneAccountHandle defaultAccount = 475 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 476 assertEquals(telAccount1, defaultAccount); 477 478 // Register third account with the second component name, but same group id 479 PhoneAccountHandle telAccount3 = makeQuickAccountHandle("tel_acct3"); 480 registerAndEnableAccount(new PhoneAccount.Builder(telAccount3, "tel_acct3") 481 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER) 482 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL) 483 .setGroupId("testGroup") 484 .build()); 485 486 // Make sure that the default account is still the original PhoneAccount and that the 487 // second PhoneAccount with the second ComponentName was replaced by the third PhoneAccount 488 defaultAccount = 489 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL); 490 assertEquals(telAccount1, defaultAccount); 491 492 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1)); 493 assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount2)); 494 assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount3)); 495 } 496 497 @MediumTest 498 public void testPhoneAccountParceling() throws Exception { 499 PhoneAccountHandle handle = makeQuickAccountHandle("foo"); 500 roundTripPhoneAccount(new PhoneAccount.Builder(handle, null).build()); 501 roundTripPhoneAccount(new PhoneAccount.Builder(handle, "foo").build()); 502 roundTripPhoneAccount( 503 new PhoneAccount.Builder(handle, "foo") 504 .setAddress(Uri.parse("tel:123456")) 505 .setCapabilities(23) 506 .setHighlightColor(0xf0f0f0) 507 .setIcon(Icon.createWithResource( 508 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)) 509 // TODO: set icon tint (0xfefefe) 510 .setShortDescription("short description") 511 .setSubscriptionAddress(Uri.parse("tel:2345678")) 512 .setSupportedUriSchemes(Arrays.asList("tel", "sip")) 513 .setGroupId("testGroup") 514 .build()); 515 roundTripPhoneAccount( 516 new PhoneAccount.Builder(handle, "foo") 517 .setAddress(Uri.parse("tel:123456")) 518 .setCapabilities(23) 519 .setHighlightColor(0xf0f0f0) 520 .setIcon(Icon.createWithBitmap( 521 BitmapFactory.decodeResource( 522 getContext().getResources(), 523 R.drawable.stat_sys_phone_call))) 524 .setShortDescription("short description") 525 .setSubscriptionAddress(Uri.parse("tel:2345678")) 526 .setSupportedUriSchemes(Arrays.asList("tel", "sip")) 527 .setGroupId("testGroup") 528 .build()); 529 } 530 531 /** 532 * Tests ability to register a self-managed PhoneAccount; verifies that the user defined label 533 * is overridden. 534 * @throws Exception 535 */ 536 @MediumTest 537 public void testSelfManagedPhoneAccount() throws Exception { 538 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 539 Mockito.mock(IConnectionService.class)); 540 541 PhoneAccountHandle selfManagedHandle = makeQuickAccountHandle( 542 new ComponentName("self", "managed"), "selfie1"); 543 544 PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, "Wrong") 545 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) 546 .build(); 547 548 mRegistrar.registerPhoneAccount(selfManagedAccount); 549 550 PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle); 551 assertEquals(TEST_LABEL, registeredAccount.getLabel()); 552 } 553 554 /** 555 * Tests to ensure that when registering a self-managed PhoneAccount, it cannot also be defined 556 * as a call provider, connection manager, or sim subscription. 557 * @throws Exception 558 */ 559 @MediumTest 560 public void testSelfManagedCapabilityOverride() throws Exception { 561 mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(), 562 Mockito.mock(IConnectionService.class)); 563 564 PhoneAccountHandle selfManagedHandle = makeQuickAccountHandle( 565 new ComponentName("self", "managed"), "selfie1"); 566 567 PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, TEST_LABEL) 568 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED | 569 PhoneAccount.CAPABILITY_CALL_PROVIDER | 570 PhoneAccount.CAPABILITY_CONNECTION_MANAGER | 571 PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) 572 .build(); 573 574 mRegistrar.registerPhoneAccount(selfManagedAccount); 575 576 PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle); 577 assertEquals(PhoneAccount.CAPABILITY_SELF_MANAGED, registeredAccount.getCapabilities()); 578 } 579 580 private static ComponentName makeQuickConnectionServiceComponentName() { 581 return new ComponentName( 582 "com.android.server.telecom.tests", 583 "com.android.server.telecom.tests.MockConnectionService"); 584 } 585 586 private static PhoneAccountHandle makeQuickAccountHandle(String id) { 587 return makeQuickAccountHandle(makeQuickConnectionServiceComponentName(), id); 588 } 589 590 private static PhoneAccountHandle makeQuickAccountHandle(ComponentName name, String id) { 591 return new PhoneAccountHandle(name, id, Process.myUserHandle()); 592 } 593 594 private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) { 595 return new PhoneAccount.Builder( 596 makeQuickAccountHandle(id), 597 "label" + idx); 598 } 599 600 private PhoneAccount makeQuickAccount(String id, int idx) { 601 return makeQuickAccountBuilder(id, idx) 602 .setAddress(Uri.parse("http://foo.com/" + idx)) 603 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx)) 604 .setCapabilities(idx) 605 .setIcon(Icon.createWithResource( 606 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call)) 607 .setShortDescription("desc" + idx) 608 .setIsEnabled(true) 609 .build(); 610 } 611 612 private static void roundTripPhoneAccount(PhoneAccount original) throws Exception { 613 PhoneAccount copy = null; 614 615 { 616 Parcel parcel = Parcel.obtain(); 617 parcel.writeParcelable(original, 0); 618 parcel.setDataPosition(0); 619 copy = parcel.readParcelable(PhoneAccountRegistrarTest.class.getClassLoader()); 620 parcel.recycle(); 621 } 622 623 assertPhoneAccountEquals(original, copy); 624 } 625 626 private static <T> T roundTripXml( 627 Object self, 628 T input, 629 PhoneAccountRegistrar.XmlSerialization<T> xml, 630 Context context) 631 throws Exception { 632 Log.d(self, "Input = %s", input); 633 634 byte[] data; 635 { 636 XmlSerializer serializer = new FastXmlSerializer(); 637 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 638 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 639 xml.writeToXml(input, serializer, context); 640 serializer.flush(); 641 data = baos.toByteArray(); 642 } 643 644 Log.i(self, "====== XML data ======\n%s", new String(data)); 645 646 T result = null; 647 { 648 XmlPullParser parser = Xml.newPullParser(); 649 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null); 650 parser.nextTag(); 651 result = xml.readFromXml(parser, MAX_VERSION, context); 652 } 653 654 Log.i(self, "result = " + result); 655 656 return result; 657 } 658 659 private static void assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b) { 660 if (a != b) { 661 assertEquals( 662 a.getComponentName().getPackageName(), 663 b.getComponentName().getPackageName()); 664 assertEquals( 665 a.getComponentName().getClassName(), 666 b.getComponentName().getClassName()); 667 assertEquals(a.getId(), b.getId()); 668 } 669 } 670 671 private static void assertIconEquals(Icon a, Icon b) { 672 if (a != b) { 673 if (a != null && b != null) { 674 assertEquals(a.toString(), b.toString()); 675 } else { 676 fail("Icons not equal: " + a + ", " + b); 677 } 678 } 679 } 680 681 private static void assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a, 682 DefaultPhoneAccountHandle b) { 683 if (a != b) { 684 if (a!= null && b != null) { 685 assertEquals(a.userHandle, b.userHandle); 686 assertPhoneAccountHandleEquals(a.phoneAccountHandle, b.phoneAccountHandle); 687 } else { 688 fail("Default phone account handles are not equal: " + a + ", " + b); 689 } 690 } 691 } 692 693 private static void assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b) { 694 if (a != b) { 695 if (a != null && b != null) { 696 assertPhoneAccountHandleEquals(a.getAccountHandle(), b.getAccountHandle()); 697 assertEquals(a.getAddress(), b.getAddress()); 698 assertEquals(a.getSubscriptionAddress(), b.getSubscriptionAddress()); 699 assertEquals(a.getCapabilities(), b.getCapabilities()); 700 assertIconEquals(a.getIcon(), b.getIcon()); 701 assertEquals(a.getHighlightColor(), b.getHighlightColor()); 702 assertEquals(a.getLabel(), b.getLabel()); 703 assertEquals(a.getShortDescription(), b.getShortDescription()); 704 assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes()); 705 assertBundlesEqual(a.getExtras(), b.getExtras()); 706 assertEquals(a.isEnabled(), b.isEnabled()); 707 } else { 708 fail("Phone accounts not equal: " + a + ", " + b); 709 } 710 } 711 } 712 713 private static void assertBundlesEqual(Bundle a, Bundle b) { 714 if (a == null && b == null) { 715 return; 716 } 717 718 assertNotNull(a); 719 assertNotNull(b); 720 Set<String> keySetA = a.keySet(); 721 Set<String> keySetB = b.keySet(); 722 723 assertTrue("Bundle keys not the same", keySetA.containsAll(keySetB)); 724 assertTrue("Bundle keys not the same", keySetB.containsAll(keySetA)); 725 726 for (String keyA : keySetA) { 727 assertEquals("Bundle value not the same", a.get(keyA), b.get(keyA)); 728 } 729 } 730 731 private static void assertStateEquals( 732 PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) { 733 assertEquals(a.defaultOutgoingAccountHandles.size(), 734 b.defaultOutgoingAccountHandles.size()); 735 for (int i = 0; i < a.defaultOutgoingAccountHandles.size(); i++) { 736 assertDefaultPhoneAccountHandleEquals(a.defaultOutgoingAccountHandles.get(i), 737 b.defaultOutgoingAccountHandles.get(i)); 738 } 739 assertEquals(a.accounts.size(), b.accounts.size()); 740 for (int i = 0; i < a.accounts.size(); i++) { 741 assertPhoneAccountEquals(a.accounts.get(i), b.accounts.get(i)); 742 } 743 } 744 745 private PhoneAccountRegistrar.State makeQuickState() { 746 PhoneAccountRegistrar.State s = new PhoneAccountRegistrar.State(); 747 s.accounts.add(makeQuickAccount("id0", 0)); 748 s.accounts.add(makeQuickAccount("id1", 1)); 749 s.accounts.add(makeQuickAccount("id2", 2)); 750 PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle( 751 new ComponentName("pkg0", "cls0"), "id0"); 752 UserHandle userHandle = phoneAccountHandle.getUserHandle(); 753 s.defaultOutgoingAccountHandles 754 .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle, 755 "testGroup")); 756 return s; 757 } 758} 759