1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.telecom.tests;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25 import static org.mockito.Matchers.anyInt;
26 import static org.mockito.Matchers.anyString;
27 import static org.mockito.Mockito.when;
28 
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.graphics.BitmapFactory;
32 import android.graphics.Rect;
33 import android.graphics.drawable.Icon;
34 import android.net.Uri;
35 import android.os.Bundle;
36 import android.os.Parcel;
37 import android.os.Process;
38 import android.os.UserHandle;
39 import android.os.UserManager;
40 import android.telecom.Log;
41 import android.telecom.PhoneAccount;
42 import android.telecom.PhoneAccountHandle;
43 import android.telecom.TelecomManager;
44 import android.test.suitebuilder.annotation.SmallTest;
45 import android.test.suitebuilder.annotation.MediumTest;
46 import android.util.Xml;
47 
48 import androidx.test.InstrumentationRegistry;
49 
50 import com.android.internal.telecom.IConnectionService;
51 import com.android.internal.util.FastXmlSerializer;
52 import com.android.server.telecom.AppLabelProxy;
53 import com.android.server.telecom.DefaultDialerCache;
54 import com.android.server.telecom.PhoneAccountRegistrar;
55 import com.android.server.telecom.PhoneAccountRegistrar.DefaultPhoneAccountHandle;
56 
57 import org.junit.After;
58 import org.junit.Before;
59 import org.junit.Test;
60 import org.junit.runner.RunWith;
61 import org.junit.runners.JUnit4;
62 import org.mockito.Mock;
63 import org.mockito.Mockito;
64 import org.mockito.MockitoAnnotations;
65 import org.xmlpull.v1.XmlPullParser;
66 import org.xmlpull.v1.XmlSerializer;
67 
68 import java.io.BufferedInputStream;
69 import java.io.BufferedOutputStream;
70 import java.io.ByteArrayInputStream;
71 import java.io.ByteArrayOutputStream;
72 import java.io.File;
73 import java.util.ArrayList;
74 import java.util.Arrays;
75 import java.util.List;
76 import java.util.Map;
77 import java.util.Set;
78 
79 @RunWith(JUnit4.class)
80 public class PhoneAccountRegistrarTest extends TelecomTestCase {
81 
82     private static final int MAX_VERSION = Integer.MAX_VALUE;
83     private static final String FILE_NAME = "phone-account-registrar-test-1223.xml";
84     private static final String TEST_LABEL = "right";
85     private PhoneAccountRegistrar mRegistrar;
86     @Mock private TelecomManager mTelecomManager;
87     @Mock private DefaultDialerCache mDefaultDialerCache;
88     @Mock private AppLabelProxy mAppLabelProxy;
89 
90     @Override
91     @Before
setUp()92     public void setUp() throws Exception {
93         super.setUp();
94         MockitoAnnotations.initMocks(this);
95         mComponentContextFixture.setTelecomManager(mTelecomManager);
96         new File(
97                 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(),
98                 FILE_NAME)
99                 .delete();
100         when(mDefaultDialerCache.getDefaultDialerApplication(anyInt()))
101                 .thenReturn("com.android.dialer");
102         when(mAppLabelProxy.getAppLabel(anyString()))
103                 .thenReturn(TEST_LABEL);
104         mRegistrar = new PhoneAccountRegistrar(
105                 mComponentContextFixture.getTestDouble().getApplicationContext(),
106                 FILE_NAME, mDefaultDialerCache, mAppLabelProxy);
107     }
108 
109     @Override
110     @After
tearDown()111     public void tearDown() throws Exception {
112         mRegistrar = null;
113         new File(
114                 mComponentContextFixture.getTestDouble().getApplicationContext().getFilesDir(),
115                 FILE_NAME)
116                 .delete();
117         super.tearDown();
118     }
119 
120     @MediumTest
121     @Test
testPhoneAccountHandle()122     public void testPhoneAccountHandle() throws Exception {
123         PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0");
124         PhoneAccountHandle result = roundTripXml(this, input,
125                 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
126         assertPhoneAccountHandleEquals(input, result);
127 
128         PhoneAccountHandle inputN = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), null);
129         PhoneAccountHandle resultN = roundTripXml(this, inputN,
130                 PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
131         Log.i(this, "inputN = %s, resultN = %s", inputN, resultN);
132         assertPhoneAccountHandleEquals(inputN, resultN);
133     }
134 
135     @MediumTest
136     @Test
testPhoneAccount()137     public void testPhoneAccount() throws Exception {
138         Bundle testBundle = new Bundle();
139         testBundle.putInt("EXTRA_INT_1", 1);
140         testBundle.putInt("EXTRA_INT_100", 100);
141         testBundle.putBoolean("EXTRA_BOOL_TRUE", true);
142         testBundle.putBoolean("EXTRA_BOOL_FALSE", false);
143         testBundle.putString("EXTRA_STR1", "Hello");
144         testBundle.putString("EXTRA_STR2", "There");
145 
146         PhoneAccount input = makeQuickAccountBuilder("id0", 0)
147                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
148                 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
149                 .setExtras(testBundle)
150                 .setIsEnabled(true)
151                 .build();
152         PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
153                 mContext);
154 
155         assertPhoneAccountEquals(input, result);
156     }
157 
158     @SmallTest
159     @Test
testFilterPhoneAccountForTest()160     public void testFilterPhoneAccountForTest() throws Exception {
161         ComponentName componentA = new ComponentName("a", "a");
162         ComponentName componentB1 = new ComponentName("b", "b1");
163         ComponentName componentB2 = new ComponentName("b", "b2");
164         ComponentName componentC = new ComponentName("c", "c");
165 
166         PhoneAccount simAccountA = new PhoneAccount.Builder(
167                 makeQuickAccountHandle(componentA, "1"), "1")
168                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
169                 .setIsEnabled(true)
170                 .build();
171 
172         List<PhoneAccount> accountAList = new ArrayList<>();
173         accountAList.add(simAccountA);
174 
175         PhoneAccount simAccountB1 = new PhoneAccount.Builder(
176                 makeQuickAccountHandle(componentB1, "2"), "2")
177                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
178                 .setIsEnabled(true)
179                 .build();
180 
181         PhoneAccount simAccountB2 = new PhoneAccount.Builder(
182                 makeQuickAccountHandle(componentB2, "3"), "3")
183                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
184                 .setIsEnabled(true)
185                 .build();
186 
187         List<PhoneAccount> accountBList = new ArrayList<>();
188         accountBList.add(simAccountB1);
189         accountBList.add(simAccountB2);
190 
191         PhoneAccount simAccountC = new PhoneAccount.Builder(
192                 makeQuickAccountHandle(componentC, "4"), "4")
193                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
194                 .setIsEnabled(true)
195                 .build();
196 
197         List<PhoneAccount> accountCList = new ArrayList<>();
198         accountCList.add(simAccountC);
199 
200         List<PhoneAccount> allAccounts = new ArrayList<>();
201         allAccounts.addAll(accountAList);
202         allAccounts.addAll(accountBList);
203         allAccounts.addAll(accountCList);
204 
205         assertEquals(allAccounts, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
206 
207         mRegistrar.setTestPhoneAccountPackageNameFilter(componentA.getPackageName());
208         assertEquals(accountAList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
209 
210         mRegistrar.setTestPhoneAccountPackageNameFilter(componentB1.getPackageName());
211         assertEquals(accountBList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
212 
213         mRegistrar.setTestPhoneAccountPackageNameFilter(componentC.getPackageName());
214         assertEquals(accountCList, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
215 
216         mRegistrar.setTestPhoneAccountPackageNameFilter(null);
217         assertEquals(allAccounts, mRegistrar.filterRestrictedPhoneAccounts(allAccounts));
218     }
219 
220     @MediumTest
221     @Test
testDefaultPhoneAccountHandleEmptyGroup()222     public void testDefaultPhoneAccountHandleEmptyGroup() throws Exception {
223         DefaultPhoneAccountHandle input = new DefaultPhoneAccountHandle(Process.myUserHandle(),
224                 makeQuickAccountHandle("i1"), "");
225         when(UserManager.get(mContext).getSerialNumberForUser(input.userHandle))
226                 .thenReturn(0L);
227         when(UserManager.get(mContext).getUserForSerialNumber(0L))
228                 .thenReturn(input.userHandle);
229         DefaultPhoneAccountHandle result = roundTripXml(this, input,
230                 PhoneAccountRegistrar.sDefaultPhoneAcountHandleXml, mContext);
231 
232         assertDefaultPhoneAccountHandleEquals(input, result);
233     }
234 
235     /**
236      * Test to ensure non-supported values
237      * @throws Exception
238      */
239     @MediumTest
240     @Test
testPhoneAccountExtrasEdge()241     public void testPhoneAccountExtrasEdge() throws Exception {
242         Bundle testBundle = new Bundle();
243         // Ensure null values for string are not persisted.
244         testBundle.putString("EXTRA_STR2", null);
245         //
246 
247         // Ensure unsupported data types are not persisted.
248         testBundle.putShort("EXTRA_SHORT", (short) 2);
249         testBundle.putByte("EXTRA_BYTE", (byte) 1);
250         testBundle.putParcelable("EXTRA_PARC", new Rect(1, 1, 1, 1));
251         // Put in something valid so the bundle exists.
252         testBundle.putString("EXTRA_OK", "OK");
253 
254         PhoneAccount input = makeQuickAccountBuilder("id0", 0)
255                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
256                 .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
257                 .setExtras(testBundle)
258                 .build();
259         PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
260                 mContext);
261 
262         Bundle extras = result.getExtras();
263         assertFalse(extras.keySet().contains("EXTRA_STR2"));
264         assertFalse(extras.keySet().contains("EXTRA_SHORT"));
265         assertFalse(extras.keySet().contains("EXTRA_BYTE"));
266         assertFalse(extras.keySet().contains("EXTRA_PARC"));
267     }
268 
269     @MediumTest
270     @Test
testState()271     public void testState() throws Exception {
272         PhoneAccountRegistrar.State input = makeQuickState();
273         PhoneAccountRegistrar.State result = roundTripXml(this, input,
274                 PhoneAccountRegistrar.sStateXml,
275                 mContext);
276         assertStateEquals(input, result);
277     }
278 
registerAndEnableAccount(PhoneAccount account)279     private void registerAndEnableAccount(PhoneAccount account) {
280         mRegistrar.registerPhoneAccount(account);
281         mRegistrar.enablePhoneAccount(account.getAccountHandle(), true);
282     }
283 
284     @MediumTest
285     @Test
testAccounts()286     public void testAccounts() throws Exception {
287         int i = 0;
288 
289         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
290                 Mockito.mock(IConnectionService.class));
291 
292         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
293                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
294                         | PhoneAccount.CAPABILITY_CALL_PROVIDER)
295                 .build());
296         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
297                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
298                         | PhoneAccount.CAPABILITY_CALL_PROVIDER)
299                 .build());
300         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
301                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER
302                         | PhoneAccount.CAPABILITY_CALL_PROVIDER)
303                 .build());
304         registerAndEnableAccount(makeQuickAccountBuilder("id" + i, i++)
305                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
306                 .build());
307 
308         assertEquals(4, mRegistrar.getAllPhoneAccountsOfCurrentUser().size());
309         assertEquals(3, mRegistrar.getCallCapablePhoneAccountsOfCurrentUser(null, false).size());
310         assertEquals(null, mRegistrar.getSimCallManagerOfCurrentUser());
311         assertEquals(null, mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
312                 PhoneAccount.SCHEME_TEL));
313     }
314 
315     @MediumTest
316     @Test
testSimCallManager()317     public void testSimCallManager() throws Exception {
318         // TODO
319     }
320 
321     @MediumTest
322     @Test
testDefaultOutgoing()323     public void testDefaultOutgoing() throws Exception {
324         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
325                 Mockito.mock(IConnectionService.class));
326 
327         // By default, there is no default outgoing account (nothing has been registered)
328         assertNull(
329                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
330 
331         // Register one tel: account
332         PhoneAccountHandle telAccount = makeQuickAccountHandle("tel_acct");
333         registerAndEnableAccount(new PhoneAccount.Builder(telAccount, "tel_acct")
334                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
335                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
336                 .build());
337         PhoneAccountHandle defaultAccount =
338                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
339         assertEquals(telAccount, defaultAccount);
340 
341         // Add a SIP account, make sure tel: doesn't change
342         PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct");
343         registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct")
344                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
345                 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
346                 .build());
347         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
348                 PhoneAccount.SCHEME_SIP);
349         assertEquals(sipAccount, defaultAccount);
350         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
351                 PhoneAccount.SCHEME_TEL);
352         assertEquals(telAccount, defaultAccount);
353 
354         // Add a connection manager, make sure tel: doesn't change
355         PhoneAccountHandle connectionManager = makeQuickAccountHandle("mgr_acct");
356         registerAndEnableAccount(new PhoneAccount.Builder(connectionManager, "mgr_acct")
357                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
358                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
359                 .build());
360         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
361                 PhoneAccount.SCHEME_TEL);
362         assertEquals(telAccount, defaultAccount);
363 
364         // Unregister the tel: account, make sure there is no tel: default now.
365         mRegistrar.unregisterPhoneAccount(telAccount);
366         assertNull(
367                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
368     }
369 
370     @MediumTest
371     @Test
testReplacePhoneAccountByGroup()372     public void testReplacePhoneAccountByGroup() throws Exception {
373         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
374                 Mockito.mock(IConnectionService.class));
375 
376         // By default, there is no default outgoing account (nothing has been registered)
377         assertNull(
378                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
379 
380         // Register one tel: account
381         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
382         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
383                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
384                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
385                 .setGroupId("testGroup")
386                 .build());
387         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
388         PhoneAccountHandle defaultAccount =
389                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
390         assertEquals(telAccount1, defaultAccount);
391 
392         // Add call capable SIP account, make sure tel: doesn't change
393         PhoneAccountHandle sipAccount = makeQuickAccountHandle("sip_acct");
394         registerAndEnableAccount(new PhoneAccount.Builder(sipAccount, "sip_acct")
395                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
396                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
397                 .build());
398         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
399                 PhoneAccount.SCHEME_TEL);
400         assertEquals(telAccount1, defaultAccount);
401 
402         // Replace tel: account with another in the same Group
403         PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
404         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
405                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
406                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
407                 .setGroupId("testGroup")
408                 .build());
409         defaultAccount = mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
410                 PhoneAccount.SCHEME_TEL);
411         assertEquals(telAccount2, defaultAccount);
412         assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
413     }
414 
415     @MediumTest
416     @Test
testAddSameDefault()417     public void testAddSameDefault() throws Exception {
418         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
419                 Mockito.mock(IConnectionService.class));
420 
421         // By default, there is no default outgoing account (nothing has been registered)
422         assertNull(
423                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
424 
425         // Register one tel: account
426         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
427         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
428                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
429                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
430                 .setGroupId("testGroup")
431                 .build());
432         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
433         PhoneAccountHandle defaultAccount =
434                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
435         assertEquals(telAccount1, defaultAccount);
436         mRegistrar.unregisterPhoneAccount(telAccount1);
437 
438         // Register Emergency Account and unregister
439         PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct");
440         registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct")
441                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
442                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
443                 .build());
444         defaultAccount =
445                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
446         assertNull(defaultAccount);
447         mRegistrar.unregisterPhoneAccount(emerAccount);
448 
449         // Re-register the same account and make sure the default is in place
450         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
451                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
452                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
453                 .setGroupId("testGroup")
454                 .build());
455         defaultAccount =
456                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
457         assertEquals(telAccount1, defaultAccount);
458     }
459 
460     @MediumTest
461     @Test
testAddSameGroup()462     public void testAddSameGroup() throws Exception {
463         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
464                 Mockito.mock(IConnectionService.class));
465 
466         // By default, there is no default outgoing account (nothing has been registered)
467         assertNull(
468                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL));
469 
470         // Register one tel: account
471         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
472         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
473                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
474                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
475                 .setGroupId("testGroup")
476                 .build());
477         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
478         PhoneAccountHandle defaultAccount =
479                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
480         assertEquals(telAccount1, defaultAccount);
481         mRegistrar.unregisterPhoneAccount(telAccount1);
482 
483         // Register Emergency Account and unregister
484         PhoneAccountHandle emerAccount = makeQuickAccountHandle("emer_acct");
485         registerAndEnableAccount(new PhoneAccount.Builder(emerAccount, "emer_acct")
486                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
487                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
488                 .build());
489         defaultAccount =
490                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
491         assertNull(defaultAccount);
492         mRegistrar.unregisterPhoneAccount(emerAccount);
493 
494         // Re-register a new account with the same group
495         PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
496         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
497                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
498                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
499                 .setGroupId("testGroup")
500                 .build());
501         defaultAccount =
502                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
503         assertEquals(telAccount2, defaultAccount);
504     }
505 
506     @MediumTest
507     @Test
testAddSameGroupButDifferentComponent()508     public void testAddSameGroupButDifferentComponent() throws Exception {
509         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
510                 Mockito.mock(IConnectionService.class));
511 
512         // By default, there is no default outgoing account (nothing has been registered)
513         assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
514                 PhoneAccount.SCHEME_TEL));
515 
516         // Register one tel: account
517         PhoneAccountHandle telAccount1 = makeQuickAccountHandle("tel_acct1");
518         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
519                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
520                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
521                 .setGroupId("testGroup")
522                 .build());
523         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
524         PhoneAccountHandle defaultAccount =
525                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
526         assertEquals(telAccount1, defaultAccount);
527         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
528 
529         // Register a new account with the same group, but different Component, so don't replace
530         // Default
531         PhoneAccountHandle telAccount2 =  makeQuickAccountHandle(
532                 new ComponentName("other1", "other2"), "tel_acct2");
533         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
534                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
535                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
536                 .setGroupId("testGroup")
537                 .build());
538         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount2));
539 
540         defaultAccount =
541                 mRegistrar.getUserSelectedOutgoingPhoneAccount(Process.myUserHandle());
542         assertEquals(telAccount1, defaultAccount);
543     }
544 
545     @MediumTest
546     @Test
testAddSameGroupButDifferentComponent2()547     public void testAddSameGroupButDifferentComponent2() throws Exception {
548         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
549                 Mockito.mock(IConnectionService.class));
550 
551         // By default, there is no default outgoing account (nothing has been registered)
552         assertNull(mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
553                 PhoneAccount.SCHEME_TEL));
554 
555         // Register first tel: account
556         PhoneAccountHandle telAccount1 =  makeQuickAccountHandle(
557                 new ComponentName("other1", "other2"), "tel_acct1");
558         registerAndEnableAccount(new PhoneAccount.Builder(telAccount1, "tel_acct1")
559                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
560                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
561                 .setGroupId("testGroup")
562                 .build());
563         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
564         mRegistrar.setUserSelectedOutgoingPhoneAccount(telAccount1, Process.myUserHandle());
565 
566         // Register second account with the same group, but a second Component, so don't replace
567         // Default
568         PhoneAccountHandle telAccount2 = makeQuickAccountHandle("tel_acct2");
569         registerAndEnableAccount(new PhoneAccount.Builder(telAccount2, "tel_acct2")
570                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
571                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
572                 .setGroupId("testGroup")
573                 .build());
574 
575         PhoneAccountHandle defaultAccount =
576                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
577         assertEquals(telAccount1, defaultAccount);
578 
579         // Register third account with the second component name, but same group id
580         PhoneAccountHandle telAccount3 = makeQuickAccountHandle("tel_acct3");
581         registerAndEnableAccount(new PhoneAccount.Builder(telAccount3, "tel_acct3")
582                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
583                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
584                 .setGroupId("testGroup")
585                 .build());
586 
587         // Make sure that the default account is still the original PhoneAccount and that the
588         // second PhoneAccount with the second ComponentName was replaced by the third PhoneAccount
589         defaultAccount =
590                 mRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(PhoneAccount.SCHEME_TEL);
591         assertEquals(telAccount1, defaultAccount);
592 
593         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount1));
594         assertNull(mRegistrar.getPhoneAccountUnchecked(telAccount2));
595         assertNotNull(mRegistrar.getPhoneAccountUnchecked(telAccount3));
596     }
597 
598     @MediumTest
599     @Test
testPhoneAccountParceling()600     public void testPhoneAccountParceling() throws Exception {
601         PhoneAccountHandle handle = makeQuickAccountHandle("foo");
602         roundTripPhoneAccount(new PhoneAccount.Builder(handle, null).build());
603         roundTripPhoneAccount(new PhoneAccount.Builder(handle, "foo").build());
604         roundTripPhoneAccount(
605                 new PhoneAccount.Builder(handle, "foo")
606                         .setAddress(Uri.parse("tel:123456"))
607                         .setCapabilities(23)
608                         .setHighlightColor(0xf0f0f0)
609                         .setIcon(Icon.createWithResource(
610                                 "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
611                         // TODO: set icon tint (0xfefefe)
612                         .setShortDescription("short description")
613                         .setSubscriptionAddress(Uri.parse("tel:2345678"))
614                         .setSupportedUriSchemes(Arrays.asList("tel", "sip"))
615                         .setGroupId("testGroup")
616                         .build());
617         roundTripPhoneAccount(
618                 new PhoneAccount.Builder(handle, "foo")
619                         .setAddress(Uri.parse("tel:123456"))
620                         .setCapabilities(23)
621                         .setHighlightColor(0xf0f0f0)
622                         .setIcon(Icon.createWithBitmap(
623                                 BitmapFactory.decodeResource(
624                                         InstrumentationRegistry.getContext().getResources(),
625                                         R.drawable.stat_sys_phone_call)))
626                         .setShortDescription("short description")
627                         .setSubscriptionAddress(Uri.parse("tel:2345678"))
628                         .setSupportedUriSchemes(Arrays.asList("tel", "sip"))
629                         .setGroupId("testGroup")
630                         .build());
631     }
632 
633     /**
634      * Tests ability to register a self-managed PhoneAccount; verifies that the user defined label
635      * is overridden.
636      * @throws Exception
637      */
638     @MediumTest
639     @Test
testSelfManagedPhoneAccount()640     public void testSelfManagedPhoneAccount() throws Exception {
641         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
642                 Mockito.mock(IConnectionService.class));
643 
644         PhoneAccountHandle selfManagedHandle =  makeQuickAccountHandle(
645                 new ComponentName("self", "managed"), "selfie1");
646 
647         PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, "Wrong")
648                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
649                 .build();
650 
651         mRegistrar.registerPhoneAccount(selfManagedAccount);
652 
653         PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle);
654         assertEquals(TEST_LABEL, registeredAccount.getLabel());
655     }
656 
657     /**
658      * Tests to ensure that when registering a self-managed PhoneAccount, it cannot also be defined
659      * as a call provider, connection manager, or sim subscription.
660      * @throws Exception
661      */
662     @MediumTest
663     @Test
testSelfManagedCapabilityOverride()664     public void testSelfManagedCapabilityOverride() throws Exception {
665         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
666                 Mockito.mock(IConnectionService.class));
667 
668         PhoneAccountHandle selfManagedHandle =  makeQuickAccountHandle(
669                 new ComponentName("self", "managed"), "selfie1");
670 
671         PhoneAccount selfManagedAccount = new PhoneAccount.Builder(selfManagedHandle, TEST_LABEL)
672                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
673                         PhoneAccount.CAPABILITY_CALL_PROVIDER |
674                         PhoneAccount.CAPABILITY_CONNECTION_MANAGER |
675                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
676                 .build();
677 
678         mRegistrar.registerPhoneAccount(selfManagedAccount);
679 
680         PhoneAccount registeredAccount = mRegistrar.getPhoneAccountUnchecked(selfManagedHandle);
681         assertEquals(PhoneAccount.CAPABILITY_SELF_MANAGED, registeredAccount.getCapabilities());
682     }
683 
684     @MediumTest
685     @Test
testSortSimFirst()686     public void testSortSimFirst() throws Exception {
687         ComponentName componentA = new ComponentName("a", "a");
688         ComponentName componentB = new ComponentName("b", "b");
689         mComponentContextFixture.addConnectionService(componentA,
690                 Mockito.mock(IConnectionService.class));
691         mComponentContextFixture.addConnectionService(componentB,
692                 Mockito.mock(IConnectionService.class));
693 
694         PhoneAccount simAccount = new PhoneAccount.Builder(
695                 makeQuickAccountHandle(componentB, "2"), "2")
696                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
697                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
698                 .setIsEnabled(true)
699                 .build();
700 
701         PhoneAccount nonSimAccount = new PhoneAccount.Builder(
702                 makeQuickAccountHandle(componentA, "1"), "1")
703                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
704                 .setIsEnabled(true)
705                 .build();
706 
707         registerAndEnableAccount(nonSimAccount);
708         registerAndEnableAccount(simAccount);
709 
710         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
711         assertTrue(accounts.get(0).getLabel().toString().equals("2"));
712         assertTrue(accounts.get(1).getLabel().toString().equals("1"));
713     }
714 
715     @MediumTest
716     @Test
testSortBySortOrder()717     public void testSortBySortOrder() throws Exception {
718         ComponentName componentA = new ComponentName("a", "a");
719         ComponentName componentB = new ComponentName("b", "b");
720         ComponentName componentC = new ComponentName("c", "c");
721         mComponentContextFixture.addConnectionService(componentA,
722                 Mockito.mock(IConnectionService.class));
723         mComponentContextFixture.addConnectionService(componentB,
724                 Mockito.mock(IConnectionService.class));
725         mComponentContextFixture.addConnectionService(componentC,
726                 Mockito.mock(IConnectionService.class));
727 
728         Bundle account1Extras = new Bundle();
729         account1Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 1);
730         PhoneAccount account1 = new PhoneAccount.Builder(
731                 makeQuickAccountHandle(componentA, "c"), "c")
732                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
733                 .setExtras(account1Extras)
734                 .build();
735 
736         Bundle account2Extras = new Bundle();
737         account2Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 2);
738         PhoneAccount account2 = new PhoneAccount.Builder(
739                 makeQuickAccountHandle(componentB, "b"), "b")
740                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
741                 .setExtras(account2Extras)
742                 .build();
743 
744         PhoneAccount account3 = new PhoneAccount.Builder(
745                 makeQuickAccountHandle(componentC, "c"), "a")
746                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
747                 .build();
748 
749         registerAndEnableAccount(account3);
750         registerAndEnableAccount(account2);
751         registerAndEnableAccount(account1);
752 
753         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
754         assertTrue(accounts.get(0).getLabel().toString().equals("c"));
755         assertTrue(accounts.get(1).getLabel().toString().equals("b"));
756         assertTrue(accounts.get(2).getLabel().toString().equals("a"));
757     }
758 
759     @MediumTest
760     @Test
testSortByLabel()761     public void testSortByLabel() throws Exception {
762         ComponentName componentA = new ComponentName("a", "a");
763         ComponentName componentB = new ComponentName("b", "b");
764         ComponentName componentC = new ComponentName("c", "c");
765         mComponentContextFixture.addConnectionService(componentA,
766                 Mockito.mock(IConnectionService.class));
767         mComponentContextFixture.addConnectionService(componentB,
768                 Mockito.mock(IConnectionService.class));
769         mComponentContextFixture.addConnectionService(componentC,
770                 Mockito.mock(IConnectionService.class));
771 
772         PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(componentA, "c"),
773                 "c")
774                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
775                 .build();
776 
777         PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(componentB, "b"),
778                 "b")
779                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
780                 .build();
781 
782         PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(componentC, "a"),
783                 "a")
784                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
785                 .build();
786 
787         registerAndEnableAccount(account1);
788         registerAndEnableAccount(account2);
789         registerAndEnableAccount(account3);
790 
791         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
792         assertTrue(accounts.get(0).getLabel().toString().equals("a"));
793         assertTrue(accounts.get(1).getLabel().toString().equals("b"));
794         assertTrue(accounts.get(2).getLabel().toString().equals("c"));
795     }
796 
797     @MediumTest
798     @Test
testSortAll()799     public void testSortAll() throws Exception {
800         ComponentName componentA = new ComponentName("a", "a");
801         ComponentName componentB = new ComponentName("b", "b");
802         ComponentName componentC = new ComponentName("c", "c");
803         ComponentName componentW = new ComponentName("w", "w");
804         ComponentName componentX = new ComponentName("x", "x");
805         ComponentName componentY = new ComponentName("y", "y");
806         ComponentName componentZ = new ComponentName("z", "z");
807         mComponentContextFixture.addConnectionService(componentA,
808                 Mockito.mock(IConnectionService.class));
809         mComponentContextFixture.addConnectionService(componentB,
810                 Mockito.mock(IConnectionService.class));
811         mComponentContextFixture.addConnectionService(componentC,
812                 Mockito.mock(IConnectionService.class));
813         mComponentContextFixture.addConnectionService(componentW,
814                 Mockito.mock(IConnectionService.class));
815         mComponentContextFixture.addConnectionService(componentX,
816                 Mockito.mock(IConnectionService.class));
817         mComponentContextFixture.addConnectionService(componentY,
818                 Mockito.mock(IConnectionService.class));
819         mComponentContextFixture.addConnectionService(componentZ,
820                 Mockito.mock(IConnectionService.class));
821 
822         Bundle account1Extras = new Bundle();
823         account1Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 2);
824         PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(
825                 makeQuickConnectionServiceComponentName(), "y"), "y")
826                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
827                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
828                 .setExtras(account1Extras)
829                 .build();
830 
831         Bundle account2Extras = new Bundle();
832         account2Extras.putInt(PhoneAccount.EXTRA_SORT_ORDER, 1);
833         PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(
834                 makeQuickConnectionServiceComponentName(), "z"), "z")
835                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
836                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
837                 .setExtras(account2Extras)
838                 .build();
839 
840         PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(
841                 makeQuickConnectionServiceComponentName(), "x"), "x")
842                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
843                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
844                 .build();
845 
846         PhoneAccount account4 = new PhoneAccount.Builder(makeQuickAccountHandle(
847                 makeQuickConnectionServiceComponentName(), "w"), "w")
848                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
849                         PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
850                 .build();
851 
852         PhoneAccount account5 = new PhoneAccount.Builder(makeQuickAccountHandle(
853                 makeQuickConnectionServiceComponentName(), "b"), "b")
854                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
855                 .build();
856 
857         PhoneAccount account6 = new PhoneAccount.Builder(makeQuickAccountHandle(
858                 makeQuickConnectionServiceComponentName(), "c"), "a")
859                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
860                 .build();
861 
862         registerAndEnableAccount(account1);
863         registerAndEnableAccount(account2);
864         registerAndEnableAccount(account3);
865         registerAndEnableAccount(account4);
866         registerAndEnableAccount(account5);
867         registerAndEnableAccount(account6);
868 
869         List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
870         // Sim accts ordered by sort order first
871         assertTrue(accounts.get(0).getLabel().toString().equals("z"));
872         assertTrue(accounts.get(1).getLabel().toString().equals("y"));
873 
874         // Sim accts with no sort order next
875         assertTrue(accounts.get(2).getLabel().toString().equals("w"));
876         assertTrue(accounts.get(3).getLabel().toString().equals("x"));
877 
878         // Other accts sorted by label next
879         assertTrue(accounts.get(4).getLabel().toString().equals("a"));
880         assertTrue(accounts.get(5).getLabel().toString().equals("b"));
881     }
882 
883     /**
884      * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle)}
885      * to ensure disabled accounts are filtered out of results when requested.
886      * @throws Exception
887      */
888     @MediumTest
889     @Test
testGetByEnabledState()890     public void testGetByEnabledState() throws Exception {
891         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
892                 Mockito.mock(IConnectionService.class));
893         mRegistrar.registerPhoneAccount(makeQuickAccountBuilder("id1", 1)
894                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
895                 .build());
896 
897         assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
898                 false /* includeDisabled */, Process.myUserHandle()).size());
899         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
900                 true /* includeDisabled */, Process.myUserHandle()).size());
901     }
902 
903     /**
904      * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle)}
905      * to ensure scheme filtering operates.
906      * @throws Exception
907      */
908     @MediumTest
909     @Test
testGetByScheme()910     public void testGetByScheme() throws Exception {
911         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
912                 Mockito.mock(IConnectionService.class));
913         registerAndEnableAccount(makeQuickAccountBuilder("id1", 1)
914                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
915                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
916                 .build());
917         registerAndEnableAccount(makeQuickAccountBuilder("id2", 2)
918                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
919                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_TEL))
920                 .build());
921 
922         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
923                 false /* includeDisabled */, Process.myUserHandle()).size());
924         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_TEL,
925                 false /* includeDisabled */, Process.myUserHandle()).size());
926         assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(null, false /* includeDisabled */,
927                 Process.myUserHandle()).size());
928     }
929 
930     /**
931      * Tests {@link PhoneAccountRegistrar#getCallCapablePhoneAccounts(String, boolean, UserHandle,
932      * int)} to ensure capability filtering operates.
933      * @throws Exception
934      */
935     @MediumTest
936     @Test
testGetByCapability()937     public void testGetByCapability() throws Exception {
938         mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
939                 Mockito.mock(IConnectionService.class));
940         registerAndEnableAccount(makeQuickAccountBuilder("id1", 1)
941                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER
942                         | PhoneAccount.CAPABILITY_VIDEO_CALLING)
943                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
944                 .build());
945         registerAndEnableAccount(makeQuickAccountBuilder("id2", 2)
946                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
947                 .setSupportedUriSchemes(Arrays.asList(PhoneAccount.SCHEME_SIP))
948                 .build());
949 
950         assertEquals(1, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
951                 false /* includeDisabled */, Process.myUserHandle()).size(),
952                 PhoneAccount.CAPABILITY_VIDEO_CALLING);
953         assertEquals(2, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
954                 false /* includeDisabled */, Process.myUserHandle()).size(), 0 /* none extra */);
955         assertEquals(0, mRegistrar.getCallCapablePhoneAccounts(PhoneAccount.SCHEME_SIP,
956                 false /* includeDisabled */, Process.myUserHandle()).size(),
957                 PhoneAccount.CAPABILITY_RTT);
958     }
959 
960     /**
961      * Tests {@link PhoneAccount#equals(Object)} operator.
962      * @throws Exception
963      */
964     @MediumTest
965     @Test
testPhoneAccountEquality()966     public void testPhoneAccountEquality() throws Exception {
967         PhoneAccountHandle handle = new PhoneAccountHandle(new ComponentName("foo", "bar"), "id");
968         PhoneAccount.Builder builder = new PhoneAccount.Builder(handle, "label");
969         builder.addSupportedUriScheme("tel");
970         builder.setAddress(Uri.fromParts("tel", "6505551212", null));
971         builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER);
972         Bundle extras = new Bundle();
973         extras.putInt("INT", 1);
974         extras.putString("STR", "str");
975         builder.setExtras(extras);
976         builder.setGroupId("group");
977         builder.setHighlightColor(1);
978         builder.setShortDescription("short");
979         builder.setSubscriptionAddress(Uri.fromParts("tel", "6505551213", null));
980         builder.setSupportedAudioRoutes(2);
981 
982         PhoneAccount account1 = builder.build();
983         PhoneAccount account2 = builder.build();
984         assertEquals(account1, account2);
985     }
986 
987     /**
988      * Tests {@link PhoneAccountHandle#areFromSamePackage(PhoneAccountHandle,
989      * PhoneAccountHandle)} comparison.
990      */
991     @SmallTest
992     @Test
testSamePhoneAccountHandlePackage()993     public void testSamePhoneAccountHandlePackage() {
994         PhoneAccountHandle a = new PhoneAccountHandle(new ComponentName("packageA", "class1"),
995                 "id1");
996         PhoneAccountHandle b = new PhoneAccountHandle(new ComponentName("packageA", "class2"),
997                 "id2");
998         PhoneAccountHandle c = new PhoneAccountHandle(new ComponentName("packageA", "class1"),
999                 "id3");
1000         PhoneAccountHandle d = new PhoneAccountHandle(new ComponentName("packageB", "class1"),
1001                 "id1");
1002 
1003         assertTrue(PhoneAccountHandle.areFromSamePackage(null, null));
1004         assertTrue(PhoneAccountHandle.areFromSamePackage(a, b));
1005         assertTrue(PhoneAccountHandle.areFromSamePackage(a, c));
1006         assertTrue(PhoneAccountHandle.areFromSamePackage(b, c));
1007         assertFalse(PhoneAccountHandle.areFromSamePackage(a, d));
1008         assertFalse(PhoneAccountHandle.areFromSamePackage(b, d));
1009         assertFalse(PhoneAccountHandle.areFromSamePackage(c, d));
1010         assertFalse(PhoneAccountHandle.areFromSamePackage(a, null));
1011         assertFalse(PhoneAccountHandle.areFromSamePackage(b, null));
1012         assertFalse(PhoneAccountHandle.areFromSamePackage(c, null));
1013         assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
1014         assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
1015         assertFalse(PhoneAccountHandle.areFromSamePackage(null, d));
1016     }
1017 
makeQuickConnectionServiceComponentName()1018     private static ComponentName makeQuickConnectionServiceComponentName() {
1019         return new ComponentName(
1020                 "com.android.server.telecom.tests",
1021                 "com.android.server.telecom.tests.MockConnectionService");
1022     }
1023 
makeQuickAccountHandle(String id)1024     private static PhoneAccountHandle makeQuickAccountHandle(String id) {
1025         return makeQuickAccountHandle(makeQuickConnectionServiceComponentName(), id);
1026     }
1027 
makeQuickAccountHandle(ComponentName name, String id)1028     private static PhoneAccountHandle makeQuickAccountHandle(ComponentName name, String id) {
1029         return new PhoneAccountHandle(name, id, Process.myUserHandle());
1030     }
1031 
makeQuickAccountBuilder(String id, int idx)1032     private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
1033         return new PhoneAccount.Builder(
1034                 makeQuickAccountHandle(id),
1035                 "label" + idx);
1036     }
1037 
makeQuickAccount(String id, int idx)1038     private PhoneAccount makeQuickAccount(String id, int idx) {
1039         return makeQuickAccountBuilder(id, idx)
1040                 .setAddress(Uri.parse("http://foo.com/" + idx))
1041                 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
1042                 .setCapabilities(idx)
1043                 .setIcon(Icon.createWithResource(
1044                             "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
1045                 .setShortDescription("desc" + idx)
1046                 .setIsEnabled(true)
1047                 .build();
1048     }
1049 
roundTripPhoneAccount(PhoneAccount original)1050     private static void roundTripPhoneAccount(PhoneAccount original) throws Exception {
1051         PhoneAccount copy = null;
1052 
1053         {
1054             Parcel parcel = Parcel.obtain();
1055             parcel.writeParcelable(original, 0);
1056             parcel.setDataPosition(0);
1057             copy = parcel.readParcelable(PhoneAccountRegistrarTest.class.getClassLoader());
1058             parcel.recycle();
1059         }
1060 
1061         assertPhoneAccountEquals(original, copy);
1062     }
1063 
roundTripXml( Object self, T input, PhoneAccountRegistrar.XmlSerialization<T> xml, Context context)1064     private static <T> T roundTripXml(
1065             Object self,
1066             T input,
1067             PhoneAccountRegistrar.XmlSerialization<T> xml,
1068             Context context)
1069             throws Exception {
1070         Log.d(self, "Input = %s", input);
1071 
1072         byte[] data;
1073         {
1074             XmlSerializer serializer = new FastXmlSerializer();
1075             ByteArrayOutputStream baos = new ByteArrayOutputStream();
1076             serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
1077             xml.writeToXml(input, serializer, context);
1078             serializer.flush();
1079             data = baos.toByteArray();
1080         }
1081 
1082         Log.i(self, "====== XML data ======\n%s", new String(data));
1083 
1084         T result = null;
1085         {
1086             XmlPullParser parser = Xml.newPullParser();
1087             parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null);
1088             parser.nextTag();
1089             result = xml.readFromXml(parser, MAX_VERSION, context);
1090         }
1091 
1092         Log.i(self, "result = " + result);
1093 
1094         return result;
1095     }
1096 
assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b)1097     private static void assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b) {
1098         if (a != b) {
1099             assertEquals(
1100                     a.getComponentName().getPackageName(),
1101                     b.getComponentName().getPackageName());
1102             assertEquals(
1103                     a.getComponentName().getClassName(),
1104                     b.getComponentName().getClassName());
1105             assertEquals(a.getId(), b.getId());
1106         }
1107     }
1108 
assertIconEquals(Icon a, Icon b)1109     private static void assertIconEquals(Icon a, Icon b) {
1110         if (a != b) {
1111             if (a != null && b != null) {
1112                 assertEquals(a.toString(), b.toString());
1113             } else {
1114                 fail("Icons not equal: " + a + ", " + b);
1115             }
1116         }
1117     }
1118 
assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a, DefaultPhoneAccountHandle b)1119     private static void assertDefaultPhoneAccountHandleEquals(DefaultPhoneAccountHandle a,
1120             DefaultPhoneAccountHandle b) {
1121         if (a != b) {
1122             if (a!= null && b != null) {
1123                 assertEquals(a.userHandle, b.userHandle);
1124                 assertPhoneAccountHandleEquals(a.phoneAccountHandle, b.phoneAccountHandle);
1125             } else {
1126                 fail("Default phone account handles are not equal: " + a + ", " + b);
1127             }
1128         }
1129     }
1130 
assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b)1131     private static void assertPhoneAccountEquals(PhoneAccount a, PhoneAccount b) {
1132         if (a != b) {
1133             if (a != null && b != null) {
1134                 assertPhoneAccountHandleEquals(a.getAccountHandle(), b.getAccountHandle());
1135                 assertEquals(a.getAddress(), b.getAddress());
1136                 assertEquals(a.getSubscriptionAddress(), b.getSubscriptionAddress());
1137                 assertEquals(a.getCapabilities(), b.getCapabilities());
1138                 assertIconEquals(a.getIcon(), b.getIcon());
1139                 assertEquals(a.getHighlightColor(), b.getHighlightColor());
1140                 assertEquals(a.getLabel(), b.getLabel());
1141                 assertEquals(a.getShortDescription(), b.getShortDescription());
1142                 assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes());
1143                 assertBundlesEqual(a.getExtras(), b.getExtras());
1144                 assertEquals(a.isEnabled(), b.isEnabled());
1145             } else {
1146                 fail("Phone accounts not equal: " + a + ", " + b);
1147             }
1148         }
1149     }
1150 
assertBundlesEqual(Bundle a, Bundle b)1151     private static void assertBundlesEqual(Bundle a, Bundle b) {
1152         if (a == null && b == null) {
1153             return;
1154         }
1155 
1156         assertNotNull(a);
1157         assertNotNull(b);
1158         Set<String> keySetA = a.keySet();
1159         Set<String> keySetB = b.keySet();
1160 
1161         assertTrue("Bundle keys not the same", keySetA.containsAll(keySetB));
1162         assertTrue("Bundle keys not the same", keySetB.containsAll(keySetA));
1163 
1164         for (String keyA : keySetA) {
1165             assertEquals("Bundle value not the same", a.get(keyA), b.get(keyA));
1166         }
1167     }
1168 
assertStateEquals( PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b)1169     private static void assertStateEquals(
1170             PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) {
1171         assertEquals(a.defaultOutgoingAccountHandles.size(),
1172                 b.defaultOutgoingAccountHandles.size());
1173         for (Map.Entry<UserHandle, DefaultPhoneAccountHandle> e :
1174                 a.defaultOutgoingAccountHandles.entrySet()) {
1175             assertDefaultPhoneAccountHandleEquals(e.getValue(),
1176                     b.defaultOutgoingAccountHandles.get(e.getKey()));
1177         }
1178         assertEquals(a.accounts.size(), b.accounts.size());
1179         for (int i = 0; i < a.accounts.size(); i++) {
1180             assertPhoneAccountEquals(a.accounts.get(i), b.accounts.get(i));
1181         }
1182     }
1183 
makeQuickState()1184     private PhoneAccountRegistrar.State makeQuickState() {
1185         PhoneAccountRegistrar.State s = new PhoneAccountRegistrar.State();
1186         s.accounts.add(makeQuickAccount("id0", 0));
1187         s.accounts.add(makeQuickAccount("id1", 1));
1188         s.accounts.add(makeQuickAccount("id2", 2));
1189         PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(
1190                 new ComponentName("pkg0", "cls0"), "id0");
1191         UserHandle userHandle = phoneAccountHandle.getUserHandle();
1192         when(UserManager.get(mContext).getSerialNumberForUser(userHandle))
1193                 .thenReturn(0L);
1194         when(UserManager.get(mContext).getUserForSerialNumber(0L))
1195                 .thenReturn(userHandle);
1196         s.defaultOutgoingAccountHandles
1197                 .put(userHandle, new DefaultPhoneAccountHandle(userHandle, phoneAccountHandle,
1198                         "testGroup"));
1199         return s;
1200     }
1201 }
1202