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