• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Matchers.anyBoolean;
26 import static org.mockito.Matchers.anyInt;
27 import static org.mockito.Matchers.anyString;
28 import static org.mockito.Mockito.clearInvocations;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.times;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33 
34 import android.annotation.Nullable;
35 import android.content.ComponentName;
36 import android.content.Context;
37 import android.content.pm.PackageInfo;
38 import android.content.pm.PackageManager;
39 import android.graphics.BitmapFactory;
40 import android.graphics.Rect;
41 import android.graphics.drawable.Icon;
42 import android.net.Uri;
43 import android.os.Bundle;
44 import android.os.Parcel;
45 import android.os.PersistableBundle;
46 import android.os.Process;
47 import android.os.UserHandle;
48 import android.os.UserManager;
49 import android.telecom.Log;
50 import android.telecom.PhoneAccount;
51 import android.telecom.PhoneAccountHandle;
52 import android.telecom.TelecomManager;
53 import android.telephony.CarrierConfigManager;
54 import android.telephony.SubscriptionInfo;
55 import android.telephony.SubscriptionManager;
56 import android.test.suitebuilder.annotation.SmallTest;
57 import android.test.suitebuilder.annotation.MediumTest;
58 import android.util.Xml;
59 
60 import androidx.test.InstrumentationRegistry;
61 
62 import com.android.internal.telecom.IConnectionService;
63 import com.android.internal.util.FastXmlSerializer;
64 import com.android.server.telecom.AppLabelProxy;
65 import com.android.server.telecom.DefaultDialerCache;
66 import com.android.server.telecom.PhoneAccountRegistrar;
67 import com.android.server.telecom.PhoneAccountRegistrar.DefaultPhoneAccountHandle;
68 import com.android.server.telecom.TelecomSystem;
69 
70 import org.junit.After;
71 import org.junit.Before;
72 import org.junit.Test;
73 import org.junit.runner.RunWith;
74 import org.junit.runners.JUnit4;
75 import org.mockito.Mock;
76 import org.mockito.Mockito;
77 import org.mockito.MockitoAnnotations;
78 import org.xmlpull.v1.XmlPullParser;
79 import org.xmlpull.v1.XmlSerializer;
80 
81 import java.io.BufferedInputStream;
82 import java.io.BufferedOutputStream;
83 import java.io.ByteArrayInputStream;
84 import java.io.ByteArrayOutputStream;
85 import java.io.File;
86 import java.util.ArrayList;
87 import java.util.Arrays;
88 import java.util.Collection;
89 import java.util.List;
90 import java.util.Map;
91 import java.util.Set;
92 
93 @RunWith(JUnit4.class)
94 public class PhoneAccountRegistrarTest extends TelecomTestCase {
95 
96     private static final int MAX_VERSION = Integer.MAX_VALUE;
97     private static final String FILE_NAME = "phone-account-registrar-test-1223.xml";
98     private static final String TEST_LABEL = "right";
99     private final String PACKAGE_1 = "PACKAGE_1";
100     private final String PACKAGE_2 = "PACKAGE_2";
101     private final String COMPONENT_NAME = "com.android.server.telecom.tests.MockConnectionService";
102     private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };
103     private PhoneAccountRegistrar mRegistrar;
104     @Mock private SubscriptionManager mSubscriptionManager;
105     @Mock private TelecomManager mTelecomManager;
106     @Mock private DefaultDialerCache mDefaultDialerCache;
107     @Mock private AppLabelProxy mAppLabelProxy;
108 
109     @Override
110     @Before
setUp()111     public void setUp() throws Exception {
112         super.setUp();
113         MockitoAnnotations.initMocks(this);
114         mComponentContextFixture.setTelecomManager(mTelecomManager);
115         mComponentContextFixture.setSubscriptionManager(mSubscriptionManager);
116         new File(
117                 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(),
118                 FILE_NAME)
119                 .delete();
120         when(mDefaultDialerCache.getDefaultDialerApplication(anyInt()))
121                 .thenReturn("com.android.dialer");
122         when(mAppLabelProxy.getAppLabel(anyString()))
123                 .thenReturn(TEST_LABEL);
124         mRegistrar = new PhoneAccountRegistrar(
125                 mComponentContextFixture.getTestDouble().getApplicationContext(),
126                 mLock, FILE_NAME, mDefaultDialerCache, mAppLabelProxy);
127     }
128 
129     @Override
130     @After
tearDown()131     public void tearDown() throws Exception {
132         mRegistrar = null;
133         new File(
134                 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(),
135                 FILE_NAME)
136                 .delete();
137         super.tearDown();
138     }
139 
140     @MediumTest
141     @Test
testPhoneAccountHandle()142     public void testPhoneAccountHandle() throws Exception {
143         PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0");
144         PhoneAccountHandle result = roundTripXml(this, input,
145                 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
146         assertPhoneAccountHandleEquals(input, result);
147 
148         PhoneAccountHandle inputN = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), null);
149         PhoneAccountHandle resultN = roundTripXml(this, inputN,
150                 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
151         Log.i(this, "inputN = %s, resultN = %s", inputN, resultN);
152         assertPhoneAccountHandleEquals(inputN, resultN);
153     }
154 
155     @MediumTest
156     @Test
testPhoneAccount()157     public void testPhoneAccount() throws Exception {
158         Bundle testBundle = new Bundle();
159         testBundle.putInt("EXTRA_INT_1", 1);
160         testBundle.putInt("EXTRA_INT_100", 100);
161         testBundle.putBoolean("EXTRA_BOOL_TRUE", true);
162         testBundle.putBoolean("EXTRA_BOOL_FALSE", false);
163         testBundle.putString("EXTRA_STR1", "Hello");
164         testBundle.putString("EXTRA_STR2", "There");
165 
166         PhoneAccount input = makeQuickAccountBuilder("id0", 0)
167                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
168                 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
169                 .setExtras(testBundle)
170                 .setIsEnabled(true)
171                 .build();
172         PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
173                 mContext);
174 
175         assertPhoneAccountEquals(input, result);
176     }
177 
178     @SmallTest
179     @Test
testFilterPhoneAccountForTest()180     public void testFilterPhoneAccountForTest() throws Exception {
181         ComponentName componentA = new ComponentName("a", "a");
182         ComponentName componentB1 = new ComponentName("b", "b1");
183         ComponentName componentB2 = new ComponentName("b", "b2");
184         ComponentName componentC = new ComponentName("c", "c");
185 
186         PhoneAccount simAccountA = new PhoneAccount.Builder(
187                 makeQuickAccountHandle(componentA, "1"), "1")
188                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
189                 .setIsEnabled(true)
190                 .build();
191 
192         List<PhoneAccount> accountAList = new ArrayList<>();
193         accountAList.add(simAccountA);
194 
195         PhoneAccount simAccountB1 = new PhoneAccount.Builder(
196                 makeQuickAccountHandle(componentB1, "2"), "2")
197                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
198                 .setIsEnabled(true)
199                 .build();
200 
201         PhoneAccount simAccountB2 = new PhoneAccount.Builder(
202                 makeQuickAccountHandle(componentB2, "3"), "3")
203                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
204                 .setIsEnabled(true)
205                 .build();
206 
207         List<PhoneAccount> accountBList = new ArrayList<>();
208         accountBList.add(simAccountB1);
209         accountBList.add(simAccountB2);
210 
211         PhoneAccount simAccountC = new PhoneAccount.Builder(
212                 makeQuickAccountHandle(componentC, "4"), "4")
213                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
214                 .setIsEnabled(true)
215                 .build();
216 
217         List<PhoneAccount> accountCList = new ArrayList<>();
218         accountCList.add(simAccountC);
219 
220         List<PhoneAccount> allAccounts = new ArrayList<>();
221         allAccounts.addAll(accountAList);
222         allAccounts.addAll(accountBList);
223         allAccounts.addAll(accountCList);
224 
225         assertEquals(allAccounts, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
226 
227         mRegistrar.setTestPhoneAccountPackageNameFilter(componentA.getPackageName());
228         assertEquals(accountAList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
229 
230         mRegistrar.setTestPhoneAccountPackageNameFilter(componentB1.getPackageName());
231         assertEquals(accountBList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
232 
233         mRegistrar.setTestPhoneAccountPackageNameFilter(componentC.getPackageName());
234         assertEquals(accountCList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
235 
236         mRegistrar.setTestPhoneAccountPackageNameFilter(null);
237         assertEquals(allAccounts, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
238     }
239 
240     @MediumTest
241     @Test
testDefaultPhoneAccountHandleEmptyGroup()242     public void testDefaultPhoneAccountHandleEmptyGroup() throws Exception {
243         DefaultPhoneAccountHandle input = new DefaultPhoneAccountHandle(Process.myUserHandle(),
244                 makeQuickAccountHandle("i1"), "");
245         when(UserManager.get(mContext).getSerialNumberForUser(input.userHandle))
246                 .thenReturn(0L);
247         when(UserManager.get(mContext).getUserForSerialNumber(0L))
248                 .thenReturn(input.userHandle);
249         DefaultPhoneAccountHandle result = roundTripXml(this, input,
250                 PhoneAccountRegistrar.sDefaultPhoneAcountHandleXml, mContext);
251 
252         assertDefaultPhoneAccountHandleEquals(input, result);
253     }
254 
255     /**
256      * Test to ensure non-supported values
257      * @throws Exception
258      */
259     @MediumTest
260     @Test
testPhoneAccountExtrasEdge()261     public void testPhoneAccountExtrasEdge() throws Exception {
262         Bundle testBundle = new Bundle();
263         // Ensure null values for string are not persisted.
264         testBundle.putString("EXTRA_STR2", null);
265         //
266 
267         // Ensure unsupported data types are not persisted.
268         testBundle.putShort("EXTRA_SHORT", (short) 2);
269         testBundle.putByte("EXTRA_BYTE", (byte) 1);
270         testBundle.putParcelable("EXTRA_PARC", new Rect(1, 1, 1, 1));
271         // Put in something valid so the bundle exists.
272         testBundle.putString("EXTRA_OK", "OK");
273 
274         PhoneAccount input = makeQuickAccountBuilder("id0", 0)
275                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
276                 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
277                 .setExtras(testBundle)
278                 .build();
279         PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
280                 mContext);
281 
282         Bundle extras = result.getExtras();
283         assertFalse(extras.keySet().contains("EXTRA_STR2"));
284         assertFalse(extras.keySet().contains("EXTRA_SHORT"));
285         assertFalse(extras.keySet().contains("EXTRA_BYTE"));
286         assertFalse(extras.keySet().contains("EXTRA_PARC"));
287     }
288 
289     @MediumTest
290     @Test
testState()291     public void testState() throws Exception {
292         PhoneAccountRegistrar.State input = makeQuickState();
293         PhoneAccountRegistrar.State result = roundTripXml(this, input,
294                 PhoneAccountRegistrar.sStateXml,
295                 mContext);
296         assertStateEquals(input, result);
297     }
298 
registerAndEnableAccount(PhoneAccount account)299     private void registerAndEnableAccount(PhoneAccount account) {
300         mRegistrar.registerPhoneAccount(account);
301         mRegistrar.enablePhoneAccount(account.getAccountHandle(), true);
302     }
303 
304     @MediumTest
305     @Test
testAccounts()306     public void testAccounts() throws Exception {
307         int i = 0;
308 
309         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
310                 Mockito.mock(IConnectionService.class));
311 
312         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
313                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
314                         | PhoneAccount.CAPABILITY_CALL_PROVIDER)
315                 .build());
316         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
317                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
318                         | PhoneAccount.CAPABILITY_CALL_PROVIDER)
319                 .build());
320         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
321                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
322                         | PhoneAccount.CAPABILITY_CALL_PROVIDER)
323                 .build());
324         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
325                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
326                 .build());
327 
328         assertEquals(4, mRegistrar.getAllPhoneAccountsOfCurrentUser().size());
329         assertEquals(3, mRegistrar.getCallCapablePhoneAccountsOfCurrentUser(null, false).size());
330         assertEquals(null, mRegistrar.getSimCallManagerOfCurrentUser());
331         assertEquals(null, mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
332                 PhoneAccount.SCHEME_TEL));
333     }
334 
335     @MediumTest
336     @Test
testSimCallManager()337     public void testSimCallManager() throws Exception {
338         // TODO
339     }
340 
341     @MediumTest
342     @Test
testDefaultOutgoing()343     public void testDefaultOutgoing() throws Exception {
344         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
345                 Mockito.mock(IConnectionService.class));
346 
347         // By default, there is no default outgoing account (nothing has been registered)
348         assertNull(
349                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
350 
351         // Register one tel: account
352         PhoneAccountHandle telAccount = makeQuickAccountHandle("tel_acct");
353         registerAndEnableAccount(new PhoneAccount.Builder(telAccount, "tel_acct")
354                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
355                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
356                 .build());
357         PhoneAccountHandle defaultAccount =
358                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
359         assertEquals(telAccount, defaultAccount);
360 
361         // Add a SIP account, make sure tel: doesn't change
362         PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct");
363         registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct")
364                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
365                 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
366                 .build());
367         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
368                 PhoneAccount.SCHEME_SIP);
369         assertEquals(sipAccount, defaultAccount);
370         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
371                 PhoneAccount.SCHEME_TEL);
372         assertEquals(telAccount, defaultAccount);
373 
374         // Add a connection manager, make sure tel: doesn't change
375         PhoneAccountHandle connectionManager = makeQuickAccountHandle("mgr_acct");
376         registerAndEnableAccount(new PhoneAccount.Builder(connectionManager, "mgr_acct")
377                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
378                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
379                 .build());
380         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
381                 PhoneAccount.SCHEME_TEL);
382         assertEquals(telAccount, defaultAccount);
383 
384         // Unregister the tel: account, make sure there is no tel: default now.
385         mRegistrar.unregisterPhoneAccount(telAccount);
386         assertNull(
387                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
388     }
389 
390     @MediumTest
391     @Test
testReplacePhoneAccountByGroup()392     public void testReplacePhoneAccountByGroup() throws Exception {
393         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
394                 Mockito.mock(IConnectionService.class));
395 
396         // By default, there is no default outgoing account (nothing has been registered)
397         assertNull(
398                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
399 
400         // Register one tel: account
401         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
402         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
403                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
404                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
405                 .setGroupId("testGroup")
406                 .build());
407         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
408         PhoneAccountHandle defaultAccount =
409                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
410         assertEquals(telAccount1, defaultAccount);
411 
412         // Add call capable SIP account, make sure tel: doesn't change
413         PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct");
414         registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct")
415                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
416                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
417                 .build());
418         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
419                 PhoneAccount.SCHEME_TEL);
420         assertEquals(telAccount1, defaultAccount);
421 
422         // Replace tel: account with another in the same Group
423         PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
424         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
425                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
426                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
427                 .setGroupId("testGroup")
428                 .build());
429         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
430                 PhoneAccount.SCHEME_TEL);
431         assertEquals(telAccount2, defaultAccount);
432         assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
433     }
434 
435     @MediumTest
436     @Test
testAddSameDefault()437     public void testAddSameDefault() throws Exception {
438         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
439                 Mockito.mock(IConnectionService.class));
440 
441         // By default, there is no default outgoing account (nothing has been registered)
442         assertNull(
443                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
444 
445         // Register one tel: account
446         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
447         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
448                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
449                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
450                 .setGroupId("testGroup")
451                 .build());
452         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
453         PhoneAccountHandle defaultAccount =
454                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
455         assertEquals(telAccount1, defaultAccount);
456         mRegistrar.unregisterPhoneAccount(telAccount1);
457 
458         // Register Emergency Account and unregister
459         PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct");
460         registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct")
461                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
462                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
463                 .build());
464         defaultAccount =
465                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
466         assertNull(defaultAccount);
467         mRegistrar.unregisterPhoneAccount(emerAccount);
468 
469         // Re-register the same account and make sure the default is in place
470         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
471                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
472                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
473                 .setGroupId("testGroup")
474                 .build());
475         defaultAccount =
476                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
477         assertEquals(telAccount1, defaultAccount);
478     }
479 
480     @MediumTest
481     @Test
testAddSameGroup()482     public void testAddSameGroup() throws Exception {
483         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
484                 Mockito.mock(IConnectionService.class));
485 
486         // By default, there is no default outgoing account (nothing has been registered)
487         assertNull(
488                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
489 
490         // Register one tel: account
491         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
492         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
493                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
494                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
495                 .setGroupId("testGroup")
496                 .build());
497         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
498         PhoneAccountHandle defaultAccount =
499                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
500         assertEquals(telAccount1, defaultAccount);
501         mRegistrar.unregisterPhoneAccount(telAccount1);
502 
503         // Register Emergency Account and unregister
504         PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct");
505         registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct")
506                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
507                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
508                 .build());
509         defaultAccount =
510                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
511         assertNull(defaultAccount);
512         mRegistrar.unregisterPhoneAccount(emerAccount);
513 
514         // Re-register a new account with the same group
515         PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
516         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
517                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
518                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
519                 .setGroupId("testGroup")
520                 .build());
521         defaultAccount =
522                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
523         assertEquals(telAccount2, defaultAccount);
524     }
525 
526     @MediumTest
527     @Test
testAddSameGroupButDifferentComponent()528     public void testAddSameGroupButDifferentComponent() throws Exception {
529         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
530                 Mockito.mock(IConnectionService.class));
531 
532         // By default, there is no default outgoing account (nothing has been registered)
533         assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
534                 PhoneAccount.SCHEME_TEL));
535 
536         // Register one tel: account
537         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
538         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
539                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
540                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
541                 .setGroupId("testGroup")
542                 .build());
543         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
544         PhoneAccountHandle defaultAccount =
545                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
546         assertEquals(telAccount1, defaultAccount);
547         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
548 
549         // Register a new account with the same group, but different Component, so don't replace
550         // Default
551         PhoneAccountHandle telAccount2 =  makeQuickAccountHandle(
552                 new ComponentName("other1", "other2"), "tel_acct2");
553         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
554                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
555                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
556                 .setGroupId("testGroup")
557                 .build());
558         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount2));
559 
560         defaultAccount =
561                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
562         assertEquals(telAccount1, defaultAccount);
563     }
564 
565     @MediumTest
566     @Test
testAddSameGroupButDifferentComponent2()567     public void testAddSameGroupButDifferentComponent2() throws Exception {
568         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
569                 Mockito.mock(IConnectionService.class));
570 
571         // By default, there is no default outgoing account (nothing has been registered)
572         assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
573                 PhoneAccount.SCHEME_TEL));
574 
575         // Register first tel: account
576         PhoneAccountHandle telAccount1 =  makeQuickAccountHandle(
577                 new ComponentName("other1", "other2"), "tel_acct1");
578         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
579                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
580                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
581                 .setGroupId("testGroup")
582                 .build());
583         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
584         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
585 
586         // Register second account with the same group, but a second Component, so don't replace
587         // Default
588         PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
589         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
590                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
591                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
592                 .setGroupId("testGroup")
593                 .build());
594 
595         PhoneAccountHandle defaultAccount =
596                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
597         assertEquals(telAccount1, defaultAccount);
598 
599         // Register third account with the second component name, but same group id
600         PhoneAccountHandle telAccount3 = makeQuickAccountHandle("tel_acct3");
601         registerAndEnableAccount(new PhoneAccount.Builder(telAccount3, "tel_acct3")
602                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
603                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
604                 .setGroupId("testGroup")
605                 .build());
606 
607         // Make sure that the default account is still the original PhoneAccount and that the
608         // second PhoneAccount with the second ComponentName was replaced by the third PhoneAccount
609         defaultAccount =
610                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
611         assertEquals(telAccount1, defaultAccount);
612 
613         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
614         assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount2));
615         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount3));
616     }
617 
618     @MediumTest
619     @Test
testPhoneAccountParceling()620     public void testPhoneAccountParceling() throws Exception {
621         PhoneAccountHandle handle = makeQuickAccountHandle("foo");
622         roundTripPhoneAccount(new PhoneAccount.Builder(handle, null).build());
623         roundTripPhoneAccount(new PhoneAccount.Builder(handle, "foo").build());
624         roundTripPhoneAccount(
625                 new PhoneAccount.Builder(handle, "foo")
626                         .setAddress(Uri.parse("tel:123456"))
627                         .setCapabilities(23)
628                         .setHighlightColor(0xf0f0f0)
629                         .setIcon(Icon.createWithResource(
630                                 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
631                         // TODO: set icon tint (0xfefefe)
632                         .setShortDescription("short description")
633                         .setSubscriptionAddress(Uri.parse("tel:2345678"))
634                         .setSupportedUriSchemes(Arrays.asList("tel", "sip"))
635                         .setGroupId("testGroup")
636                         .build());
637         roundTripPhoneAccount(
638                 new PhoneAccount.Builder(handle, "foo")
639                         .setAddress(Uri.parse("tel:123456"))
640                         .setCapabilities(23)
641                         .setHighlightColor(0xf0f0f0)
642                         .setIcon(Icon.createWithBitmap(
643                                 BitmapFactory.decodeResource(
644                                         InstrumentationRegistry.getContext().getResources(),
645                                         R.drawable.stat_sys_phone_call)))
646                         .setShortDescription("short description")
647                         .setSubscriptionAddress(Uri.parse("tel:2345678"))
648                         .setSupportedUriSchemes(Arrays.asList("tel", "sip"))
649                         .setGroupId("testGroup")
650                         .build());
651     }
652 
653     /**
654      * Tests ability to register a self-managed PhoneAccount; verifies that the user defined label
655      * is overridden.
656      * @throws Exception
657      */
658     @MediumTest
659     @Test
testSelfManagedPhoneAccount()660     public void testSelfManagedPhoneAccount() throws Exception {
661         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
662                 Mockito.mock(IConnectionService.class));
663 
664         PhoneAccountHandle selfManagedHandle =  makeQuickAccountHandle(
665                 new ComponentName("self", "managed"), "selfie1");
666 
667         PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, "Wrong")
668                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
669                 .build();
670 
671         mRegistrar.registerPhoneAccount(selfManagedAccount);
672 
673         PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle);
674         assertEquals(TEST_LABEL, registeredAccount.getLabel());
675     }
676 
677     /**
678      * Tests to ensure that when registering a self-managed PhoneAccount, it cannot also be defined
679      * as a call provider, connection manager, or sim subscription.
680      * @throws Exception
681      */
682     @MediumTest
683     @Test
testSelfManagedCapabilityOverride()684     public void testSelfManagedCapabilityOverride() throws Exception {
685         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
686                 Mockito.mock(IConnectionService.class));
687 
688         PhoneAccountHandle selfManagedHandle =  makeQuickAccountHandle(
689                 new ComponentName("self", "managed"), "selfie1");
690 
691         PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, TEST_LABEL)
692                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
693                         PhoneAccount.CAPABILITY_CALL_PROVIDER |
694                         PhoneAccount.CAPABILITY_CONNECTION_MANAGER |
695                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
696                 .build();
697 
698         mRegistrar.registerPhoneAccount(selfManagedAccount);
699 
700         PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle);
701         assertEquals(PhoneAccount.CAPABILITY_SELF_MANAGED, registeredAccount.getCapabilities());
702     }
703 
704     @MediumTest
705     @Test
testSortSimFirst()706     public void testSortSimFirst() throws Exception {
707         ComponentName componentA = new ComponentName("a", "a");
708         ComponentName componentB = new ComponentName("b", "b");
709         mComponentContextFixture.addConnectionService(componentA,
710                 Mockito.mock(IConnectionService.class));
711         mComponentContextFixture.addConnectionService(componentB,
712                 Mockito.mock(IConnectionService.class));
713 
714         PhoneAccount simAccount = new PhoneAccount.Builder(
715                 makeQuickAccountHandle(componentB, "2"), "2")
716                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
717                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
718                 .setIsEnabled(true)
719                 .build();
720 
721         PhoneAccount nonSimAccount = new PhoneAccount.Builder(
722                 makeQuickAccountHandle(componentA, "1"), "1")
723                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
724                 .setIsEnabled(true)
725                 .build();
726 
727         registerAndEnableAccount(nonSimAccount);
728         registerAndEnableAccount(simAccount);
729 
730         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
731         assertTrue(accounts.get(0).getLabel().toString().equals("2"));
732         assertTrue(accounts.get(1).getLabel().toString().equals("1"));
733     }
734 
735     @MediumTest
736     @Test
testSortBySortOrder()737     public void testSortBySortOrder() throws Exception {
738         ComponentName componentA = new ComponentName("a", "a");
739         ComponentName componentB = new ComponentName("b", "b");
740         ComponentName componentC = new ComponentName("c", "c");
741         mComponentContextFixture.addConnectionService(componentA,
742                 Mockito.mock(IConnectionService.class));
743         mComponentContextFixture.addConnectionService(componentB,
744                 Mockito.mock(IConnectionService.class));
745         mComponentContextFixture.addConnectionService(componentC,
746                 Mockito.mock(IConnectionService.class));
747 
748         Bundle account1Extras = new Bundle();
749         account1Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 1);
750         PhoneAccount account1 = new PhoneAccount.Builder(
751                 makeQuickAccountHandle(componentA, "c"), "c")
752                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
753                 .setExtras(account1Extras)
754                 .build();
755 
756         Bundle account2Extras = new Bundle();
757         account2Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 2);
758         PhoneAccount account2 = new PhoneAccount.Builder(
759                 makeQuickAccountHandle(componentB, "b"), "b")
760                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
761                 .setExtras(account2Extras)
762                 .build();
763 
764         PhoneAccount account3 = new PhoneAccount.Builder(
765                 makeQuickAccountHandle(componentC, "c"), "a")
766                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
767                 .build();
768 
769         registerAndEnableAccount(account3);
770         registerAndEnableAccount(account2);
771         registerAndEnableAccount(account1);
772 
773         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
774         assertTrue(accounts.get(0).getLabel().toString().equals("c"));
775         assertTrue(accounts.get(1).getLabel().toString().equals("b"));
776         assertTrue(accounts.get(2).getLabel().toString().equals("a"));
777     }
778 
779     @MediumTest
780     @Test
testSortByLabel()781     public void testSortByLabel() throws Exception {
782         ComponentName componentA = new ComponentName("a", "a");
783         ComponentName componentB = new ComponentName("b", "b");
784         ComponentName componentC = new ComponentName("c", "c");
785         mComponentContextFixture.addConnectionService(componentA,
786                 Mockito.mock(IConnectionService.class));
787         mComponentContextFixture.addConnectionService(componentB,
788                 Mockito.mock(IConnectionService.class));
789         mComponentContextFixture.addConnectionService(componentC,
790                 Mockito.mock(IConnectionService.class));
791 
792         PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(componentA, "c"),
793                 "c")
794                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
795                 .build();
796 
797         PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(componentB, "b"),
798                 "b")
799                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
800                 .build();
801 
802         PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(componentC, "a"),
803                 "a")
804                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
805                 .build();
806 
807         registerAndEnableAccount(account1);
808         registerAndEnableAccount(account2);
809         registerAndEnableAccount(account3);
810 
811         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
812         assertTrue(accounts.get(0).getLabel().toString().equals("a"));
813         assertTrue(accounts.get(1).getLabel().toString().equals("b"));
814         assertTrue(accounts.get(2).getLabel().toString().equals("c"));
815     }
816 
817     @MediumTest
818     @Test
testSortAll()819     public void testSortAll() throws Exception {
820         ComponentName componentA = new ComponentName("a", "a");
821         ComponentName componentB = new ComponentName("b", "b");
822         ComponentName componentC = new ComponentName("c", "c");
823         ComponentName componentW = new ComponentName("w", "w");
824         ComponentName componentX = new ComponentName("x", "x");
825         ComponentName componentY = new ComponentName("y", "y");
826         ComponentName componentZ = new ComponentName("z", "z");
827         mComponentContextFixture.addConnectionService(componentA,
828                 Mockito.mock(IConnectionService.class));
829         mComponentContextFixture.addConnectionService(componentB,
830                 Mockito.mock(IConnectionService.class));
831         mComponentContextFixture.addConnectionService(componentC,
832                 Mockito.mock(IConnectionService.class));
833         mComponentContextFixture.addConnectionService(componentW,
834                 Mockito.mock(IConnectionService.class));
835         mComponentContextFixture.addConnectionService(componentX,
836                 Mockito.mock(IConnectionService.class));
837         mComponentContextFixture.addConnectionService(componentY,
838                 Mockito.mock(IConnectionService.class));
839         mComponentContextFixture.addConnectionService(componentZ,
840                 Mockito.mock(IConnectionService.class));
841 
842         Bundle account1Extras = new Bundle();
843         account1Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 2);
844         PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(
845                 makeQuickConnectionServiceComponentName(), "y"), "y")
846                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
847                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
848                 .setExtras(account1Extras)
849                 .build();
850 
851         Bundle account2Extras = new Bundle();
852         account2Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 1);
853         PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(
854                 makeQuickConnectionServiceComponentName(), "z"), "z")
855                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
856                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
857                 .setExtras(account2Extras)
858                 .build();
859 
860         PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(
861                 makeQuickConnectionServiceComponentName(), "x"), "x")
862                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
863                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
864                 .build();
865 
866         PhoneAccount account4 = new PhoneAccount.Builder(makeQuickAccountHandle(
867                 makeQuickConnectionServiceComponentName(), "w"), "w")
868                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
869                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
870                 .build();
871 
872         PhoneAccount account5 = new PhoneAccount.Builder(makeQuickAccountHandle(
873                 makeQuickConnectionServiceComponentName(), "b"), "b")
874                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
875                 .build();
876 
877         PhoneAccount account6 = new PhoneAccount.Builder(makeQuickAccountHandle(
878                 makeQuickConnectionServiceComponentName(), "c"), "a")
879                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
880                 .build();
881 
882         registerAndEnableAccount(account1);
883         registerAndEnableAccount(account2);
884         registerAndEnableAccount(account3);
885         registerAndEnableAccount(account4);
886         registerAndEnableAccount(account5);
887         registerAndEnableAccount(account6);
888 
889         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
890         // Sim accts ordered by sort order first
891         assertTrue(accounts.get(0).getLabel().toString().equals("z"));
892         assertTrue(accounts.get(1).getLabel().toString().equals("y"));
893 
894         // Sim accts with no sort order next
895         assertTrue(accounts.get(2).getLabel().toString().equals("w"));
896         assertTrue(accounts.get(3).getLabel().toString().equals("x"));
897 
898         // Other accts sorted by label next
899         assertTrue(accounts.get(4).getLabel().toString().equals("a"));
900         assertTrue(accounts.get(5).getLabel().toString().equals("b"));
901     }
902 
903     /**
904      * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle)}
905      * to ensure disabled accounts are filtered out of results when requested.
906      * @throws Exception
907      */
908     @MediumTest
909     @Test
testGetByEnabledState()910     public void testGetByEnabledState() throws Exception {
911         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
912                 Mockito.mock(IConnectionService.class));
913         mRegistrar.registerPhoneAccount(makeQuickAccountBuilder("id1", 1)
914                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
915                 .build());
916 
917         assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
918                 false /* includeDisabled */, Process.myUserHandle()).size());
919         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
920                 true /* includeDisabled */, Process.myUserHandle()).size());
921     }
922 
923     /**
924      * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle)}
925      * to ensure scheme filtering operates.
926      * @throws Exception
927      */
928     @MediumTest
929     @Test
testGetByScheme()930     public void testGetByScheme() throws Exception {
931         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
932                 Mockito.mock(IConnectionService.class));
933         registerAndEnableAccount(makeQuickAccountBuilder("id1", 1)
934                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
935                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
936                 .build());
937         registerAndEnableAccount(makeQuickAccountBuilder("id2", 2)
938                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
939                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL))
940                 .build());
941 
942         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
943                 false /* includeDisabled */, Process.myUserHandle()).size());
944         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
945                 false /* includeDisabled */, Process.myUserHandle()).size());
946         assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(null, false /* includeDisabled */,
947                 Process.myUserHandle()).size());
948     }
949 
950     /**
951      * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle,
952      * int)} to ensure capability filtering operates.
953      * @throws Exception
954      */
955     @MediumTest
956     @Test
testGetByCapability()957     public void testGetByCapability() throws Exception {
958         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
959                 Mockito.mock(IConnectionService.class));
960         registerAndEnableAccount(makeQuickAccountBuilder("id1", 1)
961                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
962                         | PhoneAccount.CAPABILITY_VIDEO_CALLING)
963                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
964                 .build());
965         registerAndEnableAccount(makeQuickAccountBuilder("id2", 2)
966                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
967                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
968                 .build());
969 
970         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
971                 false /* includeDisabled */, Process.myUserHandle()).size(),
972                 PhoneAccount.CAPABILITY_VIDEO_CALLING);
973         assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
974                 false /* includeDisabled */, Process.myUserHandle()).size(), 0 /* none extra */);
975         assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
976                 false /* includeDisabled */, Process.myUserHandle()).size(),
977                 PhoneAccount.CAPABILITY_RTT);
978     }
979 
980     /**
981      * Tests {@link PhoneAccount#equals(Object)} operator.
982      * @throws Exception
983      */
984     @MediumTest
985     @Test
testPhoneAccountEquality()986     public void testPhoneAccountEquality() throws Exception {
987         PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName("foo", "bar"), "id");
988         PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, "label");
989         builder.addSupportedUriScheme("tel");
990         builder.setAddress(Uri.fromParts("tel", "6505551212", null));
991         builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER);
992         Bundle extras = new Bundle();
993         extras.putInt("INT", 1);
994         extras.putString("STR", "str");
995         builder.setExtras(extras);
996         builder.setGroupId("group");
997         builder.setHighlightColor(1);
998         builder.setShortDescription("short");
999         builder.setSubscriptionAddress(Uri.fromParts("tel", "6505551213", null));
1000         builder.setSupportedAudioRoutes(2);
1001 
1002         PhoneAccount account1 = builder.build();
1003         PhoneAccount account2 = builder.build();
1004         assertEquals(account1, account2);
1005     }
1006 
1007     /**
1008      * Tests {@link PhoneAccountHandle#areFromSamePackage(PhoneAccountHandle,
1009      * PhoneAccountHandle)} comparison.
1010      */
1011     @SmallTest
1012     @Test
testSamePhoneAccountHandlePackage()1013     public void testSamePhoneAccountHandlePackage() {
1014         PhoneAccountHandle a = new PhoneAccountHandle(new ComponentName("packageA", "class1"),
1015                 "id1");
1016         PhoneAccountHandle b = new PhoneAccountHandle(new ComponentName("packageA", "class2"),
1017                 "id2");
1018         PhoneAccountHandle c = new PhoneAccountHandle(new ComponentName("packageA", "class1"),
1019                 "id3");
1020         PhoneAccountHandle d = new PhoneAccountHandle(new ComponentName("packageB", "class1"),
1021                 "id1");
1022 
1023         assertTrue(PhoneAccountHandle.areFromSamePackage(null, null));
1024         assertTrue(PhoneAccountHandle.areFromSamePackage(a, b));
1025         assertTrue(PhoneAccountHandle.areFromSamePackage(a, c));
1026         assertTrue(PhoneAccountHandle.areFromSamePackage(b, c));
1027         assertFalse(PhoneAccountHandle.areFromSamePackage(a, d));
1028         assertFalse(PhoneAccountHandle.areFromSamePackage(b, d));
1029         assertFalse(PhoneAccountHandle.areFromSamePackage(c, d));
1030         assertFalse(PhoneAccountHandle.areFromSamePackage(a, null));
1031         assertFalse(PhoneAccountHandle.areFromSamePackage(b, null));
1032         assertFalse(PhoneAccountHandle.areFromSamePackage(c, null));
1033         assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
1034         assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
1035         assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
1036     }
1037 
1038     /**
1039      * Tests {@link PhoneAccountRegistrar#cleanupOrphanedPhoneAccounts } cleans up / deletes an
1040      * orphan account.
1041      */
1042     @Test
testCleanUpOrphanAccounts()1043     public void testCleanUpOrphanAccounts() throws Exception {
1044         // GIVEN
1045         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
1046                 Mockito.mock(IConnectionService.class));
1047 
1048         List<UserHandle> users = Arrays.asList(new UserHandle(0),
1049                 new UserHandle(1000));
1050 
1051         PhoneAccount pa1 = new PhoneAccount.Builder(
1052                 new PhoneAccountHandle(new ComponentName(PACKAGE_1, COMPONENT_NAME), "1234",
1053                         users.get(0)), "l1").build();
1054         PhoneAccount pa2 = new PhoneAccount.Builder(
1055                 new PhoneAccountHandle(new ComponentName(PACKAGE_2, COMPONENT_NAME), "5678",
1056                         users.get(1)), "l2").build();
1057 
1058 
1059         registerAndEnableAccount(pa1);
1060         registerAndEnableAccount(pa2);
1061 
1062         assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(0)).size());
1063         assertEquals(1, mRegistrar.getAllPhoneAccounts(users.get(1)).size());
1064 
1065 
1066         // WHEN
1067         when(mContext.getPackageManager().getPackageInfo(PACKAGE_1, 0))
1068                 .thenReturn(new PackageInfo());
1069 
1070         when(mContext.getPackageManager().getPackageInfo(PACKAGE_2, 0))
1071                 .thenThrow(new PackageManager.NameNotFoundException());
1072 
1073         when(UserManager.get(mContext).getSerialNumberForUser(users.get(0)))
1074                 .thenReturn(0L);
1075 
1076         when(UserManager.get(mContext).getSerialNumberForUser(users.get(1)))
1077                 .thenReturn(-1L);
1078 
1079         // THEN
1080         int deletedAccounts = mRegistrar.cleanupOrphanedPhoneAccounts();
1081         assertEquals(1, deletedAccounts);
1082     }
1083 
1084     @Test
testGetSimPhoneAccountsFromSimCallManager()1085     public void testGetSimPhoneAccountsFromSimCallManager() throws Exception {
1086         // Register the SIM PhoneAccounts
1087         mComponentContextFixture.addConnectionService(
1088                 makeQuickConnectionServiceComponentName(), Mockito.mock(IConnectionService.class));
1089         PhoneAccount sim1Account = makeQuickSimAccount(1);
1090         PhoneAccountHandle sim1Handle = sim1Account.getAccountHandle();
1091         registerAndEnableAccount(sim1Account);
1092         PhoneAccount sim2Account = makeQuickSimAccount(2);
1093         PhoneAccountHandle sim2Handle = sim2Account.getAccountHandle();
1094         registerAndEnableAccount(sim2Account);
1095 
1096         assertEquals(
1097             List.of(sim1Handle, sim2Handle), mRegistrar.getSimPhoneAccountsOfCurrentUser());
1098 
1099         // Set up the SIM call manager app + carrier configs
1100         ComponentName simCallManagerComponent =
1101                 new ComponentName("com.carrier.app", "CarrierConnectionService");
1102         PhoneAccountHandle simCallManagerHandle =
1103                 makeQuickAccountHandle(simCallManagerComponent, "sim-call-manager");
1104         setSimCallManagerCarrierConfig(
1105                 1, new ComponentName("com.other.carrier", "OtherConnectionService"));
1106         setSimCallManagerCarrierConfig(2, simCallManagerComponent);
1107 
1108         // Since SIM 1 names another app, so we only get the handle for SIM 2
1109         assertEquals(
1110                 List.of(sim2Handle),
1111                 mRegistrar.getSimPhoneAccountsFromSimCallManager(simCallManagerHandle));
1112         // We do exact component matching, not just package name matching
1113         assertEquals(
1114                 List.of(),
1115                 mRegistrar.getSimPhoneAccountsFromSimCallManager(
1116                         makeQuickAccountHandle(
1117                                 new ComponentName("com.carrier.app", "SomeOtherUnrelatedService"),
1118                                 "same-pkg-but-diff-svc")));
1119 
1120         // Results are identical after we register the PhoneAccount
1121         mComponentContextFixture.addConnectionService(
1122                 simCallManagerComponent, Mockito.mock(IConnectionService.class));
1123         PhoneAccount simCallManagerAccount =
1124                 new PhoneAccount.Builder(simCallManagerHandle, "SIM call manager")
1125                         .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
1126                         .build();
1127         mRegistrar.registerPhoneAccount(simCallManagerAccount);
1128         assertEquals(
1129                 List.of(sim2Handle),
1130                 mRegistrar.getSimPhoneAccountsFromSimCallManager(simCallManagerHandle));
1131     }
1132 
1133     @Test
testMaybeNotifyTelephonyForVoiceServiceState()1134     public void testMaybeNotifyTelephonyForVoiceServiceState() throws Exception {
1135         // Register the SIM PhoneAccounts
1136         mComponentContextFixture.addConnectionService(
1137                 makeQuickConnectionServiceComponentName(), Mockito.mock(IConnectionService.class));
1138         PhoneAccount sim1Account = makeQuickSimAccount(1);
1139         registerAndEnableAccount(sim1Account);
1140         PhoneAccount sim2Account = makeQuickSimAccount(2);
1141         registerAndEnableAccount(sim2Account);
1142         // Telephony is notified by default when new SIM accounts are registered
1143         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1144                 .setVoiceServiceStateOverride(false);
1145         clearInvocations(mComponentContextFixture.getTelephonyManager());
1146 
1147         // Set up the SIM call manager app + carrier configs
1148         ComponentName simCallManagerComponent =
1149                 new ComponentName("com.carrier.app", "CarrierConnectionService");
1150         PhoneAccountHandle simCallManagerHandle =
1151                 makeQuickAccountHandle(simCallManagerComponent, "sim-call-manager");
1152         mComponentContextFixture.addConnectionService(
1153                 simCallManagerComponent, Mockito.mock(IConnectionService.class));
1154         setSimCallManagerCarrierConfig(1, simCallManagerComponent);
1155         setSimCallManagerCarrierConfig(2, simCallManagerComponent);
1156 
1157         // When the SIM call manager is registered without the SUPPORTS capability, telephony is
1158         // still notified for consistency (e.g. runtime capability removal + re-registration).
1159         PhoneAccount simCallManagerAccount =
1160                 new PhoneAccount.Builder(simCallManagerHandle, "SIM call manager")
1161                         .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
1162                         .build();
1163         mRegistrar.registerPhoneAccount(simCallManagerAccount);
1164         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1165                 .setVoiceServiceStateOverride(false);
1166         clearInvocations(mComponentContextFixture.getTelephonyManager());
1167 
1168         // Adding the SUPPORTS capability causes the SIMs to get notified with false again for
1169         // consistency purposes
1170         simCallManagerAccount =
1171                 copyPhoneAccountAndAddCapabilities(
1172                         simCallManagerAccount,
1173                         PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS);
1174         mRegistrar.registerPhoneAccount(simCallManagerAccount);
1175         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1176                 .setVoiceServiceStateOverride(false);
1177         clearInvocations(mComponentContextFixture.getTelephonyManager());
1178 
1179         // Adding the AVAILABLE capability updates the SIMs again, this time with hasService = true
1180         simCallManagerAccount =
1181                 copyPhoneAccountAndAddCapabilities(
1182                         simCallManagerAccount, PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE);
1183         mRegistrar.registerPhoneAccount(simCallManagerAccount);
1184         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1185                 .setVoiceServiceStateOverride(true);
1186         clearInvocations(mComponentContextFixture.getTelephonyManager());
1187 
1188         // Removing a SIM account does nothing, regardless of SIM call manager capabilities
1189         mRegistrar.unregisterPhoneAccount(sim1Account.getAccountHandle());
1190         verify(mComponentContextFixture.getTelephonyManager(), never())
1191                 .setVoiceServiceStateOverride(anyBoolean());
1192         clearInvocations(mComponentContextFixture.getTelephonyManager());
1193 
1194         // Adding a SIM account while a SIM call manager with both capabilities is registered causes
1195         // a call to telephony with hasService = true
1196         mRegistrar.registerPhoneAccount(sim1Account);
1197         verify(mComponentContextFixture.getTelephonyManager(), times(1))
1198                 .setVoiceServiceStateOverride(true);
1199         clearInvocations(mComponentContextFixture.getTelephonyManager());
1200 
1201         // Removing the SIM call manager while it has both capabilities causes a call to telephony
1202         // with hasService = false
1203         mRegistrar.unregisterPhoneAccount(simCallManagerHandle);
1204         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1205                 .setVoiceServiceStateOverride(false);
1206         clearInvocations(mComponentContextFixture.getTelephonyManager());
1207 
1208         // Removing the SIM call manager while it has the SUPPORTS capability but not AVAILABLE
1209         // still causes a call to telephony with hasService = false for consistency
1210         simCallManagerAccount =
1211                 copyPhoneAccountAndRemoveCapabilities(
1212                         simCallManagerAccount, PhoneAccount.CAPABILITY_VOICE_CALLING_AVAILABLE);
1213         mRegistrar.registerPhoneAccount(simCallManagerAccount);
1214         clearInvocations(mComponentContextFixture.getTelephonyManager()); // from re-registration
1215         mRegistrar.unregisterPhoneAccount(simCallManagerHandle);
1216         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1217                 .setVoiceServiceStateOverride(false);
1218         clearInvocations(mComponentContextFixture.getTelephonyManager());
1219 
1220         // Finally, removing the SIM call manager while it has neither capability still causes a
1221         // call to telephony with hasService = false for consistency
1222         simCallManagerAccount =
1223                 copyPhoneAccountAndRemoveCapabilities(
1224                         simCallManagerAccount,
1225                         PhoneAccount.CAPABILITY_SUPPORTS_VOICE_CALLING_INDICATIONS);
1226         mRegistrar.registerPhoneAccount(simCallManagerAccount);
1227         clearInvocations(mComponentContextFixture.getTelephonyManager()); // from re-registration
1228         mRegistrar.unregisterPhoneAccount(simCallManagerHandle);
1229         verify(mComponentContextFixture.getTelephonyManager(), times(2))
1230                 .setVoiceServiceStateOverride(false);
1231         clearInvocations(mComponentContextFixture.getTelephonyManager());
1232     }
1233 
1234     /**
1235      * Test PhoneAccountHandle Migration Logic.
1236      */
1237     @Test
testPhoneAccountMigration()1238     public void testPhoneAccountMigration() throws Exception {
1239         PhoneAccountRegistrar.State testState = makeQuickStateWithTelephonyPhoneAccountHandle();
1240         final int mTestPhoneAccountHandleSubIdInt = 123;
1241         // Mock SubscriptionManager
1242         SubscriptionInfo subscriptionInfo = new SubscriptionInfo(
1243                 mTestPhoneAccountHandleSubIdInt, "id0", 1, "a", "b", 1, 1, "test",
1244                         1, null, null, null, null, false, null, null);
1245         List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
1246         subscriptionInfoList.add(subscriptionInfo);
1247         when(mSubscriptionManager.getAllSubscriptionInfoList()).thenReturn(subscriptionInfoList);
1248         mRegistrar.migratePhoneAccountHandle(testState);
1249         Collection<DefaultPhoneAccountHandle> defaultPhoneAccountHandles
1250                 = testState.defaultOutgoingAccountHandles.values();
1251         DefaultPhoneAccountHandle defaultPhoneAccountHandle
1252                 = defaultPhoneAccountHandles.iterator().next();
1253         assertEquals(Integer.toString(mTestPhoneAccountHandleSubIdInt),
1254                 defaultPhoneAccountHandle.phoneAccountHandle.getId());
1255     }
1256 
makeQuickConnectionServiceComponentName()1257     private static ComponentName makeQuickConnectionServiceComponentName() {
1258         return new ComponentName(
1259                 "com.android.server.telecom.tests",
1260                 "com.android.server.telecom.tests.MockConnectionService");
1261     }
1262 
makeQuickAccountHandle(String id)1263     private static PhoneAccountHandle makeQuickAccountHandle(String id) {
1264         return makeQuickAccountHandle(makeQuickConnectionServiceComponentName(), id);
1265     }
1266 
makeQuickAccountHandle(ComponentName name, String id)1267     private static PhoneAccountHandle makeQuickAccountHandle(ComponentName name, String id) {
1268         return new PhoneAccountHandle(name, id, Process.myUserHandle());
1269     }
1270 
makeQuickAccountBuilder(String id, int idx)1271     private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
1272         return new PhoneAccount.Builder(
1273                 makeQuickAccountHandle(id),
1274                 "label" + idx);
1275     }
1276 
copyPhoneAccountAndOverrideCapabilities( PhoneAccount base, int newCapabilities)1277     private static PhoneAccount copyPhoneAccountAndOverrideCapabilities(
1278             PhoneAccount base, int newCapabilities) {
1279         return base.toBuilder().setCapabilities(newCapabilities).build();
1280     }
1281 
copyPhoneAccountAndAddCapabilities( PhoneAccount base, int capabilitiesToAdd)1282     private static PhoneAccount copyPhoneAccountAndAddCapabilities(
1283             PhoneAccount base, int capabilitiesToAdd) {
1284         return copyPhoneAccountAndOverrideCapabilities(
1285                 base, base.getCapabilities() | capabilitiesToAdd);
1286     }
1287 
copyPhoneAccountAndRemoveCapabilities( PhoneAccount base, int capabilitiesToRemove)1288     private static PhoneAccount copyPhoneAccountAndRemoveCapabilities(
1289             PhoneAccount base, int capabilitiesToRemove) {
1290         return copyPhoneAccountAndOverrideCapabilities(
1291                 base, base.getCapabilities() & ~capabilitiesToRemove);
1292     }
1293 
makeQuickAccount(String id, int idx)1294     private PhoneAccount makeQuickAccount(String id, int idx) {
1295         return makeQuickAccountBuilder(id, idx)
1296                 .setAddress(Uri.parse("http://foo.com/" + idx))
1297                 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
1298                 .setCapabilities(idx)
1299                 .setIcon(Icon.createWithResource(
1300                             "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
1301                 .setShortDescription("desc" + idx)
1302                 .setIsEnabled(true)
1303                 .build();
1304     }
1305 
1306     /**
1307      * Similar to {@link #makeQuickAccount}, but also hooks up {@code TelephonyManager} so that it
1308      * returns {@code simId} as the account's subscriptionId.
1309      */
makeQuickSimAccount(int simId)1310     private PhoneAccount makeQuickSimAccount(int simId) {
1311         PhoneAccount simAccount =
1312                 makeQuickAccountBuilder("sim" + simId, simId)
1313                         .setCapabilities(
1314                                 PhoneAccount.CAPABILITY_CALL_PROVIDER
1315                                         | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
1316                         .setIsEnabled(true)
1317                         .build();
1318         when(mComponentContextFixture
1319                         .getTelephonyManager()
1320                         .getSubscriptionId(simAccount.getAccountHandle()))
1321                 .thenReturn(simId);
1322         // mComponentContextFixture already sets up the createForSubscriptionId self-reference
1323         when(mComponentContextFixture
1324                         .getTelephonyManager()
1325                         .createForPhoneAccountHandle(simAccount.getAccountHandle()))
1326                 .thenReturn(mComponentContextFixture.getTelephonyManager());
1327         return simAccount;
1328     }
1329 
1330     /**
1331      * Hooks up carrier config to point to {@code simCallManagerComponent} for the given {@code
1332      * subscriptionId}.
1333      */
setSimCallManagerCarrierConfig( int subscriptionId, @Nullable ComponentName simCallManagerComponent)1334     private void setSimCallManagerCarrierConfig(
1335             int subscriptionId, @Nullable ComponentName simCallManagerComponent) {
1336         PersistableBundle config = new PersistableBundle();
1337         config.putString(
1338                 CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING,
1339                 simCallManagerComponent != null ? simCallManagerComponent.flattenToString() : null);
1340         when(mComponentContextFixture.getCarrierConfigManager().getConfigForSubId(subscriptionId))
1341                 .thenReturn(config);
1342     }
1343 
roundTripPhoneAccount(PhoneAccount original)1344     private static void roundTripPhoneAccount(PhoneAccount original) throws Exception {
1345         PhoneAccount copy = null;
1346 
1347         {
1348             Parcel parcel = Parcel.obtain();
1349             parcel.writeParcelable(original, 0);
1350             parcel.setDataPosition(0);
1351             copy = parcel.readParcelable(PhoneAccountRegistrarTest.class.getClassLoader());
1352             parcel.recycle();
1353         }
1354 
1355         assertPhoneAccountEquals(original, copy);
1356     }
1357 
roundTripXml( Object self, T input, PhoneAccountRegistrar.XmlSerialization<T> xml, Context context)1358     private static <T> T roundTripXml(
1359             Object self,
1360             T input,
1361             PhoneAccountRegistrar.XmlSerialization<T> xml,
1362             Context context)
1363             throws Exception {
1364         Log.d(self, "Input = %s", input);
1365 
1366         byte[] data;
1367         {
1368             XmlSerializer serializer = new FastXmlSerializer();
1369             ByteArrayOutputStream baos = new ByteArrayOutputStream();
1370             serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
1371             xml.writeToXml(input, serializer, context);
1372             serializer.flush();
1373             data = baos.toByteArray();
1374         }
1375 
1376         Log.i(self, "====== XML data ======\n%s", new String(data));
1377 
1378         T result = null;
1379         {
1380             XmlPullParser parser = Xml.newPullParser();
1381             parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null);
1382             parser.nextTag();
1383             result = xml.readFromXml(parser, MAX_VERSION, context);
1384         }
1385 
1386         Log.i(self, "result = " + result);
1387 
1388         return result;
1389     }
1390 
assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b)1391     private static void assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b) {
1392         if (a != b) {
1393             assertEquals(
1394                     a.getComponentName().getPackageName(),
1395                     b.getComponentName().getPackageName());
1396             assertEquals(
1397                     a.getComponentName().getClassName(),
1398                     b.getComponentName().getClassName());
1399             assertEquals(a.getId(), b.getId());
1400         }
1401     }
1402 
assertIconEquals(Icon a, Icon b)1403     private static void assertIconEquals(Icon a, Icon b) {
1404         if (a != b) {
1405             if (a != null && b != null) {
1406                 assertEquals(a.toString(), b.toString());
1407             } else {
1408                 fail("Icons not equal: " + a + ", " + b);
1409             }
1410         }
1411     }
1412 
assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a, DefaultPhoneAccountHandle b)1413     private static void assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a,
1414             DefaultPhoneAccountHandle b) {
1415         if (a != b) {
1416             if (a!= null && b != null) {
1417                 assertEquals(a.userHandle, b.userHandle);
1418                 assertPhoneAccountHandleEquals(a.phoneAccountHandle, b.phoneAccountHandle);
1419             } else {
1420                 fail("Default phone account handles are not equal: " + a + ", " + b);
1421             }
1422         }
1423     }
1424 
assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b)1425     private static void assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b) {
1426         if (a != b) {
1427             if (a != null && b != null) {
1428                 assertPhoneAccountHandleEquals(a.getAccountHandle(), b.getAccountHandle());
1429                 assertEquals(a.getAddress(), b.getAddress());
1430                 assertEquals(a.getSubscriptionAddress(), b.getSubscriptionAddress());
1431                 assertEquals(a.getCapabilities(), b.getCapabilities());
1432                 assertIconEquals(a.getIcon(), b.getIcon());
1433                 assertEquals(a.getHighlightColor(), b.getHighlightColor());
1434                 assertEquals(a.getLabel(), b.getLabel());
1435                 assertEquals(a.getShortDescription(), b.getShortDescription());
1436                 assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes());
1437                 assertBundlesEqual(a.getExtras(), b.getExtras());
1438                 assertEquals(a.isEnabled(), b.isEnabled());
1439             } else {
1440                 fail("Phone accounts not equal: " + a + ", " + b);
1441             }
1442         }
1443     }
1444 
assertBundlesEqual(Bundle a, Bundle b)1445     private static void assertBundlesEqual(Bundle a, Bundle b) {
1446         if (a == null && b == null) {
1447             return;
1448         }
1449 
1450         assertNotNull(a);
1451         assertNotNull(b);
1452         Set<String> keySetA = a.keySet();
1453         Set<String> keySetB = b.keySet();
1454 
1455         assertTrue("Bundle keys not the same", keySetA.containsAll(keySetB));
1456         assertTrue("Bundle keys not the same", keySetB.containsAll(keySetA));
1457 
1458         for (String keyA : keySetA) {
1459             assertEquals("Bundle value not the same", a.get(keyA), b.get(keyA));
1460         }
1461     }
1462 
assertStateEquals( PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b)1463     private static void assertStateEquals(
1464             PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) {
1465         assertEquals(a.defaultOutgoingAccountHandles.size(),
1466                 b.defaultOutgoingAccountHandles.size());
1467         for (Map.Entry<UserHandle, DefaultPhoneAccountHandle> e :
1468                 a.defaultOutgoingAccountHandles.entrySet()) {
1469             assertDefaultPhoneAccountHandleEquals(e.getValue(),
1470                     b.defaultOutgoingAccountHandles.get(e.getKey()));
1471         }
1472         assertEquals(a.accounts.size(), b.accounts.size());
1473         for (int i = 0; i < a.accounts.size(); i++) {
1474             assertPhoneAccountEquals(a.accounts.get(i), b.accounts.get(i));
1475         }
1476     }
1477 
makeQuickStateWithTelephonyPhoneAccountHandle()1478     private PhoneAccountRegistrar.State makeQuickStateWithTelephonyPhoneAccountHandle() {
1479         PhoneAccountRegistrar.State s = new PhoneAccountRegistrar.State();
1480         s.accounts.add(makeQuickAccount("id0", 0));
1481         s.accounts.add(makeQuickAccount("id1", 1));
1482         s.accounts.add(makeQuickAccount("id2", 2));
1483         PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(new ComponentName(
1484                 "com.android.phone",
1485                         "com.android.services.telephony.TelephonyConnectionService"), "id0");
1486         UserHandle userHandle = phoneAccountHandle.getUserHandle();
1487         when(UserManager.get(mContext).getSerialNumberForUser(userHandle))
1488             .thenReturn(0L);
1489         when(UserManager.get(mContext).getUserForSerialNumber(0L))
1490             .thenReturn(userHandle);
1491         s.defaultOutgoingAccountHandles
1492             .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle,
1493                 "testGroup"));
1494         return s;
1495     }
1496 
makeQuickState()1497     private PhoneAccountRegistrar.State makeQuickState() {
1498         PhoneAccountRegistrar.State s = new PhoneAccountRegistrar.State();
1499         s.accounts.add(makeQuickAccount("id0", 0));
1500         s.accounts.add(makeQuickAccount("id1", 1));
1501         s.accounts.add(makeQuickAccount("id2", 2));
1502         PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(
1503                 new ComponentName("pkg0", "cls0"), "id0");
1504         UserHandle userHandle = phoneAccountHandle.getUserHandle();
1505         when(UserManager.get(mContext).getSerialNumberForUser(userHandle))
1506                 .thenReturn(0L);
1507         when(UserManager.get(mContext).getUserForSerialNumber(0L))
1508                 .thenReturn(userHandle);
1509         s.defaultOutgoingAccountHandles
1510                 .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle,
1511                         "testGroup"));
1512         return s;
1513     }
1514 }
1515