• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 android.telecom.cts;
18 
19 import static android.telecom.PhoneAccount.CAPABILITY_CALL_PROVIDER;
20 import static android.telecom.PhoneAccount.CAPABILITY_SELF_MANAGED;
21 
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.ServiceConnection;
26 import android.net.Uri;
27 import android.os.IBinder;
28 import android.os.RemoteException;
29 import android.telecom.PhoneAccount;
30 import android.telecom.PhoneAccountHandle;
31 import android.telecom.TelecomManager;
32 import android.telecom.cts.carmodetestapp.ICtsCarModeInCallServiceControl;
33 import android.telecom.cts.carmodetestappselfmanaged.CtsCarModeInCallServiceControlSelfManaged;
34 import android.util.Log;
35 
36 import com.android.compatibility.common.util.ShellIdentityUtils;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.concurrent.CountDownLatch;
41 import java.util.concurrent.TimeUnit;
42 
43 public class PhoneAccountRegistrarTest extends BaseTelecomTestWithMockServices {
44 
45     private static final String TAG = "PhoneAccountRegistrarTest";
46     private static final long TIMEOUT = 3000L;
47     private static final int LARGE_ACCT_HANDLE_ID_MIN_SIZE = 50000;
48     private static final String RANDOM_CHAR_VALUE = "a";
49     private static final String TEL_PREFIX = "tel:";
50     private static final String TELECOM_CLEANUP_ACCTS_CMD = "telecom cleanup-orphan-phone-accounts";
51     public static final long SEED = 52L; // random seed chosen
52     public static final int MAX_PHONE_ACCOUNT_REGISTRATIONS = 10; // mirrors constant in...
53     // PhoneAccountRegistrar called MAX_PHONE_ACCOUNT_REGISTRATIONS
54 
55     // permissions
56     private static final String READ_PRIVILEGED_PHONE_STATE =
57             "android.permission.READ_PRIVILEGED_PHONE_STATE";
58     private static final String MODIFY_PHONE_STATE_PERMISSION =
59             "android.permission.MODIFY_PHONE_STATE";
60     private static final String REGISTER_SIM_SUBSCRIPTION_PERMISSION =
61             "android.permission.REGISTER_SIM_SUBSCRIPTION";
62 
63     // telecom cts test package (default package that registers phoneAccounts)
64     private static final ComponentName TEST_COMPONENT_NAME =
65             new ComponentName(TestUtils.PACKAGE, TestUtils.COMPONENT);
66 
67     // secondary test package (extra package that can be set up to register phoneAccounts)
68     private static final String SELF_MANAGED_CAR_PACKAGE =
69             CtsCarModeInCallServiceControlSelfManaged.class.getPackage().getName();
70     private static final ComponentName SELF_MANAGED_CAR_RELATIVE_COMPONENT = ComponentName
71             .createRelative(SELF_MANAGED_CAR_PACKAGE,
72                     CtsCarModeInCallServiceControlSelfManaged.class.getName());
73     private static final ComponentName CAR_COMPONENT = new ComponentName(SELF_MANAGED_CAR_PACKAGE,
74             TestUtils.SELF_MANAGED_COMPONENT);
75     private static final String CAR_MODE_CONTROL =
76             "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL";
77     // variables to interface with the second test package
78     TestServiceConnection mControl;
79     ICtsCarModeInCallServiceControl mSecondaryTestPackageControl;
80 
81     @Override
setUp()82     public void setUp() throws Exception {
83         // Sets up this package as default dialer in super.
84         super.setUp();
85         NewOutgoingCallBroadcastReceiver.reset();
86         if (!mShouldTestTelecom) return;
87         setupConnectionService(null, 0);
88         // cleanup any accounts registered to the test package before starting tests
89         cleanupPhoneAccounts();
90     }
91 
92     @Override
tearDown()93     public void tearDown() throws Exception {
94         // cleanup any accounts registered to the test package after testing to avoid crashing other
95         // tests.
96         cleanupPhoneAccounts();
97         super.tearDown();
98     }
99 
100     /**
101      * Test scenario where a single package can register MAX_PHONE_ACCOUNT_REGISTRATIONS via
102      * {@link android.telecom.TelecomManager#registerPhoneAccount(PhoneAccount)}  without an
103      * exception being thrown.
104      */
testRegisterMaxPhoneAccountsWithoutException()105     public void testRegisterMaxPhoneAccountsWithoutException() {
106         if (!mShouldTestTelecom) return;
107 
108         // ensure the test starts without any phone accounts registered to the test package
109         cleanupPhoneAccounts();
110 
111         //  determine the number of phone accounts that can be registered before hitting limit
112         int numberOfAccountsThatCanBeRegistered = MAX_PHONE_ACCOUNT_REGISTRATIONS
113                 - getNumberOfPhoneAccountsRegisteredToTestPackage();
114 
115         // create the remaining number of phone accounts via helper function
116         // in order to reach the upper bound MAX_PHONE_ACCOUNT_REGISTRATIONS
117         ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED,
118                 numberOfAccountsThatCanBeRegistered, TestUtils.PACKAGE, TestUtils.COMPONENT);
119         try {
120             // register all accounts created
121             accounts.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a));
122             // assert the maximum accounts that can be registered were registered successfully
123             assertEquals(MAX_PHONE_ACCOUNT_REGISTRATIONS,
124                     getNumberOfPhoneAccountsRegisteredToTestPackage());
125         } finally {
126             // cleanup accounts registered
127             accounts.stream().forEach(
128                     d -> mTelecomManager.unregisterPhoneAccount(d.getAccountHandle()));
129         }
130     }
131 
132     /**
133      * Tests a scenario where a single package exceeds MAX_PHONE_ACCOUNT_REGISTRATIONS and
134      * an {@link IllegalArgumentException}  is thrown. Will fail if no exception is thrown.
135      */
testExceptionThrownDueUserExceededMaxPhoneAccountRegistrations()136     public void testExceptionThrownDueUserExceededMaxPhoneAccountRegistrations()
137             throws IllegalArgumentException {
138         if (!mShouldTestTelecom) return;
139 
140         // ensure the test starts without any phone accounts registered to the test package
141         cleanupPhoneAccounts();
142 
143         // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function
144         ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED,
145                 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE,
146                 TestUtils.COMPONENT);
147 
148         try {
149             // Try to register more phone accounts than allowed by the upper bound limit
150             // MAX_PHONE_ACCOUNT_REGISTRATIONS
151             accounts.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a));
152             // A successful test should never reach this line of execution.
153             // However, if it does, fail the test by throwing a fail(...)
154             fail("Test failed. The test did not throw an IllegalArgumentException when "
155                     + "registering phone accounts over the upper bound: "
156                     + "MAX_PHONE_ACCOUNT_REGISTRATIONS");
157         } catch (IllegalArgumentException e) {
158             // Assert the IllegalArgumentException was thrown
159             assertNotNull(e.toString());
160         } finally {
161             // Cleanup accounts registered
162             accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount(
163                     d.getAccountHandle()));
164         }
165     }
166 
167     /**
168      * Ensure an app does not register accounts over the upper bound limit by disabling them
169      */
testDisablingAccountsAfterRegStillThrowsException()170     public void testDisablingAccountsAfterRegStillThrowsException() throws Exception {
171         if (!mShouldTestTelecom) return;
172 
173         // ensure the test starts without any phone accounts registered to the test package
174         cleanupPhoneAccounts();
175 
176         // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1 via helper function
177         ArrayList<PhoneAccount> accounts = TestUtils.generateRandomPhoneAccounts(SEED,
178                 MAX_PHONE_ACCOUNT_REGISTRATIONS + 1, TestUtils.PACKAGE,
179                 TestUtils.COMPONENT);
180 
181         try {
182             // Try to register more phone accounts than allowed by the upper bound limit
183             for (PhoneAccount pa : accounts) {
184                 mTelecomManager.registerPhoneAccount(pa);
185                 TestUtils.disablePhoneAccount(getInstrumentation(), pa.getAccountHandle());
186                 // verify the account is both registered and disabled
187                 verifyAccountIsDisabled(pa);
188             }
189 
190             // A successful test should never reach this line of execution.
191             // However, if it does, fail the test by throwing a fail(...)
192             fail("Test failed. The test did not throw an IllegalArgumentException when "
193                     + "registering phone accounts over the upper bound: "
194                     + "MAX_PHONE_ACCOUNT_REGISTRATIONS");
195         } catch (IllegalArgumentException e) {
196             // Assert the IllegalArgumentException was thrown
197             assertNotNull(e.toString());
198         } finally {
199             // Cleanup accounts registered
200             accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount(
201                     d.getAccountHandle()));
202         }
203     }
204 
205     /**
206      * Ensure an app does not register accounts that will be auto-disabled upon registered and
207      * bypass the limit. Note: CAPABILITY_CALL_PROVIDER will register the account as disabled.
208      */
testDisabledAccountsThrowsException()209     public void testDisabledAccountsThrowsException() throws Exception {
210         if (!mShouldTestTelecom) return;
211 
212         // ensure the test starts without any phone accounts registered to the test package
213         cleanupPhoneAccounts();
214 
215         // Create MAX_PHONE_ACCOUNT_REGISTRATIONS + 1
216         ArrayList<PhoneAccount> accounts = new ArrayList<>();
217         for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS + 1; i++) {
218             accounts.add(new PhoneAccount.Builder(
219                     TestUtils.makePhoneAccountHandle(Integer.toString(i)),
220                     TestUtils.ACCOUNT_LABEL)
221                     .setCapabilities(CAPABILITY_CALL_PROVIDER)
222                     .build());
223         }
224 
225         try {
226             // Try to register more phone accounts than allowed by the upper bound limit
227             for (PhoneAccount pa : accounts) {
228                 mTelecomManager.registerPhoneAccount(pa);
229                 // verify the account is both registered and disabled
230                 verifyAccountIsDisabled(pa);
231             }
232             // A successful test should never reach this line of execution.
233             // However, if it does, fail the test by throwing a fail(...)
234             fail("Test failed. The test did not throw an IllegalArgumentException when "
235                     + "registering phone accounts over the upper bound: "
236                     + "MAX_PHONE_ACCOUNT_REGISTRATIONS");
237         } catch (IllegalArgumentException e) {
238             // Assert the IllegalArgumentException was thrown
239             assertNotNull(e.toString());
240         } finally {
241             // Cleanup accounts registered
242             accounts.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount(
243                     d.getAccountHandle()));
244         }
245     }
246 
247     /**
248      * Test scenario where two distinct packages register MAX_PHONE_ACCOUNT_REGISTRATIONS via
249      * {@link
250      * android.telecom.TelecomManager#registerPhoneAccount(PhoneAccount)} without an exception being
251      * thrown.
252      * This ensures that PhoneAccountRegistrar is handling {@link PhoneAccount} registrations
253      * to distinct packages correctly.
254      */
testTwoPackagesRegisterMax()255     public void testTwoPackagesRegisterMax() throws Exception {
256         if (!mShouldTestTelecom) return;
257 
258         // ensure the test starts without any phone accounts registered to the test package
259         cleanupPhoneAccounts();
260 
261         //  determine the number of phone accounts that can be registered to package 1
262         int numberOfAccountsThatCanBeRegisteredToPackage1 = MAX_PHONE_ACCOUNT_REGISTRATIONS
263                 - getNumberOfPhoneAccountsRegisteredToTestPackage();
264 
265         // Create MAX phone accounts for package 1
266         ArrayList<PhoneAccount> accountsPackage1 = TestUtils.generateRandomPhoneAccounts(SEED,
267                 numberOfAccountsThatCanBeRegisteredToPackage1, TestUtils.PACKAGE,
268                 TestUtils.COMPONENT);
269 
270         // Constants for creating a second package to register phone accounts
271         final String carPkgSelfManaged =
272                 CtsCarModeInCallServiceControlSelfManaged.class
273                         .getPackage().getName();
274         final ComponentName carComponentSelfManaged = ComponentName.createRelative(
275                 carPkgSelfManaged, CtsCarModeInCallServiceControlSelfManaged.class.getName());
276         final String carModeControl =
277                 "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL";
278 
279         // Set up binding for second package. This is needed in order to bypass a SecurityException
280         // thrown by a second test package registering phone accounts.
281         TestServiceConnection control = setUpControl(carModeControl,
282                 carComponentSelfManaged);
283 
284         ICtsCarModeInCallServiceControl carModeIncallServiceControlSelfManaged =
285                 ICtsCarModeInCallServiceControl.Stub
286                         .asInterface(control.getService());
287 
288         carModeIncallServiceControlSelfManaged.reset(); //... done setting up binding
289 
290         // Create MAX phone accounts for package 2
291         ArrayList<PhoneAccount> accountsPackage2 = TestUtils.generateRandomPhoneAccounts(SEED,
292                 MAX_PHONE_ACCOUNT_REGISTRATIONS, carPkgSelfManaged,
293                 TestUtils.SELF_MANAGED_COMPONENT);
294 
295         try {
296 
297             // register all accounts for package 1
298             accountsPackage1.stream().forEach(a -> mTelecomManager.registerPhoneAccount(a));
299 
300 
301             // register all phone accounts for package 2
302             for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS; i++) {
303                 carModeIncallServiceControlSelfManaged.registerPhoneAccount(
304                         accountsPackage2.get(i));
305             }
306 
307         } finally {
308             // cleanup all phone accounts registered. Note, unregisterPhoneAccount will not
309             // cause a runtime error if no phone account is found when trying to unregister.
310 
311             accountsPackage1.stream().forEach(d -> mTelecomManager.unregisterPhoneAccount(
312                     d.getAccountHandle()));
313 
314             for (int i = 0; i < MAX_PHONE_ACCOUNT_REGISTRATIONS; i++) {
315                 carModeIncallServiceControlSelfManaged.unregisterPhoneAccount(
316                         accountsPackage2.get(i).getAccountHandle());
317             }
318         }
319         // unbind from second package
320         mContext.unbindService(control);
321     }
322 
323     /**
324      * Test the scenario where {@link android.telecom.TelecomManager
325      * #getCallCapablePhoneAccounts(boolean)} is called with a heavy payload
326      * that could cause a {@link android.os.TransactionTooLargeException}.  Telecom is expected to
327      * handle this by splitting the parcels via {@link android.content.pm.ParceledListSlice}.
328      */
testGettingLargeCallCapablePhoneAccountHandlePayload()329     public void testGettingLargeCallCapablePhoneAccountHandlePayload() throws Exception {
330         if (!mShouldTestTelecom) return;
331         // ensure the test starts without any phone accounts registered to the test package
332         cleanupPhoneAccounts();
333 
334         // generate a large phoneAccountHandle id string to create a large payload
335         String largeAccountHandleId = generateLargeString(
336                 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
337         assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
338 
339         // create handles for package 1
340         List<PhoneAccount> phoneAccountsForPackage1 =
341                 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
342                         numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_CALL_PROVIDER);
343 
344         //create handles for package 2
345         List<PhoneAccount> phoneAccountsForPackage2 =
346                 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
347                         MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_CALL_PROVIDER);
348         try {
349             // register all accounts for package 1
350             phoneAccountsForPackage1.stream()
351                     .forEach(a -> mTelecomManager.registerPhoneAccount(a));
352             // verify all can be fetched
353             verifyCanFetchCallCapableAccounts();
354             // register all accounts for package 2
355             bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
356             // verify all can be fetched
357             verifyCanFetchCallCapableAccounts();
358         } catch (IllegalArgumentException e) {
359             // allow test pass ...
360             Log.i(TAG, "testGettingLargeCallCapablePhoneAccountHandlePayload:"
361                     + " illegal arg exception thrown.");
362         } finally {
363             unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
364             cleanupPhoneAccounts();
365         }
366     }
367 
368     /**
369      * Test the scenario where {@link android.telecom.TelecomManager#getSelfManagedPhoneAccounts()}
370      * is called with a heavy payload that could cause a {@link
371      * android.os.TransactionTooLargeException}.  Telecom is expected to handle this by splitting
372      * the parcels via {@link android.content.pm.ParceledListSlice}.
373      */
testGettingLargeSelfManagedPhoneAccountHandlePayload()374     public void testGettingLargeSelfManagedPhoneAccountHandlePayload() throws Exception {
375         if (!mShouldTestTelecom) return;
376         // ensure the test starts without any phone accounts registered to the test package
377         cleanupPhoneAccounts();
378 
379         // generate a large phoneAccountHandle id string to create a large payload
380         String largeAccountHandleId = generateLargeString(
381                 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
382         assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
383 
384         // create handles for package 1
385         List<PhoneAccount> phoneAccountsForPackage1 =
386                 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
387                         numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED);
388 
389         //create handles for package 2
390         List<PhoneAccount> phoneAccountsForPackage2 =
391                 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
392                         MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED);
393         try {
394             // register all accounts for package 1
395             phoneAccountsForPackage1.stream()
396                     .forEach(a -> mTelecomManager.registerPhoneAccount(a));
397             // verify all can be fetched
398             verifyCanFetchSelfManagedPhoneAccounts();
399             // register all accounts for package 2
400             bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
401             // verify all can be fetched
402             verifyCanFetchSelfManagedPhoneAccounts();
403         } catch (IllegalArgumentException e) {
404             // allow test pass ...
405             Log.i(TAG, "testGettingLargeSelfManagedPhoneAccountHandlePayload:"
406                     + " illegal arg exception thrown.");
407         } finally {
408             unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
409             cleanupPhoneAccounts();
410         }
411     }
412 
413     /**
414      * Test the scenario where {@link android.telecom.TelecomManager#getAllPhoneAccountHandles()}
415      * is called with a heavy payload that could cause a {@link
416      * android.os.TransactionTooLargeException}.  Telecom is expected to handle this by splitting
417      * the parcels via {@link android.content.pm.ParceledListSlice}.
418      */
testGettingAllPhoneAccountHandlesWithLargePayload()419     public void testGettingAllPhoneAccountHandlesWithLargePayload() throws Exception {
420         if (!mShouldTestTelecom) return;
421 
422         // ensure the test starts without any phone accounts registered to the test package
423         cleanupPhoneAccounts();
424 
425         // generate a large phoneAccountHandle id string to create a large payload
426         String largeAccountHandleId = generateLargeString(
427                 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
428         assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
429 
430         // create handles for package 1
431         List<PhoneAccount> phoneAccountsForPackage1 =
432                 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
433                         numberOfPhoneAccountsCtsPackageCanRegister(), CAPABILITY_SELF_MANAGED);
434 
435         //create handles for package 2
436         List<PhoneAccount> phoneAccountsForPackage2 =
437                 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
438                         MAX_PHONE_ACCOUNT_REGISTRATIONS, CAPABILITY_SELF_MANAGED);
439         try {
440             // register all accounts for package 1
441             phoneAccountsForPackage1.stream()
442                     .forEach(a -> mTelecomManager.registerPhoneAccount(a));
443             // verify all can be fetched
444             verifyCanFetchAllPhoneAccountHandles();
445             // register all accounts for package 2
446             bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
447             // verify all can be fetched
448             verifyCanFetchAllPhoneAccountHandles();
449         } catch (IllegalArgumentException e) {
450             // allow test pass ...
451         } finally {
452 
453             unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
454             cleanupPhoneAccounts();
455         }
456     }
457 
458     /**
459      * Test the scenario where {@link TelecomManager#getAllPhoneAccounts()}
460      * is called with a heavy payload that could cause a {@link
461      * android.os.TransactionTooLargeException}.  Telecom is expected to handle this by splitting
462      * the parcels via {@link android.content.pm.ParceledListSlice}.
463      */
testGetAllPhoneAccountsWithLargePayload()464     public void testGetAllPhoneAccountsWithLargePayload() throws Exception {
465         if (!mShouldTestTelecom) return;
466 
467         // ensure the test starts without any phone accounts registered to the test package
468         cleanupPhoneAccounts();
469 
470         // generate a large phoneAccountHandle id string to create a large payload
471         String largeAccountHandleId = generateLargeString(
472                 LARGE_ACCT_HANDLE_ID_MIN_SIZE, RANDOM_CHAR_VALUE);
473         assertEquals(LARGE_ACCT_HANDLE_ID_MIN_SIZE, largeAccountHandleId.length());
474 
475         // create handles for package 1
476         List<PhoneAccount> phoneAccountsForPackage1 =
477                 generatePhoneAccountsForPackage(TEST_COMPONENT_NAME, largeAccountHandleId,
478                         numberOfPhoneAccountsCtsPackageCanRegister(),
479                         CAPABILITY_CALL_PROVIDER
480                                 | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
481 
482         //create handles for package 2
483         List<PhoneAccount> phoneAccountsForPackage2 =
484                 generatePhoneAccountsForPackage(CAR_COMPONENT, largeAccountHandleId,
485                         MAX_PHONE_ACCOUNT_REGISTRATIONS,
486                         CAPABILITY_SELF_MANAGED);
487         try {
488             // register all accounts for package 1
489             for (PhoneAccount pa : phoneAccountsForPackage1) {
490                 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelecomManager,
491                         tm -> tm.registerPhoneAccount(pa), REGISTER_SIM_SUBSCRIPTION_PERMISSION);
492             }
493             // verify all can be fetched
494             verifyCanFetchAllPhoneAccounts();
495             // register all accounts for package 2
496             bindToSecondTestPackageAndRegisterAccounts(phoneAccountsForPackage2);
497             // verify all can be fetched
498             verifyCanFetchAllPhoneAccounts();
499         } catch (IllegalArgumentException e) {
500             // allow test pass ...
501         } finally {
502             unbindSecondTestPackageAndUnregisterAccounts(phoneAccountsForPackage2);
503             cleanupPhoneAccounts();
504         }
505     }
506 
507     // -- The following are helper methods for this testing class. --
508 
generateLargeString(int size, String repeatStrValue)509     private String generateLargeString(int size, String repeatStrValue) {
510         StringBuilder sb = new StringBuilder();
511         for (int i = 0; i < size; i++) {
512             sb.append(repeatStrValue);
513         }
514         return sb.toString();
515     }
516 
generatePhoneAccountsForPackage(ComponentName cn, String baseId, int numOfAccountsToRegister, int capabilities)517     private List<PhoneAccount> generatePhoneAccountsForPackage(ComponentName cn, String baseId,
518             int numOfAccountsToRegister, int capabilities) {
519         List<PhoneAccount> accounts = new ArrayList<>();
520 
521         for (int i = 0; i < numOfAccountsToRegister; i++) {
522             String id = baseId + i;
523             PhoneAccountHandle pah = new PhoneAccountHandle(cn, id);
524             // create phoneAccount
525             String number = TEL_PREFIX + i;
526             PhoneAccount pa = PhoneAccount.builder(pah, TestUtils.ACCOUNT_LABEL)
527                     .setAddress(Uri.parse(number))
528                     .setSubscriptionAddress(Uri.parse(number))
529                     .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
530                     .setCapabilities(capabilities)
531                     .build();
532             accounts.add(pa);
533         }
534         return accounts;
535     }
536 
bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts)537     public void bindToSecondTestPackageAndRegisterAccounts(List<PhoneAccount> accounts)
538             throws Exception {
539         bindToSecondTestPackage();
540         registerAccountsToSecondTestPackage(accounts);
541     }
542 
unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts)543     public void unbindSecondTestPackageAndUnregisterAccounts(List<PhoneAccount> accounts) {
544         try {
545             mContext.unbindService(mControl);
546             unRegisterAccountsForSecondTestPackage(accounts);
547         } catch (Exception e) {
548             Log.d(TAG,
549                     "exception thrown while trying to unbind and unregister accts for 2nd package");
550         }
551     }
552 
bindToSecondTestPackage()553     public void bindToSecondTestPackage() throws RemoteException {
554         // Set up binding for second package. This is needed in order to bypass a SecurityException
555         // thrown by a second test package registering phone accounts.
556         mControl = setUpControl(CAR_MODE_CONTROL, SELF_MANAGED_CAR_RELATIVE_COMPONENT);
557         mSecondaryTestPackageControl =
558                 ICtsCarModeInCallServiceControl.Stub.asInterface(mControl.getService());
559         // reset all package variables etc.
560         if (mSecondaryTestPackageControl != null) {
561             mSecondaryTestPackageControl.reset(); //... done setting up binding
562         }
563     }
564 
registerAccountsToSecondTestPackage(List<PhoneAccount> accounts)565     public void registerAccountsToSecondTestPackage(List<PhoneAccount> accounts)
566             throws Exception {
567         if (mSecondaryTestPackageControl != null) {
568             for (PhoneAccount p : accounts) {
569                 mSecondaryTestPackageControl.registerPhoneAccount(p);
570                 TestUtils.enablePhoneAccount(getInstrumentation(), p.getAccountHandle());
571             }
572         }
573     }
574 
unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts)575     public void unRegisterAccountsForSecondTestPackage(List<PhoneAccount> accounts)
576             throws RemoteException {
577         if (mSecondaryTestPackageControl != null) {
578             for (PhoneAccount p : accounts) {
579                 mSecondaryTestPackageControl.unregisterPhoneAccount(p.getAccountHandle());
580             }
581         }
582     }
583 
verifyAccountIsDisabled(PhoneAccount account)584     public void verifyAccountIsDisabled(PhoneAccount account) {
585         PhoneAccount phoneAccount = mTelecomManager.getPhoneAccount(account.getAccountHandle());
586         assertNotNull(phoneAccount);
587         assertFalse(phoneAccount.isEnabled());
588     }
589 
verifyCanFetchCallCapableAccounts()590     public void verifyCanFetchCallCapableAccounts() {
591         List<PhoneAccountHandle> res =
592                 mTelecomManager.getCallCapablePhoneAccounts(true);
593         assertNotNull(res);
594         assertTrue(res.size() > 0);
595     }
596 
verifyCanFetchAllPhoneAccountHandles()597     public void verifyCanFetchAllPhoneAccountHandles() {
598         List<PhoneAccountHandle> res =
599                 ShellIdentityUtils.invokeMethodWithShellPermissions(
600                         mTelecomManager, (tm) -> tm.getAllPhoneAccountHandles(),
601                         MODIFY_PHONE_STATE_PERMISSION);
602         assertNotNull(res);
603         assertTrue(res.size() > 0);
604     }
605 
verifyCanFetchAllPhoneAccounts()606     public void verifyCanFetchAllPhoneAccounts() {
607         List<PhoneAccount> res =
608                 ShellIdentityUtils.invokeMethodWithShellPermissions(
609                         mTelecomManager, (tm) -> tm.getAllPhoneAccounts(),
610                         MODIFY_PHONE_STATE_PERMISSION);
611         assertNotNull(res);
612         assertTrue(res.size() > 0);
613     }
614 
verifyCanFetchSelfManagedPhoneAccounts()615     public void verifyCanFetchSelfManagedPhoneAccounts() {
616         List<PhoneAccountHandle> res =
617                 mTelecomManager.getSelfManagedPhoneAccounts();
618         assertNotNull(res);
619         assertTrue(res.size() > 0);
620     }
621 
numberOfPhoneAccountsCtsPackageCanRegister()622     private int numberOfPhoneAccountsCtsPackageCanRegister() {
623         return MAX_PHONE_ACCOUNT_REGISTRATIONS - getNumberOfPhoneAccountsRegisteredToTestPackage();
624     }
625 
setUpControl(String action, ComponentName componentName)626     private TestServiceConnection setUpControl(String action, ComponentName componentName) {
627         Intent bindIntent = new Intent(action);
628         bindIntent.setComponent(componentName);
629 
630         TestServiceConnection
631                 serviceConnection = new TestServiceConnection();
632         mContext.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
633         if (!serviceConnection.waitBind()) {
634             fail("fail bind to service");
635         }
636         return serviceConnection;
637     }
638 
639     private class TestServiceConnection implements ServiceConnection {
640         private IBinder mService;
641         private CountDownLatch mLatch = new CountDownLatch(1);
642         private boolean mIsConnected;
643 
644         @Override
onServiceConnected(ComponentName componentName, IBinder service)645         public void onServiceConnected(ComponentName componentName, IBinder service) {
646             Log.i(TAG, "Service Connected: " + componentName);
647             mService = service;
648             mIsConnected = true;
649             mLatch.countDown();
650         }
651 
652         @Override
onServiceDisconnected(ComponentName componentName)653         public void onServiceDisconnected(ComponentName componentName) {
654             mService = null;
655         }
656 
getService()657         public IBinder getService() {
658             return mService;
659         }
660 
waitBind()661         public boolean waitBind() {
662             try {
663                 mLatch.await(TIMEOUT, TimeUnit.MILLISECONDS);
664                 return mIsConnected;
665             } catch (InterruptedException e) {
666                 return false;
667             }
668         }
669     }
670 
671     /**
672      * Helper that cleans up any phone accounts registered to this testing package.  Requires
673      * the permission READ_PRIVILEGED_PHONE_STATE in order to invoke the
674      * getPhoneAccountsForPackage() method.
675      */
cleanupPhoneAccounts()676     private void cleanupPhoneAccounts() {
677         try {
678             if (mTelecomManager != null) {
679                 // Get all handles registered to the testing package
680                 List<PhoneAccountHandle> handles =
681                         ShellIdentityUtils.invokeMethodWithShellPermissions(mTelecomManager,
682                                 (tm) -> tm.getPhoneAccountsForPackage(),
683                                 READ_PRIVILEGED_PHONE_STATE);
684 
685                 // cleanup any extra phone accounts registered to the testing package
686                 if (handles.size() > 0 && mTelecomManager != null) {
687                     handles.stream().forEach(
688                             d -> mTelecomManager.unregisterPhoneAccount(d));
689                 }
690 
691                 TestUtils.executeShellCommand(getInstrumentation(), TELECOM_CLEANUP_ACCTS_CMD);
692             }
693         } catch (Exception e) {
694             Log.d(TAG, "cleanupPhoneAccounts: hit exception while trying to clean");
695         }
696     }
697 
698     /**
699      * Helper that gets the number of phone accounts registered to the testing package. Requires
700      * the permission READ_PRIVILEGED_PHONE_STATE in order to invoke the
701      * getPhoneAccountsForPackage() method.
702      * @return number of phone accounts registered to the testing package.
703      */
getNumberOfPhoneAccountsRegisteredToTestPackage()704     private int getNumberOfPhoneAccountsRegisteredToTestPackage() {
705         if (mTelecomManager != null) {
706             return ShellIdentityUtils.invokeMethodWithShellPermissions(mTelecomManager,
707                     (tm) -> tm.getPhoneAccountsForPackage(),
708                     READ_PRIVILEGED_PHONE_STATE).size();
709         }
710         return 0;
711     }
712 }
713 
714