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