Home | History | Annotate | Download | only in connectivity
      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++) {
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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      */
    637     private Vpn createVpn(@UserIdInt int userId) {
    638         return new Vpn(Looper.myLooper(), mContext, mNetService, userId, mSystemServices);
    639     }
    640 
    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 
    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      */
    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      */
    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 
    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.
    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 
    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