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