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