1 /* 2 * Copyright (C) 2016 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.connectivity; 18 19 import static android.content.pm.UserInfo.FLAG_ADMIN; 20 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; 21 import static android.content.pm.UserInfo.FLAG_PRIMARY; 22 import static android.content.pm.UserInfo.FLAG_RESTRICTED; 23 import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; 24 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 25 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; 26 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; 27 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; 28 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 29 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 30 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 31 32 import static org.junit.Assert.assertEquals; 33 import static org.junit.Assert.assertFalse; 34 import static org.junit.Assert.assertTrue; 35 import static org.mockito.AdditionalMatchers.aryEq; 36 import static org.mockito.ArgumentMatchers.any; 37 import static org.mockito.ArgumentMatchers.anyBoolean; 38 import static org.mockito.ArgumentMatchers.anyInt; 39 import static org.mockito.ArgumentMatchers.anyString; 40 import static org.mockito.ArgumentMatchers.eq; 41 import static org.mockito.Mockito.atLeastOnce; 42 import static org.mockito.Mockito.doAnswer; 43 import static org.mockito.Mockito.doNothing; 44 import static org.mockito.Mockito.inOrder; 45 import static org.mockito.Mockito.times; 46 import static org.mockito.Mockito.verify; 47 import static org.mockito.Mockito.when; 48 49 import android.annotation.UserIdInt; 50 import android.app.AppOpsManager; 51 import android.app.NotificationManager; 52 import android.content.Context; 53 import android.content.pm.ApplicationInfo; 54 import android.content.pm.PackageManager; 55 import android.content.pm.ResolveInfo; 56 import android.content.pm.ServiceInfo; 57 import android.content.pm.UserInfo; 58 import android.content.res.Resources; 59 import android.net.ConnectivityManager; 60 import android.net.IConnectivityManager; 61 import android.net.IpPrefix; 62 import android.net.LinkProperties; 63 import android.net.Network; 64 import android.net.NetworkCapabilities; 65 import android.net.NetworkInfo.DetailedState; 66 import android.net.RouteInfo; 67 import android.net.UidRange; 68 import android.net.VpnService; 69 import android.os.Build.VERSION_CODES; 70 import android.os.Bundle; 71 import android.os.INetworkManagementService; 72 import android.os.Looper; 73 import android.os.SystemClock; 74 import android.os.UserHandle; 75 import android.os.UserManager; 76 import android.support.test.filters.SmallTest; 77 import android.support.test.runner.AndroidJUnit4; 78 import android.util.ArrayMap; 79 import android.util.ArraySet; 80 81 import com.android.internal.R; 82 import com.android.internal.net.VpnConfig; 83 84 import org.junit.Before; 85 import org.junit.Test; 86 import org.junit.runner.RunWith; 87 import org.mockito.Answers; 88 import org.mockito.InOrder; 89 import org.mockito.Mock; 90 import org.mockito.MockitoAnnotations; 91 92 import java.net.Inet4Address; 93 import java.net.UnknownHostException; 94 import java.util.ArrayList; 95 import java.util.Arrays; 96 import java.util.Collections; 97 import java.util.HashMap; 98 import java.util.Map; 99 import java.util.Set; 100 import java.util.stream.Collectors; 101 import java.util.stream.Stream; 102 103 /** 104 * Tests for {@link Vpn}. 105 * 106 * Build, install and run with: 107 * runtest frameworks-net -c com.android.server.connectivity.VpnTest 108 */ 109 @RunWith(AndroidJUnit4.class) 110 @SmallTest 111 public class VpnTest { 112 private static final String TAG = "VpnTest"; 113 114 // Mock users 115 static final UserInfo primaryUser = new UserInfo(27, "Primary", FLAG_ADMIN | FLAG_PRIMARY); 116 static final UserInfo secondaryUser = new UserInfo(15, "Secondary", FLAG_ADMIN); 117 static final UserInfo restrictedProfileA = new UserInfo(40, "RestrictedA", FLAG_RESTRICTED); 118 static final UserInfo restrictedProfileB = new UserInfo(42, "RestrictedB", FLAG_RESTRICTED); 119 static final UserInfo managedProfileA = new UserInfo(45, "ManagedA", FLAG_MANAGED_PROFILE); 120 static { 121 restrictedProfileA.restrictedProfileParentId = primaryUser.id; 122 restrictedProfileB.restrictedProfileParentId = secondaryUser.id; 123 managedProfileA.profileGroupId = primaryUser.id; 124 } 125 126 /** 127 * Names and UIDs for some fake packages. Important points: 128 * - UID is ordered increasing. 129 * - One pair of packages have consecutive UIDs. 130 */ 131 static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"}; 132 static final int[] PKG_UIDS = {66, 77, 78, 400}; 133 134 // Mock packages 135 static final Map<String, Integer> mPackages = new ArrayMap<>(); 136 static { 137 for (int i = 0; i < PKGS.length; i++) { mPackages.put(PKGS[i], PKG_UIDS[i])138 mPackages.put(PKGS[i], PKG_UIDS[i]); 139 } 140 } 141 142 @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; 143 @Mock private UserManager mUserManager; 144 @Mock private PackageManager mPackageManager; 145 @Mock private INetworkManagementService mNetService; 146 @Mock private AppOpsManager mAppOps; 147 @Mock private NotificationManager mNotificationManager; 148 @Mock private Vpn.SystemServices mSystemServices; 149 @Mock private ConnectivityManager mConnectivityManager; 150 151 @Before setUp()152 public void setUp() throws Exception { 153 MockitoAnnotations.initMocks(this); 154 155 when(mContext.getPackageManager()).thenReturn(mPackageManager); 156 setMockedPackages(mPackages); 157 158 when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName()); 159 when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); 160 when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps); 161 when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE))) 162 .thenReturn(mNotificationManager); 163 when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) 164 .thenReturn(mConnectivityManager); 165 when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) 166 .thenReturn(Resources.getSystem().getString( 167 R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); 168 169 // Used by {@link Notification.Builder} 170 ApplicationInfo applicationInfo = new ApplicationInfo(); 171 applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; 172 when(mContext.getApplicationInfo()).thenReturn(applicationInfo); 173 174 doNothing().when(mNetService).registerObserver(any()); 175 } 176 177 @Test testRestrictedProfilesAreAddedToVpn()178 public void testRestrictedProfilesAreAddedToVpn() { 179 setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB); 180 181 final Vpn vpn = createVpn(primaryUser.id); 182 final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 183 null, null); 184 185 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 186 UidRange.createForUser(primaryUser.id), 187 UidRange.createForUser(restrictedProfileA.id) 188 })), ranges); 189 } 190 191 @Test testManagedProfilesAreNotAddedToVpn()192 public void testManagedProfilesAreNotAddedToVpn() { 193 setMockedUsers(primaryUser, managedProfileA); 194 195 final Vpn vpn = createVpn(primaryUser.id); 196 final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 197 null, null); 198 199 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 200 UidRange.createForUser(primaryUser.id) 201 })), ranges); 202 } 203 204 @Test testAddUserToVpnOnlyAddsOneUser()205 public void testAddUserToVpnOnlyAddsOneUser() { 206 setMockedUsers(primaryUser, restrictedProfileA, managedProfileA); 207 208 final Vpn vpn = createVpn(primaryUser.id); 209 final Set<UidRange> ranges = new ArraySet<>(); 210 vpn.addUserToRanges(ranges, primaryUser.id, null, null); 211 212 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 213 UidRange.createForUser(primaryUser.id) 214 })), ranges); 215 } 216 217 @Test testUidWhiteAndBlacklist()218 public void testUidWhiteAndBlacklist() throws Exception { 219 final Vpn vpn = createVpn(primaryUser.id); 220 final UidRange user = UidRange.createForUser(primaryUser.id); 221 final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; 222 223 // Whitelist 224 final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 225 Arrays.asList(packages), null); 226 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 227 new UidRange(user.start + PKG_UIDS[0], user.start + PKG_UIDS[0]), 228 new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]) 229 })), allow); 230 231 // Blacklist 232 final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, 233 null, Arrays.asList(packages)); 234 assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { 235 new UidRange(user.start, user.start + PKG_UIDS[0] - 1), 236 new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), 237 /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ 238 new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) 239 })), disallow); 240 } 241 242 @Test testLockdownChangingPackage()243 public void testLockdownChangingPackage() throws Exception { 244 final Vpn vpn = createVpn(primaryUser.id); 245 final UidRange user = UidRange.createForUser(primaryUser.id); 246 247 // Default state. 248 assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); 249 250 // Set always-on without lockdown. 251 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false)); 252 assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); 253 254 // Set always-on with lockdown. 255 assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true)); 256 verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { 257 new UidRange(user.start, user.start + PKG_UIDS[1] - 1), 258 new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) 259 })); 260 assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); 261 assertUnblocked(vpn, user.start + PKG_UIDS[1]); 262 263 // Switch to another app. 264 assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); 265 verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { 266 new UidRange(user.start, user.start + PKG_UIDS[1] - 1), 267 new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) 268 })); 269 verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { 270 new UidRange(user.start, user.start + PKG_UIDS[3] - 1), 271 new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) 272 })); 273 assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); 274 assertUnblocked(vpn, user.start + PKG_UIDS[3]); 275 } 276 277 @Test testLockdownAddingAProfile()278 public void testLockdownAddingAProfile() throws Exception { 279 final Vpn vpn = createVpn(primaryUser.id); 280 setMockedUsers(primaryUser); 281 282 // Make a copy of the restricted profile, as we're going to mark it deleted halfway through. 283 final UserInfo tempProfile = new UserInfo(restrictedProfileA.id, restrictedProfileA.name, 284 restrictedProfileA.flags); 285 tempProfile.restrictedProfileParentId = primaryUser.id; 286 287 final UidRange user = UidRange.createForUser(primaryUser.id); 288 final UidRange profile = UidRange.createForUser(tempProfile.id); 289 290 // Set lockdown. 291 assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true)); 292 verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { 293 new UidRange(user.start, user.start + PKG_UIDS[3] - 1), 294 new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) 295 })); 296 297 // Verify restricted user isn't affected at first. 298 assertUnblocked(vpn, profile.start + PKG_UIDS[0]); 299 300 // Add the restricted user. 301 setMockedUsers(primaryUser, tempProfile); 302 vpn.onUserAdded(tempProfile.id); 303 verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { 304 new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1), 305 new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop) 306 })); 307 308 // Remove the restricted user. 309 tempProfile.partial = true; 310 vpn.onUserRemoved(tempProfile.id); 311 verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { 312 new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1), 313 new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop) 314 })); 315 } 316 317 @Test testLockdownRuleRepeatability()318 public void testLockdownRuleRepeatability() throws Exception { 319 final Vpn vpn = createVpn(primaryUser.id); 320 321 // Given legacy lockdown is already enabled, 322 vpn.setLockdown(true); 323 verify(mNetService, times(1)).setAllowOnlyVpnForUids( 324 eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); 325 326 // Enabling legacy lockdown twice should do nothing. 327 vpn.setLockdown(true); 328 verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); 329 330 // And disabling should remove the rules exactly once. 331 vpn.setLockdown(false); 332 verify(mNetService, times(1)).setAllowOnlyVpnForUids( 333 eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); 334 335 // Removing the lockdown again should have no effect. 336 vpn.setLockdown(false); 337 verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); 338 } 339 340 @Test testLockdownRuleReversibility()341 public void testLockdownRuleReversibility() throws Exception { 342 final Vpn vpn = createVpn(primaryUser.id); 343 344 final UidRange[] entireUser = { 345 UidRange.createForUser(primaryUser.id) 346 }; 347 final UidRange[] exceptPkg0 = { 348 new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), 349 new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) 350 }; 351 352 final InOrder order = inOrder(mNetService); 353 354 // Given lockdown is enabled with no package (legacy VPN), 355 vpn.setLockdown(true); 356 order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); 357 358 // When a new VPN package is set the rules should change to cover that package. 359 vpn.prepare(null, PKGS[0]); 360 order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser)); 361 order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0)); 362 363 // When that VPN package is unset, everything should be undone again in reverse. 364 vpn.prepare(null, VpnConfig.LEGACY_VPN); 365 order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0)); 366 order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); 367 } 368 369 @Test testIsAlwaysOnPackageSupported()370 public void testIsAlwaysOnPackageSupported() throws Exception { 371 final Vpn vpn = createVpn(primaryUser.id); 372 373 ApplicationInfo appInfo = new ApplicationInfo(); 374 when(mPackageManager.getApplicationInfoAsUser(eq(PKGS[0]), anyInt(), eq(primaryUser.id))) 375 .thenReturn(appInfo); 376 377 ServiceInfo svcInfo = new ServiceInfo(); 378 ResolveInfo resInfo = new ResolveInfo(); 379 resInfo.serviceInfo = svcInfo; 380 when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), 381 eq(primaryUser.id))) 382 .thenReturn(Collections.singletonList(resInfo)); 383 384 // null package name should return false 385 assertFalse(vpn.isAlwaysOnPackageSupported(null)); 386 387 // Pre-N apps are not supported 388 appInfo.targetSdkVersion = VERSION_CODES.M; 389 assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); 390 391 // N+ apps are supported by default 392 appInfo.targetSdkVersion = VERSION_CODES.N; 393 assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0])); 394 395 // Apps that opt out explicitly are not supported 396 appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; 397 Bundle metaData = new Bundle(); 398 metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); 399 svcInfo.metaData = metaData; 400 assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); 401 } 402 403 @Test testNotificationShownForAlwaysOnApp()404 public void testNotificationShownForAlwaysOnApp() { 405 final UserHandle userHandle = UserHandle.of(primaryUser.id); 406 final Vpn vpn = createVpn(primaryUser.id); 407 setMockedUsers(primaryUser); 408 409 final InOrder order = inOrder(mNotificationManager); 410 411 // Don't show a notification for regular disconnected states. 412 vpn.updateState(DetailedState.DISCONNECTED, TAG); 413 order.verify(mNotificationManager, atLeastOnce()) 414 .cancelAsUser(anyString(), anyInt(), eq(userHandle)); 415 416 // Start showing a notification for disconnected once always-on. 417 vpn.setAlwaysOnPackage(PKGS[0], false); 418 order.verify(mNotificationManager) 419 .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); 420 421 // Stop showing the notification once connected. 422 vpn.updateState(DetailedState.CONNECTED, TAG); 423 order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle)); 424 425 // Show the notification if we disconnect again. 426 vpn.updateState(DetailedState.DISCONNECTED, TAG); 427 order.verify(mNotificationManager) 428 .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); 429 430 // Notification should be cleared after unsetting always-on package. 431 vpn.setAlwaysOnPackage(null, false); 432 order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle)); 433 } 434 435 @Test testCapabilities()436 public void testCapabilities() { 437 final Vpn vpn = createVpn(primaryUser.id); 438 setMockedUsers(primaryUser); 439 440 final Network mobile = new Network(1); 441 final Network wifi = new Network(2); 442 443 final Map<Network, NetworkCapabilities> networks = new HashMap<>(); 444 networks.put(mobile, new NetworkCapabilities() 445 .addTransportType(TRANSPORT_CELLULAR) 446 .addCapability(NET_CAPABILITY_INTERNET) 447 .addCapability(NET_CAPABILITY_NOT_METERED) 448 .addCapability(NET_CAPABILITY_NOT_CONGESTED) 449 .setLinkDownstreamBandwidthKbps(10)); 450 networks.put(wifi, new NetworkCapabilities() 451 .addTransportType(TRANSPORT_WIFI) 452 .addCapability(NET_CAPABILITY_INTERNET) 453 .addCapability(NET_CAPABILITY_NOT_ROAMING) 454 .addCapability(NET_CAPABILITY_NOT_CONGESTED) 455 .setLinkUpstreamBandwidthKbps(20)); 456 setMockedNetworks(networks); 457 458 final NetworkCapabilities caps = new NetworkCapabilities(); 459 460 Vpn.updateCapabilities(mConnectivityManager, new Network[] { }, caps); 461 assertTrue(caps.hasTransport(TRANSPORT_VPN)); 462 assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); 463 assertFalse(caps.hasTransport(TRANSPORT_WIFI)); 464 assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps()); 465 assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps()); 466 assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 467 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); 468 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); 469 470 Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile }, caps); 471 assertTrue(caps.hasTransport(TRANSPORT_VPN)); 472 assertTrue(caps.hasTransport(TRANSPORT_CELLULAR)); 473 assertFalse(caps.hasTransport(TRANSPORT_WIFI)); 474 assertEquals(10, caps.getLinkDownstreamBandwidthKbps()); 475 assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps()); 476 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 477 assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); 478 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); 479 480 Vpn.updateCapabilities(mConnectivityManager, new Network[] { wifi }, caps); 481 assertTrue(caps.hasTransport(TRANSPORT_VPN)); 482 assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); 483 assertTrue(caps.hasTransport(TRANSPORT_WIFI)); 484 assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps()); 485 assertEquals(20, caps.getLinkUpstreamBandwidthKbps()); 486 assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 487 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); 488 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); 489 490 Vpn.updateCapabilities(mConnectivityManager, new Network[] { mobile, wifi }, caps); 491 assertTrue(caps.hasTransport(TRANSPORT_VPN)); 492 assertTrue(caps.hasTransport(TRANSPORT_CELLULAR)); 493 assertTrue(caps.hasTransport(TRANSPORT_WIFI)); 494 assertEquals(10, caps.getLinkDownstreamBandwidthKbps()); 495 assertEquals(20, caps.getLinkUpstreamBandwidthKbps()); 496 assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); 497 assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); 498 assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); 499 } 500 501 /** 502 * Mock some methods of vpn object. 503 */ createVpn(@serIdInt int userId)504 private Vpn createVpn(@UserIdInt int userId) { 505 return new Vpn(Looper.myLooper(), mContext, mNetService, userId, mSystemServices); 506 } 507 assertBlocked(Vpn vpn, int... uids)508 private static void assertBlocked(Vpn vpn, int... uids) { 509 for (int uid : uids) { 510 assertTrue("Uid " + uid + " should be blocked", vpn.isBlockingUid(uid)); 511 } 512 } 513 assertUnblocked(Vpn vpn, int... uids)514 private static void assertUnblocked(Vpn vpn, int... uids) { 515 for (int uid : uids) { 516 assertFalse("Uid " + uid + " should not be blocked", vpn.isBlockingUid(uid)); 517 } 518 } 519 520 /** 521 * Populate {@link #mUserManager} with a list of fake users. 522 */ setMockedUsers(UserInfo... users)523 private void setMockedUsers(UserInfo... users) { 524 final Map<Integer, UserInfo> userMap = new ArrayMap<>(); 525 for (UserInfo user : users) { 526 userMap.put(user.id, user); 527 } 528 529 /** 530 * @see UserManagerService#getUsers(boolean) 531 */ 532 doAnswer(invocation -> { 533 final boolean excludeDying = (boolean) invocation.getArguments()[0]; 534 final ArrayList<UserInfo> result = new ArrayList<>(users.length); 535 for (UserInfo ui : users) { 536 if (!excludeDying || (ui.isEnabled() && !ui.partial)) { 537 result.add(ui); 538 } 539 } 540 return result; 541 }).when(mUserManager).getUsers(anyBoolean()); 542 543 doAnswer(invocation -> { 544 final int id = (int) invocation.getArguments()[0]; 545 return userMap.get(id); 546 }).when(mUserManager).getUserInfo(anyInt()); 547 548 doAnswer(invocation -> { 549 final int id = (int) invocation.getArguments()[0]; 550 return (userMap.get(id).flags & UserInfo.FLAG_ADMIN) != 0; 551 }).when(mUserManager).canHaveRestrictedProfile(anyInt()); 552 } 553 554 /** 555 * Populate {@link #mPackageManager} with a fake packageName-to-UID mapping. 556 */ setMockedPackages(final Map<String, Integer> packages)557 private void setMockedPackages(final Map<String, Integer> packages) { 558 try { 559 doAnswer(invocation -> { 560 final String appName = (String) invocation.getArguments()[0]; 561 final int userId = (int) invocation.getArguments()[1]; 562 return UserHandle.getUid(userId, packages.get(appName)); 563 }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt()); 564 } catch (Exception e) { 565 } 566 } 567 setMockedNetworks(final Map<Network, NetworkCapabilities> networks)568 private void setMockedNetworks(final Map<Network, NetworkCapabilities> networks) { 569 doAnswer(invocation -> { 570 final Network network = (Network) invocation.getArguments()[0]; 571 return networks.get(network); 572 }).when(mConnectivityManager).getNetworkCapabilities(any()); 573 } 574 575 // Need multiple copies of this, but Java's Stream objects can't be reused or 576 // duplicated. publicIpV4Routes()577 private Stream<String> publicIpV4Routes() { 578 return Stream.of( 579 "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4", 580 "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6", 581 "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", 582 "173.0.0.0/8", "174.0.0.0/7", "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11", 583 "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14", 584 "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7", 585 "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"); 586 } 587 publicIpV6Routes()588 private Stream<String> publicIpV6Routes() { 589 return Stream.of( 590 "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6", 591 "fe00::/8", "2605:ef80:e:af1d::/64"); 592 } 593 594 @Test testProvidesRoutesToMostDestinations()595 public void testProvidesRoutesToMostDestinations() { 596 final LinkProperties lp = new LinkProperties(); 597 598 // Default route provides routes to all IPv4 destinations. 599 lp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"))); 600 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 601 602 // Empty LP provides routes to no destination 603 lp.clear(); 604 assertFalse(Vpn.providesRoutesToMostDestinations(lp)); 605 606 // All IPv4 routes except for local networks. This is the case most relevant 607 // to this function. It provides routes to almost the entire space. 608 // (clone the stream so that we can reuse it later) 609 publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); 610 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 611 612 // Removing a 16-bit prefix, which is 65536 addresses. This is still enough to 613 // provide routes to "most" destinations. 614 lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16"))); 615 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 616 617 // Remove the /2 route, which represent a quarter of the available routing space. 618 // This LP does not provides routes to "most" destinations any more. 619 lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2"))); 620 assertFalse(Vpn.providesRoutesToMostDestinations(lp)); 621 622 lp.clear(); 623 publicIpV6Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); 624 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 625 626 lp.removeRoute(new RouteInfo(new IpPrefix("::/1"))); 627 assertFalse(Vpn.providesRoutesToMostDestinations(lp)); 628 629 // V6 does not provide sufficient coverage but v4 does 630 publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s)))); 631 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 632 633 // V4 still does 634 lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16"))); 635 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 636 637 // V4 does not any more 638 lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2"))); 639 assertFalse(Vpn.providesRoutesToMostDestinations(lp)); 640 641 // V4 does not, but V6 has sufficient coverage again 642 lp.addRoute(new RouteInfo(new IpPrefix("::/1"))); 643 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 644 } 645 646 @Test testDoesNotLockUpWithTooManyRoutes()647 public void testDoesNotLockUpWithTooManyRoutes() { 648 final LinkProperties lp = new LinkProperties(); 649 final byte[] ad = new byte[4]; 650 // Actually evaluating this many routes under 1500ms is impossible on 651 // current hardware and for some time, as the algorithm is O(n²). 652 // Make sure the system has a safeguard against this and does not 653 // lock up. 654 final int MAX_ROUTES = 4000; 655 final long MAX_ALLOWED_TIME_MS = 1500; 656 for (int i = 0; i < MAX_ROUTES; ++i) { 657 ad[0] = (byte)((i >> 24) & 0xFF); 658 ad[1] = (byte)((i >> 16) & 0xFF); 659 ad[2] = (byte)((i >> 8) & 0xFF); 660 ad[3] = (byte)(i & 0xFF); 661 try { 662 lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.getByAddress(ad), 32))); 663 } catch (UnknownHostException e) { 664 // UnknownHostException is only thrown for an address of illegal length, 665 // which can't happen in the case above. 666 } 667 } 668 final long start = SystemClock.currentThreadTimeMillis(); 669 assertTrue(Vpn.providesRoutesToMostDestinations(lp)); 670 final long end = SystemClock.currentThreadTimeMillis(); 671 assertTrue(end - start < MAX_ALLOWED_TIME_MS); 672 } 673 } 674