1 /*
2  * Copyright (C) 2015 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.telephony.cts;
18 
19 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
20 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
21 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
22 import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
23 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
24 import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
25 
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNotEquals;
29 import static org.junit.Assert.assertNotNull;
30 import static org.junit.Assert.assertNull;
31 import static org.junit.Assert.assertTrue;
32 import static org.junit.Assert.fail;
33 
34 import android.annotation.Nullable;
35 import android.app.UiAutomation;
36 import android.content.pm.PackageManager;
37 import android.content.res.Resources;
38 import android.net.ConnectivityManager;
39 import android.net.ConnectivityManager.NetworkCallback;
40 import android.net.Network;
41 import android.net.NetworkCapabilities;
42 import android.net.NetworkRequest;
43 import android.net.Uri;
44 import android.os.Looper;
45 import android.os.ParcelUuid;
46 import android.os.PersistableBundle;
47 import android.telephony.CarrierConfigManager;
48 import android.telephony.SubscriptionInfo;
49 import android.telephony.SubscriptionManager;
50 import android.telephony.SubscriptionPlan;
51 import android.telephony.TelephonyManager;
52 import android.telephony.ims.ImsException;
53 import android.telephony.ims.ImsManager;
54 import android.telephony.ims.ImsMmTelManager;
55 import android.telephony.ims.ImsRcsManager;
56 import android.telephony.ims.RcsUceAdapter;
57 import android.util.Log;
58 
59 import androidx.test.InstrumentationRegistry;
60 
61 import com.android.compatibility.common.util.ShellIdentityUtils;
62 import com.android.compatibility.common.util.SystemUtil;
63 import com.android.compatibility.common.util.TestThread;
64 import com.android.internal.util.ArrayUtils;
65 
66 import org.junit.AfterClass;
67 import org.junit.Before;
68 import org.junit.BeforeClass;
69 import org.junit.Test;
70 
71 import java.io.ByteArrayInputStream;
72 import java.io.IOException;
73 import java.time.Period;
74 import java.time.ZonedDateTime;
75 import java.util.ArrayList;
76 import java.util.Arrays;
77 import java.util.List;
78 import java.util.UUID;
79 import java.util.concurrent.CountDownLatch;
80 import java.util.concurrent.Executor;
81 import java.util.concurrent.LinkedBlockingQueue;
82 import java.util.concurrent.TimeUnit;
83 import java.util.concurrent.atomic.AtomicBoolean;
84 import java.util.function.Consumer;
85 import java.util.function.Predicate;
86 import java.util.stream.Collectors;
87 
88 
89 public class SubscriptionManagerTest {
90     private static final String TAG = "SubscriptionManagerTest";
91     private static final String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
92     private SubscriptionManager mSm;
93     private static final List<Uri> CONTACTS = new ArrayList<>();
94     static {
95         CONTACTS.add(Uri.fromParts("tel", "+16505551212", null));
96         CONTACTS.add(Uri.fromParts("tel", "+16505552323", null));
97     }
98 
99     private int mSubId;
100     private String mPackageName;
101 
102     /**
103      * Callback used in testRegisterNetworkCallback that allows caller to block on
104      * {@code onAvailable}.
105      */
106     private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
107         private final CountDownLatch mAvailableLatch = new CountDownLatch(1);
108 
waitForAvailable()109         public void waitForAvailable() throws InterruptedException {
110             assertTrue("Cellular network did not come up after 5 seconds",
111                     mAvailableLatch.await(5, TimeUnit.SECONDS));
112         }
113 
114         @Override
onAvailable(Network network)115         public void onAvailable(Network network) {
116             mAvailableLatch.countDown();
117         }
118     }
119 
120     @BeforeClass
setUpClass()121     public static void setUpClass() throws Exception {
122         if (!isSupported()) return;
123 
124         final TestNetworkCallback callback = new TestNetworkCallback();
125         final ConnectivityManager cm = InstrumentationRegistry.getContext()
126                 .getSystemService(ConnectivityManager.class);
127         cm.registerNetworkCallback(new NetworkRequest.Builder()
128                 .addTransportType(TRANSPORT_CELLULAR)
129                 .addCapability(NET_CAPABILITY_INTERNET)
130                 .build(), callback);
131         try {
132             // Wait to get callback for availability of internet
133             callback.waitForAvailable();
134         } catch (InterruptedException e) {
135             fail("NetworkCallback wait was interrupted.");
136         } finally {
137             cm.unregisterNetworkCallback(callback);
138         }
139     }
140 
141     @AfterClass
tearDownClass()142     public static void tearDownClass() throws Exception {
143         if (!isSupported()) return;
144         TelephonyUtils.flushTelephonyMetrics(InstrumentationRegistry.getInstrumentation());
145     }
146 
147     @Before
setUp()148     public void setUp() throws Exception {
149         if (!isSupported()) return;
150 
151         mSm = InstrumentationRegistry.getContext().getSystemService(SubscriptionManager.class);
152         mSubId = SubscriptionManager.getDefaultDataSubscriptionId();
153         mPackageName = InstrumentationRegistry.getContext().getPackageName();
154     }
155 
156     /**
157      * Correctness check that both {@link PackageManager#FEATURE_TELEPHONY} and
158      * {@link NetworkCapabilities#TRANSPORT_CELLULAR} network must both be
159      * either defined or undefined; you can't cross the streams.
160      */
161     @Test
testCorrectness()162     public void testCorrectness() throws Exception {
163         if (!isSupported()) return;
164 
165         final boolean hasCellular = findCellularNetwork() != null;
166         if (isSupported() && !hasCellular) {
167             fail("Device claims to support " + PackageManager.FEATURE_TELEPHONY
168                     + " but has no active cellular network, which is required for validation");
169         } else if (!isSupported() && hasCellular) {
170             fail("Device has active cellular network, but claims to not support "
171                     + PackageManager.FEATURE_TELEPHONY);
172         }
173 
174         if (isSupported()) {
175             if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
176                 fail("Device must have a valid default data subId for validation");
177             }
178         }
179     }
180 
181     @Test
testGetActiveSubscriptionInfoCount()182     public void testGetActiveSubscriptionInfoCount() throws Exception {
183         if (!isSupported()) return;
184         assertTrue(mSm.getActiveSubscriptionInfoCount() <=
185                 mSm.getActiveSubscriptionInfoCountMax());
186     }
187 
188     @Test
testGetActiveSubscriptionInfoForIcc()189     public void testGetActiveSubscriptionInfoForIcc() throws Exception {
190         if (!isSupported()) return;
191         SubscriptionInfo info = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
192                 (sm) -> sm.getActiveSubscriptionInfo(mSubId));
193         assertNotNull(ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
194                 (sm) -> sm.getActiveSubscriptionInfoForIcc(info.getIccId())));
195     }
196 
197     @Test
testIsActiveSubscriptionId()198     public void testIsActiveSubscriptionId() throws Exception {
199         if (!isSupported()) return;
200         assertTrue(mSm.isActiveSubscriptionId(mSubId));
201     }
202 
203     @Test
testGetSubscriptionIds()204     public void testGetSubscriptionIds() throws Exception {
205         if (!isSupported()) return;
206         int slotId = SubscriptionManager.getSlotIndex(mSubId);
207         int[] subIds = mSm.getSubscriptionIds(slotId);
208         assertNotNull(subIds);
209         assertTrue(ArrayUtils.contains(subIds, mSubId));
210     }
211 
212     @Test
testGetResourcesForSubId()213     public void testGetResourcesForSubId() {
214         if (!isSupported()) return;
215         Resources r = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
216                 (sm) -> sm.getResourcesForSubId(InstrumentationRegistry.getContext(), mSubId));
217         // this is an old method which returns mcc/mnc as ints, so use the old SM.getMcc/Mnc methods
218         // because they also use ints
219         assertEquals(mSm.getActiveSubscriptionInfo(mSubId).getMcc(), r.getConfiguration().mcc);
220         assertEquals(mSm.getActiveSubscriptionInfo(mSubId).getMnc(), r.getConfiguration().mnc);
221     }
222 
223     @Test
testIsUsableSubscriptionId()224     public void testIsUsableSubscriptionId() throws Exception {
225         if (!isSupported()) return;
226         assertTrue(SubscriptionManager.isUsableSubscriptionId(mSubId));
227     }
228 
229     @Test
testActiveSubscriptions()230     public void testActiveSubscriptions() throws Exception {
231         if (!isSupported()) return;
232 
233         List<SubscriptionInfo> subList = mSm.getActiveSubscriptionInfoList();
234         int[] idList = mSm.getActiveSubscriptionIdList();
235         // Assert when there is no sim card present or detected
236         assertNotNull("Active subscriber required", subList);
237         assertNotNull("Active subscriber required", idList);
238         assertFalse("Active subscriber required", subList.isEmpty());
239         assertNotEquals("Active subscriber required", 0, idList.length);
240         for (int i = 0; i < subList.size(); i++) {
241             assertTrue(subList.get(i).getSubscriptionId() >= 0);
242             assertTrue(subList.get(i).getSimSlotIndex() >= 0);
243             assertTrue(ArrayUtils.contains(idList, subList.get(i).getSubscriptionId()));
244             if (i >= 1) {
245                 assertTrue(subList.get(i - 1).getSimSlotIndex()
246                         <= subList.get(i).getSimSlotIndex());
247                 assertTrue(subList.get(i - 1).getSimSlotIndex() < subList.get(i).getSimSlotIndex()
248                         || subList.get(i - 1).getSubscriptionId()
249                         < subList.get(i).getSubscriptionId());
250             }
251         }
252     }
253 
254     @Test
255     public void testSubscriptionPlans() throws Exception {
256         if (!isSupported()) return;
257 
258         // Make ourselves the owner
259         setSubPlanOwner(mSubId, mPackageName);
260 
261         // Push empty list and we get empty back
262         mSm.setSubscriptionPlans(mSubId, Arrays.asList());
263         assertEquals(Arrays.asList(), mSm.getSubscriptionPlans(mSubId));
264 
265         // Push simple plan and get it back
266         final SubscriptionPlan plan = buildValidSubscriptionPlan(System.currentTimeMillis());
267         mSm.setSubscriptionPlans(mSubId, Arrays.asList(plan));
268         assertEquals(Arrays.asList(plan), mSm.getSubscriptionPlans(mSubId));
269 
270         // Now revoke our access
271         setSubPlanOwner(mSubId, null);
272         try {
273             mSm.setSubscriptionPlans(mSubId, Arrays.asList());
274             fail();
275         } catch (SecurityException expected) {
276         }
277         try {
278             mSm.getSubscriptionPlans(mSubId);
279             fail();
280         } catch (SecurityException expected) {
281         }
282     }
283 
284     @Test
285     public void testSubscriptionPlansOverrideCongested() throws Exception {
286         if (!isSupported()) return;
287 
288         final ConnectivityManager cm = InstrumentationRegistry.getContext()
289                 .getSystemService(ConnectivityManager.class);
290         final Network net = findCellularNetwork();
291         assertNotNull("Active cellular network required", net);
292 
293         // Make ourselves the owner
294         setSubPlanOwner(mSubId, mPackageName);
295 
296         // Missing plans means no overrides
297         mSm.setSubscriptionPlans(mSubId, Arrays.asList());
298         try {
299             mSm.setSubscriptionOverrideCongested(mSubId, true, 0);
300             fail();
301         } catch (SecurityException | IllegalStateException expected) {
302         }
303 
304         // Defining plans means we get to override
305         mSm.setSubscriptionPlans(mSubId,
306                 Arrays.asList(buildValidSubscriptionPlan(System.currentTimeMillis())));
307 
308         // Cellular is uncongested by default
309         assertTrue(cm.getNetworkCapabilities(net).hasCapability(NET_CAPABILITY_NOT_CONGESTED));
310 
311         // Override should make it go congested
312         {
313             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
314                 return !caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
315             });
316             mSm.setSubscriptionOverrideCongested(
317                     mSubId, true, TelephonyManager.getAllNetworkTypes(), 0);
318             assertTrue(latch.await(10, TimeUnit.SECONDS));
319         }
320 
321         // Clearing override should make it go uncongested
322         {
323             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
324                 return caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
325             });
326             mSm.setSubscriptionOverrideCongested(mSubId, false, 0);
327             assertTrue(latch.await(10, TimeUnit.SECONDS));
328         }
329 
330         // Now revoke our access
331         setSubPlanOwner(mSubId, null);
332         try {
333             mSm.setSubscriptionOverrideCongested(
334                     mSubId, true, TelephonyManager.getAllNetworkTypes(), 0);
335             fail();
336         } catch (SecurityException | IllegalStateException expected) {
337         }
338     }
339 
340     @Test
testSetDefaultVoiceSubId()341     public void testSetDefaultVoiceSubId() {
342         if (!isSupported()) return;
343 
344         int oldSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
345         InstrumentationRegistry.getInstrumentation().getUiAutomation()
346                 .adoptShellPermissionIdentity();
347         try {
348             mSm.setDefaultVoiceSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
349             assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
350                     SubscriptionManager.getDefaultVoiceSubscriptionId());
351             mSm.setDefaultVoiceSubscriptionId(oldSubId);
352             assertEquals(oldSubId, SubscriptionManager.getDefaultVoiceSubscriptionId());
353         } finally {
354             InstrumentationRegistry.getInstrumentation().getUiAutomation()
355                     .dropShellPermissionIdentity();
356         }
357     }
358 
359     @Test
testSubscriptionPlansOverrideUnmetered()360     public void testSubscriptionPlansOverrideUnmetered() throws Exception {
361         if (!isSupported()) return;
362 
363         final ConnectivityManager cm = InstrumentationRegistry.getContext()
364                 .getSystemService(ConnectivityManager.class);
365         final Network net = findCellularNetwork();
366         assertNotNull("Active cellular network required", net);
367 
368         // TODO: Remove this check after b/176119724 is fixed.
369         if (!isUnmetered5GSupported()) return;
370 
371         // Cellular is metered by default
372         assertFalse(cm.getNetworkCapabilities(net).hasCapability(
373                 NET_CAPABILITY_TEMPORARILY_NOT_METERED));
374 
375         // Override should make it go temporarily unmetered
376         {
377             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
378                 return caps.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
379             });
380             mSm.setSubscriptionOverrideUnmetered(
381                     mSubId, true, TelephonyManager.getAllNetworkTypes(), 0);
382             assertTrue(latch.await(10, TimeUnit.SECONDS));
383         }
384 
385         // Clearing override should make it go metered
386         {
387             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
388                 return !caps.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
389             });
390             mSm.setSubscriptionOverrideUnmetered(
391                     mSubId, false, TelephonyManager.getAllNetworkTypes(), 0);
392             assertTrue(latch.await(10, TimeUnit.SECONDS));
393         }
394     }
395 
396     @Test
testSubscriptionPlansUnmetered()397     public void testSubscriptionPlansUnmetered() throws Exception {
398         if (!isSupported()) return;
399 
400         final ConnectivityManager cm = InstrumentationRegistry.getContext()
401                 .getSystemService(ConnectivityManager.class);
402         final Network net = findCellularNetwork();
403         assertNotNull("Active cellular network required", net);
404 
405         // TODO: Remove this check after b/176119724 is fixed.
406         if (!isUnmetered5GSupported()) return;
407 
408         // Make ourselves the owner and define some plans
409         setSubPlanOwner(mSubId, mPackageName);
410         mSm.setSubscriptionPlans(mSubId,
411                 Arrays.asList(buildValidSubscriptionPlan(System.currentTimeMillis())));
412 
413         // Cellular is metered by default
414         assertFalse(cm.getNetworkCapabilities(net).hasCapability(
415                 NET_CAPABILITY_TEMPORARILY_NOT_METERED));
416 
417         SubscriptionPlan unmeteredPlan = SubscriptionPlan.Builder
418                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
419                         Period.ofMonths(1))
420                 .setTitle("CTS")
421                 .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
422                         SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
423                 .build();
424 
425         // Unmetered plan should make it go unmetered
426         {
427             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
428                 return caps.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
429             });
430             mSm.setSubscriptionPlans(mSubId, Arrays.asList(unmeteredPlan));
431             assertTrue(latch.await(10, TimeUnit.SECONDS));
432         }
433 
434         // Metered plan should make it go metered
435         {
436             final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> {
437                 return !caps.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
438             });
439             mSm.setSubscriptionPlans(mSubId,
440                     Arrays.asList(buildValidSubscriptionPlan(System.currentTimeMillis())));
441             assertTrue(latch.await(10, TimeUnit.SECONDS));
442         }
443     }
444 
445     @Test
testSubscriptionPlansInvalid()446     public void testSubscriptionPlansInvalid() throws Exception {
447         if (!isSupported()) return;
448 
449         // Make ourselves the owner
450         setSubPlanOwner(mSubId, mPackageName);
451 
452         // Empty plans can't override
453         assertOverrideFails();
454 
455         // Nonrecurring plan in the past can't override
456         assertOverrideFails(SubscriptionPlan.Builder
457                 .createNonrecurring(ZonedDateTime.now().minusDays(14),
458                         ZonedDateTime.now().minusDays(7))
459                 .setTitle("CTS")
460                 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
461                 .build());
462 
463         // Plan with undefined limit can't override
464         assertOverrideFails(SubscriptionPlan.Builder
465                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
466                         Period.ofMonths(1))
467                 .setTitle("CTS")
468                 .build());
469 
470         // We can override when there is an active plan somewhere
471         final SubscriptionPlan older = SubscriptionPlan.Builder
472                 .createNonrecurring(ZonedDateTime.now().minusDays(14),
473                         ZonedDateTime.now().minusDays(7))
474                 .setTitle("CTS")
475                 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
476                 .build();
477         final SubscriptionPlan newer = SubscriptionPlan.Builder
478                 .createNonrecurring(ZonedDateTime.now().minusDays(7),
479                         ZonedDateTime.now().plusDays(7))
480                 .setTitle("CTS")
481                 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
482                 .build();
483         assertOverrideSuccess(older, newer);
484     }
485 
486     @Test
testSubscriptionPlansNetworkTypeValidation()487     public void testSubscriptionPlansNetworkTypeValidation() throws Exception {
488         if (!isSupported()) return;
489 
490         // Make ourselves the owner
491         setSubPlanOwner(mSubId, mPackageName);
492 
493         // Error when adding 2 plans with the same network type
494         List<SubscriptionPlan> plans = new ArrayList<>();
495         plans.add(buildValidSubscriptionPlan(System.currentTimeMillis()));
496         plans.add(SubscriptionPlan.Builder
497                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
498                         Period.ofMonths(1))
499                 .setTitle("CTS")
500                 .setNetworkTypes(new int[] {TelephonyManager.NETWORK_TYPE_LTE})
501                 .build());
502         plans.add(SubscriptionPlan.Builder
503                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
504                         Period.ofMonths(1))
505                 .setTitle("CTS")
506                 .setNetworkTypes(new int[] {TelephonyManager.NETWORK_TYPE_LTE})
507                 .build());
508         try {
509             mSm.setSubscriptionPlans(mSubId, plans);
510             fail();
511         } catch (IllegalArgumentException expected) {
512         }
513 
514         // Error when there is no general plan
515         plans.clear();
516         plans.add(SubscriptionPlan.Builder
517                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
518                         Period.ofMonths(1))
519                 .setTitle("CTS")
520                 .setNetworkTypes(new int[] {TelephonyManager.NETWORK_TYPE_LTE})
521                 .build());
522         try {
523             mSm.setSubscriptionPlans(mSubId, plans);
524             fail();
525         } catch (IllegalArgumentException expected) {
526         }
527     }
528 
529     @Test
testSubscriptionPlanResetNetworkTypes()530     public void testSubscriptionPlanResetNetworkTypes() {
531         long time = System.currentTimeMillis();
532         SubscriptionPlan plan = SubscriptionPlan.Builder
533                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
534                         Period.ofMonths(1))
535                 .setTitle("CTS")
536                 .setNetworkTypes(new int[] {TelephonyManager.NETWORK_TYPE_LTE})
537                 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
538                 .setDataUsage(500_000_000, time)
539                 .resetNetworkTypes()
540                 .build();
541         assertEquals(plan, buildValidSubscriptionPlan(time));
542     }
543 
544     @Test
testSubscriptionGrouping()545     public void testSubscriptionGrouping() throws Exception {
546         if (!isSupported()) return;
547 
548         // Set subscription group with current sub Id. This should fail
549         // because we don't have MODIFY_PHONE_STATE or carrier privilege permission.
550         List<Integer> subGroup = new ArrayList();
551         subGroup.add(mSubId);
552         try {
553             mSm.createSubscriptionGroup(subGroup);
554             fail();
555         } catch (SecurityException expected) {
556         }
557 
558         // Getting subscriptions in group should return null as setSubscriptionGroup
559         // should fail.
560         SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId);
561         assertNull(info.getGroupUuid());
562 
563         // Remove from subscription group with current sub Id. This should fail
564         // because we don't have MODIFY_PHONE_STATE or carrier privilege permission.
565         try {
566             mSm.addSubscriptionsIntoGroup(subGroup, null);
567             fail();
568         } catch (NullPointerException expected) {
569         }
570 
571         // Add into subscription group that doesn't exist. This should fail
572         // because we don't have MODIFY_PHONE_STATE or carrier privilege permission.
573         try {
574             ParcelUuid groupUuid = new ParcelUuid(UUID.randomUUID());
575             mSm.addSubscriptionsIntoGroup(subGroup, groupUuid);
576             fail();
577         } catch (SecurityException expected) {
578         }
579 
580         // Remove from subscription group with current sub Id. This should fail
581         // because we don't have MODIFY_PHONE_STATE or carrier privilege permission.
582         try {
583             mSm.removeSubscriptionsFromGroup(subGroup, null);
584             fail();
585         } catch (NullPointerException expected) {
586         }
587     }
588 
589     @Test
testSubscriptionGroupingWithPermission()590     public void testSubscriptionGroupingWithPermission() throws Exception {
591         if (!isSupported()) return;
592 
593         // Set subscription group with current sub Id.
594         List<Integer> subGroup = new ArrayList();
595         subGroup.add(mSubId);
596         ParcelUuid uuid = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
597                 (sm) -> sm.createSubscriptionGroup(subGroup));
598 
599         // Getting subscriptions in group.
600         List<SubscriptionInfo> infoList = mSm.getSubscriptionsInGroup(uuid);
601         assertNotNull(infoList);
602         assertEquals(1, infoList.size());
603         assertNull(infoList.get(0).getGroupUuid());
604 
605         infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
606                 (sm) -> sm.getSubscriptionsInGroup(uuid));
607         assertNotNull(infoList);
608         assertEquals(1, infoList.size());
609         assertEquals(uuid, infoList.get(0).getGroupUuid());
610 
611         List<SubscriptionInfo> availableInfoList;
612         try {
613             mSm.getAvailableSubscriptionInfoList();
614             fail("SecurityException should be thrown without READ_PRIVILEGED_PHONE_STATE");
615         } catch (SecurityException ex) {
616             // Ignore
617         }
618         availableInfoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
619                 (sm) -> sm.getAvailableSubscriptionInfoList());
620         if (availableInfoList.size() > 1) {
621             List<Integer> availableSubGroup = availableInfoList.stream()
622                     .map(info -> info.getSubscriptionId())
623                     .filter(subId -> subId != mSubId)
624                     .collect(Collectors.toList());
625 
626             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
627                     (sm) -> sm.addSubscriptionsIntoGroup(availableSubGroup, uuid));
628 
629             infoList = mSm.getSubscriptionsInGroup(uuid);
630             assertNotNull(infoList);
631             assertEquals(availableInfoList.size(), infoList.size());
632 
633             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
634                     (sm) -> sm.removeSubscriptionsFromGroup(availableSubGroup, uuid));
635         }
636 
637         // Remove from subscription group with current sub Id.
638         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
639                 (sm) -> sm.removeSubscriptionsFromGroup(subGroup, uuid));
640 
641         infoList = mSm.getSubscriptionsInGroup(uuid);
642         assertNotNull(infoList);
643         assertTrue(infoList.isEmpty());
644     }
645 
646     @Test
testAddSubscriptionIntoNewGroupWithPermission()647     public void testAddSubscriptionIntoNewGroupWithPermission() throws Exception {
648         if (!isSupported()) return;
649 
650         // Set subscription group with current sub Id.
651         List<Integer> subGroup = new ArrayList();
652         subGroup.add(mSubId);
653         ParcelUuid uuid = new ParcelUuid(UUID.randomUUID());
654         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
655                 (sm) -> sm.addSubscriptionsIntoGroup(subGroup, uuid));
656 
657         // Getting subscriptions in group.
658         List<SubscriptionInfo> infoList = mSm.getSubscriptionsInGroup(uuid);
659         assertNotNull(infoList);
660         assertEquals(1, infoList.size());
661         assertNull(infoList.get(0).getGroupUuid());
662 
663         infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
664                 (sm) -> sm.getSubscriptionsInGroup(uuid));
665         assertNotNull(infoList);
666         assertEquals(1, infoList.size());
667         assertEquals(uuid, infoList.get(0).getGroupUuid());
668 
669         // Remove from subscription group with current sub Id.
670         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
671                 (sm) -> sm.removeSubscriptionsFromGroup(subGroup, uuid));
672 
673         infoList = mSm.getSubscriptionsInGroup(uuid);
674         assertNotNull(infoList);
675         assertTrue(infoList.isEmpty());
676     }
677 
678     @Test
testSettingOpportunisticSubscription()679     public void testSettingOpportunisticSubscription() throws Exception {
680         if (!isSupported()) return;
681 
682         // Set subscription to be opportunistic. This should fail
683         // because we don't have MODIFY_PHONE_STATE or carrier privilege permission.
684         try {
685             mSm.setOpportunistic(true, mSubId);
686             fail();
687         } catch (SecurityException expected) {
688         }
689 
690         // Shouldn't crash.
691         SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId);
692         info.isOpportunistic();
693     }
694 
695     @Test
testMccMncString()696     public void testMccMncString() {
697         if (!isSupported()) return;
698 
699         SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId);
700         String mcc = info.getMccString();
701         String mnc = info.getMncString();
702         assertTrue(mcc == null || mcc.length() <= 3);
703         assertTrue(mnc == null || mnc.length() <= 3);
704     }
705 
706     @Test
testSetUiccApplicationsEnabled()707     public void testSetUiccApplicationsEnabled() {
708         if (!isSupported()) return;
709 
710         boolean canDisable = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
711                 (sm) -> sm.canDisablePhysicalSubscription());
712         if (canDisable) {
713             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
714                     (sm) -> sm.setUiccApplicationsEnabled(mSubId, false));
715             assertFalse(mSm.getActiveSubscriptionInfo(mSubId).areUiccApplicationsEnabled());
716 
717             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
718                     (sm) -> sm.setUiccApplicationsEnabled(mSubId, true));
719             assertTrue(mSm.getActiveSubscriptionInfo(mSubId).areUiccApplicationsEnabled());
720         }
721     }
722 
723     @Test
testSubscriptionInfoCarrierId()724     public void testSubscriptionInfoCarrierId() {
725         if (!isSupported()) return;
726 
727         SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId);
728         int carrierId = info.getCarrierId();
729         assertTrue(carrierId >= TelephonyManager.UNKNOWN_CARRIER_ID);
730     }
731 
732     @Test
testGetOpportunisticSubscriptions()733     public void testGetOpportunisticSubscriptions() throws Exception {
734         if (!isSupported()) return;
735 
736         List<SubscriptionInfo> infoList = mSm.getOpportunisticSubscriptions();
737 
738         for (SubscriptionInfo info : infoList) {
739             assertTrue(info.isOpportunistic());
740         }
741     }
742 
743     @Test
testGetEnabledSubscriptionId()744     public void testGetEnabledSubscriptionId() {
745         if (!isSupported()) return;
746         int slotId = SubscriptionManager.getSlotIndex(mSubId);
747         if (!SubscriptionManager.isValidSlotIndex(slotId)) {
748             fail("Invalid slot id " + slotId + " for subscription id " + mSubId);
749         }
750         int enabledSubId = executeWithShellPermissionAndDefault(-1, mSm,
751                 (sm) -> sm.getEnabledSubscriptionId(slotId));
752         assertEquals(mSubId, enabledSubId);
753     }
754 
755     @Test
testSetAndCheckSubscriptionEnabled()756     public void testSetAndCheckSubscriptionEnabled() {
757         if (!isSupported()) return;
758         boolean enabled = executeWithShellPermissionAndDefault(false, mSm,
759                 (sm) -> sm.isSubscriptionEnabled(mSubId));
760 
761         AtomicBoolean waitForIsEnabledValue = new AtomicBoolean(!enabled);
762         // wait for the first call to take effect
763         Object lock = new Object();
764         AtomicBoolean setSubscriptionEnabledCallCompleted = new AtomicBoolean(false);
765         TestThread t = new TestThread(new Runnable() {
766             @Override
767             public void run() {
768                 Looper.prepare();
769 
770                 SubscriptionManager.OnSubscriptionsChangedListener listener =
771                         new SubscriptionManager.OnSubscriptionsChangedListener() {
772                             @Override
773                             public void onSubscriptionsChanged() {
774                                 boolean waitForValue = waitForIsEnabledValue.get();
775                                 if (executeWithShellPermissionAndDefault(!waitForValue, mSm,
776                                         (sm) -> sm.isSubscriptionEnabled(mSubId)) == waitForValue) {
777                                     synchronized (lock) {
778                                         setSubscriptionEnabledCallCompleted.set(true);
779                                         lock.notifyAll();
780                                     }
781                                 }
782                             }
783                         };
784                 mSm.addOnSubscriptionsChangedListener(listener);
785 
786                 Looper.loop();
787             }
788         });
789 
790         try {
791             t.start();
792             // Enable or disable subscription may require users UX confirmation or may not be
793             // supported. Call APIs to make sure there's no crash.
794             executeWithShellPermissionAndDefault(false, mSm,
795                     (sm) -> sm.setSubscriptionEnabled(mSubId, !enabled));
796 
797             synchronized (lock) {
798                 if (!setSubscriptionEnabledCallCompleted.get()) {
799                     lock.wait(5000);
800                 }
801             }
802             if (!setSubscriptionEnabledCallCompleted.get()) {
803                 // not treating this as test failure as it may be due to UX confirmation or may not
804                 // be supported
805                 Log.e(TAG, "setSubscriptionEnabled() did not complete");
806                 executeWithShellPermissionAndDefault(false, mSm,
807                     (sm) -> sm.setSubscriptionEnabled(mSubId, enabled));
808                 return;
809             }
810 
811             // switch back to the original value
812             waitForIsEnabledValue.set(enabled);
813             setSubscriptionEnabledCallCompleted.set(false);
814             executeWithShellPermissionAndDefault(false, mSm,
815                     (sm) -> sm.setSubscriptionEnabled(mSubId, enabled));
816 
817             // wait to make sure device is left in the same state after the test as it was before
818             // the test
819             synchronized (lock) {
820                 if (!setSubscriptionEnabledCallCompleted.get()) {
821                     // longer wait time on purpose as re-enabling can take a longer time
822                     lock.wait(50000);
823                 }
824             }
825             if (!setSubscriptionEnabledCallCompleted.get()) {
826                 // treat this as failure because it worked the first time
827                 fail("setSubscriptionEnabled() did not work second time");
828             }
829 
830             // Reset default data subId as it may have been changed as part of the calls above
831             ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
832                     (sm) -> sm.setDefaultDataSubId(mSubId));
833 
834             // Other tests also expect that cellular data must be available if telephony is
835             // supported. Wait for that before returning.
836             final CountDownLatch latch = waitForCellularNetwork();
837             latch.await(10, TimeUnit.SECONDS);
838         } catch (InterruptedException e) {
839             fail("InterruptedException");
840         }
841     }
842 
843     @Test
testGetActiveDataSubscriptionId()844     public void testGetActiveDataSubscriptionId() {
845         if (!isSupported()) return;
846 
847         int activeDataSubIdCurrent = executeWithShellPermissionAndDefault(
848                 SubscriptionManager.INVALID_SUBSCRIPTION_ID, mSm,
849                 (sm) -> sm.getActiveDataSubscriptionId());
850 
851         if (activeDataSubIdCurrent != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
852             List<SubscriptionInfo> subscriptionInfos = mSm.getCompleteActiveSubscriptionInfoList();
853             boolean foundSub = subscriptionInfos.stream()
854                     .anyMatch(x -> x.getSubscriptionId() == activeDataSubIdCurrent);
855             assertTrue(foundSub);
856         }
857     }
858 
859     @Test
testSetPreferredDataSubscriptionId()860     public void testSetPreferredDataSubscriptionId() {
861         if (!isSupported()) return;
862         int preferredSubId = executeWithShellPermissionAndDefault(-1, mSm,
863                 (sm) -> sm.getPreferredDataSubscriptionId());
864         if (preferredSubId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
865             // Make sure to switch back to primary/default data sub first.
866             setPreferredDataSubId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
867         }
868 
869         List<SubscriptionInfo> subscriptionInfos = mSm.getCompleteActiveSubscriptionInfoList();
870 
871         for (SubscriptionInfo subInfo : subscriptionInfos) {
872             // Only test on opportunistic subscriptions.
873             if (!subInfo.isOpportunistic()) continue;
874             setPreferredDataSubId(subInfo.getSubscriptionId());
875         }
876 
877         // Switch data back to previous preferredSubId.
878         setPreferredDataSubId(preferredSubId);
879     }
880 
881     @Test
testRestoreAllSimSpecificSettingsFromBackup()882     public void testRestoreAllSimSpecificSettingsFromBackup() throws Exception {
883         if (!isSupported()) return;
884 
885         int activeDataSubId = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
886                 (sm) -> sm.getActiveDataSubscriptionId());
887         assertNotEquals(activeDataSubId, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
888         SubscriptionInfo activeSubInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
889                 (sm) -> sm.getActiveSubscriptionInfo(activeDataSubId));
890         String isoCountryCode = activeSubInfo.getCountryIso();
891 
892         byte[] backupData = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm,
893                 (sm) -> sm.getAllSimSpecificSettingsForBackup());
894         assertTrue(backupData.length > 0);
895 
896         PersistableBundle bundle = new PersistableBundle();
897         bundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true);
898         bundle.putBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL, false);
899         overrideCarrierConfig(bundle, activeDataSubId);
900 
901         // Get the original ims values.
902         ImsManager imsManager = InstrumentationRegistry.getContext().getSystemService(
903                 ImsManager.class);
904         ImsMmTelManager mMmTelManager = imsManager.getImsMmTelManager(activeDataSubId);
905         boolean isVolteVtEnabledOriginal = ShellIdentityUtils.invokeMethodWithShellPermissions(
906                 mMmTelManager, (m) -> m.isAdvancedCallingSettingEnabled());
907         boolean isVtImsEnabledOriginal = ShellIdentityUtils.invokeMethodWithShellPermissions(
908                 mMmTelManager, (m) -> m.isVtSettingEnabled());
909         boolean isVoWiFiSettingEnabledOriginal =
910                 ShellIdentityUtils.invokeMethodWithShellPermissions(
911                         mMmTelManager, (m) -> m.isVoWiFiSettingEnabled());
912         int voWifiModeOriginal = ShellIdentityUtils.invokeMethodWithShellPermissions(
913                 mMmTelManager, (m) -> m.getVoWiFiModeSetting());
914         int voWiFiRoamingModeOriginal = ShellIdentityUtils.invokeMethodWithShellPermissions(
915                 mMmTelManager, (m) -> m.getVoWiFiRoamingModeSetting());
916 
917         // Get the original RcsUce values.
918         ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(activeDataSubId);
919         RcsUceAdapter rcsUceAdapter = imsRcsManager.getUceAdapter();
920         boolean isImsRcsUceEnabledOriginal =
921                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
922                 rcsUceAdapter, (a) -> a.isUceSettingEnabled(), ImsException.class,
923                 android.Manifest.permission.READ_PHONE_STATE);
924 
925         //Change values in DB.
926         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager,
927                 (m) -> m.setAdvancedCallingSettingEnabled(!isVolteVtEnabledOriginal));
928         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager,
929                 (m) -> m.setVtSettingEnabled(!isVtImsEnabledOriginal));
930         ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(
931                 rcsUceAdapter, (a) -> a.setUceSettingEnabled(!isImsRcsUceEnabledOriginal),
932                 ImsException.class);
933         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager,
934                 (m) -> m.setVoWiFiSettingEnabled(!isVoWiFiSettingEnabledOriginal));
935         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager,
936                 (m) -> m.setVoWiFiModeSetting((voWifiModeOriginal + 1) % 3));
937         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mMmTelManager,
938                 (m) -> m.setVoWiFiRoamingModeSetting((voWiFiRoamingModeOriginal + 1) % 3));
939 
940         // Restore back to original values.
941         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
942                 (sm) -> sm.restoreAllSimSpecificSettingsFromBackup(backupData));
943 
944         // Get ims values to verify with.
945         boolean isVolteVtEnabledAfterRestore = ShellIdentityUtils.invokeMethodWithShellPermissions(
946                 mMmTelManager, (m) -> m.isAdvancedCallingSettingEnabled());
947         boolean isVtImsEnabledAfterRestore = ShellIdentityUtils.invokeMethodWithShellPermissions(
948                 mMmTelManager, (m) -> m.isVtSettingEnabled());
949         boolean isVoWiFiSettingEnabledAfterRestore =
950                 ShellIdentityUtils.invokeMethodWithShellPermissions(
951                         mMmTelManager, (m) -> m.isVoWiFiSettingEnabled());
952         int voWifiModeAfterRestore = ShellIdentityUtils.invokeMethodWithShellPermissions(
953                 mMmTelManager, (m) -> m.getVoWiFiModeSetting());
954         int voWiFiRoamingModeAfterRestore = ShellIdentityUtils.invokeMethodWithShellPermissions(
955                 mMmTelManager, (m) -> m.getVoWiFiRoamingModeSetting());
956         // Get RcsUce values to verify with.
957         boolean isImsRcsUceEnabledAfterRestore =
958                 ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
959                         rcsUceAdapter, (a) -> a.isUceSettingEnabled(), ImsException.class,
960                         android.Manifest.permission.READ_PHONE_STATE);
961 
962         assertEquals(isVolteVtEnabledOriginal, isVolteVtEnabledAfterRestore);
963         if (isoCountryCode == null || isoCountryCode.equals("us") || isoCountryCode.equals("ca")) {
964             assertEquals(!isVoWiFiSettingEnabledOriginal, isVoWiFiSettingEnabledAfterRestore);
965         } else {
966             assertEquals(isVoWiFiSettingEnabledOriginal, isVoWiFiSettingEnabledAfterRestore);
967         }
968         assertEquals(voWifiModeOriginal, voWifiModeAfterRestore);
969         assertEquals(voWiFiRoamingModeOriginal, voWiFiRoamingModeAfterRestore);
970         assertEquals(isVtImsEnabledOriginal, isVtImsEnabledAfterRestore);
971         assertEquals(isImsRcsUceEnabledOriginal, isImsRcsUceEnabledAfterRestore);
972 
973         // restore original carrier config.
974         overrideCarrierConfig(null, activeDataSubId);
975 
976 
977         try {
978             // Check api call will fail without proper permissions.
979             mSm.restoreAllSimSpecificSettingsFromBackup(backupData);
980             fail("SecurityException expected");
981         } catch (SecurityException e) {
982             // expected
983         }
984     }
985 
986     @Test
testSetAndGetD2DStatusSharing()987     public void testSetAndGetD2DStatusSharing() {
988         if (!isSupported()) return;
989 
990         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
991         uiAutomation.adoptShellPermissionIdentity(MODIFY_PHONE_STATE);
992         int originalD2DStatusSharing = mSm.getDeviceToDeviceStatusSharingPreference(mSubId);
993         mSm.setDeviceToDeviceStatusSharingPreference(mSubId,
994                 SubscriptionManager.D2D_SHARING_ALL_CONTACTS);
995         assertEquals(SubscriptionManager.D2D_SHARING_ALL_CONTACTS,
996                 mSm.getDeviceToDeviceStatusSharingPreference(mSubId));
997         mSm.setDeviceToDeviceStatusSharingPreference(mSubId, SubscriptionManager.D2D_SHARING_ALL);
998         assertEquals(SubscriptionManager.D2D_SHARING_ALL,
999                 mSm.getDeviceToDeviceStatusSharingPreference(mSubId));
1000         mSm.setDeviceToDeviceStatusSharingPreference(mSubId, originalD2DStatusSharing);
1001         uiAutomation.dropShellPermissionIdentity();
1002     }
1003 
1004     @Test
testSetAndGetD2DSharingContacts()1005     public void testSetAndGetD2DSharingContacts() {
1006         if (!isSupported()) return;
1007 
1008         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
1009         uiAutomation.adoptShellPermissionIdentity(MODIFY_PHONE_STATE);
1010         List<Uri> originalD2DSharingContacts = mSm.getDeviceToDeviceStatusSharingContacts(mSubId);
1011         mSm.setDeviceToDeviceStatusSharingContacts(mSubId, CONTACTS);
1012         assertEquals(CONTACTS, mSm.getDeviceToDeviceStatusSharingContacts(mSubId));
1013         mSm.setDeviceToDeviceStatusSharingContacts(mSubId, originalD2DSharingContacts);
1014         uiAutomation.dropShellPermissionIdentity();
1015     }
1016 
1017     @Nullable
getBundleFromBackupData(byte[] data)1018     private PersistableBundle getBundleFromBackupData(byte[] data) {
1019         try (ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
1020             return PersistableBundle.readFromStream(bis);
1021         } catch (IOException e) {
1022             return null;
1023         }
1024     }
1025 
overrideCarrierConfig(PersistableBundle bundle, int subId)1026     private void overrideCarrierConfig(PersistableBundle bundle, int subId) throws Exception {
1027         CarrierConfigManager carrierConfigManager = InstrumentationRegistry.getContext()
1028                 .getSystemService(CarrierConfigManager.class);
1029         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(carrierConfigManager,
1030                 (m) -> m.overrideConfig(subId, bundle));
1031     }
1032 
setPreferredDataSubId(int subId)1033     private void setPreferredDataSubId(int subId) {
1034         final LinkedBlockingQueue<Integer> resultQueue = new LinkedBlockingQueue<>(1);
1035         Executor executor = (command)-> command.run();
1036         Consumer<Integer> consumer = (res)-> {
1037             if (res == null) {
1038                 resultQueue.offer(-1);
1039             } else {
1040                 resultQueue.offer(res);
1041             }
1042         };
1043 
1044         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm,
1045                 (sm) -> sm.setPreferredDataSubscriptionId(subId, false,
1046                         executor, consumer));
1047         int res = -1;
1048         try {
1049             res = resultQueue.poll(2, TimeUnit.SECONDS);
1050         } catch (InterruptedException e) {
1051             fail("Cannot get the modem result in time");
1052         }
1053 
1054         assertEquals(SET_OPPORTUNISTIC_SUB_SUCCESS, res);
1055         int getValue = executeWithShellPermissionAndDefault(-1, mSm,
1056                 (sm) -> sm.getPreferredDataSubscriptionId());
1057         assertEquals(subId, getValue);
1058     }
1059 
executeWithShellPermissionAndDefault(T defaultValue, U targetObject, ShellIdentityUtils.ShellPermissionMethodHelper<T, U> helper)1060     private <T, U> T executeWithShellPermissionAndDefault(T defaultValue, U targetObject,
1061             ShellIdentityUtils.ShellPermissionMethodHelper<T, U> helper) {
1062         try {
1063             return ShellIdentityUtils.invokeMethodWithShellPermissions(targetObject, helper);
1064         } catch (Exception e) {
1065             // do nothing, return default
1066         }
1067         return defaultValue;
1068     }
1069 
assertOverrideSuccess(SubscriptionPlan... plans)1070     private void assertOverrideSuccess(SubscriptionPlan... plans) {
1071         mSm.setSubscriptionPlans(mSubId, Arrays.asList(plans));
1072         mSm.setSubscriptionOverrideCongested(mSubId, false, 0);
1073     }
1074 
assertOverrideFails(SubscriptionPlan... plans)1075     private void assertOverrideFails(SubscriptionPlan... plans) {
1076         mSm.setSubscriptionPlans(mSubId, Arrays.asList(plans));
1077         try {
1078             mSm.setSubscriptionOverrideCongested(mSubId, false, 0);
1079             fail();
1080         } catch (SecurityException | IllegalStateException expected) {
1081         }
1082     }
1083 
waitForNetworkCapabilities(Network network, Predicate<NetworkCapabilities> predicate)1084     public static CountDownLatch waitForNetworkCapabilities(Network network,
1085             Predicate<NetworkCapabilities> predicate) {
1086         final CountDownLatch latch = new CountDownLatch(1);
1087         final ConnectivityManager cm = InstrumentationRegistry.getContext()
1088                 .getSystemService(ConnectivityManager.class);
1089         cm.registerNetworkCallback(new NetworkRequest.Builder().build(),
1090                 new NetworkCallback() {
1091                     @Override
1092                     public void onCapabilitiesChanged(Network net, NetworkCapabilities caps) {
1093                         if (net.equals(network) && predicate.test(caps)) {
1094                             latch.countDown();
1095                             cm.unregisterNetworkCallback(this);
1096                         }
1097                     }
1098                 });
1099         return latch;
1100     }
1101 
1102     /**
1103      * Corresponding to findCellularNetwork()
1104      */
waitForCellularNetwork()1105     private static CountDownLatch waitForCellularNetwork() {
1106         final CountDownLatch latch = new CountDownLatch(1);
1107         final ConnectivityManager cm = InstrumentationRegistry.getContext()
1108                 .getSystemService(ConnectivityManager.class);
1109         cm.registerNetworkCallback(new NetworkRequest.Builder().build(),
1110                 new NetworkCallback() {
1111                     @Override
1112                     public void onCapabilitiesChanged(Network net, NetworkCapabilities caps) {
1113                         if (caps.hasTransport(TRANSPORT_CELLULAR)
1114                                 && caps.hasCapability(NET_CAPABILITY_INTERNET)
1115                                 && caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
1116                             latch.countDown();
1117                             cm.unregisterNetworkCallback(this);
1118                         }
1119                     }
1120                 });
1121         return latch;
1122     }
1123 
buildValidSubscriptionPlan(long dataUsageTime)1124     private static SubscriptionPlan buildValidSubscriptionPlan(long dataUsageTime) {
1125         return SubscriptionPlan.Builder
1126                 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"),
1127                         Period.ofMonths(1))
1128                 .setTitle("CTS")
1129                 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
1130                 .setDataUsage(500_000_000, dataUsageTime)
1131                 .build();
1132     }
1133 
findCellularNetwork()1134     private static @Nullable Network findCellularNetwork() {
1135         final ConnectivityManager cm = InstrumentationRegistry.getContext()
1136                 .getSystemService(ConnectivityManager.class);
1137         for (Network net : cm.getAllNetworks()) {
1138             final NetworkCapabilities caps = cm.getNetworkCapabilities(net);
1139             if (caps != null && caps.hasTransport(TRANSPORT_CELLULAR)
1140                     && caps.hasCapability(NET_CAPABILITY_INTERNET)
1141                     && caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
1142                 return net;
1143             }
1144         }
1145         return null;
1146     }
1147 
isSupported()1148     private static boolean isSupported() {
1149         return InstrumentationRegistry.getContext().getPackageManager()
1150                 .hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
1151     }
1152 
isDSDS()1153     private static boolean isDSDS() {
1154         TelephonyManager tm = InstrumentationRegistry.getContext()
1155                 .getSystemService(TelephonyManager.class);
1156         return tm != null && tm.getPhoneCount() > 1;
1157     }
1158 
setSubPlanOwner(int subId, String packageName)1159     private static void setSubPlanOwner(int subId, String packageName) throws Exception {
1160         SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
1161                 "cmd netpolicy set sub-plan-owner " + subId + " " + packageName);
1162     }
1163 
isUnmetered5GSupported()1164     private boolean isUnmetered5GSupported() {
1165         final CarrierConfigManager ccm = InstrumentationRegistry.getContext()
1166                 .getSystemService(CarrierConfigManager.class);
1167         PersistableBundle carrierConfig = ccm.getConfigForSubId(mSubId);
1168 
1169         final TelephonyManager tm = InstrumentationRegistry.getContext()
1170                 .getSystemService(TelephonyManager.class);
1171         int dataNetworkType = tm.getDataNetworkType(mSubId);
1172         long supportedRats = ShellIdentityUtils.invokeMethodWithShellPermissions(tm,
1173                 TelephonyManager::getSupportedRadioAccessFamily);
1174 
1175         boolean validCarrier = carrierConfig.getBoolean(
1176                 CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL);
1177         boolean validCapabilities = (supportedRats & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0;
1178         // TODO: need to check for TelephonyDisplayInfo override for NR NSA
1179         boolean validNetworkType = dataNetworkType == TelephonyManager.NETWORK_TYPE_NR;
1180 
1181         return validCarrier && validNetworkType && validCapabilities;
1182     }
1183 }
1184