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_METERED; 22 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 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.assertNotNull; 29 import static org.junit.Assert.assertNull; 30 import static org.junit.Assert.assertTrue; 31 import static org.junit.Assert.fail; 32 33 import android.annotation.Nullable; 34 import android.content.pm.PackageManager; 35 import android.net.ConnectivityManager; 36 import android.net.ConnectivityManager.NetworkCallback; 37 import android.net.Network; 38 import android.net.NetworkCapabilities; 39 import android.net.NetworkRequest; 40 import android.os.ParcelUuid; 41 import android.telephony.SubscriptionInfo; 42 import android.telephony.SubscriptionManager; 43 import android.telephony.SubscriptionPlan; 44 import android.telephony.TelephonyManager; 45 46 import androidx.test.InstrumentationRegistry; 47 48 import com.android.compatibility.common.util.ShellIdentityUtils; 49 import com.android.compatibility.common.util.SystemUtil; 50 import com.android.internal.util.ArrayUtils; 51 52 import org.junit.AfterClass; 53 import org.junit.Before; 54 import org.junit.BeforeClass; 55 import org.junit.Test; 56 57 import java.time.Period; 58 import java.time.ZonedDateTime; 59 import java.util.ArrayList; 60 import java.util.Arrays; 61 import java.util.List; 62 import java.util.UUID; 63 import java.util.concurrent.CountDownLatch; 64 import java.util.concurrent.Executor; 65 import java.util.concurrent.LinkedBlockingQueue; 66 import java.util.concurrent.TimeUnit; 67 import java.util.function.Consumer; 68 import java.util.function.Predicate; 69 import java.util.stream.Collectors; 70 71 public class SubscriptionManagerTest { 72 private SubscriptionManager mSm; 73 74 private int mSubId; 75 private String mPackageName; 76 77 /** 78 * Callback used in testRegisterNetworkCallback that allows caller to block on 79 * {@code onAvailable}. 80 */ 81 private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback { 82 private final CountDownLatch mAvailableLatch = new CountDownLatch(1); 83 waitForAvailable()84 public void waitForAvailable() throws InterruptedException { 85 assertTrue("Cellular network did not come up after 5 seconds", 86 mAvailableLatch.await(5, TimeUnit.SECONDS)); 87 } 88 89 @Override onAvailable(Network network)90 public void onAvailable(Network network) { 91 mAvailableLatch.countDown(); 92 } 93 } 94 95 @BeforeClass setUpClass()96 public static void setUpClass() throws Exception { 97 if (!isSupported()) return; 98 99 InstrumentationRegistry.getInstrumentation().getUiAutomation() 100 .executeShellCommand("svc wifi disable"); 101 102 final TestNetworkCallback callback = new TestNetworkCallback(); 103 final ConnectivityManager cm = InstrumentationRegistry.getContext() 104 .getSystemService(ConnectivityManager.class); 105 cm.registerNetworkCallback(new NetworkRequest.Builder() 106 .addTransportType(TRANSPORT_CELLULAR) 107 .addCapability(NET_CAPABILITY_INTERNET) 108 .build(), callback); 109 try { 110 // Wait to get callback for availability of internet 111 callback.waitForAvailable(); 112 } catch (InterruptedException e) { 113 fail("NetworkCallback wait was interrupted."); 114 } finally { 115 cm.unregisterNetworkCallback(callback); 116 } 117 } 118 119 @AfterClass tearDownClass()120 public static void tearDownClass() throws Exception { 121 if (!isSupported()) return; 122 123 InstrumentationRegistry.getInstrumentation().getUiAutomation() 124 .executeShellCommand("svc wifi enable"); 125 } 126 127 @Before setUp()128 public void setUp() throws Exception { 129 if (!isSupported()) return; 130 131 mSm = InstrumentationRegistry.getContext().getSystemService(SubscriptionManager.class); 132 mSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 133 mPackageName = InstrumentationRegistry.getContext().getPackageName(); 134 } 135 136 /** 137 * Sanity check that the device has a cellular network and a valid default data subId 138 * when {@link PackageManager#FEATURE_TELEPHONY} support. 139 */ 140 @Test testSanity()141 public void testSanity() throws Exception { 142 if (!isSupported()) return; 143 144 final boolean hasCellular = findCellularNetwork() != null; 145 if (!hasCellular) { 146 fail("Device claims to support " + PackageManager.FEATURE_TELEPHONY 147 + " but has no active cellular network, which is required for validation"); 148 } 149 150 if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 151 fail("Device must have a valid default data subId for validation"); 152 } 153 } 154 155 @Test testGetActiveSubscriptionInfoCount()156 public void testGetActiveSubscriptionInfoCount() throws Exception { 157 if (!isSupported()) return; 158 assertTrue(mSm.getActiveSubscriptionInfoCount() <= 159 mSm.getActiveSubscriptionInfoCountMax()); 160 } 161 162 @Test testIsActiveSubscriptionId()163 public void testIsActiveSubscriptionId() throws Exception { 164 if (!isSupported()) return; 165 assertTrue(mSm.isActiveSubscriptionId(mSubId)); 166 } 167 168 @Test testGetSubscriptionIds()169 public void testGetSubscriptionIds() throws Exception { 170 if (!isSupported()) return; 171 int slotId = SubscriptionManager.getSlotIndex(mSubId); 172 int[] subIds = mSm.getSubscriptionIds(slotId); 173 assertNotNull(subIds); 174 assertTrue(ArrayUtils.contains(subIds, mSubId)); 175 } 176 177 @Test testIsUsableSubscriptionId()178 public void testIsUsableSubscriptionId() throws Exception { 179 if (!isSupported()) return; 180 assertTrue(SubscriptionManager.isUsableSubscriptionId(mSubId)); 181 } 182 183 @Test testActiveSubscriptions()184 public void testActiveSubscriptions() throws Exception { 185 if (!isSupported()) return; 186 187 List<SubscriptionInfo> subList = mSm.getActiveSubscriptionInfoList(); 188 // Assert when there is no sim card present or detected 189 assertNotNull("Active subscriber required", subList); 190 assertFalse("Active subscriber required", subList.isEmpty()); 191 for (int i = 0; i < subList.size(); i++) { 192 assertTrue(subList.get(i).getSubscriptionId() >= 0); 193 assertTrue(subList.get(i).getSimSlotIndex() >= 0); 194 if (i >= 1) { 195 assertTrue(subList.get(i - 1).getSimSlotIndex() 196 <= subList.get(i).getSimSlotIndex()); 197 assertTrue(subList.get(i - 1).getSimSlotIndex() < subList.get(i).getSimSlotIndex() 198 || subList.get(i - 1).getSubscriptionId() 199 < subList.get(i).getSubscriptionId()); 200 } 201 } 202 } 203 204 @Test 205 public void testSubscriptionPlans() throws Exception { 206 if (!isSupported()) return; 207 208 // Make ourselves the owner 209 setSubPlanOwner(mSubId, mPackageName); 210 211 // Push empty list and we get empty back 212 mSm.setSubscriptionPlans(mSubId, Arrays.asList()); 213 assertEquals(Arrays.asList(), mSm.getSubscriptionPlans(mSubId)); 214 215 // Push simple plan and get it back 216 final SubscriptionPlan plan = buildValidSubscriptionPlan(); 217 mSm.setSubscriptionPlans(mSubId, Arrays.asList(plan)); 218 assertEquals(Arrays.asList(plan), mSm.getSubscriptionPlans(mSubId)); 219 220 // Now revoke our access 221 setSubPlanOwner(mSubId, null); 222 try { 223 mSm.setSubscriptionPlans(mSubId, Arrays.asList()); 224 fail(); 225 } catch (SecurityException expected) { 226 } 227 try { 228 mSm.getSubscriptionPlans(mSubId); 229 fail(); 230 } catch (SecurityException expected) { 231 } 232 } 233 234 @Test 235 public void testSubscriptionPlansOverrideCongested() throws Exception { 236 if (!isSupported()) return; 237 238 final ConnectivityManager cm = InstrumentationRegistry.getContext() 239 .getSystemService(ConnectivityManager.class); 240 final Network net = findCellularNetwork(); 241 assertNotNull("Active cellular network required", net); 242 243 // Make ourselves the owner 244 setSubPlanOwner(mSubId, mPackageName); 245 246 // Missing plans means no overrides 247 mSm.setSubscriptionPlans(mSubId, Arrays.asList()); 248 try { 249 mSm.setSubscriptionOverrideCongested(mSubId, true, 0); 250 fail(); 251 } catch (SecurityException | IllegalStateException expected) { 252 } 253 254 // Defining plans means we get to override 255 mSm.setSubscriptionPlans(mSubId, Arrays.asList(buildValidSubscriptionPlan())); 256 257 // Cellular is uncongested by default 258 assertTrue(cm.getNetworkCapabilities(net).hasCapability(NET_CAPABILITY_NOT_CONGESTED)); 259 260 // Override should make it go congested 261 { 262 final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> { 263 return !caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED); 264 }); 265 mSm.setSubscriptionOverrideCongested(mSubId, true, 0); 266 assertTrue(latch.await(10, TimeUnit.SECONDS)); 267 } 268 269 // Clearing override should make it go uncongested 270 { 271 final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> { 272 return caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED); 273 }); 274 mSm.setSubscriptionOverrideCongested(mSubId, false, 0); 275 assertTrue(latch.await(10, TimeUnit.SECONDS)); 276 } 277 278 // Now revoke our access 279 setSubPlanOwner(mSubId, null); 280 try { 281 mSm.setSubscriptionOverrideCongested(mSubId, true, 0); 282 fail(); 283 } catch (SecurityException | IllegalStateException expected) { 284 } 285 } 286 287 @Test testSubscriptionPlansOverrideUnmetered()288 public void testSubscriptionPlansOverrideUnmetered() throws Exception { 289 if (!isSupported()) return; 290 291 final ConnectivityManager cm = InstrumentationRegistry.getContext() 292 .getSystemService(ConnectivityManager.class); 293 final Network net = findCellularNetwork(); 294 assertNotNull("Active cellular network required", net); 295 296 // Make ourselves the owner and define some plans 297 setSubPlanOwner(mSubId, mPackageName); 298 mSm.setSubscriptionPlans(mSubId, Arrays.asList(buildValidSubscriptionPlan())); 299 300 // Cellular is metered by default 301 assertFalse(cm.getNetworkCapabilities(net).hasCapability(NET_CAPABILITY_NOT_METERED)); 302 303 // Override should make it go unmetered 304 { 305 final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> { 306 return caps.hasCapability(NET_CAPABILITY_NOT_METERED); 307 }); 308 mSm.setSubscriptionOverrideUnmetered(mSubId, true, 0); 309 assertTrue(latch.await(10, TimeUnit.SECONDS)); 310 } 311 312 // Clearing override should make it go metered 313 { 314 final CountDownLatch latch = waitForNetworkCapabilities(net, caps -> { 315 return !caps.hasCapability(NET_CAPABILITY_NOT_METERED); 316 }); 317 mSm.setSubscriptionOverrideUnmetered(mSubId, false, 0); 318 assertTrue(latch.await(10, TimeUnit.SECONDS)); 319 } 320 } 321 322 @Test testSubscriptionPlansInvalid()323 public void testSubscriptionPlansInvalid() throws Exception { 324 if (!isSupported()) return; 325 326 // Make ourselves the owner 327 setSubPlanOwner(mSubId, mPackageName); 328 329 // Empty plans can't override 330 assertOverrideFails(); 331 332 // Nonrecurring plan in the past can't override 333 assertOverrideFails(SubscriptionPlan.Builder 334 .createNonrecurring(ZonedDateTime.now().minusDays(14), 335 ZonedDateTime.now().minusDays(7)) 336 .setTitle("CTS") 337 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) 338 .build()); 339 340 // Plan with undefined limit can't override 341 assertOverrideFails(SubscriptionPlan.Builder 342 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"), 343 Period.ofMonths(1)) 344 .setTitle("CTS") 345 .build()); 346 347 // We can override when there is an active plan somewhere 348 final SubscriptionPlan older = SubscriptionPlan.Builder 349 .createNonrecurring(ZonedDateTime.now().minusDays(14), 350 ZonedDateTime.now().minusDays(7)) 351 .setTitle("CTS") 352 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) 353 .build(); 354 final SubscriptionPlan newer = SubscriptionPlan.Builder 355 .createNonrecurring(ZonedDateTime.now().minusDays(7), 356 ZonedDateTime.now().plusDays(7)) 357 .setTitle("CTS") 358 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) 359 .build(); 360 assertOverrideSuccess(older, newer); 361 } 362 363 @Test testSubscriptionGrouping()364 public void testSubscriptionGrouping() throws Exception { 365 if (!isSupported()) return; 366 367 // Set subscription group with current sub Id. This should fail 368 // because we don't have MODIFY_PHONE_STATE or carrier privilege permission. 369 List<Integer> subGroup = new ArrayList(); 370 subGroup.add(mSubId); 371 try { 372 mSm.createSubscriptionGroup(subGroup); 373 fail(); 374 } catch (SecurityException expected) { 375 } 376 377 // Getting subscriptions in group should return null as setSubscriptionGroup 378 // should fail. 379 SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId); 380 assertNull(info.getGroupUuid()); 381 382 // Remove from subscription group with current sub Id. This should fail 383 // because we don't have MODIFY_PHONE_STATE or carrier privilege permission. 384 try { 385 mSm.addSubscriptionsIntoGroup(subGroup, null); 386 fail(); 387 } catch (NullPointerException expected) { 388 } 389 390 // Add into subscription group that doesn't exist. This should fail 391 // with IllegalArgumentException. 392 try { 393 ParcelUuid groupUuid = new ParcelUuid(UUID.randomUUID()); 394 mSm.addSubscriptionsIntoGroup(subGroup, groupUuid); 395 fail(); 396 } catch (IllegalArgumentException expected) { 397 } 398 399 // Remove from subscription group with current sub Id. This should fail 400 // because we don't have MODIFY_PHONE_STATE or carrier privilege permission. 401 try { 402 mSm.removeSubscriptionsFromGroup(subGroup, null); 403 fail(); 404 } catch (NullPointerException expected) { 405 } 406 } 407 408 @Test testSubscriptionGroupingWithPermission()409 public void testSubscriptionGroupingWithPermission() throws Exception { 410 if (!isSupported()) return; 411 412 // Set subscription group with current sub Id. 413 List<Integer> subGroup = new ArrayList(); 414 subGroup.add(mSubId); 415 ParcelUuid uuid = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm, 416 (sm) -> sm.createSubscriptionGroup(subGroup)); 417 418 // Getting subscriptions in group. 419 List<SubscriptionInfo> infoList = mSm.getSubscriptionsInGroup(uuid); 420 assertNotNull(infoList); 421 assertEquals(1, infoList.size()); 422 assertEquals(uuid, infoList.get(0).getGroupUuid()); 423 424 List<SubscriptionInfo> availableInfoList = mSm.getAvailableSubscriptionInfoList(); 425 if (availableInfoList.size() > 1) { 426 List<Integer> availableSubGroup = availableInfoList.stream() 427 .map(info -> info.getSubscriptionId()) 428 .filter(subId -> subId != mSubId) 429 .collect(Collectors.toList()); 430 431 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, 432 (sm) -> sm.addSubscriptionsIntoGroup(availableSubGroup, uuid)); 433 434 infoList = mSm.getSubscriptionsInGroup(uuid); 435 assertNotNull(infoList); 436 assertEquals(availableInfoList.size(), infoList.size()); 437 438 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, 439 (sm) -> sm.removeSubscriptionsFromGroup(availableSubGroup, uuid)); 440 } 441 442 // Remove from subscription group with current sub Id. 443 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, 444 (sm) -> sm.removeSubscriptionsFromGroup(subGroup, uuid)); 445 446 infoList = mSm.getSubscriptionsInGroup(uuid); 447 assertNotNull(infoList); 448 assertTrue(infoList.isEmpty()); 449 } 450 451 @Test testSettingOpportunisticSubscription()452 public void testSettingOpportunisticSubscription() throws Exception { 453 if (!isSupported()) return; 454 455 // Set subscription to be opportunistic. This should fail 456 // because we don't have MODIFY_PHONE_STATE or carrier privilege permission. 457 try { 458 mSm.setOpportunistic(true, mSubId); 459 fail(); 460 } catch (SecurityException expected) { 461 } 462 463 // Shouldn't crash. 464 SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId); 465 info.isOpportunistic(); 466 } 467 468 @Test testMccMncString()469 public void testMccMncString() { 470 if (!isSupported()) return; 471 472 SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId); 473 String mcc = info.getMccString(); 474 String mnc = info.getMncString(); 475 assertTrue(mcc == null || mcc.length() <= 3); 476 assertTrue(mnc == null || mnc.length() <= 3); 477 } 478 479 @Test testSubscriptionInfoCarrierId()480 public void testSubscriptionInfoCarrierId() { 481 if (!isSupported()) return; 482 483 SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId); 484 int carrierId = info.getCarrierId(); 485 assertTrue(carrierId >= TelephonyManager.UNKNOWN_CARRIER_ID); 486 } 487 488 @Test testGetOpportunisticSubscriptions()489 public void testGetOpportunisticSubscriptions() throws Exception { 490 if (!isSupported()) return; 491 492 List<SubscriptionInfo> infoList = mSm.getOpportunisticSubscriptions(); 493 494 for (SubscriptionInfo info : infoList) { 495 assertTrue(info.isOpportunistic()); 496 } 497 } 498 499 @Test testGetEnabledSubscriptionId()500 public void testGetEnabledSubscriptionId() { 501 if (!isSupported()) return; 502 int slotId = SubscriptionManager.getSlotIndex(mSubId); 503 if (!SubscriptionManager.isValidSlotIndex(slotId)) { 504 fail("Invalid slot id " + slotId + " for subscription id " + mSubId); 505 } 506 int enabledSubId = executeWithShellPermissionAndDefault(-1, mSm, 507 (sm) -> sm.getEnabledSubscriptionId(slotId)); 508 assertEquals(mSubId, enabledSubId); 509 } 510 511 @Test testSetAndCheckSubscriptionEnabled()512 public void testSetAndCheckSubscriptionEnabled() { 513 if (!isSupported()) return; 514 boolean enabled = executeWithShellPermissionAndDefault(false, mSm, 515 (sm) -> sm.isSubscriptionEnabled(mSubId)); 516 if (isDSDS()) { 517 // Change it to a different value 518 changeAndVerifySubscriptionEnabledValue(mSubId, !enabled); 519 // Reset it back to original 520 changeAndVerifySubscriptionEnabledValue(mSubId, enabled); 521 } else { 522 boolean changeSuccessfully = executeWithShellPermissionAndDefault(false, mSm, 523 (sm) -> sm.setSubscriptionEnabled(mSubId, !enabled)); 524 assertFalse(changeSuccessfully); 525 } 526 } 527 528 @Test testSetPreferredDataSubscriptionId()529 public void testSetPreferredDataSubscriptionId() { 530 if (!isSupported()) return; 531 int preferredSubId = executeWithShellPermissionAndDefault(-1, mSm, 532 (sm) -> sm.getPreferredDataSubscriptionId()); 533 534 final LinkedBlockingQueue<Integer> resultQueue = new LinkedBlockingQueue<>(1); 535 Executor executor = new Executor() { 536 @Override 537 public void execute(Runnable command) { 538 command.run(); 539 } 540 }; 541 542 Consumer<Integer> consumer = new Consumer<Integer>() { 543 @Override 544 public void accept(Integer res) { 545 if (res == null) { 546 resultQueue.offer(-1); 547 } else { 548 resultQueue.offer(res); 549 } 550 } 551 }; 552 553 List<SubscriptionInfo> subscriptionInfos = mSm.getActiveSubscriptionInfoList(); 554 boolean changes = false; 555 556 for (SubscriptionInfo subInfo : subscriptionInfos) { 557 int subId = subInfo.getSubscriptionId(); 558 if (subId != preferredSubId) { 559 int newPreferredSubId = subId; 560 // Change to a new value. 561 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, 562 (sm) -> sm.setPreferredDataSubscriptionId(newPreferredSubId, false, 563 executor, consumer)); 564 int res = -1; 565 try { 566 res = resultQueue.poll(2, TimeUnit.SECONDS); 567 } catch (InterruptedException e) { 568 fail("Cannot get the modem result in time"); 569 } 570 assertEquals(SET_OPPORTUNISTIC_SUB_SUCCESS, res); 571 int newGetValue = executeWithShellPermissionAndDefault(-1, mSm, 572 (sm) -> sm.getPreferredDataSubscriptionId()); 573 assertEquals(newPreferredSubId, newGetValue); 574 changes = true; 575 break; 576 } 577 } 578 579 // Reset back, or set the duplicate. 580 if (SubscriptionManager.isValidSubscriptionId(preferredSubId)) { 581 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, 582 (sm) -> sm.setPreferredDataSubscriptionId(preferredSubId, false, 583 executor, consumer)); 584 int res = -1; 585 try { 586 res = resultQueue.poll(2, TimeUnit.SECONDS); 587 } catch (InterruptedException e) { 588 fail("Cannot get the modem result in time"); 589 } 590 // Duplicate setting ends up with nothing. 591 if (!changes) { 592 assertEquals(-1, res); 593 } else { 594 assertEquals(SET_OPPORTUNISTIC_SUB_SUCCESS, res); 595 int resetGetValue = executeWithShellPermissionAndDefault(-1, mSm, 596 (sm) -> sm.getPreferredDataSubscriptionId()); 597 assertEquals(resetGetValue, preferredSubId); 598 } 599 } 600 } 601 changeAndVerifySubscriptionEnabledValue(int subId, boolean targetValue)602 private void changeAndVerifySubscriptionEnabledValue(int subId, boolean targetValue) { 603 boolean changeSuccessfully = executeWithShellPermissionAndDefault(false, mSm, 604 (sm) -> sm.setSubscriptionEnabled(subId, targetValue)); 605 if (!changeSuccessfully) { 606 fail("Cannot change subscription " + subId 607 + " from " + !targetValue + " to " + targetValue); 608 } 609 boolean res = executeWithShellPermissionAndDefault(targetValue, mSm, 610 (sm) -> sm.isSubscriptionEnabled(subId)); 611 assertEquals(targetValue, res); 612 } 613 executeWithShellPermissionAndDefault(T defaultValue, U targetObject, ShellIdentityUtils.ShellPermissionMethodHelper<T, U> helper)614 private <T, U> T executeWithShellPermissionAndDefault(T defaultValue, U targetObject, 615 ShellIdentityUtils.ShellPermissionMethodHelper<T, U> helper) { 616 try { 617 return ShellIdentityUtils.invokeMethodWithShellPermissions(targetObject, helper); 618 } catch (Exception e) { 619 // do nothing, return default 620 } 621 return defaultValue; 622 } 623 assertOverrideSuccess(SubscriptionPlan... plans)624 private void assertOverrideSuccess(SubscriptionPlan... plans) { 625 mSm.setSubscriptionPlans(mSubId, Arrays.asList(plans)); 626 mSm.setSubscriptionOverrideCongested(mSubId, false, 0); 627 } 628 assertOverrideFails(SubscriptionPlan... plans)629 private void assertOverrideFails(SubscriptionPlan... plans) { 630 mSm.setSubscriptionPlans(mSubId, Arrays.asList(plans)); 631 try { 632 mSm.setSubscriptionOverrideCongested(mSubId, false, 0); 633 fail(); 634 } catch (SecurityException | IllegalStateException expected) { 635 } 636 } 637 waitForNetworkCapabilities(Network network, Predicate<NetworkCapabilities> predicate)638 public static CountDownLatch waitForNetworkCapabilities(Network network, 639 Predicate<NetworkCapabilities> predicate) { 640 final CountDownLatch latch = new CountDownLatch(1); 641 final ConnectivityManager cm = InstrumentationRegistry.getContext() 642 .getSystemService(ConnectivityManager.class); 643 cm.registerNetworkCallback(new NetworkRequest.Builder().build(), 644 new NetworkCallback() { 645 @Override 646 public void onCapabilitiesChanged(Network net, NetworkCapabilities caps) { 647 if (net.equals(network) && predicate.test(caps)) { 648 latch.countDown(); 649 cm.unregisterNetworkCallback(this); 650 } 651 } 652 }); 653 return latch; 654 } 655 buildValidSubscriptionPlan()656 private static SubscriptionPlan buildValidSubscriptionPlan() { 657 return SubscriptionPlan.Builder 658 .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"), 659 Period.ofMonths(1)) 660 .setTitle("CTS") 661 .setDataLimit(1_000_000_000, SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED) 662 .setDataUsage(500_000_000, System.currentTimeMillis()) 663 .build(); 664 } 665 findCellularNetwork()666 private static @Nullable Network findCellularNetwork() { 667 final ConnectivityManager cm = InstrumentationRegistry.getContext() 668 .getSystemService(ConnectivityManager.class); 669 for (Network net : cm.getAllNetworks()) { 670 final NetworkCapabilities caps = cm.getNetworkCapabilities(net); 671 if (caps != null && caps.hasTransport(TRANSPORT_CELLULAR) 672 && caps.hasCapability(NET_CAPABILITY_INTERNET) 673 && caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { 674 return net; 675 } 676 } 677 return null; 678 } 679 isSupported()680 private static boolean isSupported() { 681 return InstrumentationRegistry.getContext().getPackageManager() 682 .hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 683 } 684 isDSDS()685 private static boolean isDSDS() { 686 TelephonyManager tm = InstrumentationRegistry.getContext() 687 .getSystemService(TelephonyManager.class); 688 return tm != null && tm.getPhoneCount() > 1; 689 } 690 setSubPlanOwner(int subId, String packageName)691 private static void setSubPlanOwner(int subId, String packageName) throws Exception { 692 SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), 693 "cmd netpolicy set sub-plan-owner " + subId + " " + packageName); 694 } 695 } 696