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.net.vcn.cts; 18 19 import static android.content.pm.PackageManager.FEATURE_TELEPHONY; 20 import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION; 21 import static android.ipsec.ike.cts.IkeTunUtils.PortPair; 22 import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS; 23 import static android.net.ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT; 24 import static android.net.ConnectivitySettingsManager.getCaptivePortalMode; 25 import static android.net.ConnectivitySettingsManager.setCaptivePortalMode; 26 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; 27 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 28 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 29 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; 30 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; 31 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; 32 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 33 import static android.net.NetworkCapabilities.TRANSPORT_TEST; 34 import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY; 35 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; 36 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED; 37 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; 38 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY; 39 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN; 40 import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED; 41 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; 42 43 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 44 45 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 46 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 47 import static com.android.compatibility.common.util.TestUtils.waitUntil; 48 import static com.android.internal.util.HexDump.hexStringToByteArray; 49 50 import static org.junit.Assert.assertEquals; 51 import static org.junit.Assert.assertFalse; 52 import static org.junit.Assert.assertNotNull; 53 import static org.junit.Assert.assertNull; 54 import static org.junit.Assert.assertTrue; 55 import static org.junit.Assert.fail; 56 import static org.junit.Assume.assumeTrue; 57 58 import android.annotation.NonNull; 59 import android.annotation.Nullable; 60 import android.content.Context; 61 import android.content.pm.PackageManager; 62 import android.ipsec.ike.cts.IkeTunUtils; 63 import android.net.ConnectivityManager; 64 import android.net.InetAddresses; 65 import android.net.LinkProperties; 66 import android.net.Network; 67 import android.net.NetworkCapabilities; 68 import android.net.NetworkRequest; 69 import android.net.vcn.Flags; 70 import android.net.vcn.VcnCellUnderlyingNetworkTemplate; 71 import android.net.vcn.VcnConfig; 72 import android.net.vcn.VcnGatewayConnectionConfig; 73 import android.net.vcn.VcnManager; 74 import android.net.vcn.VcnNetworkPolicyResult; 75 import android.net.vcn.VcnUnderlyingNetworkTemplate; 76 import android.net.vcn.VcnWifiUnderlyingNetworkTemplate; 77 import android.net.vcn.cts.TestNetworkWrapper.VcnTestNetworkCallback; 78 import android.net.vcn.cts.TestNetworkWrapper.VcnTestNetworkCallback.CapabilitiesChangedEvent; 79 import android.os.ParcelUuid; 80 import android.os.PersistableBundle; 81 import android.os.SystemClock; 82 import android.platform.test.annotations.RequiresFlagsEnabled; 83 import android.platform.test.flag.junit.CheckFlagsRule; 84 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 85 import android.telephony.CarrierConfigManager; 86 import android.telephony.SubscriptionManager; 87 import android.telephony.TelephonyManager; 88 import android.telephony.cts.util.SubscriptionGroupUtils; 89 90 import androidx.test.InstrumentationRegistry; 91 import androidx.test.ext.junit.runners.AndroidJUnit4; 92 93 import com.android.compatibility.common.util.CarrierPrivilegeUtils; 94 95 import org.junit.After; 96 import org.junit.Before; 97 import org.junit.Rule; 98 import org.junit.Test; 99 import org.junit.runner.RunWith; 100 101 import java.net.InetAddress; 102 import java.util.ArrayList; 103 import java.util.Collections; 104 import java.util.HashSet; 105 import java.util.List; 106 import java.util.Set; 107 import java.util.UUID; 108 import java.util.concurrent.BlockingQueue; 109 import java.util.concurrent.CompletableFuture; 110 import java.util.concurrent.Executor; 111 import java.util.concurrent.LinkedBlockingQueue; 112 import java.util.concurrent.TimeUnit; 113 114 @RunWith(AndroidJUnit4.class) 115 public class VcnManagerTest extends VcnTestBase { 116 @Rule 117 public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 118 119 private static final String TAG = VcnManagerTest.class.getSimpleName(); 120 121 private static final int TIMEOUT_MS = 500; 122 private static final long SAFEMODE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(35); 123 124 private static final int ACTIVE_SUB_ID_TIMEOUT_SECONDS = 60; 125 126 private static final Executor INLINE_EXECUTOR = Runnable::run; 127 128 private static final int TEST_NETWORK_MTU = 1500; 129 130 private static final int VCN_STATUS_CODE_AWAIT_TIMEOUT = -1; 131 132 private static final InetAddress LOCAL_ADDRESS = 133 InetAddresses.parseNumericAddress("198.51.100.1"); 134 private static final InetAddress SECONDARY_LOCAL_ADDRESS = 135 InetAddresses.parseNumericAddress("198.51.100.2"); 136 137 private static final long IKE_DETERMINISTIC_INITIATOR_SPI = 138 Long.parseLong("46B8ECA1E0D72A18", 16); 139 140 private final Context mContext; 141 private final VcnManager mVcnManager; 142 private final SubscriptionManager mSubscriptionManager; 143 private final TelephonyManager mTelephonyManager; 144 private final ConnectivityManager mConnectivityManager; 145 private final CarrierConfigManager mCarrierConfigManager; 146 private final int mOldCaptivePortalMode; 147 VcnManagerTest()148 public VcnManagerTest() { 149 mContext = InstrumentationRegistry.getContext(); 150 mVcnManager = mContext.getSystemService(VcnManager.class); 151 mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); 152 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 153 mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); 154 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 155 156 mOldCaptivePortalMode = getCaptivePortalMode(mContext, CAPTIVE_PORTAL_MODE_PROMPT); 157 } 158 159 @Before setUp()160 public void setUp() throws Exception { 161 final boolean hasFeatureTelephony = 162 mContext.getPackageManager().hasSystemFeature(FEATURE_TELEPHONY); 163 final boolean hasFeatureTelSubscription = 164 mContext.getPackageManager().hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION); 165 final boolean hasTelephonyFlag = hasFeatureTelephony || hasFeatureTelSubscription; 166 167 // Before V, only devices with FEATURE_TELEPHONY are required to run the tests. Starting 168 // from V, tests are also required on following cases: 169 // 170 // Device that has a non-null VcnManager even if it has neither of FEATURE_TELEPHONY or 171 // FEATURE_TELEPHONY_SUBSCRIPTION. 172 // 173 // Device that has FEATURE_TELEPHONY_SUBSCRIPTION. This should not be a new requirement 174 // since before V devices with FEATURE_TELEPHONY_SUBSCRIPTION are already enforced to have 175 // FEATURE_TELEPHONY. 176 assumeTrue(hasTelephonyFlag || mVcnManager != null); 177 178 getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(); 179 180 // Ensure Internet probing check will be performed on VCN networks 181 setCaptivePortalMode(mContext, CAPTIVE_PORTAL_MODE_PROMPT); 182 183 runShellCommand("cmd connectivity airplane-mode disable"); 184 } 185 186 @After tearDown()187 public void tearDown() throws Exception { 188 setCaptivePortalMode(mContext, mOldCaptivePortalMode); 189 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 190 } 191 buildVcnConfigBase()192 private VcnConfig.Builder buildVcnConfigBase() { 193 return buildVcnConfigBase(new ArrayList<VcnUnderlyingNetworkTemplate>()); 194 } 195 buildVcnConfigBase(List<VcnUnderlyingNetworkTemplate> nwTemplate)196 private VcnConfig.Builder buildVcnConfigBase(List<VcnUnderlyingNetworkTemplate> nwTemplate) { 197 // TODO(b/191371669): remove the exposed MMS capability and use 198 // VcnGatewayConnectionConfigTest.buildVcnGatewayConnectionConfig() instead 199 return new VcnConfig.Builder(mContext) 200 .addGatewayConnectionConfig( 201 VcnGatewayConnectionConfigTest.buildVcnGatewayConnectionConfigBase() 202 .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_MMS) 203 .setVcnUnderlyingNetworkPriorities(nwTemplate) 204 .addGatewayOption( 205 VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY) 206 .build()); 207 } 208 buildVcnConfig()209 private VcnConfig buildVcnConfig() { 210 return buildVcnConfigBase().build(); 211 } 212 buildTestModeVcnConfig()213 private VcnConfig buildTestModeVcnConfig() { 214 return buildVcnConfigBase().setIsTestModeProfile().build(); 215 } 216 verifyAndGetValidDataSubId()217 private int verifyAndGetValidDataSubId() throws Exception { 218 // Wait for an active sub ID to mitigate the cuttlefish test issue where the CTS will 219 // start before a valid data subId is ready. In most cases this should return immediately 220 // without needing to wait. 221 waitUntil( 222 "There must be an active data subscription to complete CTS", 223 ACTIVE_SUB_ID_TIMEOUT_SECONDS, 224 () -> 225 SubscriptionManager.getDefaultDataSubscriptionId() 226 != INVALID_SUBSCRIPTION_ID); 227 return SubscriptionManager.getDefaultDataSubscriptionId(); 228 } 229 230 @Test(expected = SecurityException.class) testSetVcnConfig_noCarrierPrivileges()231 public void testSetVcnConfig_noCarrierPrivileges() throws Exception { 232 mVcnManager.setVcnConfig(new ParcelUuid(UUID.randomUUID()), buildVcnConfig()); 233 } 234 235 @Test testSetVcnConfig_withCarrierPrivileges()236 public void testSetVcnConfig_withCarrierPrivileges() throws Exception { 237 final int dataSubId = verifyAndGetValidDataSubId(); 238 CarrierPrivilegeUtils.withCarrierPrivileges(mContext, dataSubId, () -> { 239 SubscriptionGroupUtils.withEphemeralSubscriptionGroup(mContext, dataSubId, (subGrp) -> { 240 mVcnManager.setVcnConfig(subGrp, buildVcnConfig()); 241 }); 242 }); 243 244 assertFalse(mTelephonyManager.createForSubscriptionId(dataSubId).hasCarrierPrivileges()); 245 } 246 247 @Test(expected = SecurityException.class) testClearVcnConfig_noCarrierPrivileges()248 public void testClearVcnConfig_noCarrierPrivileges() throws Exception { 249 mVcnManager.clearVcnConfig(new ParcelUuid(UUID.randomUUID())); 250 } 251 252 @Test testClearVcnConfig_withCarrierPrivileges()253 public void testClearVcnConfig_withCarrierPrivileges() throws Exception { 254 final int dataSubId = verifyAndGetValidDataSubId(); 255 256 CarrierPrivilegeUtils.withCarrierPrivileges(mContext, dataSubId, () -> { 257 SubscriptionGroupUtils.withEphemeralSubscriptionGroup(mContext, dataSubId, (subGrp) -> { 258 mVcnManager.clearVcnConfig(subGrp); 259 }); 260 }); 261 } 262 263 /** Test implementation of VcnNetworkPolicyChangeListener for verification purposes. */ 264 private static class TestVcnNetworkPolicyChangeListener 265 implements VcnManager.VcnNetworkPolicyChangeListener { 266 private final CompletableFuture<Void> mFutureOnPolicyChanged = new CompletableFuture<>(); 267 268 @Override onPolicyChanged()269 public void onPolicyChanged() { 270 mFutureOnPolicyChanged.complete(null /* unused */); 271 } 272 awaitOnPolicyChanged()273 public void awaitOnPolicyChanged() throws Exception { 274 mFutureOnPolicyChanged.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); 275 } 276 } 277 278 @Test(expected = SecurityException.class) testAddVcnNetworkPolicyChangeListener_noNetworkFactoryPermission()279 public void testAddVcnNetworkPolicyChangeListener_noNetworkFactoryPermission() 280 throws Exception { 281 // Drop shell permission identity to test unpermissioned behavior. 282 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 283 284 final TestVcnNetworkPolicyChangeListener listener = 285 new TestVcnNetworkPolicyChangeListener(); 286 287 try { 288 mVcnManager.addVcnNetworkPolicyChangeListener(INLINE_EXECUTOR, listener); 289 } finally { 290 mVcnManager.removeVcnNetworkPolicyChangeListener(listener); 291 } 292 } 293 294 @Test testRemoveVcnNetworkPolicyChangeListener_noNetworkFactoryPermission()295 public void testRemoveVcnNetworkPolicyChangeListener_noNetworkFactoryPermission() { 296 final TestVcnNetworkPolicyChangeListener listener = 297 new TestVcnNetworkPolicyChangeListener(); 298 299 mVcnManager.removeVcnNetworkPolicyChangeListener(listener); 300 } 301 302 @Test(expected = SecurityException.class) testApplyVcnNetworkPolicy_noNetworkFactoryPermission()303 public void testApplyVcnNetworkPolicy_noNetworkFactoryPermission() throws Exception { 304 // Drop shell permission identity to test unpermissioned behavior. 305 getInstrumentation().getUiAutomation().dropShellPermissionIdentity(); 306 307 final NetworkCapabilities nc = new NetworkCapabilities.Builder().build(); 308 final LinkProperties lp = new LinkProperties(); 309 310 mVcnManager.applyVcnNetworkPolicy(nc, lp); 311 } 312 313 @Test testApplyVcnNetworkPolicy_manageTestNetworkRequiresTransportTest()314 public void testApplyVcnNetworkPolicy_manageTestNetworkRequiresTransportTest() 315 throws Exception { 316 final NetworkCapabilities nc = 317 new NetworkCapabilities.Builder().addTransportType(TRANSPORT_CELLULAR).build(); 318 final LinkProperties lp = new LinkProperties(); 319 320 runWithShellPermissionIdentity( 321 () -> { 322 try { 323 mVcnManager.applyVcnNetworkPolicy(nc, lp); 324 fail("Expected IllegalStateException for applyVcnNetworkPolicy"); 325 } catch (IllegalStateException e) { 326 } 327 }, 328 android.Manifest.permission.MANAGE_TEST_NETWORKS); 329 } 330 createTestNetworkWrapperForPolicyTest( boolean isRestricted, int subId)331 private TestNetworkWrapper createTestNetworkWrapperForPolicyTest( 332 boolean isRestricted, int subId) throws Exception { 333 final Set<Integer> capabilities = new HashSet<>(); 334 capabilities.add(NET_CAPABILITY_CBS); 335 if (!isRestricted) { 336 capabilities.add(NET_CAPABILITY_NOT_RESTRICTED); 337 } 338 339 return createTestNetworkWrapper(subId, LOCAL_ADDRESS, capabilities); 340 } 341 buildVcnConfigWithTransportTestRestricted()342 private VcnConfig buildVcnConfigWithTransportTestRestricted() { 343 return buildVcnConfigBase() 344 .setIsTestModeProfile() 345 .setRestrictedUnderlyingNetworkTransports(Set.of(TRANSPORT_TEST)) 346 .build(); 347 } 348 349 @Test testApplyVcnNetworkPolicyDuringVcnSetup_onUnrestrictedNetwork()350 public void testApplyVcnNetworkPolicyDuringVcnSetup_onUnrestrictedNetwork() throws Exception { 351 final int subId = verifyAndGetValidDataSubId(); 352 final VcnConfig vcnConfig = buildVcnConfigWithTransportTestRestricted(); 353 354 try (TestNetworkWrapper networkWrapperUnrestricted = 355 createTestNetworkWrapperForPolicyTest(false /* isRestricted */, subId)) { 356 verifyUnderlyingCellAndRunTest( 357 subId, 358 (subGrp, cellNetwork, cellNetworkCb) -> { 359 cellNetworkCb.waitForAvailable(); 360 361 // Attempt VCN setup on an unrestricted network; expect the network to 362 // change to be restricted 363 mVcnManager.setVcnConfig(subGrp, vcnConfig); 364 365 VcnNetworkPolicyResult policyResult = 366 networkWrapperUnrestricted.awaitVcnNetworkPolicyChange(); 367 368 // Expect teardown due to restriction capability change 369 assertTrue(policyResult.isTeardownRequested()); 370 assertFalse( 371 policyResult 372 .getNetworkCapabilities() 373 .hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 374 375 // Verify underlying network is lost 376 networkWrapperUnrestricted.vcnNetworkCallback.waitForLost(); 377 378 mVcnManager.clearVcnConfig(subGrp); 379 }); 380 } 381 } 382 383 @Test testApplyVcnNetworkPolicyDuringVcnSetup_onRestrictedNetwork()384 public void testApplyVcnNetworkPolicyDuringVcnSetup_onRestrictedNetwork() throws Exception { 385 final int subId = verifyAndGetValidDataSubId(); 386 final VcnConfig vcnConfig = buildVcnConfigWithTransportTestRestricted(); 387 388 try (TestNetworkWrapper networkWrapperRestricted = 389 createTestNetworkWrapperForPolicyTest(true /* isRestricted */, subId)) { 390 391 verifyUnderlyingCellAndRunTest( 392 subId, 393 (subGrp, cellNetwork, cellNetworkCb) -> { 394 // Set up VCN on a restricted network 395 final VcnSetupResult vcnSetupResult = 396 setupAndGetVcnNetwork( 397 subGrp, 398 cellNetwork, 399 cellNetworkCb, 400 vcnConfig, 401 networkWrapperRestricted); 402 403 VcnNetworkPolicyResult policyResult = 404 networkWrapperRestricted.awaitVcnNetworkPolicyChange(); 405 406 // Do not expect teardown since the restriction capability does not change 407 assertFalse(policyResult.isTeardownRequested()); 408 assertFalse( 409 policyResult 410 .getNetworkCapabilities() 411 .hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 412 413 clearVcnConfigsAndVerifyNetworkTeardown( 414 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 415 }); 416 } 417 } 418 waitForSafeMode(TestNetworkWrapper networkWrapper)419 private void waitForSafeMode(TestNetworkWrapper networkWrapper) throws Exception { 420 // Once VCN starts, the test network should lose NOT_VCN_MANAGED 421 waitForExpectedUnderlyingNetworkWithCapabilities( 422 networkWrapper, 423 false /* expectNotVcnManaged */, 424 false /* expectNotMetered */, 425 TestNetworkWrapper.NETWORK_CB_TIMEOUT_MS); 426 427 // After VCN has started up, wait for safemode to kick in and expect the 428 // underlying Test Network to regain NOT_VCN_MANAGED. 429 waitForExpectedUnderlyingNetworkWithCapabilities( 430 networkWrapper, 431 true /* expectNotVcnManaged */, 432 false /* expectNotMetered */, 433 SAFEMODE_TIMEOUT_MILLIS); 434 } 435 verifyApplyVcnNetworkPolicyPostVcnSetupChangeNetworkRestriction( boolean isSafeMode, boolean isRestrictedBefore, boolean expectRestrictedAfter)436 private void verifyApplyVcnNetworkPolicyPostVcnSetupChangeNetworkRestriction( 437 boolean isSafeMode, boolean isRestrictedBefore, boolean expectRestrictedAfter) 438 throws Exception { 439 final int subId = verifyAndGetValidDataSubId(); 440 final VcnConfig vcnConfig = buildVcnConfigWithTransportTestRestricted(); 441 442 try (TestNetworkWrapper networkWrapperRestricted = 443 createTestNetworkWrapperForPolicyTest(true /* isRestricted */, subId)) { 444 445 verifyUnderlyingCellAndRunTest( 446 subId, 447 (subGrp, cellNetwork, cellNetworkCb) -> { 448 // Set up VCN on a restricted network 449 final VcnSetupResult vcnSetupResult = 450 setupAndGetVcnNetwork( 451 subGrp, 452 cellNetwork, 453 cellNetworkCb, 454 vcnConfig, 455 networkWrapperRestricted); 456 457 if (isSafeMode) { 458 waitForSafeMode(networkWrapperRestricted); 459 } 460 461 // Bring up another test network and verify its restriction capability 462 // change. 463 try (TestNetworkWrapper testNetworkWrapper = 464 createTestNetworkWrapperForPolicyTest(isRestrictedBefore, subId)) { 465 466 // The requested NetworkCapabilities should have been changed by 467 // VcnManager before the test network was brought up. Verify it by 468 // checking the NetworkCapabilities after the network setup. 469 final NetworkCapabilities nc = 470 mConnectivityManager.getNetworkCapabilities( 471 testNetworkWrapper.tunNetwork); 472 assertEquals( 473 !expectRestrictedAfter, 474 nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); 475 } 476 477 clearVcnConfigsAndVerifyNetworkTeardown( 478 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 479 }); 480 } 481 } 482 483 @Test testApplyVcnNetworkPolicy_activeMode_onRestrictedNetwork()484 public void testApplyVcnNetworkPolicy_activeMode_onRestrictedNetwork() throws Exception { 485 verifyApplyVcnNetworkPolicyPostVcnSetupChangeNetworkRestriction( 486 false /* isSafeMode */, 487 true /* isRestrictedBefore */, 488 true /* expectRestrictedAfter */); 489 } 490 491 @Test testApplyVcnNetworkPolicy_safeMode_onRestrictedNetwork()492 public void testApplyVcnNetworkPolicy_safeMode_onRestrictedNetwork() throws Exception { 493 verifyApplyVcnNetworkPolicyPostVcnSetupChangeNetworkRestriction( 494 true /* isSafeMode */, 495 true /* isRestrictedBefore */, 496 true /* expectRestrictedAfter */); 497 } 498 499 @Test testApplyVcnNetworkPolicy_activeMode_onUnrestrictedNetwork()500 public void testApplyVcnNetworkPolicy_activeMode_onUnrestrictedNetwork() throws Exception { 501 verifyApplyVcnNetworkPolicyPostVcnSetupChangeNetworkRestriction( 502 false /* isSafeMode */, 503 false /* isRestrictedBefore */, 504 true /* expectRestrictedAfter */); 505 } 506 507 @Test testApplyVcnNetworkPolicy_safeMode_onUnrestrictedNetwork()508 public void testApplyVcnNetworkPolicy_safeMode_onUnrestrictedNetwork() throws Exception { 509 verifyApplyVcnNetworkPolicyPostVcnSetupChangeNetworkRestriction( 510 true /* isSafeMode */, 511 false /* isRestrictedBefore */, 512 false /* expectRestrictedAfter */); 513 } 514 515 /** Test implementation of VcnStatusCallback for verification purposes. */ 516 private static class TestVcnStatusCallback extends VcnManager.VcnStatusCallback { 517 private final BlockingQueue<Integer> mOnStatusChangedHistory = new LinkedBlockingQueue<>(); 518 private final BlockingQueue<GatewayConnectionError> mOnGatewayConnectionErrorHistory = 519 new LinkedBlockingQueue<>(); 520 521 @Override onStatusChanged(int statusCode)522 public void onStatusChanged(int statusCode) { 523 mOnStatusChangedHistory.offer(statusCode); 524 } 525 526 @Override onGatewayConnectionError( @onNull String gatewayConnectionName, int errorCode, @Nullable Throwable detail)527 public void onGatewayConnectionError( 528 @NonNull String gatewayConnectionName, int errorCode, @Nullable Throwable detail) { 529 mOnGatewayConnectionErrorHistory.offer( 530 new GatewayConnectionError(gatewayConnectionName, errorCode, detail)); 531 } 532 awaitOnStatusChanged()533 public int awaitOnStatusChanged() throws Exception { 534 final Integer status = mOnStatusChangedHistory.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS); 535 536 // Null means timeout 537 return status == null ? VCN_STATUS_CODE_AWAIT_TIMEOUT : status; 538 } 539 awaitOnGatewayConnectionError()540 public GatewayConnectionError awaitOnGatewayConnectionError() throws Exception { 541 return mOnGatewayConnectionErrorHistory.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS); 542 } 543 } 544 verifyVcnStatus(ParcelUuid subGrp, int expectedStatus)545 private void verifyVcnStatus(ParcelUuid subGrp, int expectedStatus) throws Exception { 546 final TestVcnStatusCallback callback = new TestVcnStatusCallback(); 547 mVcnManager.registerVcnStatusCallback(subGrp, INLINE_EXECUTOR, callback); 548 549 assertEquals(expectedStatus, callback.awaitOnStatusChanged()); 550 551 mVcnManager.unregisterVcnStatusCallback(callback); 552 } 553 554 /** Info class for organizing VcnStatusCallback#onGatewayConnectionError response data. */ 555 private static class GatewayConnectionError { 556 @NonNull public final String gatewayConnectionName; 557 public final int errorCode; 558 @Nullable public final Throwable detail; 559 GatewayConnectionError( @onNull String gatewayConnectionName, int errorCode, @Nullable Throwable detail)560 public GatewayConnectionError( 561 @NonNull String gatewayConnectionName, int errorCode, @Nullable Throwable detail) { 562 this.gatewayConnectionName = gatewayConnectionName; 563 this.errorCode = errorCode; 564 this.detail = detail; 565 } 566 } 567 registerVcnStatusCallbackForSubId( @onNull TestVcnStatusCallback callback, int subId)568 private void registerVcnStatusCallbackForSubId( 569 @NonNull TestVcnStatusCallback callback, int subId) throws Exception { 570 CarrierPrivilegeUtils.withCarrierPrivileges(mContext, subId, () -> { 571 SubscriptionGroupUtils.withEphemeralSubscriptionGroup(mContext, subId, (subGrp) -> { 572 mVcnManager.registerVcnStatusCallback(subGrp, INLINE_EXECUTOR, callback); 573 }); 574 }); 575 } 576 577 @Test testRegisterVcnStatusCallback()578 public void testRegisterVcnStatusCallback() throws Exception { 579 final TestVcnStatusCallback callback = new TestVcnStatusCallback(); 580 final int subId = verifyAndGetValidDataSubId(); 581 582 try { 583 registerVcnStatusCallbackForSubId(callback, subId); 584 585 final int statusCode = callback.awaitOnStatusChanged(); 586 assertEquals(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED, statusCode); 587 } finally { 588 mVcnManager.unregisterVcnStatusCallback(callback); 589 } 590 } 591 592 @Test testRegisterVcnStatusCallback_reuseUnregisteredCallback()593 public void testRegisterVcnStatusCallback_reuseUnregisteredCallback() throws Exception { 594 final TestVcnStatusCallback callback = new TestVcnStatusCallback(); 595 final int subId = verifyAndGetValidDataSubId(); 596 597 try { 598 registerVcnStatusCallbackForSubId(callback, subId); 599 mVcnManager.unregisterVcnStatusCallback(callback); 600 registerVcnStatusCallbackForSubId(callback, subId); 601 } finally { 602 mVcnManager.unregisterVcnStatusCallback(callback); 603 } 604 } 605 606 @Test(expected = IllegalStateException.class) testRegisterVcnStatusCallback_duplicateRegister()607 public void testRegisterVcnStatusCallback_duplicateRegister() throws Exception { 608 final TestVcnStatusCallback callback = new TestVcnStatusCallback(); 609 final int subId = verifyAndGetValidDataSubId(); 610 611 try { 612 registerVcnStatusCallbackForSubId(callback, subId); 613 registerVcnStatusCallbackForSubId(callback, subId); 614 } finally { 615 mVcnManager.unregisterVcnStatusCallback(callback); 616 } 617 } 618 619 @Test testUnregisterVcnStatusCallback()620 public void testUnregisterVcnStatusCallback() throws Exception { 621 final TestVcnStatusCallback callback = new TestVcnStatusCallback(); 622 623 mVcnManager.unregisterVcnStatusCallback(callback); 624 } 625 createTestNetworkWrapper( int subId, InetAddress localAddress, Set<Integer> capabilities)626 private TestNetworkWrapper createTestNetworkWrapper( 627 int subId, InetAddress localAddress, Set<Integer> capabilities) throws Exception { 628 TestNetworkWrapper testNetworkWrapper = 629 new TestNetworkWrapper( 630 mContext, 631 TEST_NETWORK_MTU, 632 capabilities, 633 Collections.singleton(subId), 634 localAddress); 635 assertNotNull("No test network found", testNetworkWrapper.tunNetwork); 636 return testNetworkWrapper; 637 } 638 createTestNetworkWrapper( boolean isMetered, int subId, InetAddress localAddress)639 private TestNetworkWrapper createTestNetworkWrapper( 640 boolean isMetered, int subId, InetAddress localAddress) throws Exception { 641 final Set<Integer> capabilities = new HashSet<>(); 642 capabilities.add(NET_CAPABILITY_CBS); 643 if (!isMetered) { 644 capabilities.add(NET_CAPABILITY_NOT_METERED); 645 } 646 647 return createTestNetworkWrapper(subId, localAddress, capabilities); 648 } 649 650 @Test testVcnManagedNetworkLosesNotVcnManagedCapability()651 public void testVcnManagedNetworkLosesNotVcnManagedCapability() throws Exception { 652 final int subId = verifyAndGetValidDataSubId(); 653 try (TestNetworkWrapper testNetworkWrapper = 654 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 655 // Before the VCN starts, the test network should have NOT_VCN_MANAGED 656 waitForExpectedUnderlyingNetworkWithCapabilities( 657 testNetworkWrapper, 658 true /* expectNotVcnManaged */, 659 false /* expectNotMetered */, 660 TestNetworkWrapper.NETWORK_CB_TIMEOUT_MS); 661 662 CarrierPrivilegeUtils.withCarrierPrivilegesForShell(mContext, subId, () -> { 663 SubscriptionGroupUtils.withEphemeralSubscriptionGroup(mContext, subId, (subGrp) -> { 664 mVcnManager.setVcnConfig(subGrp, buildVcnConfig()); 665 666 // Once VCN starts, the test network should lose NOT_VCN_MANAGED 667 waitForExpectedUnderlyingNetworkWithCapabilities( 668 testNetworkWrapper, 669 false /* expectNotVcnManaged */, 670 false /* expectNotMetered */, 671 TestNetworkWrapper.NETWORK_CB_TIMEOUT_MS); 672 673 mVcnManager.clearVcnConfig(subGrp); 674 675 // After the VCN tears down, the test network should have 676 // NOT_VCN_MANAGED again 677 waitForExpectedUnderlyingNetworkWithCapabilities( 678 testNetworkWrapper, 679 true /* expectNotVcnManaged */, 680 false /* expectNotMetered */, 681 TestNetworkWrapper.NETWORK_CB_TIMEOUT_MS); 682 }); 683 }); 684 } 685 } 686 waitForExpectedUnderlyingNetworkWithCapabilities( TestNetworkWrapper testNetworkWrapper, boolean expectNotVcnManaged, boolean expectNotMetered, long timeoutMillis)687 private void waitForExpectedUnderlyingNetworkWithCapabilities( 688 TestNetworkWrapper testNetworkWrapper, 689 boolean expectNotVcnManaged, 690 boolean expectNotMetered, 691 long timeoutMillis) 692 throws Exception { 693 final long start = SystemClock.elapsedRealtime(); 694 695 // Wait for NetworkCapabilities changes until they match the expected capabilities 696 do { 697 final CapabilitiesChangedEvent capabilitiesChangedEvent = 698 testNetworkWrapper.vcnNetworkCallback.waitForOnCapabilitiesChanged( 699 timeoutMillis); 700 assertNotNull("Failed to receive NetworkCapabilities change", capabilitiesChangedEvent); 701 702 final NetworkCapabilities nc = capabilitiesChangedEvent.networkCapabilities; 703 if (testNetworkWrapper.tunNetwork.equals(capabilitiesChangedEvent.network) 704 && nc.hasCapability(NET_CAPABILITY_VALIDATED) 705 && expectNotVcnManaged == nc.hasCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 706 && expectNotMetered == nc.hasCapability(NET_CAPABILITY_NOT_METERED)) { 707 return; 708 } 709 } while (SystemClock.elapsedRealtime() - start < timeoutMillis); 710 711 fail( 712 "Expected update for network=" 713 + testNetworkWrapper.tunNetwork.getNetId() 714 + ". Wanted NOT_VCN_MANAGED=" 715 + expectNotVcnManaged 716 + " NOT_METERED=" 717 + expectNotMetered); 718 } 719 720 private interface VcnTestRunnable { runTest(ParcelUuid subGrp, Network cellNetwork, VcnTestNetworkCallback cellNetworkCb)721 void runTest(ParcelUuid subGrp, Network cellNetwork, VcnTestNetworkCallback cellNetworkCb) 722 throws Exception; 723 } 724 verifyUnderlyingCellAndRunTest(int subId, VcnTestRunnable test)725 private void verifyUnderlyingCellAndRunTest(int subId, VcnTestRunnable test) throws Exception { 726 // Get current cell Network then wait for it to drop (due to losing NOT_VCN_MANAGED) 727 // before waiting for VCN Network. 728 final NetworkRequest cellNetworkReq = 729 new NetworkRequest.Builder() 730 .addTransportType(TRANSPORT_CELLULAR) 731 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 732 .build(); 733 final VcnTestNetworkCallback cellNetworkCb = new VcnTestNetworkCallback(); 734 mConnectivityManager.requestNetwork(cellNetworkReq, cellNetworkCb); 735 final Network cellNetwork = cellNetworkCb.waitForAvailable(); 736 assertNotNull("No cell network found", cellNetwork); 737 738 CarrierPrivilegeUtils.withCarrierPrivilegesForShell(mContext, subId, () -> { 739 SubscriptionGroupUtils.withEphemeralSubscriptionGroup( 740 mContext, 741 subId, 742 (subGrp) -> { 743 test.runTest(subGrp, cellNetwork, cellNetworkCb); 744 } 745 ); 746 }); 747 mConnectivityManager.unregisterNetworkCallback(cellNetworkCb); 748 } 749 750 @Test testSetVcnConfigOnTestNetwork()751 public void testSetVcnConfigOnTestNetwork() throws Exception { 752 final int subId = verifyAndGetValidDataSubId(); 753 754 try (TestNetworkWrapper testNetworkWrapper = 755 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 756 verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> { 757 final VcnSetupResult vcnSetupResult = 758 setupAndGetVcnNetwork(subGrp, cellNetwork, cellNetworkCb, testNetworkWrapper); 759 760 clearVcnConfigsAndVerifyNetworkTeardown( 761 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 762 }); 763 } 764 } 765 766 @Test testSetVcnConfigOnTestNetworkAndHandleDataStall()767 public void testSetVcnConfigOnTestNetworkAndHandleDataStall() throws Exception { 768 final int subId = verifyAndGetValidDataSubId(); 769 770 try (TestNetworkWrapper testNetworkWrapper = 771 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 772 verifyUnderlyingCellAndRunTest( 773 subId, 774 (subGrp, cellNetwork, cellNetworkCb) -> { 775 final VcnSetupResult vcnSetupResult = 776 setupAndGetVcnNetwork( 777 subGrp, cellNetwork, cellNetworkCb, testNetworkWrapper); 778 779 mConnectivityManager.simulateDataStall( 780 DETECTION_METHOD_DNS_EVENTS, 781 System.currentTimeMillis(), 782 vcnSetupResult.vcnNetwork, 783 new PersistableBundle() /* extra data stall info; unused */); 784 785 injectAndVerifyIkeMobikePackets(testNetworkWrapper.ikeTunUtils); 786 787 clearVcnConfigsAndVerifyNetworkTeardown( 788 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 789 }); 790 } 791 } 792 createTestNetworkForNetworkSelection( int subId, Set<Integer> capabilities)793 private TestNetworkWrapper createTestNetworkForNetworkSelection( 794 int subId, Set<Integer> capabilities) throws Exception { 795 return createTestNetworkWrapper(subId, LOCAL_ADDRESS, capabilities); 796 } 797 verifyVcnMigratesToPreferredUnderlyingNetwork( VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)798 private void verifyVcnMigratesToPreferredUnderlyingNetwork( 799 VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred) 800 throws Exception { 801 final int subId = verifyAndGetValidDataSubId(); 802 803 // Start on a less preferred network. 804 try (TestNetworkWrapper testNetworkWrapperLessPreferred = 805 createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) { 806 verifyUnderlyingCellAndRunTest( 807 subId, 808 (subGrp, cellNetwork, cellNetworkCb) -> { 809 final VcnSetupResult vcnSetupResult = 810 setupAndGetVcnNetwork( 811 subGrp, 812 cellNetwork, 813 cellNetworkCb, 814 vcnConfig, 815 testNetworkWrapperLessPreferred); 816 817 // Then bring up a more preferred network, and expect to switch to it. 818 try (TestNetworkWrapper testNetworkWrapperPreferred = 819 createTestNetworkForNetworkSelection(subId, capSetPreferred)) { 820 injectAndVerifyIkeMobikePackets( 821 testNetworkWrapperPreferred.ikeTunUtils); 822 823 clearVcnConfigsAndVerifyNetworkTeardown( 824 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 825 } 826 }); 827 } 828 } 829 verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork( VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)830 private void verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork( 831 VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred) 832 throws Exception { 833 final int subId = verifyAndGetValidDataSubId(); 834 835 // Start on a more preferred network. 836 try (TestNetworkWrapper testNetworkWrapperPreferred = 837 createTestNetworkForNetworkSelection(subId, capSetPreferred)) { 838 verifyUnderlyingCellAndRunTest( 839 subId, 840 (subGrp, cellNetwork, cellNetworkCb) -> { 841 final VcnSetupResult vcnSetupResult = 842 setupAndGetVcnNetwork( 843 subGrp, 844 cellNetwork, 845 cellNetworkCb, 846 vcnConfig, 847 testNetworkWrapperPreferred); 848 849 // Then bring up a less preferred network, and expect the VCN underlying 850 // network does not change. 851 try (TestNetworkWrapper testNetworkWrapperLessPreferred = 852 createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) { 853 injectAndVerifyIkeDpdPackets( 854 testNetworkWrapperPreferred.ikeTunUtils, 855 vcnSetupResult.ikeExchangePortPair); 856 857 clearVcnConfigsAndVerifyNetworkTeardown( 858 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 859 } 860 }); 861 } 862 } 863 verifyVcnMigratesAfterPreferredUnderlyingNetworkDies( VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)864 private void verifyVcnMigratesAfterPreferredUnderlyingNetworkDies( 865 VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred) 866 throws Exception { 867 final int subId = verifyAndGetValidDataSubId(); 868 869 // Start on a more preferred network 870 try (TestNetworkWrapper testNetworkWrapperPreferred = 871 createTestNetworkForNetworkSelection(subId, capSetPreferred)) { 872 verifyUnderlyingCellAndRunTest( 873 subId, 874 (subGrp, cellNetwork, cellNetworkCb) -> { 875 final VcnSetupResult vcnSetupResult = 876 setupAndGetVcnNetwork( 877 subGrp, 878 cellNetwork, 879 cellNetworkCb, 880 vcnConfig, 881 testNetworkWrapperPreferred); 882 883 // Bring up a less preferred network 884 try (TestNetworkWrapper testNetworkWrapperLessPreferred = 885 createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) { 886 // Teardown the preferred network 887 testNetworkWrapperPreferred.close(); 888 testNetworkWrapperPreferred.vcnNetworkCallback.waitForLost(); 889 890 // Verify the VCN switches to the remaining less preferred network 891 injectAndVerifyIkeMobikePackets( 892 testNetworkWrapperLessPreferred.ikeTunUtils); 893 894 clearVcnConfigsAndVerifyNetworkTeardown( 895 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 896 } 897 }); 898 } 899 } 900 createCellTemplateBaseBuilder()901 private VcnCellUnderlyingNetworkTemplate.Builder createCellTemplateBaseBuilder() 902 throws Exception { 903 return new VcnCellUnderlyingNetworkTemplate.Builder().setInternet(MATCH_ANY); 904 } 905 createVcnConfigPrefersMetered()906 private VcnConfig createVcnConfigPrefersMetered() throws Exception { 907 final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>(); 908 nwTemplates.add( 909 createCellTemplateBaseBuilder() 910 .setCbs(MATCH_REQUIRED) 911 .setMetered(MATCH_REQUIRED) 912 .build()); 913 nwTemplates.add( 914 createCellTemplateBaseBuilder() 915 .setCbs(MATCH_REQUIRED) 916 .setMetered(MATCH_FORBIDDEN) 917 .build()); 918 return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build(); 919 } 920 921 @Test testVcnMigratesToPreferredUnderlyingNetwork_preferMetered()922 public void testVcnMigratesToPreferredUnderlyingNetwork_preferMetered() throws Exception { 923 verifyVcnMigratesToPreferredUnderlyingNetwork( 924 createVcnConfigPrefersMetered(), 925 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS), 926 Set.of(NET_CAPABILITY_CBS)); 927 } 928 929 @Test testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferMetered()930 public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferMetered() 931 throws Exception { 932 verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork( 933 createVcnConfigPrefersMetered(), 934 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS), 935 Set.of(NET_CAPABILITY_CBS)); 936 } 937 938 @Test testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferMetered()939 public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferMetered() 940 throws Exception { 941 verifyVcnMigratesAfterPreferredUnderlyingNetworkDies( 942 createVcnConfigPrefersMetered(), 943 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS), 944 Set.of(NET_CAPABILITY_CBS)); 945 } 946 createVcnConfigPrefersCbs()947 private VcnConfig createVcnConfigPrefersCbs() throws Exception { 948 final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>(); 949 nwTemplates.add(createCellTemplateBaseBuilder().setCbs(MATCH_REQUIRED).build()); 950 nwTemplates.add(createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).build()); 951 952 return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build(); 953 } 954 955 @Test testVcnMigratesToPreferredUnderlyingNetwork_preferCbs()956 public void testVcnMigratesToPreferredUnderlyingNetwork_preferCbs() throws Exception { 957 verifyVcnMigratesToPreferredUnderlyingNetwork( 958 createVcnConfigPrefersCbs(), 959 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS), 960 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS)); 961 } 962 963 @Test testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferCbs()964 public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferCbs() throws Exception { 965 verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork( 966 createVcnConfigPrefersCbs(), 967 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS), 968 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS)); 969 } 970 971 @Test testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferCbs()972 public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferCbs() throws Exception { 973 verifyVcnMigratesAfterPreferredUnderlyingNetworkDies( 974 createVcnConfigPrefersCbs(), 975 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS), 976 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS)); 977 } 978 createVcnConfigPrefersNonCbs()979 private VcnConfig createVcnConfigPrefersNonCbs() throws Exception { 980 final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>(); 981 nwTemplates.add( 982 createCellTemplateBaseBuilder() 983 .setRcs(MATCH_REQUIRED) 984 .setCbs(MATCH_FORBIDDEN) 985 .build()); 986 nwTemplates.add( 987 createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build()); 988 989 return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build(); 990 } 991 992 @Test testVcnMigratesToPreferredUnderlyingNetwork_preferNonCbs()993 public void testVcnMigratesToPreferredUnderlyingNetwork_preferNonCbs() throws Exception { 994 verifyVcnMigratesToPreferredUnderlyingNetwork( 995 createVcnConfigPrefersNonCbs(), 996 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS), 997 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS)); 998 } 999 1000 @Test testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferNonCbs()1001 public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferNonCbs() throws Exception { 1002 verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork( 1003 createVcnConfigPrefersNonCbs(), 1004 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS), 1005 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS)); 1006 } 1007 1008 @Test testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferNonCbs()1009 public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferNonCbs() throws Exception { 1010 verifyVcnMigratesAfterPreferredUnderlyingNetworkDies( 1011 createVcnConfigPrefersNonCbs(), 1012 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS), 1013 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS)); 1014 } 1015 1016 @Test testSetVcnWithCbsMatchAny_preferCbsNetworkOverUnmatchedNetwork()1017 public void testSetVcnWithCbsMatchAny_preferCbsNetworkOverUnmatchedNetwork() throws Exception { 1018 final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>(); 1019 nwTemplates.add( 1020 createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build()); 1021 1022 final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build(); 1023 1024 verifyVcnMigratesToPreferredUnderlyingNetwork( 1025 vcnConfig, 1026 Set.of(NET_CAPABILITY_NOT_METERED), 1027 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS)); 1028 } 1029 1030 @Test testSetVcnWithCbsMatchAny_preferNonCbsNetworkOverUnmatchedNetwork()1031 public void testSetVcnWithCbsMatchAny_preferNonCbsNetworkOverUnmatchedNetwork() 1032 throws Exception { 1033 final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>(); 1034 nwTemplates.add( 1035 createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build()); 1036 1037 final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build(); 1038 1039 verifyVcnMigratesToPreferredUnderlyingNetwork( 1040 vcnConfig, 1041 Set.of(NET_CAPABILITY_NOT_METERED), 1042 Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS)); 1043 } 1044 1045 @Test testVcnNoUnderlyingNetworkSelectedFallback()1046 public void testVcnNoUnderlyingNetworkSelectedFallback() throws Exception { 1047 final int subId = verifyAndGetValidDataSubId(); 1048 final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>(); 1049 nwTemplates.add( 1050 new VcnWifiUnderlyingNetworkTemplate.Builder().setMetered(MATCH_REQUIRED).build()); 1051 final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build(); 1052 1053 // Bring up a network that does not match any of the configured network templates 1054 try (TestNetworkWrapper testNetworkWrapper = 1055 createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) { 1056 verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> { 1057 // Verify the VCN can still be set up on the only one underlying network 1058 final VcnSetupResult vcnSetupResult = 1059 setupAndGetVcnNetwork( 1060 subGrp, 1061 cellNetwork, 1062 cellNetworkCb, 1063 vcnConfig, 1064 testNetworkWrapper); 1065 1066 clearVcnConfigsAndVerifyNetworkTeardown( 1067 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 1068 }); 1069 } 1070 } 1071 1072 private static class VcnSetupResult { 1073 public final Network vcnNetwork; 1074 public final PortPair ikeExchangePortPair; 1075 VcnSetupResult(Network vcnNetwork, PortPair ikeExchangePortPair)1076 VcnSetupResult(Network vcnNetwork, PortPair ikeExchangePortPair) { 1077 this.vcnNetwork = vcnNetwork; 1078 this.ikeExchangePortPair = ikeExchangePortPair; 1079 } 1080 } 1081 setupAndGetVcnNetwork( @onNull ParcelUuid subGrp, @NonNull Network cellNetwork, @NonNull VcnTestNetworkCallback cellNetworkCb, @NonNull VcnConfig testModeVcnConfig, @NonNull TestNetworkWrapper testNetworkWrapper)1082 private VcnSetupResult setupAndGetVcnNetwork( 1083 @NonNull ParcelUuid subGrp, 1084 @NonNull Network cellNetwork, 1085 @NonNull VcnTestNetworkCallback cellNetworkCb, 1086 @NonNull VcnConfig testModeVcnConfig, 1087 @NonNull TestNetworkWrapper testNetworkWrapper) 1088 throws Exception { 1089 cellNetworkCb.waitForAvailable(); 1090 mVcnManager.setVcnConfig(subGrp, testModeVcnConfig); 1091 1092 // Wait until the cell Network is lost (due to losing NOT_VCN_MANAGED) to wait for 1093 // VCN network 1094 final Network lostCellNetwork = cellNetworkCb.waitForLost(); 1095 assertEquals(cellNetwork, lostCellNetwork); 1096 1097 final PortPair ikeExchangePortPair = 1098 injectAndVerifyIkeSessionNegotiationPackets(testNetworkWrapper.ikeTunUtils); 1099 1100 final Network vcnNetwork = cellNetworkCb.waitForAvailable(); 1101 assertNotNull("VCN network did not come up", vcnNetwork); 1102 return new VcnSetupResult(vcnNetwork, ikeExchangePortPair); 1103 } 1104 setupAndGetVcnNetwork( @onNull ParcelUuid subGrp, @NonNull Network cellNetwork, @NonNull VcnTestNetworkCallback cellNetworkCb, @NonNull TestNetworkWrapper testNetworkWrapper)1105 private VcnSetupResult setupAndGetVcnNetwork( 1106 @NonNull ParcelUuid subGrp, 1107 @NonNull Network cellNetwork, 1108 @NonNull VcnTestNetworkCallback cellNetworkCb, 1109 @NonNull TestNetworkWrapper testNetworkWrapper) 1110 throws Exception { 1111 return setupAndGetVcnNetwork( 1112 subGrp, cellNetwork, cellNetworkCb, buildTestModeVcnConfig(), testNetworkWrapper); 1113 } 1114 injectAndVerifyIkeSessionNegotiationPackets(@onNull IkeTunUtils ikeTunUtils)1115 private PortPair injectAndVerifyIkeSessionNegotiationPackets(@NonNull IkeTunUtils ikeTunUtils) 1116 throws Exception { 1117 // Generated by forcing IKE to use Test Mode (RandomnessFactory#mIsTestModeEnabled) and 1118 // capturing IKE packets with a live server. 1119 final String ikeInitResp = 1120 "46b8eca1e0d72a189b9f8e0158e1c0a52120222000000000000001d022000030" 1121 + "0000002c010100040300000c0100000c800e0080030000080300000803000008" 1122 + "02000008000000080400000e28000108000e0000164d3413d855a1642d4d6355" 1123 + "a8ef6666bfaa28a4b5264600c9ffbaef7930bd33af49022926013aae0a48d764" 1124 + "750ccb3987605957e31a2ef0e6838cfa67af989933c2879434081c4e9787f0d4" 1125 + "4da0d7dacca5589702a4537ee4fb18e8db21a948b245260f55212a1c619f61c6" 1126 + "fa1caaff4474082f9714b14ef4bcc7b2b8f43fcb939931119e53b05274faec65" 1127 + "2816c563529e60c1a88183eba9c456ecb644faf57b726b83e3242e08489d95e9" 1128 + "81e59c7ad82cf3cdfb00fe0213c4e65d61e88bbefbd536261027da722a2bbf89" 1129 + "c6378e63ce6fbcef282421e5576bba1b2faa3c4c2d41028f91df7ba165a24a18" 1130 + "fcba4f96db3e5e0eed76dc7c3c432362dd4a82d32900002461cbd03c08819730" 1131 + "f1060ed0c0446f784eb8dd884d3f73f54eb2b0c3071cc4f32900001c00004004" 1132 + "07150f3fd9584dbebb7e88ad256c7bfb9b0bb55a2900001c00004005e3aa3788" 1133 + "7040e38dbb4de8fd435161cce904ec59290000080000402e290000100000402f" 1134 + "00020003000400050000000800004014"; 1135 final String ikeAuthResp = 1136 "46b8eca1e0d72a189b9f8e0158e1c0a52e20232000000001000000fc240000e0" 1137 + "1a666eb2a02b37682436a18fff5e9cef67b9096d6c7887ed235f8b5173c9469e" 1138 + "361621b66849de2dbcabf956b3d055cafafd503530543540e81dac9bf8fb8826" 1139 + "e08bc99e9ed2185d8f1322c8885abe4f98a9832c694da775eaa4ae69f17b8cbf" 1140 + "b009bf82b4bf4012bca489595631c3168cd417f813e7d177d2ceb70766a0773c" 1141 + "8819d8763627ddc9455ae3d5a5a03224020a66c8e58c8073c4a1fcf5d67cfa95" 1142 + "15de86b392a63ff54ff5572302b9ce7725085b05839252794c3680f5d8f34019" 1143 + "fa1930ea045d2a9987850e2049235c7328ef148370b6a3403408b987"; 1144 1145 ikeTunUtils.awaitReqAndInjectResp( 1146 IKE_DETERMINISTIC_INITIATOR_SPI, 1147 0 /* expectedMsgId */, 1148 false /* expectedUseEncap */, 1149 ikeInitResp); 1150 1151 byte[] ikeAuthReqPkt = 1152 ikeTunUtils.awaitReqAndInjectResp( 1153 IKE_DETERMINISTIC_INITIATOR_SPI, 1154 1 /* expectedMsgId */, 1155 true /* expectedUseEncap */, 1156 ikeAuthResp); 1157 1158 return IkeTunUtils.getSrcDestPortPair(ikeAuthReqPkt); 1159 } 1160 clearVcnConfigsAndVerifyNetworkTeardown( @onNull ParcelUuid subGrp, @NonNull VcnTestNetworkCallback cellNetworkCb, @NonNull Network vcnNetwork)1161 private void clearVcnConfigsAndVerifyNetworkTeardown( 1162 @NonNull ParcelUuid subGrp, 1163 @NonNull VcnTestNetworkCallback cellNetworkCb, 1164 @NonNull Network vcnNetwork) 1165 throws Exception { 1166 // Clear the history to remove other networks have been matched to the request 1167 cellNetworkCb.clearLostHistory(); 1168 1169 mVcnManager.clearVcnConfig(subGrp); 1170 1171 // Expect VCN Network to disappear after VcnConfig is cleared. 1172 if (mConnectivityManager.getNetworkCapabilities(vcnNetwork) != null) { 1173 1174 // If not already torn down, wait for teardown. In the event that the underlying network 1175 // has already regained the NOT_VCN_MANAGED bit (before the VCN's NetworkAgent teardown) 1176 // the VCN network MAY be immediately replaced with the underlying Cell, which only 1177 // fires an onAvailable for the new network, as opposed to an onLost() for the VCN 1178 // network. In that case, check that the VCN network has been unregistered. 1179 // 1180 // An alternative approach is to monitor #onAvailable as an indicator of potential 1181 // network loss. However, since #onAvailable can mean either 1) the new network has 1182 // higher priority, or 2) the old network is disconnected, this approach will introduce 1183 // a lot more complexities. 1184 final Network lostVcnNetwork = cellNetworkCb.waitForLost(); 1185 if (lostVcnNetwork != null) { 1186 assertEquals(vcnNetwork, lostVcnNetwork); 1187 } else { 1188 assertNull(mConnectivityManager.getNetworkCapabilities(vcnNetwork)); 1189 } 1190 } // Else already torn down, pass. 1191 } 1192 1193 @Test testVcnMigrationAfterNetworkDies()1194 public void testVcnMigrationAfterNetworkDies() throws Exception { 1195 final int subId = verifyAndGetValidDataSubId(); 1196 1197 try (TestNetworkWrapper testNetworkWrapper = 1198 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 1199 verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> { 1200 final VcnSetupResult vcnSetupResult = 1201 setupAndGetVcnNetwork(subGrp, cellNetwork, cellNetworkCb, testNetworkWrapper); 1202 1203 testNetworkWrapper.close(); 1204 testNetworkWrapper.vcnNetworkCallback.waitForLost(); 1205 1206 try (TestNetworkWrapper secondaryTestNetworkWrapper = 1207 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 1208 try { 1209 injectAndVerifyIkeMobikePackets(secondaryTestNetworkWrapper.ikeTunUtils); 1210 1211 clearVcnConfigsAndVerifyNetworkTeardown( 1212 subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork); 1213 } finally { 1214 secondaryTestNetworkWrapper.close(); 1215 } 1216 } 1217 }); 1218 } 1219 } 1220 injectAndVerifyIkeMobikePackets(@onNull IkeTunUtils ikeTunUtils)1221 private void injectAndVerifyIkeMobikePackets(@NonNull IkeTunUtils ikeTunUtils) 1222 throws Exception { 1223 // Generated by forcing IKE to use Test Mode (RandomnessFactory#mIsTestModeEnabled) and 1224 // capturing IKE packets with a live server. To force the mobility event, use 1225 // IkeSession#setNetwork with the new desired Network. 1226 final String ikeUpdateSaResp = 1227 "46b8eca1e0d72a189b9f8e0158e1c0a52e202520000000020000007c29000060" 1228 + "a1fd35f112d92d1df19ce734f6edf56ccda1bfd44ef6de428a097e04d5b40b28" 1229 + "3897e42f23dd53e444dc6c676cf9a7d9d73bb3975d663ec351fb5ae4e56a55d8" 1230 + "cbcf376a3b99cc6fd858621cc78b3017d895e4309f09a444028dba85"; 1231 final String ikeCreateChildResp = 1232 "46b8eca1e0d72a189b9f8e0158e1c0a52e20242000000003000000cc210000b0" 1233 + "e6bb78203dbe2189806c5cecef5040b8c4c0253895c7c0acea6483a1f0f72425" 1234 + "77ab46e18d553329d4ae1bd31cf57eec6ec31ceb1f2ed6b1195cac98b4b97a25" 1235 + "115d14c414e44dba8ebbdaf502e43f98a09036bee0ea2a621176300874a3eae8" 1236 + "c988357255b4e5923928d335b0ef62a565333fae6a64c85ac30e7da34ceeade4" 1237 + "1a161bcad0b51f8209ee1fdaf53d50359ad6b986ecd4290c9f69a34c64ddc0eb" 1238 + "73b8f3231f3f4e057404c18d"; 1239 final String ikeDeleteChildResp = 1240 "46b8eca1e0d72a189b9f8e0158e1c0a52e202520000000040000004c2a000030" 1241 + "53d97806d48ce44e0d4e1adf1de36778f77c3823bfaf8186cc71d4dc73497099" 1242 + "a9049e7be8a2013affd56ab7"; 1243 1244 ikeTunUtils.awaitReqAndInjectResp( 1245 IKE_DETERMINISTIC_INITIATOR_SPI, 1246 2 /* expectedMsgId */, 1247 true /* expectedUseEncap */, 1248 ikeUpdateSaResp); 1249 1250 // If Kernel migration enabled, it will be used instead of MOBIKE-rekey 1251 // TODO (b/277939911): Decouple VCN CTS from IKE implementation behavior 1252 if (!mContext.getPackageManager() 1253 .hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION)) { 1254 ikeTunUtils.awaitReqAndInjectResp( 1255 IKE_DETERMINISTIC_INITIATOR_SPI, 1256 3 /* expectedMsgId */, 1257 true /* expectedUseEncap */, 1258 ikeCreateChildResp); 1259 1260 ikeTunUtils.awaitReqAndInjectResp( 1261 IKE_DETERMINISTIC_INITIATOR_SPI, 1262 4 /* expectedMsgId */, 1263 true /* expectedUseEncap */, 1264 ikeDeleteChildResp); 1265 } 1266 } 1267 injectAndVerifyIkeDpdPackets( @onNull IkeTunUtils ikeTunUtils, PortPair localRemotePorts)1268 private void injectAndVerifyIkeDpdPackets( 1269 @NonNull IkeTunUtils ikeTunUtils, PortPair localRemotePorts) throws Exception { 1270 // Generated by forcing IKE to use Test Mode (RandomnessFactory#mIsTestModeEnabled) and 1271 // capturing IKE packets with a live server. 1272 final String ikeDpdRequestHex = 1273 "46b8eca1e0d72a189b9f8e0158e1c0a52E202500000000000000004c00000030" 1274 + "3A31D5FAC230FEA67246B0C1A049A28944C341301979EB7B52FC669274B77D5F" 1275 + "A6CFE8D768CF390536436D08"; 1276 1277 byte[] ikeDpdRequest = 1278 IkeTunUtils.buildIkePacket( 1279 REMOTE_ADDRESS, 1280 LOCAL_ADDRESS, 1281 localRemotePorts.dstPort, 1282 localRemotePorts.srcPort, 1283 true /* useEncap */, 1284 hexStringToByteArray(ikeDpdRequestHex)); 1285 1286 ikeTunUtils.injectPacket(ikeDpdRequest); 1287 ikeTunUtils.awaitResp( 1288 IKE_DETERMINISTIC_INITIATOR_SPI, 1289 0 /* expectedMsgId */, 1290 true /* expectedUseEncap */); 1291 } 1292 verifyVcnSafeModeTimeoutOnTestNetwork(int subId, long timeoutMillis)1293 private void verifyVcnSafeModeTimeoutOnTestNetwork(int subId, long timeoutMillis) 1294 throws Exception { 1295 try (TestNetworkWrapper testNetworkWrapper = 1296 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 1297 // Before the VCN starts, the test network should have NOT_VCN_MANAGED 1298 waitForExpectedUnderlyingNetworkWithCapabilities( 1299 testNetworkWrapper, 1300 true /* expectNotVcnManaged */, 1301 false /* expectNotMetered */, 1302 TestNetworkWrapper.NETWORK_CB_TIMEOUT_MS); 1303 verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> { 1304 final VcnSetupResult vcnSetupResult = 1305 setupAndGetVcnNetwork(subGrp, cellNetwork, cellNetworkCb, testNetworkWrapper); 1306 1307 // Once VCN starts, the test network should lose NOT_VCN_MANAGED 1308 waitForExpectedUnderlyingNetworkWithCapabilities( 1309 testNetworkWrapper, 1310 false /* expectNotVcnManaged */, 1311 false /* expectNotMetered */, 1312 TestNetworkWrapper.NETWORK_CB_TIMEOUT_MS); 1313 1314 // After VCN has started up, wait for safemode to kick in and expect the 1315 // underlying Test Network to regain NOT_VCN_MANAGED. 1316 waitForExpectedUnderlyingNetworkWithCapabilities( 1317 testNetworkWrapper, 1318 true /* expectNotVcnManaged */, 1319 false /* expectNotMetered */, 1320 timeoutMillis); 1321 1322 // Verify that VCN Network is also lost in safemode 1323 cellNetworkCb.waitForLostNetwork(vcnSetupResult.vcnNetwork); 1324 1325 verifyVcnStatus(subGrp, VCN_STATUS_CODE_SAFE_MODE); 1326 1327 mVcnManager.clearVcnConfig(subGrp); 1328 }); 1329 } 1330 } 1331 setSafeModeTimeoutForCarrier(int subId, int timeoutSeconds)1332 private void setSafeModeTimeoutForCarrier(int subId, int timeoutSeconds) { 1333 final PersistableBundle carrierConfig = new PersistableBundle(); 1334 carrierConfig.putInt(VcnManager.VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY, timeoutSeconds); 1335 mCarrierConfigManager.overrideConfig(subId, carrierConfig); 1336 } 1337 1338 @Test testVcnSafeModeOnTestNetwork_defaultTimeout()1339 public void testVcnSafeModeOnTestNetwork_defaultTimeout() throws Exception { 1340 final int subId = verifyAndGetValidDataSubId(); 1341 verifyVcnSafeModeTimeoutOnTestNetwork(subId, SAFEMODE_TIMEOUT_MILLIS); 1342 } 1343 1344 @RequiresFlagsEnabled(Flags.FLAG_SAFE_MODE_TIMEOUT_CONFIG) 1345 @Test testVcnSafeModeOnTestNetwork_overrideTimeout()1346 public void testVcnSafeModeOnTestNetwork_overrideTimeout() throws Exception { 1347 final int subId = verifyAndGetValidDataSubId(); 1348 final int safeModeTimeoutSeconds = 5; 1349 final int gracePeriod = 5; 1350 1351 final PersistableBundle oldCarrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 1352 setSafeModeTimeoutForCarrier(subId, safeModeTimeoutSeconds); 1353 1354 verifyVcnSafeModeTimeoutOnTestNetwork( 1355 subId, TimeUnit.SECONDS.toMillis(safeModeTimeoutSeconds + gracePeriod)); 1356 1357 mCarrierConfigManager.overrideConfig(subId, oldCarrierConfig); 1358 } 1359 verifyEnterSafeModeImmediately(VcnConfig vcnConfig, boolean isSafeModeExpected)1360 private void verifyEnterSafeModeImmediately(VcnConfig vcnConfig, boolean isSafeModeExpected) 1361 throws Exception { 1362 final int subId = verifyAndGetValidDataSubId(); 1363 final TestVcnStatusCallback callback = new TestVcnStatusCallback(); 1364 1365 // Override the safe mode timeout to be zero 1366 final PersistableBundle oldCarrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 1367 setSafeModeTimeoutForCarrier(subId, 0); 1368 1369 try (TestNetworkWrapper testNetworkWrapper = 1370 createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) { 1371 verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> { 1372 mVcnManager.registerVcnStatusCallback(subGrp, INLINE_EXECUTOR, callback); 1373 mVcnManager.setVcnConfig(subGrp, vcnConfig); 1374 1375 assertEquals( 1376 VCN_STATUS_CODE_NOT_CONFIGURED, callback.awaitOnStatusChanged()); 1377 assertEquals(VCN_STATUS_CODE_ACTIVE, callback.awaitOnStatusChanged()); 1378 1379 if (isSafeModeExpected) { 1380 assertEquals( 1381 VCN_STATUS_CODE_SAFE_MODE, callback.awaitOnStatusChanged()); 1382 } else { 1383 assertEquals( 1384 VCN_STATUS_CODE_AWAIT_TIMEOUT, callback.awaitOnStatusChanged()); 1385 } 1386 1387 mVcnManager.clearVcnConfig(subGrp); 1388 mVcnManager.unregisterVcnStatusCallback(callback); 1389 }); 1390 } 1391 1392 // Reset Carrier Config 1393 mCarrierConfigManager.overrideConfig(subId, oldCarrierConfig); 1394 } 1395 newVcnConfig(boolean isSafeModeEnabled)1396 private VcnConfig newVcnConfig(boolean isSafeModeEnabled) { 1397 final VcnGatewayConnectionConfig.Builder gatewayConfigBuilder = 1398 VcnGatewayConnectionConfigTest.buildVcnGatewayConnectionConfigBase() 1399 .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 1400 1401 if (!isSafeModeEnabled) { 1402 gatewayConfigBuilder.setSafeModeEnabled(false); 1403 } 1404 // Don't call setSafeModeEnabled since enabling safe mode should not be flag gated 1405 1406 return new VcnConfig.Builder(mContext) 1407 .setIsTestModeProfile() 1408 .addGatewayConnectionConfig(gatewayConfigBuilder.build()) 1409 .build(); 1410 } 1411 1412 @RequiresFlagsEnabled({Flags.FLAG_SAFE_MODE_TIMEOUT_CONFIG}) 1413 @Test testEnterSafeModeImmediately_safeModeEnabled()1414 public void testEnterSafeModeImmediately_safeModeEnabled() throws Exception { 1415 verifyEnterSafeModeImmediately( 1416 newVcnConfig(true /* isSafeModeEnabled */), true /* isSafeModeExpected */); 1417 } 1418 1419 @RequiresFlagsEnabled({Flags.FLAG_SAFE_MODE_CONFIG, Flags.FLAG_SAFE_MODE_TIMEOUT_CONFIG}) 1420 @Test testEnterSafeModeImmediately_safeModeDisabled()1421 public void testEnterSafeModeImmediately_safeModeDisabled() throws Exception { 1422 verifyEnterSafeModeImmediately( 1423 newVcnConfig(false /* isSafeModeEnabled */), false /* isSafeModeExpected */); 1424 } 1425 } 1426