1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static android.net.ConnectivityManager.NetworkCallback; 20 import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; 21 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS; 22 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 23 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; 24 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; 25 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 26 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 27 import static android.net.vcn.VcnManager.VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY; 28 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; 29 import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE; 30 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; 31 import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 32 import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 33 34 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; 35 import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback; 36 import static com.android.server.vcn.VcnTestUtils.setupSystemService; 37 38 import static org.junit.Assert.assertEquals; 39 import static org.junit.Assert.assertFalse; 40 import static org.junit.Assert.assertNotNull; 41 import static org.junit.Assert.assertNull; 42 import static org.junit.Assert.assertTrue; 43 import static org.junit.Assert.fail; 44 import static org.mockito.ArgumentMatchers.any; 45 import static org.mockito.ArgumentMatchers.anyBoolean; 46 import static org.mockito.ArgumentMatchers.anyInt; 47 import static org.mockito.ArgumentMatchers.eq; 48 import static org.mockito.Mockito.CALLS_REAL_METHODS; 49 import static org.mockito.Mockito.any; 50 import static org.mockito.Mockito.argThat; 51 import static org.mockito.Mockito.doAnswer; 52 import static org.mockito.Mockito.doNothing; 53 import static org.mockito.Mockito.doReturn; 54 import static org.mockito.Mockito.doThrow; 55 import static org.mockito.Mockito.eq; 56 import static org.mockito.Mockito.mock; 57 import static org.mockito.Mockito.never; 58 import static org.mockito.Mockito.times; 59 import static org.mockito.Mockito.verify; 60 61 import android.annotation.NonNull; 62 import android.app.AppOpsManager; 63 import android.content.BroadcastReceiver; 64 import android.content.Context; 65 import android.content.Intent; 66 import android.content.pm.PackageManager; 67 import android.net.ConnectivityManager; 68 import android.net.LinkProperties; 69 import android.net.Network; 70 import android.net.NetworkCapabilities; 71 import android.net.NetworkRequest; 72 import android.net.Uri; 73 import android.net.vcn.IVcnStatusCallback; 74 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; 75 import android.net.vcn.VcnConfig; 76 import android.net.vcn.VcnConfigTest; 77 import android.net.vcn.VcnGatewayConnectionConfigTest; 78 import android.net.vcn.VcnManager; 79 import android.net.vcn.VcnUnderlyingNetworkPolicy; 80 import android.os.IBinder; 81 import android.os.ParcelUuid; 82 import android.os.PersistableBundle; 83 import android.os.Process; 84 import android.os.UserHandle; 85 import android.os.test.TestLooper; 86 import android.telephony.SubscriptionInfo; 87 import android.telephony.SubscriptionManager; 88 import android.telephony.TelephonyManager; 89 import android.util.ArraySet; 90 91 import androidx.test.filters.SmallTest; 92 import androidx.test.runner.AndroidJUnit4; 93 94 import com.android.server.VcnManagementService.VcnCallback; 95 import com.android.server.VcnManagementService.VcnStatusCallbackInfo; 96 import com.android.server.vcn.TelephonySubscriptionTracker; 97 import com.android.server.vcn.Vcn; 98 import com.android.server.vcn.VcnContext; 99 import com.android.server.vcn.VcnNetworkProvider; 100 import com.android.server.vcn.util.PersistableBundleUtils; 101 import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper; 102 103 import org.junit.Before; 104 import org.junit.Test; 105 import org.junit.runner.RunWith; 106 import org.mockito.ArgumentCaptor; 107 108 import java.io.FileNotFoundException; 109 import java.util.Arrays; 110 import java.util.Collections; 111 import java.util.List; 112 import java.util.Map; 113 import java.util.Map.Entry; 114 import java.util.Set; 115 import java.util.UUID; 116 117 /** Tests for {@link VcnManagementService}. */ 118 @RunWith(AndroidJUnit4.class) 119 @SmallTest 120 public class VcnManagementServiceTest { 121 private static final String CONTEXT_ATTRIBUTION_TAG = "VCN"; 122 private static final String TEST_PACKAGE_NAME = 123 VcnManagementServiceTest.class.getPackage().getName(); 124 private static final String TEST_PACKAGE_NAME_2 = "TEST_PKG_2"; 125 private static final String TEST_CB_PACKAGE_NAME = 126 VcnManagementServiceTest.class.getPackage().getName() + ".callback"; 127 private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0)); 128 private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1)); 129 private static final ParcelUuid TEST_UUID_3 = new ParcelUuid(new UUID(2, 2)); 130 private static final VcnConfig TEST_VCN_CONFIG; 131 private static final VcnConfig TEST_VCN_CONFIG_PKG_2; 132 private static final int TEST_UID = Process.FIRST_APPLICATION_UID; 133 private static final String TEST_IFACE_NAME = "TEST_IFACE"; 134 private static final String TEST_IFACE_NAME_2 = "TEST_IFACE2"; 135 private static final LinkProperties TEST_LP_1 = new LinkProperties(); 136 private static final LinkProperties TEST_LP_2 = new LinkProperties(); 137 138 static { 139 TEST_LP_1.setInterfaceName(TEST_IFACE_NAME); 140 TEST_LP_2.setInterfaceName(TEST_IFACE_NAME_2); 141 } 142 143 static { 144 final Context mockConfigContext = mock(Context.class); 145 146 doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName(); 147 TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig(mockConfigContext); 148 149 doReturn(TEST_PACKAGE_NAME_2).when(mockConfigContext).getOpPackageName(); 150 TEST_VCN_CONFIG_PKG_2 = VcnConfigTest.buildTestConfig(mockConfigContext); 151 } 152 153 private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP = 154 Collections.unmodifiableMap(Collections.singletonMap(TEST_UUID_1, TEST_VCN_CONFIG)); 155 156 private static final int TEST_SUBSCRIPTION_ID = 1; 157 private static final int TEST_SUBSCRIPTION_ID_2 = 2; 158 private static final SubscriptionInfo TEST_SUBSCRIPTION_INFO = 159 new SubscriptionInfo( 160 TEST_SUBSCRIPTION_ID /* id */, 161 "" /* iccId */, 162 0 /* simSlotIndex */, 163 "Carrier" /* displayName */, 164 "Carrier" /* carrierName */, 165 0 /* nameSource */, 166 255 /* iconTint */, 167 "12345" /* number */, 168 0 /* roaming */, 169 null /* icon */, 170 "0" /* mcc */, 171 "0" /* mnc */, 172 "0" /* countryIso */, 173 false /* isEmbedded */, 174 null /* nativeAccessRules */, 175 null /* cardString */, 176 false /* isOpportunistic */, 177 TEST_UUID_1.toString() /* groupUUID */, 178 0 /* carrierId */, 179 0 /* profileClass */); 180 181 private final Context mMockContextWithoutAttributionTag = mock(Context.class); 182 private final Context mMockContext = mock(Context.class); 183 private final VcnManagementService.Dependencies mMockDeps = 184 mock(VcnManagementService.Dependencies.class); 185 private final TestLooper mTestLooper = new TestLooper(); 186 private final ConnectivityManager mConnMgr = mock(ConnectivityManager.class); 187 private final TelephonyManager mTelMgr = mock(TelephonyManager.class); 188 private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class); 189 private final AppOpsManager mAppOpsMgr = mock(AppOpsManager.class); 190 private final VcnContext mVcnContext = mock(VcnContext.class); 191 private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper = 192 mock(PersistableBundleUtils.LockingReadWriteHelper.class); 193 private final TelephonySubscriptionTracker mSubscriptionTracker = 194 mock(TelephonySubscriptionTracker.class); 195 196 private final ArgumentCaptor<VcnCallback> mVcnCallbackCaptor = 197 ArgumentCaptor.forClass(VcnCallback.class); 198 199 private final VcnManagementService mVcnMgmtSvc; 200 201 private final IVcnUnderlyingNetworkPolicyListener mMockPolicyListener = 202 mock(IVcnUnderlyingNetworkPolicyListener.class); 203 private final IVcnStatusCallback mMockStatusCallback = mock(IVcnStatusCallback.class); 204 private final IBinder mMockIBinder = mock(IBinder.class); 205 VcnManagementServiceTest()206 public VcnManagementServiceTest() throws Exception { 207 doReturn(mMockContext) 208 .when(mMockContextWithoutAttributionTag) 209 .createAttributionContext(CONTEXT_ATTRIBUTION_TAG); 210 211 setupSystemService( 212 mMockContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); 213 setupSystemService( 214 mMockContext, mTelMgr, Context.TELEPHONY_SERVICE, TelephonyManager.class); 215 setupSystemService( 216 mMockContext, 217 mSubMgr, 218 Context.TELEPHONY_SUBSCRIPTION_SERVICE, 219 SubscriptionManager.class); 220 setupSystemService(mMockContext, mAppOpsMgr, Context.APP_OPS_SERVICE, AppOpsManager.class); 221 222 doReturn(TEST_PACKAGE_NAME).when(mMockContext).getOpPackageName(); 223 224 doReturn(mMockContext).when(mVcnContext).getContext(); 225 doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper(); 226 doReturn(TEST_UID).when(mMockDeps).getBinderCallingUid(); 227 doReturn(mVcnContext) 228 .when(mMockDeps) 229 .newVcnContext( 230 eq(mMockContext), 231 eq(mTestLooper.getLooper()), 232 any(VcnNetworkProvider.class), 233 anyBoolean()); 234 doReturn(mSubscriptionTracker) 235 .when(mMockDeps) 236 .newTelephonySubscriptionTracker( 237 eq(mMockContext), 238 eq(mTestLooper.getLooper()), 239 any(TelephonySubscriptionTrackerCallback.class)); 240 doReturn(mConfigReadWriteHelper) 241 .when(mMockDeps) 242 .newPersistableBundleLockingReadWriteHelper(any()); 243 244 // Setup VCN instance generation 245 doAnswer((invocation) -> { 246 // Mock-within a doAnswer is safe, because it doesn't actually run nested. 247 return mock(Vcn.class); 248 }).when(mMockDeps).newVcn(any(), any(), any(), any(), any()); 249 250 final PersistableBundle bundle = 251 PersistableBundleUtils.fromMap( 252 TEST_VCN_CONFIG_MAP, 253 PersistableBundleUtils::fromParcelUuid, 254 VcnConfig::toPersistableBundle); 255 doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk(); 256 257 setupMockedCarrierPrivilege(true); 258 mVcnMgmtSvc = new VcnManagementService(mMockContextWithoutAttributionTag, mMockDeps); 259 setupActiveSubscription(TEST_UUID_1); 260 261 doReturn(mMockIBinder).when(mMockPolicyListener).asBinder(); 262 doReturn(mMockIBinder).when(mMockStatusCallback).asBinder(); 263 264 // Make sure the profiles are loaded. 265 mTestLooper.dispatchAll(); 266 } 267 268 @Before setUp()269 public void setUp() { 270 doNothing() 271 .when(mMockContext) 272 .enforceCallingOrSelfPermission( 273 eq(android.Manifest.permission.NETWORK_FACTORY), any()); 274 275 doReturn(Collections.singleton(TRANSPORT_WIFI)) 276 .when(mMockDeps) 277 .getRestrictedTransports(any(), any(), any()); 278 } 279 280 setupMockedCarrierPrivilege(boolean isPrivileged)281 private void setupMockedCarrierPrivilege(boolean isPrivileged) { 282 setupMockedCarrierPrivilege(isPrivileged, TEST_PACKAGE_NAME); 283 } 284 setupMockedCarrierPrivilege(boolean isPrivileged, String pkg)285 private void setupMockedCarrierPrivilege(boolean isPrivileged, String pkg) { 286 doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO)) 287 .when(mSubMgr) 288 .getSubscriptionsInGroup(any()); 289 doReturn(mTelMgr) 290 .when(mTelMgr) 291 .createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId())); 292 doReturn( 293 isPrivileged 294 ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS 295 : CARRIER_PRIVILEGE_STATUS_NO_ACCESS) 296 .when(mTelMgr) 297 .checkCarrierPrivilegesForPackage(eq(pkg)); 298 } 299 300 @Test testSystemReady()301 public void testSystemReady() throws Exception { 302 mVcnMgmtSvc.systemReady(); 303 304 verify(mConnMgr).registerNetworkProvider(any(VcnNetworkProvider.class)); 305 verify(mSubscriptionTracker).register(); 306 verify(mConnMgr) 307 .registerNetworkCallback( 308 eq(new NetworkRequest.Builder().clearCapabilities().build()), 309 any(NetworkCallback.class)); 310 } 311 312 @Test testNonSystemServerRealConfigFileAccessPermission()313 public void testNonSystemServerRealConfigFileAccessPermission() throws Exception { 314 // Attempt to build a real instance of the dependencies, and verify we cannot write to the 315 // file. 316 VcnManagementService.Dependencies deps = new VcnManagementService.Dependencies(); 317 PersistableBundleUtils.LockingReadWriteHelper configReadWriteHelper = 318 deps.newPersistableBundleLockingReadWriteHelper( 319 VcnManagementService.VCN_CONFIG_FILE); 320 321 // Even tests should not be able to read/write configs from disk; SELinux policies restrict 322 // it to only the system server. 323 // Reading config should always return null since the file "does not exist", and writing 324 // should throw an IOException. 325 assertNull(configReadWriteHelper.readFromDisk()); 326 327 try { 328 configReadWriteHelper.writeToDisk(new PersistableBundle()); 329 fail("Expected IOException due to SELinux policy"); 330 } catch (FileNotFoundException expected) { 331 } 332 } 333 334 @Test testLoadVcnConfigsOnStartup()335 public void testLoadVcnConfigsOnStartup() throws Exception { 336 mTestLooper.dispatchAll(); 337 338 assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs()); 339 verify(mConfigReadWriteHelper).readFromDisk(); 340 } 341 triggerSubscriptionTrackerCbAndGetSnapshot( ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups)342 private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( 343 ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups) { 344 return triggerSubscriptionTrackerCbAndGetSnapshot( 345 activeDataSubGrp, activeSubscriptionGroups, Collections.emptyMap()); 346 } 347 triggerSubscriptionTrackerCbAndGetSnapshot( ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap)348 private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( 349 ParcelUuid activeDataSubGrp, 350 Set<ParcelUuid> activeSubscriptionGroups, 351 Map<Integer, ParcelUuid> subIdToGroupMap) { 352 return triggerSubscriptionTrackerCbAndGetSnapshot( 353 activeDataSubGrp, 354 activeSubscriptionGroups, 355 subIdToGroupMap, 356 true /* hasCarrierPrivileges */); 357 } 358 triggerSubscriptionTrackerCbAndGetSnapshot( ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap, boolean hasCarrierPrivileges)359 private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( 360 ParcelUuid activeDataSubGrp, 361 Set<ParcelUuid> activeSubscriptionGroups, 362 Map<Integer, ParcelUuid> subIdToGroupMap, 363 boolean hasCarrierPrivileges) { 364 return triggerSubscriptionTrackerCbAndGetSnapshot( 365 TEST_SUBSCRIPTION_ID, 366 activeDataSubGrp, 367 activeSubscriptionGroups, 368 subIdToGroupMap, 369 hasCarrierPrivileges); 370 } 371 triggerSubscriptionTrackerCbAndGetSnapshot( int activeDataSubId, ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap, boolean hasCarrierPrivileges)372 private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( 373 int activeDataSubId, 374 ParcelUuid activeDataSubGrp, 375 Set<ParcelUuid> activeSubscriptionGroups, 376 Map<Integer, ParcelUuid> subIdToGroupMap, 377 boolean hasCarrierPrivileges) { 378 final TelephonySubscriptionSnapshot snapshot = 379 buildSubscriptionSnapshot( 380 activeDataSubId, 381 activeDataSubGrp, 382 activeSubscriptionGroups, 383 subIdToGroupMap, 384 hasCarrierPrivileges); 385 386 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 387 cb.onNewSnapshot(snapshot); 388 389 return snapshot; 390 } 391 buildSubscriptionSnapshot( int activeDataSubId, ParcelUuid activeDataSubGrp, Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap, boolean hasCarrierPrivileges)392 private TelephonySubscriptionSnapshot buildSubscriptionSnapshot( 393 int activeDataSubId, 394 ParcelUuid activeDataSubGrp, 395 Set<ParcelUuid> activeSubscriptionGroups, 396 Map<Integer, ParcelUuid> subIdToGroupMap, 397 boolean hasCarrierPrivileges) { 398 final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class); 399 doReturn(activeSubscriptionGroups).when(snapshot).getActiveSubscriptionGroups(); 400 doReturn(activeDataSubGrp).when(snapshot).getActiveDataSubscriptionGroup(); 401 doReturn(activeDataSubId).when(snapshot).getActiveDataSubscriptionId(); 402 403 final Set<String> privilegedPackages = 404 (activeSubscriptionGroups == null || activeSubscriptionGroups.isEmpty()) 405 ? Collections.emptySet() 406 : Collections.singleton(TEST_PACKAGE_NAME); 407 doReturn(hasCarrierPrivileges) 408 .when(snapshot) 409 .packageHasPermissionsForSubscriptionGroup( 410 argThat(val -> activeSubscriptionGroups.contains(val)), 411 eq(TEST_PACKAGE_NAME)); 412 413 doAnswer(invocation -> { 414 return subIdToGroupMap.get(invocation.getArgument(0)); 415 }).when(snapshot).getGroupForSubId(anyInt()); 416 417 doAnswer(invocation -> { 418 final ParcelUuid subGrp = invocation.getArgument(0); 419 final Set<Integer> subIds = new ArraySet<>(); 420 for (Entry<Integer, ParcelUuid> entry : subIdToGroupMap.entrySet()) { 421 if (entry.getValue().equals(subGrp)) { 422 subIds.add(entry.getKey()); 423 } 424 } 425 return subIds; 426 }).when(snapshot).getAllSubIdsInGroup(any()); 427 428 return snapshot; 429 } 430 setupActiveSubscription(ParcelUuid activeDataSubGrp)431 private void setupActiveSubscription(ParcelUuid activeDataSubGrp) { 432 mVcnMgmtSvc.setLastSnapshot( 433 buildSubscriptionSnapshot( 434 TEST_SUBSCRIPTION_ID, 435 activeDataSubGrp, 436 Collections.emptySet(), 437 Collections.emptyMap(), 438 true /* hasCarrierPrivileges */)); 439 } 440 getTelephonySubscriptionTrackerCallback()441 private TelephonySubscriptionTrackerCallback getTelephonySubscriptionTrackerCallback() { 442 final ArgumentCaptor<TelephonySubscriptionTrackerCallback> captor = 443 ArgumentCaptor.forClass(TelephonySubscriptionTrackerCallback.class); 444 verify(mMockDeps) 445 .newTelephonySubscriptionTracker( 446 eq(mMockContext), eq(mTestLooper.getLooper()), captor.capture()); 447 return captor.getValue(); 448 } 449 getPackageChangeReceiver()450 private BroadcastReceiver getPackageChangeReceiver() { 451 final ArgumentCaptor<BroadcastReceiver> captor = 452 ArgumentCaptor.forClass(BroadcastReceiver.class); 453 verify(mMockContext).registerReceiver(captor.capture(), argThat(filter -> { 454 return filter.hasAction(Intent.ACTION_PACKAGE_ADDED) 455 && filter.hasAction(Intent.ACTION_PACKAGE_REPLACED) 456 && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED) 457 && filter.hasAction(Intent.ACTION_PACKAGE_DATA_CLEARED) 458 && filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); 459 }), any(), any()); 460 return captor.getValue(); 461 } 462 startAndGetVcnInstance(ParcelUuid uuid)463 private Vcn startAndGetVcnInstance(ParcelUuid uuid) { 464 mVcnMgmtSvc.setVcnConfig(uuid, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 465 return mVcnMgmtSvc.getAllVcns().get(uuid); 466 } 467 468 @Test testTelephonyNetworkTrackerCallbackStartsInstances()469 public void testTelephonyNetworkTrackerCallbackStartsInstances() throws Exception { 470 // Add a record for a non-active SIM 471 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 472 473 TelephonySubscriptionSnapshot snapshot = 474 triggerSubscriptionTrackerCbAndGetSnapshot( 475 TEST_UUID_1, new ArraySet<>(Arrays.asList(TEST_UUID_1, TEST_UUID_2))); 476 verify(mMockDeps) 477 .newVcnContext( 478 eq(mMockContext), 479 eq(mTestLooper.getLooper()), 480 any(VcnNetworkProvider.class), 481 anyBoolean()); 482 483 // Verify that only the VCN for the active data SIM was started. 484 verify(mMockDeps) 485 .newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot), any()); 486 verify(mMockDeps, never()) 487 .newVcn(eq(mVcnContext), eq(TEST_UUID_2), eq(TEST_VCN_CONFIG), eq(snapshot), any()); 488 } 489 490 @Test testTelephonyNetworkTrackerCallbackSwitchingActiveDataStartsAndStopsInstances()491 public void testTelephonyNetworkTrackerCallbackSwitchingActiveDataStartsAndStopsInstances() 492 throws Exception { 493 // Add a record for a non-active SIM 494 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 495 final Vcn vcn = startAndGetVcnInstance(TEST_UUID_1); 496 497 TelephonySubscriptionSnapshot snapshot = 498 triggerSubscriptionTrackerCbAndGetSnapshot( 499 TEST_UUID_2, new ArraySet<>(Arrays.asList(TEST_UUID_1, TEST_UUID_2))); 500 501 // Verify that a new VCN for UUID_2 was started, and the old instance was torn down 502 // immediately 503 verify(mMockDeps) 504 .newVcn(eq(mVcnContext), eq(TEST_UUID_2), eq(TEST_VCN_CONFIG), eq(snapshot), any()); 505 verify(vcn).teardownAsynchronously(); 506 assertEquals(1, mVcnMgmtSvc.getAllVcns().size()); 507 assertFalse(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_1)); 508 assertTrue(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_2)); 509 } 510 511 @Test testTelephonyNetworkTrackerCallbackStopsInstances()512 public void testTelephonyNetworkTrackerCallbackStopsInstances() throws Exception { 513 setupActiveSubscription(TEST_UUID_2); 514 515 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 516 final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); 517 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 518 519 triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet()); 520 521 // Verify teardown after delay 522 mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); 523 mTestLooper.dispatchAll(); 524 verify(vcn).teardownAsynchronously(); 525 verify(mMockPolicyListener).onPolicyChanged(); 526 } 527 528 @Test testTelephonyNetworkTrackerCallbackSwitchToNewSubscriptionImmediatelyTearsDown()529 public void testTelephonyNetworkTrackerCallbackSwitchToNewSubscriptionImmediatelyTearsDown() 530 throws Exception { 531 setupActiveSubscription(TEST_UUID_2); 532 533 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 534 final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); 535 536 // Simulate switch to different default data subscription that does not have a VCN. 537 triggerSubscriptionTrackerCbAndGetSnapshot( 538 TEST_SUBSCRIPTION_ID, 539 null /* activeDataSubscriptionGroup */, 540 Collections.emptySet(), 541 Collections.emptyMap(), 542 false /* hasCarrierPrivileges */); 543 mTestLooper.dispatchAll(); 544 545 verify(vcn).teardownAsynchronously(); 546 assertEquals(0, mVcnMgmtSvc.getAllVcns().size()); 547 } 548 549 /** 550 * Tests an intermediate state where carrier privileges are marked as lost before active data 551 * subId changes during a SIM ejection. 552 * 553 * <p>The expected outcome is that the VCN is torn down after a delay, as opposed to 554 * immediately. 555 */ 556 @Test testTelephonyNetworkTrackerCallbackLostCarrierPrivilegesBeforeActiveDataSubChanges()557 public void testTelephonyNetworkTrackerCallbackLostCarrierPrivilegesBeforeActiveDataSubChanges() 558 throws Exception { 559 setupActiveSubscription(TEST_UUID_2); 560 561 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 562 final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); 563 564 // Simulate privileges lost 565 triggerSubscriptionTrackerCbAndGetSnapshot( 566 TEST_SUBSCRIPTION_ID, 567 TEST_UUID_2, 568 Collections.emptySet(), 569 Collections.emptyMap(), 570 false /* hasCarrierPrivileges */); 571 572 // Verify teardown after delay 573 mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); 574 mTestLooper.dispatchAll(); 575 verify(vcn).teardownAsynchronously(); 576 } 577 578 @Test testTelephonyNetworkTrackerCallbackSimSwitchesDoNotKillVcnInstances()579 public void testTelephonyNetworkTrackerCallbackSimSwitchesDoNotKillVcnInstances() 580 throws Exception { 581 setupActiveSubscription(TEST_UUID_2); 582 583 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 584 final Vcn vcn = startAndGetVcnInstance(TEST_UUID_2); 585 586 // Simulate SIM unloaded 587 triggerSubscriptionTrackerCbAndGetSnapshot( 588 INVALID_SUBSCRIPTION_ID, 589 null /* activeDataSubscriptionGroup */, 590 Collections.emptySet(), 591 Collections.emptyMap(), 592 false /* hasCarrierPrivileges */); 593 594 // Simulate new SIM loaded right during teardown delay. 595 mTestLooper.moveTimeForward( 596 VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); 597 mTestLooper.dispatchAll(); 598 triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); 599 600 // Verify that even after the full timeout duration, the VCN instance is not torn down 601 mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); 602 mTestLooper.dispatchAll(); 603 verify(vcn, never()).teardownAsynchronously(); 604 } 605 606 @Test testTelephonyNetworkTrackerCallbackDoesNotKillNewVcnInstances()607 public void testTelephonyNetworkTrackerCallbackDoesNotKillNewVcnInstances() throws Exception { 608 setupActiveSubscription(TEST_UUID_2); 609 610 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 611 final Vcn oldInstance = startAndGetVcnInstance(TEST_UUID_2); 612 613 // Simulate SIM unloaded 614 triggerSubscriptionTrackerCbAndGetSnapshot(null, Collections.emptySet()); 615 616 // Config cleared, SIM reloaded & config re-added right before teardown delay, staring new 617 // vcnInstance. 618 mTestLooper.moveTimeForward( 619 VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS / 2); 620 mTestLooper.dispatchAll(); 621 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME); 622 triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); 623 final Vcn newInstance = startAndGetVcnInstance(TEST_UUID_2); 624 625 // Verify that new instance was different, and the old one was torn down 626 assertTrue(oldInstance != newInstance); 627 verify(oldInstance).teardownAsynchronously(); 628 629 // Verify that even after the full timeout duration, the new VCN instance is not torn down 630 mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); 631 mTestLooper.dispatchAll(); 632 verify(newInstance, never()).teardownAsynchronously(); 633 } 634 635 @Test testPackageChangeListenerRegistered()636 public void testPackageChangeListenerRegistered() throws Exception { 637 verify(mMockContext).registerReceiver(any(BroadcastReceiver.class), argThat(filter -> { 638 return filter.hasAction(Intent.ACTION_PACKAGE_ADDED) 639 && filter.hasAction(Intent.ACTION_PACKAGE_REPLACED) 640 && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED); 641 }), any(), any()); 642 } 643 644 @Test testPackageChangeListener_packageAdded()645 public void testPackageChangeListener_packageAdded() throws Exception { 646 final BroadcastReceiver receiver = getPackageChangeReceiver(); 647 648 verify(mMockContext).registerReceiver(any(), argThat(filter -> { 649 return filter.hasAction(Intent.ACTION_PACKAGE_ADDED) 650 && filter.hasAction(Intent.ACTION_PACKAGE_REPLACED) 651 && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED); 652 }), any(), any()); 653 654 receiver.onReceive(mMockContext, new Intent(Intent.ACTION_PACKAGE_ADDED)); 655 verify(mSubscriptionTracker).handleSubscriptionsChanged(); 656 } 657 658 @Test testPackageChangeListener_packageRemoved()659 public void testPackageChangeListener_packageRemoved() throws Exception { 660 final BroadcastReceiver receiver = getPackageChangeReceiver(); 661 662 verify(mMockContext).registerReceiver(any(), argThat(filter -> { 663 return filter.hasAction(Intent.ACTION_PACKAGE_REMOVED); 664 }), any(), any()); 665 666 receiver.onReceive(mMockContext, new Intent(Intent.ACTION_PACKAGE_REMOVED)); 667 verify(mSubscriptionTracker).handleSubscriptionsChanged(); 668 } 669 670 @Test testPackageChangeListener_packageDataCleared()671 public void testPackageChangeListener_packageDataCleared() throws Exception { 672 triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); 673 final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1); 674 675 final BroadcastReceiver receiver = getPackageChangeReceiver(); 676 assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs()); 677 678 final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED); 679 intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME)); 680 intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID)); 681 682 receiver.onReceive(mMockContext, intent); 683 mTestLooper.dispatchAll(); 684 verify(vcn).teardownAsynchronously(); 685 assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); 686 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 687 } 688 689 @Test testPackageChangeListener_packageFullyRemoved()690 public void testPackageChangeListener_packageFullyRemoved() throws Exception { 691 triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); 692 final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1); 693 694 final BroadcastReceiver receiver = getPackageChangeReceiver(); 695 assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs()); 696 697 final Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED); 698 intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME)); 699 intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID)); 700 701 receiver.onReceive(mMockContext, intent); 702 mTestLooper.dispatchAll(); 703 verify(vcn).teardownAsynchronously(); 704 assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); 705 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 706 } 707 708 @Test testSetVcnConfigRequiresNonSystemServer()709 public void testSetVcnConfigRequiresNonSystemServer() throws Exception { 710 doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); 711 712 try { 713 mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 714 fail("Expected IllegalStateException exception for system server"); 715 } catch (IllegalStateException expected) { 716 } 717 } 718 719 @Test testSetVcnConfigRequiresSystemUser()720 public void testSetVcnConfigRequiresSystemUser() throws Exception { 721 doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID)) 722 .when(mMockDeps) 723 .getBinderCallingUid(); 724 725 try { 726 mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 727 fail("Expected security exception for non system user"); 728 } catch (SecurityException expected) { 729 verify(mMockPolicyListener, never()).onPolicyChanged(); 730 } 731 } 732 733 @Test testSetVcnConfigRequiresCarrierPrivileges()734 public void testSetVcnConfigRequiresCarrierPrivileges() throws Exception { 735 setupMockedCarrierPrivilege(false); 736 737 try { 738 mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 739 fail("Expected security exception for missing carrier privileges"); 740 } catch (SecurityException expected) { 741 verify(mMockPolicyListener, never()).onPolicyChanged(); 742 } 743 } 744 745 @Test testSetVcnConfigMismatchedPackages()746 public void testSetVcnConfigMismatchedPackages() throws Exception { 747 try { 748 mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME_2); 749 fail("Expected exception due to mismatched packages in config and method call"); 750 } catch (IllegalArgumentException expected) { 751 verify(mMockPolicyListener, never()).onPolicyChanged(); 752 } 753 } 754 755 @Test testSetVcnConfig()756 public void testSetVcnConfig() throws Exception { 757 // Use a different UUID to simulate a new VCN config. 758 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 759 assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2)); 760 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 761 } 762 763 @Test testSetVcnConfigNonActiveSimDoesNotStartVcn()764 public void testSetVcnConfigNonActiveSimDoesNotStartVcn() throws Exception { 765 // Use a different UUID to simulate a new VCN config. 766 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 767 assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2)); 768 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 769 770 verify(mMockDeps, never()).newVcn(any(), any(), any(), any(), any()); 771 } 772 773 @Test testSetVcnConfigActiveSimTearsDownExistingVcnsImmediately()774 public void testSetVcnConfigActiveSimTearsDownExistingVcnsImmediately() throws Exception { 775 final Vcn vcn = startAndGetVcnInstance(TEST_UUID_1); 776 777 // Use a different UUID to simulate a new VCN config. 778 setupActiveSubscription(TEST_UUID_2); 779 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 780 781 verify(mMockDeps, times(2)).newVcn(any(), any(), any(), any(), any()); 782 verify(vcn).teardownAsynchronously(); 783 assertEquals(1, mVcnMgmtSvc.getAllVcns().size()); 784 assertFalse(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_1)); 785 assertTrue(mVcnMgmtSvc.getAllVcns().containsKey(TEST_UUID_2)); 786 } 787 788 @Test testSetVcnConfigTestModeRequiresPermission()789 public void testSetVcnConfigTestModeRequiresPermission() throws Exception { 790 doThrow(new SecurityException("Requires MANAGE_TEST_NETWORKS")) 791 .when(mMockContext) 792 .enforceCallingPermission( 793 eq(android.Manifest.permission.MANAGE_TEST_NETWORKS), any()); 794 795 final VcnConfig vcnConfig = 796 new VcnConfig.Builder(mMockContext) 797 .addGatewayConnectionConfig( 798 VcnGatewayConnectionConfigTest.buildTestConfig()) 799 .setIsTestModeProfile() 800 .build(); 801 802 try { 803 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, vcnConfig, TEST_PACKAGE_NAME); 804 fail("Expected exception due to using test-mode without permission"); 805 } catch (SecurityException e) { 806 verify(mMockPolicyListener, never()).onPolicyChanged(); 807 } 808 } 809 810 @Test testSetVcnConfigNotifiesStatusCallback()811 public void testSetVcnConfigNotifiesStatusCallback() throws Exception { 812 triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_2, Collections.singleton(TEST_UUID_2)); 813 814 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); 815 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); 816 817 // Use a different UUID to simulate a new VCN config. 818 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 819 820 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); 821 } 822 823 @Test testClearVcnConfigRequiresNonSystemServer()824 public void testClearVcnConfigRequiresNonSystemServer() throws Exception { 825 doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); 826 827 try { 828 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); 829 fail("Expected IllegalStateException exception for system server"); 830 } catch (IllegalStateException expected) { 831 } 832 } 833 834 @Test testClearVcnConfigRequiresSystemUser()835 public void testClearVcnConfigRequiresSystemUser() throws Exception { 836 doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID)) 837 .when(mMockDeps) 838 .getBinderCallingUid(); 839 840 try { 841 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); 842 fail("Expected security exception for non system user"); 843 } catch (SecurityException expected) { 844 } 845 } 846 847 @Test testClearVcnConfigRequiresCarrierPrivilegesOrProvisioningPackage()848 public void testClearVcnConfigRequiresCarrierPrivilegesOrProvisioningPackage() 849 throws Exception { 850 setupMockedCarrierPrivilege(false); 851 852 try { 853 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2); 854 fail("Expected security exception for missing carrier privileges"); 855 } catch (SecurityException expected) { 856 } 857 } 858 859 @Test testClearVcnConfigMismatchedPackages()860 public void testClearVcnConfigMismatchedPackages() throws Exception { 861 try { 862 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2); 863 fail("Expected security exception due to mismatched packages"); 864 } catch (SecurityException expected) { 865 } 866 } 867 868 @Test testClearVcnConfig_callerIsProvisioningPackage()869 public void testClearVcnConfig_callerIsProvisioningPackage() throws Exception { 870 // Lose carrier privileges to test that provisioning package is sufficient. 871 setupMockedCarrierPrivilege(false); 872 873 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME); 874 assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); 875 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 876 } 877 878 @Test testClearVcnConfig_callerIsCarrierPrivileged()879 public void testClearVcnConfig_callerIsCarrierPrivileged() throws Exception { 880 setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2); 881 882 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2); 883 assertTrue(mVcnMgmtSvc.getConfigs().isEmpty()); 884 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 885 } 886 887 @Test testClearVcnConfigNotifiesStatusCallback()888 public void testClearVcnConfigNotifiesStatusCallback() throws Exception { 889 setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */); 890 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); 891 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); 892 893 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME); 894 895 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); 896 } 897 898 @Test testSetVcnConfigClearVcnConfigStartsUpdatesAndTearsDownVcns()899 public void testSetVcnConfigClearVcnConfigStartsUpdatesAndTearsDownVcns() throws Exception { 900 setupActiveSubscription(TEST_UUID_2); 901 902 // Use a different UUID to simulate a new VCN config. 903 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 904 final Map<ParcelUuid, Vcn> vcnInstances = mVcnMgmtSvc.getAllVcns(); 905 final Vcn vcnInstance = vcnInstances.get(TEST_UUID_2); 906 assertEquals(1, vcnInstances.size()); 907 assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2)); 908 verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class)); 909 910 // Verify Vcn is started 911 verify(mMockDeps) 912 .newVcn(eq(mVcnContext), eq(TEST_UUID_2), eq(TEST_VCN_CONFIG), any(), any()); 913 914 // Verify Vcn is updated if it was previously started 915 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 916 verify(vcnInstance).updateConfig(TEST_VCN_CONFIG); 917 918 // Verify Vcn is stopped if it was already started 919 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME); 920 verify(vcnInstance).teardownAsynchronously(); 921 } 922 923 @Test testGetConfiguredSubscriptionGroupsRequiresSystemUser()924 public void testGetConfiguredSubscriptionGroupsRequiresSystemUser() throws Exception { 925 doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, TEST_UID)) 926 .when(mMockDeps) 927 .getBinderCallingUid(); 928 929 try { 930 mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); 931 fail("Expected security exception for non system user"); 932 } catch (SecurityException expected) { 933 } 934 } 935 936 @Test testGetConfiguredSubscriptionGroupsMismatchedPackages()937 public void testGetConfiguredSubscriptionGroupsMismatchedPackages() throws Exception { 938 doThrow(new SecurityException()) 939 .when(mAppOpsMgr) 940 .checkPackage(TEST_UID, TEST_PACKAGE_NAME_2); 941 942 try { 943 mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME_2); 944 fail("Expected security exception due to mismatched packages"); 945 } catch (SecurityException expected) { 946 } 947 } 948 949 @Test testGetConfiguredSubscriptionGroups()950 public void testGetConfiguredSubscriptionGroups() throws Exception { 951 setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2); 952 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 953 mVcnMgmtSvc.setVcnConfig(TEST_UUID_3, TEST_VCN_CONFIG_PKG_2, TEST_PACKAGE_NAME_2); 954 955 // Assert that if UUIDs 1, 2 and 3 are provisioned, the caller only gets ones that they are 956 // privileged for, or are the provisioning package of. 957 triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1)); 958 final List<ParcelUuid> subGrps = 959 mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME); 960 assertEquals(Arrays.asList(new ParcelUuid[] {TEST_UUID_1, TEST_UUID_2}), subGrps); 961 } 962 963 @Test testAddVcnUnderlyingNetworkPolicyListener()964 public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception { 965 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 966 967 verify(mMockIBinder).linkToDeath(any(), anyInt()); 968 } 969 970 @Test(expected = SecurityException.class) testAddVcnUnderlyingNetworkPolicyListenerInvalidPermission()971 public void testAddVcnUnderlyingNetworkPolicyListenerInvalidPermission() { 972 doReturn(PackageManager.PERMISSION_DENIED) 973 .when(mMockContext) 974 .checkCallingOrSelfPermission(any()); 975 976 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 977 } 978 979 @Test testRemoveVcnUnderlyingNetworkPolicyListener()980 public void testRemoveVcnUnderlyingNetworkPolicyListener() { 981 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 982 983 mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 984 } 985 986 @Test(expected = SecurityException.class) testRemoveVcnUnderlyingNetworkPolicyListenerInvalidPermission()987 public void testRemoveVcnUnderlyingNetworkPolicyListenerInvalidPermission() { 988 doReturn(PackageManager.PERMISSION_DENIED) 989 .when(mMockContext) 990 .checkCallingOrSelfPermission(any()); 991 992 mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 993 } 994 995 @Test testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered()996 public void testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered() { 997 mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 998 } 999 verifyMergedNetworkCapabilities( NetworkCapabilities mergedCapabilities, int transportType, boolean isVcnManaged, boolean isRestricted)1000 private void verifyMergedNetworkCapabilities( 1001 NetworkCapabilities mergedCapabilities, 1002 int transportType, 1003 boolean isVcnManaged, 1004 boolean isRestricted) { 1005 assertTrue(mergedCapabilities.hasTransport(transportType)); 1006 assertEquals( 1007 !isVcnManaged, 1008 mergedCapabilities.hasCapability( 1009 NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)); 1010 assertEquals( 1011 !isRestricted, 1012 mergedCapabilities.hasCapability( 1013 NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)); 1014 } 1015 setupSubscriptionAndStartVcn(int subId, ParcelUuid subGrp, boolean isVcnActive)1016 private void setupSubscriptionAndStartVcn(int subId, ParcelUuid subGrp, boolean isVcnActive) { 1017 setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive, true /* hasCarrierPrivileges */); 1018 } 1019 setupSubscriptionAndStartVcn( int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges)1020 private void setupSubscriptionAndStartVcn( 1021 int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) { 1022 mVcnMgmtSvc.systemReady(); 1023 triggerSubscriptionTrackerCbAndGetSnapshot( 1024 subGrp, 1025 Collections.singleton(subGrp), 1026 Collections.singletonMap(subId, subGrp), 1027 hasCarrierPrivileges); 1028 1029 final Vcn vcn = startAndGetVcnInstance(subGrp); 1030 doReturn(isVcnActive ? VCN_STATUS_CODE_ACTIVE : VCN_STATUS_CODE_SAFE_MODE) 1031 .when(vcn) 1032 .getStatus(); 1033 } 1034 getNetworkCapabilitiesBuilderForTransport( int subId, int transport)1035 private NetworkCapabilities.Builder getNetworkCapabilitiesBuilderForTransport( 1036 int subId, int transport) { 1037 final NetworkCapabilities.Builder ncBuilder = 1038 new NetworkCapabilities.Builder() 1039 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 1040 .addTransportType(transport); 1041 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 1042 ncBuilder.setSubscriptionIds(Collections.singleton(subId)); 1043 } 1044 1045 return ncBuilder; 1046 } 1047 startVcnAndGetPolicyForTransport( int subId, ParcelUuid subGrp, boolean isVcnActive, int transport)1048 private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( 1049 int subId, ParcelUuid subGrp, boolean isVcnActive, int transport) { 1050 setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive); 1051 1052 return mVcnMgmtSvc.getUnderlyingNetworkPolicy( 1053 getNetworkCapabilitiesBuilderForTransport(subId, transport).build(), TEST_LP_1); 1054 } 1055 checkGetRestrictedTransportsFromCarrierConfig( ParcelUuid subGrp, TelephonySubscriptionSnapshot lastSnapshot, Set<Integer> expectedTransports)1056 private void checkGetRestrictedTransportsFromCarrierConfig( 1057 ParcelUuid subGrp, 1058 TelephonySubscriptionSnapshot lastSnapshot, 1059 Set<Integer> expectedTransports) { 1060 Set<Integer> result = 1061 new VcnManagementService.Dependencies() 1062 .getRestrictedTransportsFromCarrierConfig(subGrp, lastSnapshot); 1063 assertEquals(expectedTransports, result); 1064 } 1065 1066 @Test testGetRestrictedTransportsFromCarrierConfig()1067 public void testGetRestrictedTransportsFromCarrierConfig() { 1068 final Set<Integer> restrictedTransports = new ArraySet<>(); 1069 restrictedTransports.add(TRANSPORT_CELLULAR); 1070 restrictedTransports.add(TRANSPORT_WIFI); 1071 1072 PersistableBundle carrierConfigBundle = new PersistableBundle(); 1073 carrierConfigBundle.putIntArray( 1074 VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY, 1075 restrictedTransports.stream().mapToInt(i -> i).toArray()); 1076 final PersistableBundleWrapper carrierConfig = 1077 new PersistableBundleWrapper(carrierConfigBundle); 1078 1079 final TelephonySubscriptionSnapshot lastSnapshot = 1080 mock(TelephonySubscriptionSnapshot.class); 1081 doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2)); 1082 1083 checkGetRestrictedTransportsFromCarrierConfig( 1084 TEST_UUID_2, lastSnapshot, restrictedTransports); 1085 } 1086 1087 @Test testGetRestrictedTransportsFromCarrierConfig_noRestrictPolicyConfigured()1088 public void testGetRestrictedTransportsFromCarrierConfig_noRestrictPolicyConfigured() { 1089 final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI); 1090 1091 final PersistableBundleWrapper carrierConfig = 1092 new PersistableBundleWrapper(new PersistableBundle()); 1093 final TelephonySubscriptionSnapshot lastSnapshot = 1094 mock(TelephonySubscriptionSnapshot.class); 1095 doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2)); 1096 1097 checkGetRestrictedTransportsFromCarrierConfig( 1098 TEST_UUID_2, lastSnapshot, restrictedTransports); 1099 } 1100 1101 @Test testGetRestrictedTransportsFromCarrierConfig_noCarrierConfig()1102 public void testGetRestrictedTransportsFromCarrierConfig_noCarrierConfig() { 1103 final Set<Integer> restrictedTransports = Collections.singleton(TRANSPORT_WIFI); 1104 1105 final TelephonySubscriptionSnapshot lastSnapshot = 1106 mock(TelephonySubscriptionSnapshot.class); 1107 1108 checkGetRestrictedTransportsFromCarrierConfig( 1109 TEST_UUID_2, lastSnapshot, restrictedTransports); 1110 } 1111 1112 @Test testGetRestrictedTransportsFromCarrierConfigAndVcnConfig()1113 public void testGetRestrictedTransportsFromCarrierConfigAndVcnConfig() { 1114 // Configure restricted transport in CarrierConfig 1115 final Set<Integer> restrictedTransportInCarrierConfig = 1116 Collections.singleton(TRANSPORT_WIFI); 1117 1118 PersistableBundle carrierConfigBundle = new PersistableBundle(); 1119 carrierConfigBundle.putIntArray( 1120 VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY, 1121 restrictedTransportInCarrierConfig.stream().mapToInt(i -> i).toArray()); 1122 final PersistableBundleWrapper carrierConfig = 1123 new PersistableBundleWrapper(carrierConfigBundle); 1124 1125 final TelephonySubscriptionSnapshot lastSnapshot = 1126 mock(TelephonySubscriptionSnapshot.class); 1127 doReturn(carrierConfig).when(lastSnapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2)); 1128 1129 // Configure restricted transport in VcnConfig 1130 final Context mockContext = mock(Context.class); 1131 doReturn(TEST_PACKAGE_NAME).when(mockContext).getOpPackageName(); 1132 final VcnConfig vcnConfig = 1133 VcnConfigTest.buildTestConfig( 1134 mockContext, Collections.singleton(TRANSPORT_CELLULAR)); 1135 1136 // Verifications 1137 final Set<Integer> expectedTransports = new ArraySet<>(); 1138 expectedTransports.add(TRANSPORT_CELLULAR); 1139 expectedTransports.add(TRANSPORT_WIFI); 1140 1141 Set<Integer> result = 1142 new VcnManagementService.Dependencies() 1143 .getRestrictedTransports(TEST_UUID_2, lastSnapshot, vcnConfig); 1144 assertEquals(expectedTransports, result); 1145 } 1146 checkGetUnderlyingNetworkPolicy( int transportType, boolean isTransportRestricted, boolean isActive, boolean expectVcnManaged, boolean expectRestricted)1147 private void checkGetUnderlyingNetworkPolicy( 1148 int transportType, 1149 boolean isTransportRestricted, 1150 boolean isActive, 1151 boolean expectVcnManaged, 1152 boolean expectRestricted) 1153 throws Exception { 1154 1155 final Set<Integer> restrictedTransports = new ArraySet(); 1156 if (isTransportRestricted) { 1157 restrictedTransports.add(transportType); 1158 } 1159 doReturn(restrictedTransports).when(mMockDeps).getRestrictedTransports(any(), any(), any()); 1160 1161 final VcnUnderlyingNetworkPolicy policy = 1162 startVcnAndGetPolicyForTransport( 1163 TEST_SUBSCRIPTION_ID, TEST_UUID_2, isActive, transportType); 1164 1165 assertFalse(policy.isTeardownRequested()); 1166 verifyMergedNetworkCapabilities( 1167 policy.getMergedNetworkCapabilities(), 1168 transportType, 1169 expectVcnManaged, 1170 expectRestricted); 1171 } 1172 1173 @Test testGetUnderlyingNetworkPolicy_unrestrictCell()1174 public void testGetUnderlyingNetworkPolicy_unrestrictCell() throws Exception { 1175 checkGetUnderlyingNetworkPolicy( 1176 TRANSPORT_CELLULAR, 1177 false /* isTransportRestricted */, 1178 true /* isActive */, 1179 true /* expectVcnManaged */, 1180 false /* expectRestricted */); 1181 } 1182 1183 @Test testGetUnderlyingNetworkPolicy_unrestrictCellSafeMode()1184 public void testGetUnderlyingNetworkPolicy_unrestrictCellSafeMode() throws Exception { 1185 checkGetUnderlyingNetworkPolicy( 1186 TRANSPORT_CELLULAR, 1187 false /* isTransportRestricted */, 1188 false /* isActive */, 1189 false /* expectVcnManaged */, 1190 false /* expectRestricted */); 1191 } 1192 1193 @Test testGetUnderlyingNetworkPolicy_restrictCell()1194 public void testGetUnderlyingNetworkPolicy_restrictCell() throws Exception { 1195 checkGetUnderlyingNetworkPolicy( 1196 TRANSPORT_CELLULAR, 1197 true /* isTransportRestricted */, 1198 true /* isActive */, 1199 true /* expectVcnManaged */, 1200 true /* expectRestricted */); 1201 } 1202 1203 @Test testGetUnderlyingNetworkPolicy_restrictCellSafeMode()1204 public void testGetUnderlyingNetworkPolicy_restrictCellSafeMode() throws Exception { 1205 checkGetUnderlyingNetworkPolicy( 1206 TRANSPORT_CELLULAR, 1207 true /* isTransportRestricted */, 1208 false /* isActive */, 1209 false /* expectVcnManaged */, 1210 false /* expectRestricted */); 1211 } 1212 1213 @Test testGetUnderlyingNetworkPolicy_unrestrictWifi()1214 public void testGetUnderlyingNetworkPolicy_unrestrictWifi() throws Exception { 1215 checkGetUnderlyingNetworkPolicy( 1216 TRANSPORT_WIFI, 1217 false /* isTransportRestricted */, 1218 true /* isActive */, 1219 true /* expectVcnManaged */, 1220 false /* expectRestricted */); 1221 } 1222 1223 @Test testGetUnderlyingNetworkPolicy_unrestrictWifiSafeMode()1224 public void testGetUnderlyingNetworkPolicy_unrestrictWifiSafeMode() throws Exception { 1225 checkGetUnderlyingNetworkPolicy( 1226 TRANSPORT_WIFI, 1227 false /* isTransportRestricted */, 1228 false /* isActive */, 1229 false /* expectVcnManaged */, 1230 false /* expectRestricted */); 1231 } 1232 1233 @Test testGetUnderlyingNetworkPolicy_restrictWifi()1234 public void testGetUnderlyingNetworkPolicy_restrictWifi() throws Exception { 1235 checkGetUnderlyingNetworkPolicy( 1236 TRANSPORT_WIFI, 1237 true /* isTransportRestricted */, 1238 true /* isActive */, 1239 true /* expectVcnManaged */, 1240 true /* expectRestricted */); 1241 } 1242 1243 @Test testGetUnderlyingNetworkPolicy_restrictWifiSafeMode()1244 public void testGetUnderlyingNetworkPolicy_restrictWifiSafeMode() throws Exception { 1245 checkGetUnderlyingNetworkPolicy( 1246 TRANSPORT_WIFI, 1247 true /* isTransportRestricted */, 1248 false /* isActive */, 1249 false /* expectVcnManaged */, 1250 true /* expectRestricted */); 1251 } 1252 1253 @Test testGetUnderlyingNetworkPolicyCell_restrictWifi()1254 public void testGetUnderlyingNetworkPolicyCell_restrictWifi() throws Exception { 1255 doReturn(Collections.singleton(TRANSPORT_WIFI)) 1256 .when(mMockDeps) 1257 .getRestrictedTransports(any(), any(), any()); 1258 1259 setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isVcnActive */); 1260 1261 // Get the policy for a cellular network and expect it won't be affected by the wifi 1262 // restriction policy 1263 final VcnUnderlyingNetworkPolicy policy = 1264 mVcnMgmtSvc.getUnderlyingNetworkPolicy( 1265 getNetworkCapabilitiesBuilderForTransport( 1266 TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR) 1267 .build(), 1268 new LinkProperties()); 1269 1270 assertFalse(policy.isTeardownRequested()); 1271 verifyMergedNetworkCapabilities( 1272 policy.getMergedNetworkCapabilities(), 1273 TRANSPORT_CELLULAR, 1274 true /* expectVcnManaged */, 1275 false /* expectRestricted */); 1276 } 1277 setupTrackedNetwork(NetworkCapabilities caps, LinkProperties lp)1278 private void setupTrackedNetwork(NetworkCapabilities caps, LinkProperties lp) { 1279 mVcnMgmtSvc.systemReady(); 1280 1281 final ArgumentCaptor<NetworkCallback> captor = 1282 ArgumentCaptor.forClass(NetworkCallback.class); 1283 verify(mConnMgr) 1284 .registerNetworkCallback( 1285 eq(new NetworkRequest.Builder().clearCapabilities().build()), 1286 captor.capture()); 1287 1288 Network mockNetwork = mock(Network.class, CALLS_REAL_METHODS); 1289 captor.getValue().onCapabilitiesChanged(mockNetwork, caps); 1290 captor.getValue().onLinkPropertiesChanged(mockNetwork, lp); 1291 } 1292 1293 @Test testGetUnderlyingNetworkPolicyVcnWifi_unrestrictingExistingNetworkRequiresRestart()1294 public void testGetUnderlyingNetworkPolicyVcnWifi_unrestrictingExistingNetworkRequiresRestart() 1295 throws Exception { 1296 final NetworkCapabilities existingNetworkCaps = 1297 getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) 1298 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 1299 .build(); 1300 setupTrackedNetwork(existingNetworkCaps, TEST_LP_1); 1301 1302 // Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED 1303 // immutable capability 1304 final VcnUnderlyingNetworkPolicy policy = 1305 mVcnMgmtSvc.getUnderlyingNetworkPolicy( 1306 getNetworkCapabilitiesBuilderForTransport( 1307 TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) 1308 .build(), 1309 TEST_LP_1); 1310 assertTrue(policy.isTeardownRequested()); 1311 } 1312 1313 @Test testGetUnderlyingNetworkPolicyVcnWifi_restrictingExistingNetworkRequiresRestart()1314 public void testGetUnderlyingNetworkPolicyVcnWifi_restrictingExistingNetworkRequiresRestart() 1315 throws Exception { 1316 final NetworkCapabilities existingNetworkCaps = 1317 getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI) 1318 .build(); 1319 setupTrackedNetwork(existingNetworkCaps, TEST_LP_1); 1320 1321 final VcnUnderlyingNetworkPolicy policy = 1322 startVcnAndGetPolicyForTransport( 1323 TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */, TRANSPORT_WIFI); 1324 1325 assertTrue(policy.isTeardownRequested()); 1326 } 1327 1328 @Test testGetUnderlyingNetworkPolicyForRestrictedImsWhenUnrestrictingCell()1329 public void testGetUnderlyingNetworkPolicyForRestrictedImsWhenUnrestrictingCell() 1330 throws Exception { 1331 final NetworkCapabilities existingNetworkCaps = 1332 getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR) 1333 .addCapability(NET_CAPABILITY_NOT_RESTRICTED) 1334 .removeCapability(NET_CAPABILITY_IMS) 1335 .build(); 1336 setupTrackedNetwork(existingNetworkCaps, TEST_LP_1); 1337 1338 final VcnUnderlyingNetworkPolicy policy = 1339 mVcnMgmtSvc.getUnderlyingNetworkPolicy( 1340 getNetworkCapabilitiesBuilderForTransport( 1341 TEST_SUBSCRIPTION_ID, TRANSPORT_CELLULAR) 1342 .addCapability(NET_CAPABILITY_IMS) 1343 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 1344 .build(), 1345 new LinkProperties()); 1346 assertFalse(policy.isTeardownRequested()); 1347 } 1348 1349 @Test testGetUnderlyingNetworkPolicyNonVcnNetwork()1350 public void testGetUnderlyingNetworkPolicyNonVcnNetwork() throws Exception { 1351 setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_1, true /* isActive */); 1352 1353 NetworkCapabilities nc = 1354 new NetworkCapabilities.Builder() 1355 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 1356 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 1357 .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2)) 1358 .build(); 1359 1360 VcnUnderlyingNetworkPolicy policy = 1361 mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc, new LinkProperties()); 1362 1363 assertFalse(policy.isTeardownRequested()); 1364 assertEquals(nc, policy.getMergedNetworkCapabilities()); 1365 } 1366 1367 /** 1368 * Checks that networks with similar capabilities do not clobber each other. 1369 * 1370 * <p>In previous iterations, the VcnMgmtSvc used capability-matching to check if a network 1371 * undergoing policy checks were the same as an existing networks. However, this meant that if 1372 * there were newly added capabilities that the VCN did not check, two networks differing only 1373 * by that capability would restart each other constantly. 1374 */ 1375 @Test testGetUnderlyingNetworkPolicySimilarNetworks()1376 public void testGetUnderlyingNetworkPolicySimilarNetworks() throws Exception { 1377 NetworkCapabilities nc1 = 1378 new NetworkCapabilities.Builder() 1379 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 1380 .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) 1381 .addCapability(NET_CAPABILITY_INTERNET) 1382 .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2)) 1383 .build(); 1384 1385 NetworkCapabilities nc2 = 1386 new NetworkCapabilities.Builder(nc1) 1387 .addCapability(NET_CAPABILITY_ENTERPRISE) 1388 .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) 1389 .build(); 1390 1391 setupTrackedNetwork(nc1, TEST_LP_1); 1392 1393 VcnUnderlyingNetworkPolicy policy = mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc2, TEST_LP_2); 1394 1395 assertFalse(policy.isTeardownRequested()); 1396 assertEquals(nc2, policy.getMergedNetworkCapabilities()); 1397 } 1398 1399 @Test(expected = SecurityException.class) testGetUnderlyingNetworkPolicyInvalidPermission()1400 public void testGetUnderlyingNetworkPolicyInvalidPermission() { 1401 doReturn(PackageManager.PERMISSION_DENIED) 1402 .when(mMockContext) 1403 .checkCallingOrSelfPermission(any()); 1404 1405 mVcnMgmtSvc.getUnderlyingNetworkPolicy(new NetworkCapabilities(), new LinkProperties()); 1406 } 1407 1408 @Test testSubscriptionSnapshotUpdateNotifiesVcn()1409 public void testSubscriptionSnapshotUpdateNotifiesVcn() { 1410 setupActiveSubscription(TEST_UUID_2); 1411 1412 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 1413 final Map<ParcelUuid, Vcn> vcnInstances = mVcnMgmtSvc.getAllVcns(); 1414 final Vcn vcnInstance = vcnInstances.get(TEST_UUID_2); 1415 1416 TelephonySubscriptionSnapshot snapshot = 1417 triggerSubscriptionTrackerCbAndGetSnapshot( 1418 TEST_UUID_2, Collections.singleton(TEST_UUID_2)); 1419 1420 verify(vcnInstance).updateSubscriptionSnapshot(eq(snapshot)); 1421 } 1422 1423 @Test testAddNewVcnUpdatesPolicyListener()1424 public void testAddNewVcnUpdatesPolicyListener() throws Exception { 1425 setupActiveSubscription(TEST_UUID_2); 1426 1427 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 1428 1429 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 1430 1431 verify(mMockPolicyListener).onPolicyChanged(); 1432 } 1433 1434 @Test testVcnConfigChangeUpdatesPolicyListener()1435 public void testVcnConfigChangeUpdatesPolicyListener() throws Exception { 1436 setupActiveSubscription(TEST_UUID_2); 1437 1438 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 1439 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 1440 1441 final Context mockContext = mock(Context.class); 1442 doReturn(TEST_PACKAGE_NAME).when(mockContext).getOpPackageName(); 1443 final VcnConfig vcnConfig = 1444 VcnConfigTest.buildTestConfig( 1445 mockContext, Collections.singleton(TRANSPORT_CELLULAR)); 1446 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, vcnConfig, TEST_PACKAGE_NAME); 1447 1448 verify(mMockPolicyListener).onPolicyChanged(); 1449 } 1450 1451 @Test testRemoveVcnUpdatesPolicyListener()1452 public void testRemoveVcnUpdatesPolicyListener() throws Exception { 1453 setupActiveSubscription(TEST_UUID_2); 1454 1455 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 1456 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 1457 1458 mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2, TEST_PACKAGE_NAME); 1459 1460 verify(mMockPolicyListener).onPolicyChanged(); 1461 } 1462 1463 @Test testVcnSubIdChangeUpdatesPolicyListener()1464 public void testVcnSubIdChangeUpdatesPolicyListener() throws Exception { 1465 setupActiveSubscription(TEST_UUID_2); 1466 1467 startAndGetVcnInstance(TEST_UUID_2); 1468 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 1469 1470 triggerSubscriptionTrackerCbAndGetSnapshot( 1471 TEST_UUID_2, 1472 Collections.singleton(TEST_UUID_2), 1473 Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_2)); 1474 1475 verify(mMockPolicyListener).onPolicyChanged(); 1476 } 1477 1478 @Test testVcnCarrierConfigChangeUpdatesPolicyListener()1479 public void testVcnCarrierConfigChangeUpdatesPolicyListener() throws Exception { 1480 setupActiveSubscription(TEST_UUID_2); 1481 1482 mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); 1483 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 1484 1485 final TelephonySubscriptionSnapshot snapshot = 1486 buildSubscriptionSnapshot( 1487 TEST_SUBSCRIPTION_ID, 1488 TEST_UUID_2, 1489 Collections.singleton(TEST_UUID_2), 1490 Collections.emptyMap(), 1491 true /* hasCarrierPrivileges */); 1492 1493 final PersistableBundleWrapper mockCarrierConfig = mock(PersistableBundleWrapper.class); 1494 doReturn(mockCarrierConfig).when(snapshot).getCarrierConfigForSubGrp(eq(TEST_UUID_2)); 1495 1496 final TelephonySubscriptionTrackerCallback cb = getTelephonySubscriptionTrackerCallback(); 1497 cb.onNewSnapshot(snapshot); 1498 1499 verify(mMockPolicyListener).onPolicyChanged(); 1500 } 1501 triggerVcnSafeMode( @onNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot, boolean isInSafeMode)1502 private void triggerVcnSafeMode( 1503 @NonNull ParcelUuid subGroup, 1504 @NonNull TelephonySubscriptionSnapshot snapshot, 1505 boolean isInSafeMode) 1506 throws Exception { 1507 verify(mMockDeps) 1508 .newVcn( 1509 eq(mVcnContext), 1510 eq(subGroup), 1511 eq(TEST_VCN_CONFIG), 1512 eq(snapshot), 1513 mVcnCallbackCaptor.capture()); 1514 1515 VcnCallback vcnCallback = mVcnCallbackCaptor.getValue(); 1516 vcnCallback.onSafeModeStatusChanged(isInSafeMode); 1517 } 1518 verifyVcnSafeModeChangesNotifiesPolicyListeners(boolean enterSafeMode)1519 private void verifyVcnSafeModeChangesNotifiesPolicyListeners(boolean enterSafeMode) 1520 throws Exception { 1521 TelephonySubscriptionSnapshot snapshot = 1522 triggerSubscriptionTrackerCbAndGetSnapshot( 1523 TEST_UUID_1, Collections.singleton(TEST_UUID_1)); 1524 1525 mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); 1526 1527 triggerVcnSafeMode(TEST_UUID_1, snapshot, enterSafeMode); 1528 1529 verify(mMockPolicyListener).onPolicyChanged(); 1530 } 1531 1532 @Test testVcnEnteringSafeModeNotifiesPolicyListeners()1533 public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception { 1534 verifyVcnSafeModeChangesNotifiesPolicyListeners(true /* enterSafeMode */); 1535 } 1536 1537 @Test testVcnExitingSafeModeNotifiesPolicyListeners()1538 public void testVcnExitingSafeModeNotifiesPolicyListeners() throws Exception { 1539 verifyVcnSafeModeChangesNotifiesPolicyListeners(false /* enterSafeMode */); 1540 } 1541 triggerVcnStatusCallbackOnSafeModeStatusChanged( @onNull ParcelUuid subGroup, @NonNull String pkgName, int uid, boolean hasPermissionsforSubGroup)1542 private void triggerVcnStatusCallbackOnSafeModeStatusChanged( 1543 @NonNull ParcelUuid subGroup, 1544 @NonNull String pkgName, 1545 int uid, 1546 boolean hasPermissionsforSubGroup) 1547 throws Exception { 1548 TelephonySubscriptionSnapshot snapshot = 1549 triggerSubscriptionTrackerCbAndGetSnapshot( 1550 subGroup, Collections.singleton(subGroup)); 1551 1552 setupSubscriptionAndStartVcn( 1553 TEST_SUBSCRIPTION_ID, subGroup, true /* isActive */, hasPermissionsforSubGroup); 1554 1555 doReturn(hasPermissionsforSubGroup) 1556 .when(snapshot) 1557 .packageHasPermissionsForSubscriptionGroup(eq(subGroup), eq(pkgName)); 1558 1559 mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName); 1560 1561 triggerVcnSafeMode(subGroup, snapshot, true /* enterSafeMode */); 1562 } 1563 1564 @Test testVcnStatusCallbackOnSafeModeStatusChangedWithCarrierPrivileges()1565 public void testVcnStatusCallbackOnSafeModeStatusChangedWithCarrierPrivileges() 1566 throws Exception { 1567 triggerVcnStatusCallbackOnSafeModeStatusChanged( 1568 TEST_UUID_1, TEST_PACKAGE_NAME, TEST_UID, true /* hasPermissionsforSubGroup */); 1569 1570 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); 1571 } 1572 1573 @Test testVcnStatusCallbackOnSafeModeStatusChangedWithoutCarrierPrivileges()1574 public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutCarrierPrivileges() 1575 throws Exception { 1576 triggerVcnStatusCallbackOnSafeModeStatusChanged( 1577 TEST_UUID_1, TEST_PACKAGE_NAME, TEST_UID, false /* hasPermissionsforSubGroup */); 1578 1579 verify(mMockStatusCallback, never()) 1580 .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); 1581 } 1582 1583 @Test testRegisterVcnStatusCallback()1584 public void testRegisterVcnStatusCallback() throws Exception { 1585 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1586 1587 Map<IBinder, VcnStatusCallbackInfo> callbacks = mVcnMgmtSvc.getAllStatusCallbacks(); 1588 VcnStatusCallbackInfo cbInfo = callbacks.get(mMockIBinder); 1589 1590 assertNotNull(cbInfo); 1591 assertEquals(TEST_UUID_1, cbInfo.mSubGroup); 1592 assertEquals(mMockStatusCallback, cbInfo.mCallback); 1593 assertEquals(TEST_PACKAGE_NAME, cbInfo.mPkgName); 1594 assertEquals(TEST_UID, cbInfo.mUid); 1595 verify(mMockIBinder).linkToDeath(eq(cbInfo), anyInt()); 1596 1597 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); 1598 } 1599 1600 @Test testRegisterVcnStatusCallback_MissingPermission()1601 public void testRegisterVcnStatusCallback_MissingPermission() throws Exception { 1602 setupSubscriptionAndStartVcn( 1603 TEST_SUBSCRIPTION_ID, 1604 TEST_UUID_1, 1605 true /* isActive */, 1606 false /* hasCarrierPrivileges */); 1607 1608 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1609 1610 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); 1611 } 1612 1613 @Test testRegisterVcnStatusCallback_VcnInactive()1614 public void testRegisterVcnStatusCallback_VcnInactive() throws Exception { 1615 setupSubscriptionAndStartVcn( 1616 TEST_SUBSCRIPTION_ID, 1617 TEST_UUID_1, 1618 true /* isActive */, 1619 true /* hasCarrierPrivileges */); 1620 1621 // VCN is currently active. Lose carrier privileges for TEST_PACKAGE and hit teardown 1622 // timeout so the VCN goes inactive. 1623 final TelephonySubscriptionSnapshot snapshot = 1624 triggerSubscriptionTrackerCbAndGetSnapshot( 1625 TEST_UUID_1, 1626 Collections.singleton(TEST_UUID_1), 1627 Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1), 1628 false /* hasCarrierPrivileges */); 1629 mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); 1630 mTestLooper.dispatchAll(); 1631 1632 // Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE 1633 // when the status callback is registered). Instead, setup permissions for TEST_CB_PACKAGE 1634 // so that it's permissioned to receive INACTIVE (instead of NOT_CONFIGURED) without 1635 // reactivating the VCN. 1636 doReturn(true) 1637 .when(snapshot) 1638 .packageHasPermissionsForSubscriptionGroup( 1639 eq(TEST_UUID_1), eq(TEST_CB_PACKAGE_NAME)); 1640 1641 mVcnMgmtSvc.registerVcnStatusCallback( 1642 TEST_UUID_1, mMockStatusCallback, TEST_CB_PACKAGE_NAME); 1643 1644 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_INACTIVE); 1645 } 1646 1647 @Test testRegisterVcnStatusCallback_VcnActive()1648 public void testRegisterVcnStatusCallback_VcnActive() throws Exception { 1649 setupSubscriptionAndStartVcn( 1650 TEST_SUBSCRIPTION_ID, 1651 TEST_UUID_1, 1652 true /* isActive */, 1653 true /* hasCarrierPrivileges */); 1654 1655 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1656 1657 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); 1658 } 1659 1660 @Test testRegisterVcnStatusCallback_VcnSafeMode()1661 public void testRegisterVcnStatusCallback_VcnSafeMode() throws Exception { 1662 setupSubscriptionAndStartVcn( 1663 TEST_SUBSCRIPTION_ID, 1664 TEST_UUID_1, 1665 false /* isActive */, 1666 true /* hasCarrierPrivileges */); 1667 1668 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1669 1670 verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); 1671 } 1672 1673 @Test(expected = IllegalStateException.class) testRegisterVcnStatusCallbackDuplicate()1674 public void testRegisterVcnStatusCallbackDuplicate() { 1675 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1676 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1677 } 1678 1679 @Test testUnregisterVcnStatusCallback()1680 public void testUnregisterVcnStatusCallback() { 1681 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1682 Map<IBinder, VcnStatusCallbackInfo> callbacks = mVcnMgmtSvc.getAllStatusCallbacks(); 1683 VcnStatusCallbackInfo cbInfo = callbacks.get(mMockIBinder); 1684 1685 mVcnMgmtSvc.unregisterVcnStatusCallback(mMockStatusCallback); 1686 assertTrue(mVcnMgmtSvc.getAllStatusCallbacks().isEmpty()); 1687 verify(mMockIBinder).unlinkToDeath(eq(cbInfo), anyInt()); 1688 } 1689 1690 @Test(expected = SecurityException.class) testRegisterVcnStatusCallbackInvalidPackage()1691 public void testRegisterVcnStatusCallbackInvalidPackage() { 1692 doThrow(new SecurityException()).when(mAppOpsMgr).checkPackage(TEST_UID, TEST_PACKAGE_NAME); 1693 1694 mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); 1695 } 1696 1697 @Test testUnregisterVcnStatusCallbackNeverRegistered()1698 public void testUnregisterVcnStatusCallbackNeverRegistered() { 1699 mVcnMgmtSvc.unregisterVcnStatusCallback(mMockStatusCallback); 1700 1701 assertTrue(mVcnMgmtSvc.getAllStatusCallbacks().isEmpty()); 1702 } 1703 } 1704