• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Manifest.permission.BIND_VPN_SERVICE;
20 import static android.Manifest.permission.CONTROL_VPN;
21 import static android.content.pm.PackageManager.PERMISSION_DENIED;
22 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
23 import static android.content.pm.UserInfo.FLAG_ADMIN;
24 import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
25 import static android.content.pm.UserInfo.FLAG_PRIMARY;
26 import static android.content.pm.UserInfo.FLAG_RESTRICTED;
27 import static android.net.ConnectivityManager.NetworkCallback;
28 import static android.net.INetd.IF_STATE_DOWN;
29 import static android.net.INetd.IF_STATE_UP;
30 import static android.net.VpnManager.TYPE_VPN_PLATFORM;
31 import static android.os.Build.VERSION_CODES.S_V2;
32 import static android.os.UserHandle.PER_USER_RANGE;
33 
34 import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
35 import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
36 import static com.android.testutils.MiscAsserts.assertThrows;
37 
38 import static org.junit.Assert.assertArrayEquals;
39 import static org.junit.Assert.assertEquals;
40 import static org.junit.Assert.assertFalse;
41 import static org.junit.Assert.assertNotNull;
42 import static org.junit.Assert.assertTrue;
43 import static org.junit.Assert.fail;
44 import static org.junit.Assume.assumeTrue;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.ArgumentMatchers.anyBoolean;
47 import static org.mockito.ArgumentMatchers.anyInt;
48 import static org.mockito.ArgumentMatchers.anyLong;
49 import static org.mockito.ArgumentMatchers.anyString;
50 import static org.mockito.ArgumentMatchers.argThat;
51 import static org.mockito.ArgumentMatchers.eq;
52 import static org.mockito.Mockito.after;
53 import static org.mockito.Mockito.atLeastOnce;
54 import static org.mockito.Mockito.doAnswer;
55 import static org.mockito.Mockito.doCallRealMethod;
56 import static org.mockito.Mockito.doNothing;
57 import static org.mockito.Mockito.doReturn;
58 import static org.mockito.Mockito.inOrder;
59 import static org.mockito.Mockito.mock;
60 import static org.mockito.Mockito.never;
61 import static org.mockito.Mockito.reset;
62 import static org.mockito.Mockito.timeout;
63 import static org.mockito.Mockito.times;
64 import static org.mockito.Mockito.verify;
65 import static org.mockito.Mockito.when;
66 
67 import android.annotation.NonNull;
68 import android.annotation.UserIdInt;
69 import android.app.AppOpsManager;
70 import android.app.NotificationManager;
71 import android.app.PendingIntent;
72 import android.content.Context;
73 import android.content.Intent;
74 import android.content.pm.ApplicationInfo;
75 import android.content.pm.PackageManager;
76 import android.content.pm.ResolveInfo;
77 import android.content.pm.ServiceInfo;
78 import android.content.pm.UserInfo;
79 import android.content.res.Resources;
80 import android.net.ConnectivityManager;
81 import android.net.INetd;
82 import android.net.Ikev2VpnProfile;
83 import android.net.InetAddresses;
84 import android.net.InterfaceConfigurationParcel;
85 import android.net.IpPrefix;
86 import android.net.IpSecManager;
87 import android.net.IpSecTunnelInterfaceResponse;
88 import android.net.LinkAddress;
89 import android.net.LinkProperties;
90 import android.net.LocalSocket;
91 import android.net.Network;
92 import android.net.NetworkAgent;
93 import android.net.NetworkAgentConfig;
94 import android.net.NetworkCapabilities;
95 import android.net.NetworkInfo.DetailedState;
96 import android.net.NetworkProvider;
97 import android.net.RouteInfo;
98 import android.net.UidRangeParcel;
99 import android.net.VpnManager;
100 import android.net.VpnProfileState;
101 import android.net.VpnService;
102 import android.net.VpnTransportInfo;
103 import android.net.ipsec.ike.IkeSessionCallback;
104 import android.net.ipsec.ike.exceptions.IkeException;
105 import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
106 import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
107 import android.net.ipsec.ike.exceptions.IkeProtocolException;
108 import android.net.ipsec.ike.exceptions.IkeTimeoutException;
109 import android.os.Build.VERSION_CODES;
110 import android.os.Bundle;
111 import android.os.ConditionVariable;
112 import android.os.INetworkManagementService;
113 import android.os.Looper;
114 import android.os.ParcelFileDescriptor;
115 import android.os.PowerWhitelistManager;
116 import android.os.Process;
117 import android.os.UserHandle;
118 import android.os.UserManager;
119 import android.os.test.TestLooper;
120 import android.provider.Settings;
121 import android.security.Credentials;
122 import android.util.ArrayMap;
123 import android.util.ArraySet;
124 import android.util.Range;
125 
126 import androidx.test.filters.SmallTest;
127 
128 import com.android.internal.R;
129 import com.android.internal.net.LegacyVpnInfo;
130 import com.android.internal.net.VpnConfig;
131 import com.android.internal.net.VpnProfile;
132 import com.android.internal.util.HexDump;
133 import com.android.modules.utils.build.SdkLevel;
134 import com.android.server.DeviceIdleInternal;
135 import com.android.server.IpSecService;
136 import com.android.server.vcn.util.PersistableBundleUtils;
137 import com.android.testutils.DevSdkIgnoreRule;
138 import com.android.testutils.DevSdkIgnoreRunner;
139 
140 import org.junit.After;
141 import org.junit.Before;
142 import org.junit.Rule;
143 import org.junit.Test;
144 import org.junit.runner.RunWith;
145 import org.mockito.AdditionalAnswers;
146 import org.mockito.Answers;
147 import org.mockito.ArgumentCaptor;
148 import org.mockito.InOrder;
149 import org.mockito.Mock;
150 import org.mockito.MockitoAnnotations;
151 
152 import java.io.BufferedWriter;
153 import java.io.File;
154 import java.io.FileDescriptor;
155 import java.io.FileWriter;
156 import java.io.IOException;
157 import java.net.Inet4Address;
158 import java.net.InetAddress;
159 import java.net.UnknownHostException;
160 import java.util.ArrayList;
161 import java.util.Arrays;
162 import java.util.Collections;
163 import java.util.HashMap;
164 import java.util.List;
165 import java.util.Map;
166 import java.util.Set;
167 import java.util.concurrent.CompletableFuture;
168 import java.util.concurrent.TimeUnit;
169 import java.util.stream.Stream;
170 
171 /**
172  * Tests for {@link Vpn}.
173  *
174  * Build, install and run with:
175  *  runtest frameworks-net -c com.android.server.connectivity.VpnTest
176  */
177 @RunWith(DevSdkIgnoreRunner.class)
178 @SmallTest
179 @IgnoreUpTo(VERSION_CODES.S_V2)
180 public class VpnTest {
181     private static final String TAG = "VpnTest";
182 
183     @Rule
184     public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
185 
186     // Mock users
187     static final UserInfo primaryUser = new UserInfo(27, "Primary", FLAG_ADMIN | FLAG_PRIMARY);
188     static final UserInfo secondaryUser = new UserInfo(15, "Secondary", FLAG_ADMIN);
189     static final UserInfo restrictedProfileA = new UserInfo(40, "RestrictedA", FLAG_RESTRICTED);
190     static final UserInfo restrictedProfileB = new UserInfo(42, "RestrictedB", FLAG_RESTRICTED);
191     static final UserInfo managedProfileA = new UserInfo(45, "ManagedA", FLAG_MANAGED_PROFILE);
192     static {
193         restrictedProfileA.restrictedProfileParentId = primaryUser.id;
194         restrictedProfileB.restrictedProfileParentId = secondaryUser.id;
195         managedProfileA.profileGroupId = primaryUser.id;
196     }
197 
198     static final Network EGRESS_NETWORK = new Network(101);
199     static final String EGRESS_IFACE = "wlan0";
200     static final String TEST_VPN_PKG = "com.testvpn.vpn";
201     private static final String TEST_VPN_SERVER = "1.2.3.4";
202     private static final String TEST_VPN_IDENTITY = "identity";
203     private static final byte[] TEST_VPN_PSK = "psk".getBytes();
204 
205     private static final Network TEST_NETWORK = new Network(Integer.MAX_VALUE);
206     private static final String TEST_IFACE_NAME = "TEST_IFACE";
207     private static final int TEST_TUNNEL_RESOURCE_ID = 0x2345;
208     private static final long TEST_TIMEOUT_MS = 500L;
209     private static final String PRIMARY_USER_APP_EXCLUDE_KEY =
210             "VPNAPPEXCLUDED_27_com.testvpn.vpn";
211     /**
212      * Names and UIDs for some fake packages. Important points:
213      *  - UID is ordered increasing.
214      *  - One pair of packages have consecutive UIDs.
215      */
216     static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"};
217     static final String PKGS_BYTES = getPackageByteString(List.of(PKGS));
218     static final int[] PKG_UIDS = {10066, 10077, 10078, 10400};
219 
220     // Mock packages
221     static final Map<String, Integer> mPackages = new ArrayMap<>();
222     static {
223         for (int i = 0; i < PKGS.length; i++) {
mPackages.put(PKGS[i], PKG_UIDS[i])224             mPackages.put(PKGS[i], PKG_UIDS[i]);
225         }
226     }
227     private static final Range<Integer> PRI_USER_RANGE = uidRangeForUser(primaryUser.id);
228 
229     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
230     @Mock private UserManager mUserManager;
231     @Mock private PackageManager mPackageManager;
232     @Mock private INetworkManagementService mNetService;
233     @Mock private INetd mNetd;
234     @Mock private AppOpsManager mAppOps;
235     @Mock private NotificationManager mNotificationManager;
236     @Mock private Vpn.SystemServices mSystemServices;
237     @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator;
238     @Mock private ConnectivityManager mConnectivityManager;
239     @Mock private IpSecService mIpSecService;
240     @Mock private VpnProfileStore mVpnProfileStore;
241     @Mock DeviceIdleInternal mDeviceIdleInternal;
242     private final VpnProfile mVpnProfile;
243 
244     private IpSecManager mIpSecManager;
245 
VpnTest()246     public VpnTest() throws Exception {
247         // Build an actual VPN profile that is capable of being converted to and from an
248         // Ikev2VpnProfile
249         final Ikev2VpnProfile.Builder builder =
250                 new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY);
251         builder.setAuthPsk(TEST_VPN_PSK);
252         mVpnProfile = builder.build().toVpnProfile();
253     }
254 
255     @Before
setUp()256     public void setUp() throws Exception {
257         MockitoAnnotations.initMocks(this);
258 
259         mIpSecManager = new IpSecManager(mContext, mIpSecService);
260 
261         when(mContext.getPackageManager()).thenReturn(mPackageManager);
262         setMockedPackages(mPackages);
263 
264         when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG);
265         when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
266         mockService(UserManager.class, Context.USER_SERVICE, mUserManager);
267         mockService(AppOpsManager.class, Context.APP_OPS_SERVICE, mAppOps);
268         mockService(NotificationManager.class, Context.NOTIFICATION_SERVICE, mNotificationManager);
269         mockService(ConnectivityManager.class, Context.CONNECTIVITY_SERVICE, mConnectivityManager);
270         mockService(IpSecManager.class, Context.IPSEC_SERVICE, mIpSecManager);
271         when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
272                 .thenReturn(Resources.getSystem().getString(
273                         R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
274         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
275                 .thenReturn(true);
276 
277         // Used by {@link Notification.Builder}
278         ApplicationInfo applicationInfo = new ApplicationInfo();
279         applicationInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT;
280         when(mContext.getApplicationInfo()).thenReturn(applicationInfo);
281         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
282                 .thenReturn(applicationInfo);
283 
284         doNothing().when(mNetService).registerObserver(any());
285 
286         // Deny all appops by default.
287         when(mAppOps.noteOpNoThrow(anyString(), anyInt(), anyString(), any(), any()))
288                 .thenReturn(AppOpsManager.MODE_IGNORED);
289 
290         // Setup IpSecService
291         final IpSecTunnelInterfaceResponse tunnelResp =
292                 new IpSecTunnelInterfaceResponse(
293                         IpSecManager.Status.OK, TEST_TUNNEL_RESOURCE_ID, TEST_IFACE_NAME);
294         when(mIpSecService.createTunnelInterface(any(), any(), any(), any(), any()))
295                 .thenReturn(tunnelResp);
296         // The unit test should know what kind of permission it needs and set the permission by
297         // itself, so set the default value of Context#checkCallingOrSelfPermission to
298         // PERMISSION_DENIED.
299         doReturn(PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission(any());
300     }
301 
302     @After
tearDown()303     public void tearDown() throws Exception {
304         doReturn(PERMISSION_DENIED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN);
305     }
306 
mockService(Class<T> clazz, String name, T service)307     private <T> void mockService(Class<T> clazz, String name, T service) {
308         doReturn(service).when(mContext).getSystemService(name);
309         doReturn(name).when(mContext).getSystemServiceName(clazz);
310         if (mContext.getSystemService(clazz).getClass().equals(Object.class)) {
311             // Test is using mockito-extended (mContext uses Answers.RETURNS_DEEP_STUBS and returned
312             // a mock object on a final method)
313             doCallRealMethod().when(mContext).getSystemService(clazz);
314         }
315     }
316 
rangeSet(Range<Integer> .... ranges)317     private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) {
318         final Set<Range<Integer>> range = new ArraySet<>();
319         for (Range<Integer> r : ranges) range.add(r);
320 
321         return range;
322     }
323 
uidRangeForUser(int userId)324     private static Range<Integer> uidRangeForUser(int userId) {
325         return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
326     }
327 
uidRange(int start, int stop)328     private Range<Integer> uidRange(int start, int stop) {
329         return new Range<Integer>(start, stop);
330     }
331 
getPackageByteString(List<String> packages)332     private static String getPackageByteString(List<String> packages) {
333         try {
334             return HexDump.toHexString(
335                     PersistableBundleUtils.toDiskStableBytes(PersistableBundleUtils.fromList(
336                             packages, PersistableBundleUtils.STRING_SERIALIZER)),
337                         true /* upperCase */);
338         } catch (IOException e) {
339             return null;
340         }
341     }
342 
343     @Test
testRestrictedProfilesAreAddedToVpn()344     public void testRestrictedProfilesAreAddedToVpn() {
345         setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
346 
347         final Vpn vpn = createVpn(primaryUser.id);
348 
349         // Assume the user can have restricted profiles.
350         doReturn(true).when(mUserManager).canHaveRestrictedProfile();
351         final Set<Range<Integer>> ranges =
352                 vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null);
353 
354         assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges);
355     }
356 
357     @Test
testManagedProfilesAreNotAddedToVpn()358     public void testManagedProfilesAreNotAddedToVpn() {
359         setMockedUsers(primaryUser, managedProfileA);
360 
361         final Vpn vpn = createVpn(primaryUser.id);
362         final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
363                 null, null);
364 
365         assertEquals(rangeSet(PRI_USER_RANGE), ranges);
366     }
367 
368     @Test
testAddUserToVpnOnlyAddsOneUser()369     public void testAddUserToVpnOnlyAddsOneUser() {
370         setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
371 
372         final Vpn vpn = createVpn(primaryUser.id);
373         final Set<Range<Integer>> ranges = new ArraySet<>();
374         vpn.addUserToRanges(ranges, primaryUser.id, null, null);
375 
376         assertEquals(rangeSet(PRI_USER_RANGE), ranges);
377     }
378 
379     @Test
testUidAllowAndDenylist()380     public void testUidAllowAndDenylist() throws Exception {
381         final Vpn vpn = createVpn(primaryUser.id);
382         final Range<Integer> user = PRI_USER_RANGE;
383         final int userStart = user.getLower();
384         final int userStop = user.getUpper();
385         final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
386 
387         // Allowed list
388         final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
389                 Arrays.asList(packages), null /* disallowedApplications */);
390         assertEquals(rangeSet(
391                 uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]),
392                 uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2]),
393                 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0]),
394                          Process.toSdkSandboxUid(userStart + PKG_UIDS[0])),
395                 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[1]),
396                          Process.toSdkSandboxUid(userStart + PKG_UIDS[2]))),
397                 allow);
398 
399         // Denied list
400         final Set<Range<Integer>> disallow =
401                 vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
402                         null /* allowedApplications */, Arrays.asList(packages));
403         assertEquals(rangeSet(
404                 uidRange(userStart, userStart + PKG_UIDS[0] - 1),
405                 uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
406                 /* Empty range between UIDS[1] and UIDS[2], should be excluded, */
407                 uidRange(userStart + PKG_UIDS[2] + 1,
408                          Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
409                 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
410                          Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
411                 uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)),
412                 disallow);
413     }
414 
verifyPowerSaveTempWhitelistApp(String packageName)415     private void verifyPowerSaveTempWhitelistApp(String packageName) {
416         verify(mDeviceIdleInternal).addPowerSaveTempWhitelistApp(anyInt(), eq(packageName),
417                 anyLong(), anyInt(), eq(false), eq(PowerWhitelistManager.REASON_VPN),
418                 eq("VpnManager event"));
419     }
420 
421     @Test
testGetAlwaysAndOnGetLockDown()422     public void testGetAlwaysAndOnGetLockDown() throws Exception {
423         final Vpn vpn = createVpn(primaryUser.id);
424 
425         // Default state.
426         assertFalse(vpn.getAlwaysOn());
427         assertFalse(vpn.getLockdown());
428 
429         // Set always-on without lockdown.
430         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList()));
431         assertTrue(vpn.getAlwaysOn());
432         assertFalse(vpn.getLockdown());
433 
434         // Set always-on with lockdown.
435         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList()));
436         assertTrue(vpn.getAlwaysOn());
437         assertTrue(vpn.getLockdown());
438 
439         // Remove always-on configuration.
440         assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList()));
441         assertFalse(vpn.getAlwaysOn());
442         assertFalse(vpn.getLockdown());
443     }
444 
445     @Test
testLockdownChangingPackage()446     public void testLockdownChangingPackage() throws Exception {
447         final Vpn vpn = createVpn(primaryUser.id);
448         final Range<Integer> user = PRI_USER_RANGE;
449         final int userStart = user.getLower();
450         final int userStop = user.getUpper();
451         // Set always-on without lockdown.
452         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null));
453 
454         // Set always-on with lockdown.
455         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
456         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
457                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
458                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
459                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
460                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
461         }));
462 
463         // Switch to another app.
464         assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
465         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
466                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
467                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
468                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
469                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
470         }));
471         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
472                 new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1),
473                 new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
474                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)),
475                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop)
476         }));
477     }
478 
479     @Test
testLockdownAllowlist()480     public void testLockdownAllowlist() throws Exception {
481         final Vpn vpn = createVpn(primaryUser.id);
482         final Range<Integer> user = PRI_USER_RANGE;
483         final int userStart = user.getLower();
484         final int userStop = user.getUpper();
485         // Set always-on with lockdown and allow app PKGS[2] from lockdown.
486         assertTrue(vpn.setAlwaysOnPackage(
487                 PKGS[1], true, Collections.singletonList(PKGS[2])));
488         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[]  {
489                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
490                 new UidRangeParcel(userStart + PKG_UIDS[2] + 1,
491                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1]) - 1),
492                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)
493         }));
494         // Change allowed app list to PKGS[3].
495         assertTrue(vpn.setAlwaysOnPackage(
496                 PKGS[1], true, Collections.singletonList(PKGS[3])));
497         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
498                 new UidRangeParcel(userStart + PKG_UIDS[2] + 1,
499                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
500                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)
501         }));
502         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
503                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1),
504                 new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
505                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
506                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1),
507                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)),
508                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop)
509         }));
510 
511         // Change the VPN app.
512         assertTrue(vpn.setAlwaysOnPackage(
513                 PKGS[0], true, Collections.singletonList(PKGS[3])));
514         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
515                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
516                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1),
517                 new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
518                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
519                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1),
520                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1))
521         }));
522         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
523                 new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1),
524                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1),
525                 new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
526                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
527                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
528                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1))
529         }));
530 
531         // Remove the list of allowed packages.
532         assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
533         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
534                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1),
535                 new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
536                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
537                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
538                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)),
539                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop)
540         }));
541         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
542                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1,
543                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
544                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop),
545         }));
546 
547         // Add the list of allowed packages.
548         assertTrue(vpn.setAlwaysOnPackage(
549                 PKGS[0], true, Collections.singletonList(PKGS[1])));
550         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
551                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1,
552                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
553                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop),
554         }));
555         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
556                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
557                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
558                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
559                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
560                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
561                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
562         }));
563 
564         // Try allowing a package with a comma, should be rejected.
565         assertFalse(vpn.setAlwaysOnPackage(
566                 PKGS[0], true, Collections.singletonList("a.b,c.d")));
567 
568         // Pass a non-existent packages in the allowlist, they (and only they) should be ignored.
569         // allowed package should change from PGKS[1] to PKGS[2].
570         assertTrue(vpn.setAlwaysOnPackage(
571                 PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app")));
572         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
573                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
574                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
575                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
576                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
577                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
578                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
579         }));
580         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
581                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1),
582                 new UidRangeParcel(userStart + PKG_UIDS[2] + 1,
583                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
584                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
585                                    Process.toSdkSandboxUid(userStart + PKG_UIDS[2] - 1)),
586                 new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)
587         }));
588     }
589 
590     @Test
testLockdownRuleRepeatability()591     public void testLockdownRuleRepeatability() throws Exception {
592         final Vpn vpn = createVpn(primaryUser.id);
593         final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
594                 new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())};
595         // Given legacy lockdown is already enabled,
596         vpn.setLockdown(true);
597         verify(mConnectivityManager, times(1)).setRequireVpnForUids(true,
598                 toRanges(primaryUserRangeParcel));
599 
600         // Enabling legacy lockdown twice should do nothing.
601         vpn.setLockdown(true);
602         verify(mConnectivityManager, times(1)).setRequireVpnForUids(anyBoolean(), any());
603 
604         // And disabling should remove the rules exactly once.
605         vpn.setLockdown(false);
606         verify(mConnectivityManager, times(1)).setRequireVpnForUids(false,
607                 toRanges(primaryUserRangeParcel));
608 
609         // Removing the lockdown again should have no effect.
610         vpn.setLockdown(false);
611         verify(mConnectivityManager, times(2)).setRequireVpnForUids(anyBoolean(), any());
612     }
613 
toRanges(UidRangeParcel[] ranges)614     private ArrayList<Range<Integer>> toRanges(UidRangeParcel[] ranges) {
615         ArrayList<Range<Integer>> rangesArray = new ArrayList<>(ranges.length);
616         for (int i = 0; i < ranges.length; i++) {
617             rangesArray.add(new Range<>(ranges[i].start, ranges[i].stop));
618         }
619         return rangesArray;
620     }
621 
622     @Test
testLockdownRuleReversibility()623     public void testLockdownRuleReversibility() throws Exception {
624         doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN);
625         final Vpn vpn = createVpn(primaryUser.id);
626         final UidRangeParcel[] entireUser = {
627             new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())
628         };
629         final UidRangeParcel[] exceptPkg0 = {
630             new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
631             new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1,
632                                Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] - 1)),
633             new UidRangeParcel(Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] + 1),
634                                entireUser[0].stop),
635         };
636 
637         final InOrder order = inOrder(mConnectivityManager);
638 
639         // Given lockdown is enabled with no package (legacy VPN),
640         vpn.setLockdown(true);
641         order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser));
642 
643         // When a new VPN package is set the rules should change to cover that package.
644         vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE);
645         order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(entireUser));
646         order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(exceptPkg0));
647 
648         // When that VPN package is unset, everything should be undone again in reverse.
649         vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE);
650         order.verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(exceptPkg0));
651         order.verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(entireUser));
652     }
653 
654     @Test
testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller()655     public void testPrepare_throwSecurityExceptionWhenGivenPackageDoesNotBelongToTheCaller()
656             throws Exception {
657         assumeTrue(isAtLeastT());
658         final Vpn vpn = createVpnAndSetupUidChecks();
659         assertThrows(SecurityException.class,
660                 () -> vpn.prepare("com.not.vpn.owner", null, VpnManager.TYPE_VPN_SERVICE));
661         assertThrows(SecurityException.class,
662                 () -> vpn.prepare(null, "com.not.vpn.owner", VpnManager.TYPE_VPN_SERVICE));
663         assertThrows(SecurityException.class,
664                 () -> vpn.prepare("com.not.vpn.owner1", "com.not.vpn.owner2",
665                         VpnManager.TYPE_VPN_SERVICE));
666     }
667 
668     @Test
testPrepare_bothOldPackageAndNewPackageAreNull()669     public void testPrepare_bothOldPackageAndNewPackageAreNull() throws Exception {
670         final Vpn vpn = createVpnAndSetupUidChecks();
671         assertTrue(vpn.prepare(null, null, VpnManager.TYPE_VPN_SERVICE));
672 
673     }
674 
675     @Test
testIsAlwaysOnPackageSupported()676     public void testIsAlwaysOnPackageSupported() throws Exception {
677         final Vpn vpn = createVpn(primaryUser.id);
678 
679         ApplicationInfo appInfo = new ApplicationInfo();
680         when(mPackageManager.getApplicationInfoAsUser(eq(PKGS[0]), anyInt(), eq(primaryUser.id)))
681                 .thenReturn(appInfo);
682 
683         ServiceInfo svcInfo = new ServiceInfo();
684         ResolveInfo resInfo = new ResolveInfo();
685         resInfo.serviceInfo = svcInfo;
686         when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA),
687                 eq(primaryUser.id)))
688                 .thenReturn(Collections.singletonList(resInfo));
689 
690         // null package name should return false
691         assertFalse(vpn.isAlwaysOnPackageSupported(null));
692 
693         // Pre-N apps are not supported
694         appInfo.targetSdkVersion = VERSION_CODES.M;
695         assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
696 
697         // N+ apps are supported by default
698         appInfo.targetSdkVersion = VERSION_CODES.N;
699         assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0]));
700 
701         // Apps that opt out explicitly are not supported
702         appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT;
703         Bundle metaData = new Bundle();
704         metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false);
705         svcInfo.metaData = metaData;
706         assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
707     }
708 
709     @Test
testNotificationShownForAlwaysOnApp()710     public void testNotificationShownForAlwaysOnApp() throws Exception {
711         final UserHandle userHandle = UserHandle.of(primaryUser.id);
712         final Vpn vpn = createVpn(primaryUser.id);
713         setMockedUsers(primaryUser);
714 
715         final InOrder order = inOrder(mNotificationManager);
716 
717         // Don't show a notification for regular disconnected states.
718         vpn.updateState(DetailedState.DISCONNECTED, TAG);
719         order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt());
720 
721         // Start showing a notification for disconnected once always-on.
722         vpn.setAlwaysOnPackage(PKGS[0], false, null);
723         order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
724 
725         // Stop showing the notification once connected.
726         vpn.updateState(DetailedState.CONNECTED, TAG);
727         order.verify(mNotificationManager).cancel(anyString(), anyInt());
728 
729         // Show the notification if we disconnect again.
730         vpn.updateState(DetailedState.DISCONNECTED, TAG);
731         order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
732 
733         // Notification should be cleared after unsetting always-on package.
734         vpn.setAlwaysOnPackage(null, false, null);
735         order.verify(mNotificationManager).cancel(anyString(), anyInt());
736     }
737 
738     /**
739      * The profile name should NOT change between releases for backwards compatibility
740      *
741      * <p>If this is changed between releases, the {@link Vpn#getVpnProfilePrivileged()} method MUST
742      * be updated to ensure backward compatibility.
743      */
744     @Test
testGetProfileNameForPackage()745     public void testGetProfileNameForPackage() throws Exception {
746         final Vpn vpn = createVpn(primaryUser.id);
747         setMockedUsers(primaryUser);
748 
749         final String expected = Credentials.PLATFORM_VPN + primaryUser.id + "_" + TEST_VPN_PKG;
750         assertEquals(expected, vpn.getProfileNameForPackage(TEST_VPN_PKG));
751     }
752 
createVpnAndSetupUidChecks(String... grantedOps)753     private Vpn createVpnAndSetupUidChecks(String... grantedOps) throws Exception {
754         return createVpnAndSetupUidChecks(primaryUser, grantedOps);
755     }
756 
createVpnAndSetupUidChecks(UserInfo user, String... grantedOps)757     private Vpn createVpnAndSetupUidChecks(UserInfo user, String... grantedOps) throws Exception {
758         final Vpn vpn = createVpn(user.id);
759         setMockedUsers(user);
760 
761         when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt()))
762                 .thenReturn(Process.myUid());
763 
764         for (final String opStr : grantedOps) {
765             when(mAppOps.noteOpNoThrow(opStr, Process.myUid(), TEST_VPN_PKG,
766                     null /* attributionTag */, null /* message */))
767                     .thenReturn(AppOpsManager.MODE_ALLOWED);
768         }
769 
770         return vpn;
771     }
772 
checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps)773     private void checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps) {
774         assertEquals(expectedResult, vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile));
775 
776         // The profile should always be stored, whether or not consent has been previously granted.
777         verify(mVpnProfileStore)
778                 .put(
779                         eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)),
780                         eq(mVpnProfile.encode()));
781 
782         for (final String checkedOpStr : checkedOps) {
783             verify(mAppOps).noteOpNoThrow(checkedOpStr, Process.myUid(), TEST_VPN_PKG,
784                     null /* attributionTag */, null /* message */);
785         }
786     }
787 
788     @Test
testProvisionVpnProfileNoIpsecTunnels()789     public void testProvisionVpnProfileNoIpsecTunnels() throws Exception {
790         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
791                 .thenReturn(false);
792         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
793 
794         try {
795             checkProvisionVpnProfile(
796                     vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
797             fail("Expected exception due to missing feature");
798         } catch (UnsupportedOperationException expected) {
799         }
800     }
801 
prepareVpnForVerifyAppExclusionList()802     private Vpn prepareVpnForVerifyAppExclusionList() throws Exception {
803         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
804         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
805                 .thenReturn(mVpnProfile.encode());
806         when(mVpnProfileStore.get(PRIMARY_USER_APP_EXCLUDE_KEY))
807                 .thenReturn(HexDump.hexStringToByteArray(PKGS_BYTES));
808 
809         vpn.startVpnProfile(TEST_VPN_PKG);
810         verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
811         vpn.mNetworkAgent = new NetworkAgent(mContext, Looper.getMainLooper(), TAG,
812                 new NetworkCapabilities.Builder().build(), new LinkProperties(), 10 /* score */,
813                 new NetworkAgentConfig.Builder().build(),
814                 new NetworkProvider(mContext, Looper.getMainLooper(), TAG)) {};
815         return vpn;
816     }
817 
818     @Test @IgnoreUpTo(S_V2)
testSetAndGetAppExclusionList()819     public void testSetAndGetAppExclusionList() throws Exception {
820         final Vpn vpn = prepareVpnForVerifyAppExclusionList();
821         verify(mVpnProfileStore, never()).put(eq(PRIMARY_USER_APP_EXCLUDE_KEY), any());
822         vpn.setAppExclusionList(TEST_VPN_PKG, Arrays.asList(PKGS));
823         verify(mVpnProfileStore)
824                 .put(eq(PRIMARY_USER_APP_EXCLUDE_KEY),
825                      eq(HexDump.hexStringToByteArray(PKGS_BYTES)));
826         assertEquals(vpn.createUserAndRestrictedProfilesRanges(
827                 primaryUser.id, null, Arrays.asList(PKGS)),
828                 vpn.mNetworkCapabilities.getUids());
829         assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG));
830     }
831 
832     @Test @IgnoreUpTo(S_V2)
testSetAndGetAppExclusionListRestrictedUser()833     public void testSetAndGetAppExclusionListRestrictedUser() throws Exception {
834         final Vpn vpn = prepareVpnForVerifyAppExclusionList();
835         // Mock it to restricted profile
836         when(mUserManager.getUserInfo(anyInt())).thenReturn(restrictedProfileA);
837         // Restricted users cannot configure VPNs
838         assertThrows(SecurityException.class,
839                 () -> vpn.setAppExclusionList(TEST_VPN_PKG, new ArrayList<>()));
840 
841         assertEquals(Arrays.asList(PKGS), vpn.getAppExclusionList(TEST_VPN_PKG));
842     }
843 
844     @Test
testProvisionVpnProfilePreconsented()845     public void testProvisionVpnProfilePreconsented() throws Exception {
846         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
847 
848         checkProvisionVpnProfile(
849                 vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
850     }
851 
852     @Test
testProvisionVpnProfileNotPreconsented()853     public void testProvisionVpnProfileNotPreconsented() throws Exception {
854         final Vpn vpn = createVpnAndSetupUidChecks();
855 
856         // Expect that both the ACTIVATE_VPN and ACTIVATE_PLATFORM_VPN were tried, but the caller
857         // had neither.
858         checkProvisionVpnProfile(vpn, false /* expectedResult */,
859                 AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, AppOpsManager.OPSTR_ACTIVATE_VPN);
860     }
861 
862     @Test
testProvisionVpnProfileVpnServicePreconsented()863     public void testProvisionVpnProfileVpnServicePreconsented() throws Exception {
864         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
865 
866         checkProvisionVpnProfile(vpn, true /* expectedResult */, AppOpsManager.OPSTR_ACTIVATE_VPN);
867     }
868 
869     @Test
testProvisionVpnProfileTooLarge()870     public void testProvisionVpnProfileTooLarge() throws Exception {
871         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
872 
873         final VpnProfile bigProfile = new VpnProfile("");
874         bigProfile.name = new String(new byte[Vpn.MAX_VPN_PROFILE_SIZE_BYTES + 1]);
875 
876         try {
877             vpn.provisionVpnProfile(TEST_VPN_PKG, bigProfile);
878             fail("Expected IAE due to profile size");
879         } catch (IllegalArgumentException expected) {
880         }
881     }
882 
883     @Test
testProvisionVpnProfileRestrictedUser()884     public void testProvisionVpnProfileRestrictedUser() throws Exception {
885         final Vpn vpn =
886                 createVpnAndSetupUidChecks(
887                         restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
888 
889         try {
890             vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile);
891             fail("Expected SecurityException due to restricted user");
892         } catch (SecurityException expected) {
893         }
894     }
895 
896     @Test
testDeleteVpnProfile()897     public void testDeleteVpnProfile() throws Exception {
898         final Vpn vpn = createVpnAndSetupUidChecks();
899 
900         vpn.deleteVpnProfile(TEST_VPN_PKG);
901 
902         verify(mVpnProfileStore)
903                 .remove(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
904     }
905 
906     @Test
testDeleteVpnProfileRestrictedUser()907     public void testDeleteVpnProfileRestrictedUser() throws Exception {
908         final Vpn vpn =
909                 createVpnAndSetupUidChecks(
910                         restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
911 
912         try {
913             vpn.deleteVpnProfile(TEST_VPN_PKG);
914             fail("Expected SecurityException due to restricted user");
915         } catch (SecurityException expected) {
916         }
917     }
918 
919     @Test
testGetVpnProfilePrivileged()920     public void testGetVpnProfilePrivileged() throws Exception {
921         final Vpn vpn = createVpnAndSetupUidChecks();
922 
923         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
924                 .thenReturn(new VpnProfile("").encode());
925 
926         vpn.getVpnProfilePrivileged(TEST_VPN_PKG);
927 
928         verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
929     }
930 
verifyPlatformVpnIsActivated(String packageName)931     private void verifyPlatformVpnIsActivated(String packageName) {
932         verify(mAppOps).noteOpNoThrow(
933                 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
934                 eq(Process.myUid()),
935                 eq(packageName),
936                 eq(null) /* attributionTag */,
937                 eq(null) /* message */);
938         verify(mAppOps).startOp(
939                 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER),
940                 eq(Process.myUid()),
941                 eq(packageName),
942                 eq(null) /* attributionTag */,
943                 eq(null) /* message */);
944     }
945 
verifyPlatformVpnIsDeactivated(String packageName)946     private void verifyPlatformVpnIsDeactivated(String packageName) {
947         // Add a small delay to double confirm that finishOp is only called once.
948         verify(mAppOps, after(100)).finishOp(
949                 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER),
950                 eq(Process.myUid()),
951                 eq(packageName),
952                 eq(null) /* attributionTag */);
953     }
954 
955     @Test
testStartVpnProfile()956     public void testStartVpnProfile() throws Exception {
957         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
958 
959         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
960                 .thenReturn(mVpnProfile.encode());
961 
962         vpn.startVpnProfile(TEST_VPN_PKG);
963 
964         verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
965         verifyPlatformVpnIsActivated(TEST_VPN_PKG);
966     }
967 
968     @Test
testStartVpnProfileVpnServicePreconsented()969     public void testStartVpnProfileVpnServicePreconsented() throws Exception {
970         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
971 
972         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
973                 .thenReturn(mVpnProfile.encode());
974 
975         vpn.startVpnProfile(TEST_VPN_PKG);
976 
977         // Verify that the ACTIVATE_VPN appop was checked, but no error was thrown.
978         verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(),
979                 TEST_VPN_PKG, null /* attributionTag */, null /* message */);
980     }
981 
982     @Test
testStartVpnProfileNotConsented()983     public void testStartVpnProfileNotConsented() throws Exception {
984         final Vpn vpn = createVpnAndSetupUidChecks();
985 
986         try {
987             vpn.startVpnProfile(TEST_VPN_PKG);
988             fail("Expected failure due to no user consent");
989         } catch (SecurityException expected) {
990         }
991 
992         // Verify both appops were checked.
993         verify(mAppOps)
994                 .noteOpNoThrow(
995                         eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
996                         eq(Process.myUid()),
997                         eq(TEST_VPN_PKG),
998                         eq(null) /* attributionTag */,
999                         eq(null) /* message */);
1000         verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(),
1001                 TEST_VPN_PKG, null /* attributionTag */, null /* message */);
1002 
1003         // Keystore should never have been accessed.
1004         verify(mVpnProfileStore, never()).get(any());
1005     }
1006 
1007     @Test
testStartVpnProfileMissingProfile()1008     public void testStartVpnProfileMissingProfile() throws Exception {
1009         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
1010 
1011         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null);
1012 
1013         try {
1014             vpn.startVpnProfile(TEST_VPN_PKG);
1015             fail("Expected failure due to missing profile");
1016         } catch (IllegalArgumentException expected) {
1017         }
1018 
1019         verify(mVpnProfileStore).get(vpn.getProfileNameForPackage(TEST_VPN_PKG));
1020         verify(mAppOps)
1021                 .noteOpNoThrow(
1022                         eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
1023                         eq(Process.myUid()),
1024                         eq(TEST_VPN_PKG),
1025                         eq(null) /* attributionTag */,
1026                         eq(null) /* message */);
1027     }
1028 
1029     @Test
testStartVpnProfileRestrictedUser()1030     public void testStartVpnProfileRestrictedUser() throws Exception {
1031         final Vpn vpn =
1032                 createVpnAndSetupUidChecks(
1033                         restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
1034 
1035         try {
1036             vpn.startVpnProfile(TEST_VPN_PKG);
1037             fail("Expected SecurityException due to restricted user");
1038         } catch (SecurityException expected) {
1039         }
1040     }
1041 
1042     @Test
testStopVpnProfileRestrictedUser()1043     public void testStopVpnProfileRestrictedUser() throws Exception {
1044         final Vpn vpn =
1045                 createVpnAndSetupUidChecks(
1046                         restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
1047 
1048         try {
1049             vpn.stopVpnProfile(TEST_VPN_PKG);
1050             fail("Expected SecurityException due to restricted user");
1051         } catch (SecurityException expected) {
1052         }
1053     }
1054 
1055     @Test
testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff()1056     public void testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff() throws Exception {
1057         assumeTrue(SdkLevel.isAtLeastT());
1058         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
1059         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
1060                 .thenReturn(mVpnProfile.encode());
1061         vpn.startVpnProfile(TEST_VPN_PKG);
1062         verifyPlatformVpnIsActivated(TEST_VPN_PKG);
1063         // Add a small delay to make sure that startOp is only called once.
1064         verify(mAppOps, after(100).times(1)).startOp(
1065                 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER),
1066                 eq(Process.myUid()),
1067                 eq(TEST_VPN_PKG),
1068                 eq(null) /* attributionTag */,
1069                 eq(null) /* message */);
1070         // Check that the startOp is not called with OPSTR_ESTABLISH_VPN_SERVICE.
1071         verify(mAppOps, never()).startOp(
1072                 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE),
1073                 eq(Process.myUid()),
1074                 eq(TEST_VPN_PKG),
1075                 eq(null) /* attributionTag */,
1076                 eq(null) /* message */);
1077         vpn.stopVpnProfile(TEST_VPN_PKG);
1078         verifyPlatformVpnIsDeactivated(TEST_VPN_PKG);
1079     }
1080 
1081     @Test
testStartOpWithSeamlessHandover()1082     public void testStartOpWithSeamlessHandover() throws Exception {
1083         assumeTrue(SdkLevel.isAtLeastT());
1084         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
1085         assertTrue(vpn.prepare(TEST_VPN_PKG, null, VpnManager.TYPE_VPN_SERVICE));
1086         final VpnConfig config = new VpnConfig();
1087         config.user = "VpnTest";
1088         config.addresses.add(new LinkAddress("192.0.2.2/32"));
1089         config.mtu = 1450;
1090         final ResolveInfo resolveInfo = new ResolveInfo();
1091         final ServiceInfo serviceInfo = new ServiceInfo();
1092         serviceInfo.permission = BIND_VPN_SERVICE;
1093         resolveInfo.serviceInfo = serviceInfo;
1094         when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
1095         when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
1096         vpn.establish(config);
1097         verify(mAppOps, times(1)).startOp(
1098                 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE),
1099                 eq(Process.myUid()),
1100                 eq(TEST_VPN_PKG),
1101                 eq(null) /* attributionTag */,
1102                 eq(null) /* message */);
1103         // Call establish() twice with the same config, it should match seamless handover case and
1104         // startOp() shouldn't be called again.
1105         vpn.establish(config);
1106         verify(mAppOps, times(1)).startOp(
1107                 eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE),
1108                 eq(Process.myUid()),
1109                 eq(TEST_VPN_PKG),
1110                 eq(null) /* attributionTag */,
1111                 eq(null) /* message */);
1112     }
1113 
verifyVpnManagerEvent(String sessionKey, String category, int errorClass, int errorCode, VpnProfileState... profileState)1114     private void verifyVpnManagerEvent(String sessionKey, String category, int errorClass,
1115             int errorCode, VpnProfileState... profileState) {
1116         final Context userContext =
1117                 mContext.createContextAsUser(UserHandle.of(primaryUser.id), 0 /* flags */);
1118         final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
1119 
1120         final int verifyTimes = (profileState == null) ? 1 : profileState.length;
1121         verify(userContext, times(verifyTimes)).startService(intentArgumentCaptor.capture());
1122 
1123         for (int i = 0; i < verifyTimes; i++) {
1124             final Intent intent = intentArgumentCaptor.getAllValues().get(i);
1125             assertEquals(sessionKey, intent.getStringExtra(VpnManager.EXTRA_SESSION_KEY));
1126             final Set<String> categories = intent.getCategories();
1127             assertTrue(categories.contains(category));
1128             assertEquals(errorClass,
1129                     intent.getIntExtra(VpnManager.EXTRA_ERROR_CLASS, -1 /* defaultValue */));
1130             assertEquals(errorCode,
1131                     intent.getIntExtra(VpnManager.EXTRA_ERROR_CODE, -1 /* defaultValue */));
1132             if (profileState != null) {
1133                 assertEquals(profileState[i], intent.getParcelableExtra(
1134                         VpnManager.EXTRA_VPN_PROFILE_STATE, VpnProfileState.class));
1135             }
1136         }
1137         reset(userContext);
1138     }
1139 
1140     @Test
testVpnManagerEventForUserDeactivated()1141     public void testVpnManagerEventForUserDeactivated() throws Exception {
1142         assumeTrue(SdkLevel.isAtLeastT());
1143         // For security reasons, Vpn#prepare() will check that oldPackage and newPackage are either
1144         // null or the package of the caller. This test will call Vpn#prepare() to pretend the old
1145         // VPN is replaced by a new one. But only Settings can change to some other packages, and
1146         // this is checked with CONTROL_VPN so simulate holding CONTROL_VPN in order to pass the
1147         // security checks.
1148         doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN);
1149         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
1150         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
1151                 .thenReturn(mVpnProfile.encode());
1152 
1153         // Test the case that the user deactivates the vpn in vpn app.
1154         final String sessionKey1 = vpn.startVpnProfile(TEST_VPN_PKG);
1155         verifyPlatformVpnIsActivated(TEST_VPN_PKG);
1156         vpn.stopVpnProfile(TEST_VPN_PKG);
1157         verifyPlatformVpnIsDeactivated(TEST_VPN_PKG);
1158         verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG);
1159         reset(mDeviceIdleInternal);
1160         // CATEGORY_EVENT_DEACTIVATED_BY_USER is not an error event, so both of errorClass and
1161         // errorCode won't be set.
1162         verifyVpnManagerEvent(sessionKey1, VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
1163                 -1 /* errorClass */, -1 /* errorCode */, null /* profileState */);
1164         reset(mAppOps);
1165 
1166         // Test the case that the user chooses another vpn and the original one is replaced.
1167         final String sessionKey2 = vpn.startVpnProfile(TEST_VPN_PKG);
1168         verifyPlatformVpnIsActivated(TEST_VPN_PKG);
1169         vpn.prepare(TEST_VPN_PKG, "com.new.vpn" /* newPackage */, TYPE_VPN_PLATFORM);
1170         verifyPlatformVpnIsDeactivated(TEST_VPN_PKG);
1171         verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG);
1172         reset(mDeviceIdleInternal);
1173         // CATEGORY_EVENT_DEACTIVATED_BY_USER is not an error event, so both of errorClass and
1174         // errorCode won't be set.
1175         verifyVpnManagerEvent(sessionKey2, VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER,
1176                 -1 /* errorClass */, -1 /* errorCode */, null /* profileState */);
1177     }
1178 
1179     @Test
testVpnManagerEventForAlwaysOnChanged()1180     public void testVpnManagerEventForAlwaysOnChanged() throws Exception {
1181         assumeTrue(SdkLevel.isAtLeastT());
1182         // Calling setAlwaysOnPackage() needs to hold CONTROL_VPN.
1183         doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN);
1184         final Vpn vpn = createVpn(primaryUser.id);
1185         // Enable VPN always-on for PKGS[1].
1186         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */,
1187                 null /* lockdownAllowlist */));
1188         verifyPowerSaveTempWhitelistApp(PKGS[1]);
1189         reset(mDeviceIdleInternal);
1190         verifyVpnManagerEvent(null /* sessionKey */,
1191                 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */,
1192                 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1193                         null /* sessionKey */, true /* alwaysOn */, false /* lockdown */));
1194 
1195         // Enable VPN lockdown for PKGS[1].
1196         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true /* lockdown */,
1197                 null /* lockdownAllowlist */));
1198         verifyPowerSaveTempWhitelistApp(PKGS[1]);
1199         reset(mDeviceIdleInternal);
1200         verifyVpnManagerEvent(null /* sessionKey */,
1201                 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */,
1202                 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1203                         null /* sessionKey */, true /* alwaysOn */, true /* lockdown */));
1204 
1205         // Disable VPN lockdown for PKGS[1].
1206         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */,
1207                 null /* lockdownAllowlist */));
1208         verifyPowerSaveTempWhitelistApp(PKGS[1]);
1209         reset(mDeviceIdleInternal);
1210         verifyVpnManagerEvent(null /* sessionKey */,
1211                 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */,
1212                 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1213                         null /* sessionKey */, true /* alwaysOn */, false /* lockdown */));
1214 
1215         // Disable VPN always-on.
1216         assertTrue(vpn.setAlwaysOnPackage(null, false /* lockdown */,
1217                 null /* lockdownAllowlist */));
1218         verifyPowerSaveTempWhitelistApp(PKGS[1]);
1219         reset(mDeviceIdleInternal);
1220         verifyVpnManagerEvent(null /* sessionKey */,
1221                 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */,
1222                 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1223                         null /* sessionKey */, false /* alwaysOn */, false /* lockdown */));
1224 
1225         // Enable VPN always-on for PKGS[1] again.
1226         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false /* lockdown */,
1227                 null /* lockdownAllowlist */));
1228         verifyPowerSaveTempWhitelistApp(PKGS[1]);
1229         reset(mDeviceIdleInternal);
1230         verifyVpnManagerEvent(null /* sessionKey */,
1231                 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */,
1232                 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1233                         null /* sessionKey */, true /* alwaysOn */, false /* lockdown */));
1234 
1235         // Enable VPN always-on for PKGS[2].
1236         assertTrue(vpn.setAlwaysOnPackage(PKGS[2], false /* lockdown */,
1237                 null /* lockdownAllowlist */));
1238         verifyPowerSaveTempWhitelistApp(PKGS[2]);
1239         reset(mDeviceIdleInternal);
1240         // PKGS[1] is replaced with PKGS[2].
1241         // Pass 2 VpnProfileState objects to verifyVpnManagerEvent(), the first one is sent to
1242         // PKGS[1] to notify PKGS[1] that the VPN always-on is disabled, the second one is sent to
1243         // PKGS[2] to notify PKGS[2] that the VPN always-on is enabled.
1244         verifyVpnManagerEvent(null /* sessionKey */,
1245                 VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED, -1 /* errorClass */,
1246                 -1 /* errorCode */, new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1247                         null /* sessionKey */, false /* alwaysOn */, false /* lockdown */),
1248                 new VpnProfileState(VpnProfileState.STATE_DISCONNECTED,
1249                         null /* sessionKey */, true /* alwaysOn */, false /* lockdown */));
1250     }
1251 
1252     @Test
testSetPackageAuthorizationVpnService()1253     public void testSetPackageAuthorizationVpnService() throws Exception {
1254         final Vpn vpn = createVpnAndSetupUidChecks();
1255 
1256         assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_SERVICE));
1257         verify(mAppOps)
1258                 .setMode(
1259                         eq(AppOpsManager.OPSTR_ACTIVATE_VPN),
1260                         eq(Process.myUid()),
1261                         eq(TEST_VPN_PKG),
1262                         eq(AppOpsManager.MODE_ALLOWED));
1263     }
1264 
1265     @Test
testSetPackageAuthorizationPlatformVpn()1266     public void testSetPackageAuthorizationPlatformVpn() throws Exception {
1267         final Vpn vpn = createVpnAndSetupUidChecks();
1268 
1269         assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, TYPE_VPN_PLATFORM));
1270         verify(mAppOps)
1271                 .setMode(
1272                         eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
1273                         eq(Process.myUid()),
1274                         eq(TEST_VPN_PKG),
1275                         eq(AppOpsManager.MODE_ALLOWED));
1276     }
1277 
1278     @Test
testSetPackageAuthorizationRevokeAuthorization()1279     public void testSetPackageAuthorizationRevokeAuthorization() throws Exception {
1280         final Vpn vpn = createVpnAndSetupUidChecks();
1281 
1282         assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_NONE));
1283         verify(mAppOps)
1284                 .setMode(
1285                         eq(AppOpsManager.OPSTR_ACTIVATE_VPN),
1286                         eq(Process.myUid()),
1287                         eq(TEST_VPN_PKG),
1288                         eq(AppOpsManager.MODE_IGNORED));
1289         verify(mAppOps)
1290                 .setMode(
1291                         eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
1292                         eq(Process.myUid()),
1293                         eq(TEST_VPN_PKG),
1294                         eq(AppOpsManager.MODE_IGNORED));
1295     }
1296 
triggerOnAvailableAndGetCallback()1297     private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception {
1298         final ArgumentCaptor<NetworkCallback> networkCallbackCaptor =
1299                 ArgumentCaptor.forClass(NetworkCallback.class);
1300         verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS))
1301                 .requestNetwork(any(), networkCallbackCaptor.capture());
1302 
1303         // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be
1304         // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException.
1305         final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel();
1306         config.flags = new String[] {IF_STATE_DOWN};
1307         when(mNetd.interfaceGetCfg(anyString())).thenReturn(config);
1308         final NetworkCallback cb = networkCallbackCaptor.getValue();
1309         cb.onAvailable(TEST_NETWORK);
1310         return cb;
1311     }
1312 
verifyInterfaceSetCfgWithFlags(String flag)1313     private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception {
1314         // Add a timeout for waiting for interfaceSetCfg to be called.
1315         verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat(
1316                 config -> Arrays.asList(config.flags).contains(flag)));
1317     }
1318 
doTestPlatformVpnWithException(IkeException exception, String category, int errorType, int errorCode)1319     private void doTestPlatformVpnWithException(IkeException exception,
1320             String category, int errorType, int errorCode) throws Exception {
1321         final ArgumentCaptor<IkeSessionCallback> captor =
1322                 ArgumentCaptor.forClass(IkeSessionCallback.class);
1323 
1324         final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
1325         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
1326                 .thenReturn(mVpnProfile.encode());
1327 
1328         final String sessionKey = vpn.startVpnProfile(TEST_VPN_PKG);
1329         final NetworkCallback cb = triggerOnAvailableAndGetCallback();
1330 
1331         verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
1332 
1333         // Wait for createIkeSession() to be called before proceeding in order to ensure consistent
1334         // state
1335         verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
1336                 .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
1337         reset(mIkev2SessionCreator);
1338         final IkeSessionCallback ikeCb = captor.getValue();
1339         ikeCb.onClosedWithException(exception);
1340 
1341         verifyPowerSaveTempWhitelistApp(TEST_VPN_PKG);
1342         reset(mDeviceIdleInternal);
1343         verifyVpnManagerEvent(sessionKey, category, errorType, errorCode, null /* profileState */);
1344         if (errorType == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) {
1345             verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS))
1346                     .unregisterNetworkCallback(eq(cb));
1347         } else if (errorType == VpnManager.ERROR_CLASS_RECOVERABLE) {
1348             // To prevent spending much time to test the retry function, only retry 2 times here.
1349             int retryIndex = 0;
1350             verify(mIkev2SessionCreator,
1351                     timeout(((TestDeps) vpn.mDeps).getNextRetryDelaySeconds(retryIndex++) * 1000
1352                             + TEST_TIMEOUT_MS))
1353                     .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
1354 
1355             // Capture a new IkeSessionCallback to get the latest token.
1356             reset(mIkev2SessionCreator);
1357             final IkeSessionCallback ikeCb2 = captor.getValue();
1358             ikeCb2.onClosedWithException(exception);
1359             verify(mIkev2SessionCreator,
1360                     timeout(((TestDeps) vpn.mDeps).getNextRetryDelaySeconds(retryIndex++) * 1000
1361                             + TEST_TIMEOUT_MS))
1362                     .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
1363             reset(mIkev2SessionCreator);
1364         }
1365     }
1366 
1367     @Test
testStartPlatformVpnAuthenticationFailed()1368     public void testStartPlatformVpnAuthenticationFailed() throws Exception {
1369         final IkeProtocolException exception = mock(IkeProtocolException.class);
1370         final int errorCode = IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
1371         when(exception.getErrorType()).thenReturn(errorCode);
1372         doTestPlatformVpnWithException(exception,
1373                 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
1374                 errorCode);
1375     }
1376 
1377     @Test
testStartPlatformVpnFailedWithRecoverableError()1378     public void testStartPlatformVpnFailedWithRecoverableError() throws Exception {
1379         final IkeProtocolException exception = mock(IkeProtocolException.class);
1380         final int errorCode = IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;
1381         when(exception.getErrorType()).thenReturn(errorCode);
1382         doTestPlatformVpnWithException(exception,
1383                 VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, errorCode);
1384     }
1385 
1386     @Test
testStartPlatformVpnFailedWithUnknownHostException()1387     public void testStartPlatformVpnFailedWithUnknownHostException() throws Exception {
1388         final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
1389         final UnknownHostException unknownHostException = new UnknownHostException();
1390         final int errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST;
1391         when(exception.getCause()).thenReturn(unknownHostException);
1392         doTestPlatformVpnWithException(exception,
1393                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
1394                 errorCode);
1395     }
1396 
1397     @Test
testStartPlatformVpnFailedWithIkeTimeoutException()1398     public void testStartPlatformVpnFailedWithIkeTimeoutException() throws Exception {
1399         final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
1400         final IkeTimeoutException ikeTimeoutException =
1401                 new IkeTimeoutException("IkeTimeoutException");
1402         final int errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT;
1403         when(exception.getCause()).thenReturn(ikeTimeoutException);
1404         doTestPlatformVpnWithException(exception,
1405                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
1406                 errorCode);
1407     }
1408 
1409     @Test
testStartPlatformVpnFailedWithIkeNetworkLostException()1410     public void testStartPlatformVpnFailedWithIkeNetworkLostException() throws Exception {
1411         final IkeNetworkLostException exception = new IkeNetworkLostException(
1412                 new Network(100));
1413         doTestPlatformVpnWithException(exception,
1414                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
1415                 VpnManager.ERROR_CODE_NETWORK_LOST);
1416     }
1417 
1418     @Test
testStartPlatformVpnFailedWithIOException()1419     public void testStartPlatformVpnFailedWithIOException() throws Exception {
1420         final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
1421         final IOException ioException = new IOException();
1422         final int errorCode = VpnManager.ERROR_CODE_NETWORK_IO;
1423         when(exception.getCause()).thenReturn(ioException);
1424         doTestPlatformVpnWithException(exception,
1425                 VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
1426                 errorCode);
1427     }
1428 
1429     @Test
testStartPlatformVpnIllegalArgumentExceptionInSetup()1430     public void testStartPlatformVpnIllegalArgumentExceptionInSetup() throws Exception {
1431         when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any()))
1432                 .thenThrow(new IllegalArgumentException());
1433         final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile);
1434         final NetworkCallback cb = triggerOnAvailableAndGetCallback();
1435 
1436         verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
1437 
1438         // Wait for createIkeSession() to be called before proceeding in order to ensure consistent
1439         // state
1440         verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb));
1441         assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state);
1442     }
1443 
1444     @Test
testVpnManagerEventWillNotBeSentToSettingsVpn()1445     public void testVpnManagerEventWillNotBeSentToSettingsVpn() throws Exception {
1446         startLegacyVpn(createVpn(primaryUser.id), mVpnProfile);
1447         triggerOnAvailableAndGetCallback();
1448 
1449         verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
1450 
1451         final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
1452         final IkeTimeoutException ikeTimeoutException =
1453                 new IkeTimeoutException("IkeTimeoutException");
1454         when(exception.getCause()).thenReturn(ikeTimeoutException);
1455 
1456         final ArgumentCaptor<IkeSessionCallback> captor =
1457                 ArgumentCaptor.forClass(IkeSessionCallback.class);
1458         verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
1459                 .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
1460         final IkeSessionCallback ikeCb = captor.getValue();
1461         ikeCb.onClosedWithException(exception);
1462 
1463         // userContext is the same Context that VPN is using, see createVpn().
1464         final Context userContext =
1465                 mContext.createContextAsUser(UserHandle.of(primaryUser.id), 0 /* flags */);
1466         verify(userContext, never()).startService(any());
1467     }
1468 
setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled)1469     private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) {
1470         assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null));
1471 
1472         verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
1473         verify(mAppOps).setMode(
1474                 eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG),
1475                 eq(AppOpsManager.MODE_ALLOWED));
1476 
1477         verify(mSystemServices).settingsSecurePutStringForUser(
1478                 eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(primaryUser.id));
1479         verify(mSystemServices).settingsSecurePutIntForUser(
1480                 eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0),
1481                 eq(primaryUser.id));
1482         verify(mSystemServices).settingsSecurePutStringForUser(
1483                 eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(primaryUser.id));
1484     }
1485 
1486     @Test
testSetAndStartAlwaysOnVpn()1487     public void testSetAndStartAlwaysOnVpn() throws Exception {
1488         final Vpn vpn = createVpn(primaryUser.id);
1489         setMockedUsers(primaryUser);
1490 
1491         // UID checks must return a different UID; otherwise it'll be treated as already prepared.
1492         final int uid = Process.myUid() + 1;
1493         when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt()))
1494                 .thenReturn(uid);
1495         when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
1496                 .thenReturn(mVpnProfile.encode());
1497 
1498         setAndVerifyAlwaysOnPackage(vpn, uid, false);
1499         assertTrue(vpn.startAlwaysOnVpn());
1500 
1501         // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
1502         // a subsequent CL.
1503     }
1504 
startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile)1505     private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception {
1506         setMockedUsers(primaryUser);
1507 
1508         // Dummy egress interface
1509         final LinkProperties lp = new LinkProperties();
1510         lp.setInterfaceName(EGRESS_IFACE);
1511 
1512         final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
1513                         InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE);
1514         lp.addRoute(defaultRoute);
1515 
1516         vpn.startLegacyVpn(vpnProfile, EGRESS_NETWORK, lp);
1517         return vpn;
1518     }
1519 
1520     @Test
testStartPlatformVpn()1521     public void testStartPlatformVpn() throws Exception {
1522         startLegacyVpn(createVpn(primaryUser.id), mVpnProfile);
1523         // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
1524         // a subsequent patch.
1525     }
1526 
1527     @Test
testStartRacoonNumericAddress()1528     public void testStartRacoonNumericAddress() throws Exception {
1529         startRacoon("1.2.3.4", "1.2.3.4");
1530     }
1531 
1532     @Test
testStartRacoonHostname()1533     public void testStartRacoonHostname() throws Exception {
1534         startRacoon("hostname", "5.6.7.8"); // address returned by deps.resolve
1535     }
1536 
1537     @Test
testStartPptp()1538     public void testStartPptp() throws Exception {
1539         startPptp(true /* useMppe */);
1540     }
1541 
1542     @Test
testStartPptp_NoMppe()1543     public void testStartPptp_NoMppe() throws Exception {
1544         startPptp(false /* useMppe */);
1545     }
1546 
assertTransportInfoMatches(NetworkCapabilities nc, int type)1547     private void assertTransportInfoMatches(NetworkCapabilities nc, int type) {
1548         assertNotNull(nc);
1549         VpnTransportInfo ti = (VpnTransportInfo) nc.getTransportInfo();
1550         assertNotNull(ti);
1551         assertEquals(type, ti.getType());
1552     }
1553 
startPptp(boolean useMppe)1554     private void startPptp(boolean useMppe) throws Exception {
1555         final VpnProfile profile = new VpnProfile("testProfile" /* key */);
1556         profile.type = VpnProfile.TYPE_PPTP;
1557         profile.name = "testProfileName";
1558         profile.username = "userName";
1559         profile.password = "thePassword";
1560         profile.server = "192.0.2.123";
1561         profile.mppe = useMppe;
1562 
1563         doReturn(new Network[] { new Network(101) }).when(mConnectivityManager).getAllNetworks();
1564         doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(any(), any(),
1565                 any(), any(), any(), any(), anyInt());
1566 
1567         final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile);
1568         final TestDeps deps = (TestDeps) vpn.mDeps;
1569 
1570         // TODO: use import when this is merged in all branches and there's no merge conflict
1571         com.android.testutils.Cleanup.testAndCleanup(() -> {
1572             final String[] mtpdArgs = deps.mtpdArgs.get(10, TimeUnit.SECONDS);
1573             final String[] argsPrefix = new String[]{
1574                     EGRESS_IFACE, "pptp", profile.server, "1723", "name", profile.username,
1575                     "password", profile.password, "linkname", "vpn", "refuse-eap", "nodefaultroute",
1576                     "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270"
1577             };
1578             assertArrayEquals(argsPrefix, Arrays.copyOf(mtpdArgs, argsPrefix.length));
1579             if (useMppe) {
1580                 assertEquals(argsPrefix.length + 2, mtpdArgs.length);
1581                 assertEquals("+mppe", mtpdArgs[argsPrefix.length]);
1582                 assertEquals("-pap", mtpdArgs[argsPrefix.length + 1]);
1583             } else {
1584                 assertEquals(argsPrefix.length + 1, mtpdArgs.length);
1585                 assertEquals("nomppe", mtpdArgs[argsPrefix.length]);
1586             }
1587 
1588             verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
1589                     any(), any(), any(), any(), anyInt());
1590         }, () -> { // Cleanup
1591                 vpn.mVpnRunner.exitVpnRunner();
1592                 deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier
1593                 vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup
1594             });
1595     }
1596 
startRacoon(final String serverAddr, final String expectedAddr)1597     public void startRacoon(final String serverAddr, final String expectedAddr)
1598             throws Exception {
1599         final ConditionVariable legacyRunnerReady = new ConditionVariable();
1600         final VpnProfile profile = new VpnProfile("testProfile" /* key */);
1601         profile.type = VpnProfile.TYPE_L2TP_IPSEC_PSK;
1602         profile.name = "testProfileName";
1603         profile.username = "userName";
1604         profile.password = "thePassword";
1605         profile.server = serverAddr;
1606         profile.ipsecIdentifier = "id";
1607         profile.ipsecSecret = "secret";
1608         profile.l2tpSecret = "l2tpsecret";
1609 
1610         when(mConnectivityManager.getAllNetworks())
1611             .thenReturn(new Network[] { new Network(101) });
1612 
1613         when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(),
1614                 any(), any(), anyInt())).thenAnswer(invocation -> {
1615                     // The runner has registered an agent and is now ready.
1616                     legacyRunnerReady.open();
1617                     return new Network(102);
1618                 });
1619         final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile);
1620         final TestDeps deps = (TestDeps) vpn.mDeps;
1621         try {
1622             // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK
1623             assertArrayEquals(
1624                     new String[] { EGRESS_IFACE, expectedAddr, "udppsk",
1625                             profile.ipsecIdentifier, profile.ipsecSecret, "1701" },
1626                     deps.racoonArgs.get(10, TimeUnit.SECONDS));
1627             // literal values are hardcoded in Vpn.java for mtpd args
1628             assertArrayEquals(
1629                     new String[] { EGRESS_IFACE, "l2tp", expectedAddr, "1701", profile.l2tpSecret,
1630                             "name", profile.username, "password", profile.password,
1631                             "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns",
1632                             "idle", "1800", "mtu", "1270", "mru", "1270" },
1633                     deps.mtpdArgs.get(10, TimeUnit.SECONDS));
1634 
1635             // Now wait for the runner to be ready before testing for the route.
1636             ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class);
1637             ArgumentCaptor<NetworkCapabilities> ncCaptor =
1638                     ArgumentCaptor.forClass(NetworkCapabilities.class);
1639             verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
1640                     lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt());
1641 
1642             // In this test the expected address is always v4 so /32.
1643             // Note that the interface needs to be specified because RouteInfo objects stored in
1644             // LinkProperties objects always acquire the LinkProperties' interface.
1645             final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"),
1646                     null, EGRESS_IFACE, RouteInfo.RTN_THROW);
1647             final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes();
1648             assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes,
1649                     actualRoutes.contains(expectedRoute));
1650 
1651             assertTransportInfoMatches(ncCaptor.getValue(), VpnManager.TYPE_VPN_LEGACY);
1652         } finally {
1653             // Now interrupt the thread, unblock the runner and clean up.
1654             vpn.mVpnRunner.exitVpnRunner();
1655             deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier
1656             vpn.mVpnRunner.join(10_000); // wait for up to 10s for the runner to die and cleanup
1657         }
1658     }
1659 
1660     private final class TestDeps extends Vpn.Dependencies {
1661         public final CompletableFuture<String[]> racoonArgs = new CompletableFuture();
1662         public final CompletableFuture<String[]> mtpdArgs = new CompletableFuture();
1663         public final File mStateFile;
1664 
1665         private final HashMap<String, Boolean> mRunningServices = new HashMap<>();
1666 
TestDeps()1667         TestDeps() {
1668             try {
1669                 mStateFile = File.createTempFile("vpnTest", ".tmp");
1670                 mStateFile.deleteOnExit();
1671             } catch (final IOException e) {
1672                 throw new RuntimeException(e);
1673             }
1674         }
1675 
1676         @Override
isCallerSystem()1677         public boolean isCallerSystem() {
1678             return true;
1679         }
1680 
1681         @Override
startService(final String serviceName)1682         public void startService(final String serviceName) {
1683             mRunningServices.put(serviceName, true);
1684         }
1685 
1686         @Override
stopService(final String serviceName)1687         public void stopService(final String serviceName) {
1688             mRunningServices.put(serviceName, false);
1689         }
1690 
1691         @Override
isServiceRunning(final String serviceName)1692         public boolean isServiceRunning(final String serviceName) {
1693             return mRunningServices.getOrDefault(serviceName, false);
1694         }
1695 
1696         @Override
isServiceStopped(final String serviceName)1697         public boolean isServiceStopped(final String serviceName) {
1698             return !isServiceRunning(serviceName);
1699         }
1700 
1701         @Override
getStateFile()1702         public File getStateFile() {
1703             return mStateFile;
1704         }
1705 
1706         @Override
getIntentForStatusPanel(Context context)1707         public PendingIntent getIntentForStatusPanel(Context context) {
1708             return null;
1709         }
1710 
1711         @Override
sendArgumentsToDaemon( final String daemon, final LocalSocket socket, final String[] arguments, final Vpn.RetryScheduler interruptChecker)1712         public void sendArgumentsToDaemon(
1713                 final String daemon, final LocalSocket socket, final String[] arguments,
1714                 final Vpn.RetryScheduler interruptChecker) throws IOException {
1715             if ("racoon".equals(daemon)) {
1716                 racoonArgs.complete(arguments);
1717             } else if ("mtpd".equals(daemon)) {
1718                 writeStateFile(arguments);
1719                 mtpdArgs.complete(arguments);
1720             } else {
1721                 throw new UnsupportedOperationException("Unsupported daemon : " + daemon);
1722             }
1723         }
1724 
writeStateFile(final String[] arguments)1725         private void writeStateFile(final String[] arguments) throws IOException {
1726             mStateFile.delete();
1727             mStateFile.createNewFile();
1728             mStateFile.deleteOnExit();
1729             final BufferedWriter writer = new BufferedWriter(
1730                     new FileWriter(mStateFile, false /* append */));
1731             writer.write(EGRESS_IFACE);
1732             writer.write("\n");
1733             // addresses
1734             writer.write("10.0.0.1/24\n");
1735             // routes
1736             writer.write("192.168.6.0/24\n");
1737             // dns servers
1738             writer.write("192.168.6.1\n");
1739             // search domains
1740             writer.write("vpn.searchdomains.com\n");
1741             // endpoint - intentionally empty
1742             writer.write("\n");
1743             writer.flush();
1744             writer.close();
1745         }
1746 
1747         @Override
1748         @NonNull
resolve(final String endpoint)1749         public InetAddress resolve(final String endpoint) {
1750             try {
1751                 // If a numeric IP address, return it.
1752                 return InetAddress.parseNumericAddress(endpoint);
1753             } catch (IllegalArgumentException e) {
1754                 // Otherwise, return some token IP to test for.
1755                 return InetAddress.parseNumericAddress("5.6.7.8");
1756             }
1757         }
1758 
1759         @Override
isInterfacePresent(final Vpn vpn, final String iface)1760         public boolean isInterfacePresent(final Vpn vpn, final String iface) {
1761             return true;
1762         }
1763 
1764         @Override
adoptFd(Vpn vpn, int mtu)1765         public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) {
1766             return new ParcelFileDescriptor(new FileDescriptor());
1767         }
1768 
1769         @Override
jniCreate(Vpn vpn, int mtu)1770         public int jniCreate(Vpn vpn, int mtu) {
1771             // Pick a random positive number as fd to return.
1772             return 345;
1773         }
1774 
1775         @Override
jniGetName(Vpn vpn, int fd)1776         public String jniGetName(Vpn vpn, int fd) {
1777             return TEST_IFACE_NAME;
1778         }
1779 
1780         @Override
jniSetAddresses(Vpn vpn, String interfaze, String addresses)1781         public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) {
1782             if (addresses == null) return 0;
1783             // Return the number of addresses.
1784             return addresses.split(" ").length;
1785         }
1786 
1787         @Override
setBlocking(FileDescriptor fd, boolean blocking)1788         public void setBlocking(FileDescriptor fd, boolean blocking) {}
1789 
1790         @Override
getDeviceIdleInternal()1791         public DeviceIdleInternal getDeviceIdleInternal() {
1792             return mDeviceIdleInternal;
1793         }
1794 
getNextRetryDelaySeconds(int retryCount)1795         public long getNextRetryDelaySeconds(int retryCount) {
1796             // Simply return retryCount as the delay seconds for retrying.
1797             return retryCount;
1798         }
1799     }
1800 
1801     /**
1802      * Mock some methods of vpn object.
1803      */
createVpn(@serIdInt int userId)1804     private Vpn createVpn(@UserIdInt int userId) {
1805         final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
1806         doReturn(UserHandle.of(userId)).when(asUserContext).getUser();
1807         when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
1808                 .thenReturn(asUserContext);
1809         final TestLooper testLooper = new TestLooper();
1810         final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
1811                 mNetd, userId, mVpnProfileStore, mSystemServices, mIkev2SessionCreator);
1812         verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat(
1813                 provider -> provider.getName().contains("VpnNetworkProvider")
1814         ));
1815         return vpn;
1816     }
1817 
1818     /**
1819      * Populate {@link #mUserManager} with a list of fake users.
1820      */
setMockedUsers(UserInfo... users)1821     private void setMockedUsers(UserInfo... users) {
1822         final Map<Integer, UserInfo> userMap = new ArrayMap<>();
1823         for (UserInfo user : users) {
1824             userMap.put(user.id, user);
1825         }
1826 
1827         /**
1828          * @see UserManagerService#getUsers(boolean)
1829          */
1830         doAnswer(invocation -> {
1831             final ArrayList<UserInfo> result = new ArrayList<>(users.length);
1832             for (UserInfo ui : users) {
1833                 if (ui.isEnabled() && !ui.partial) {
1834                     result.add(ui);
1835                 }
1836             }
1837             return result;
1838         }).when(mUserManager).getAliveUsers();
1839 
1840         doAnswer(invocation -> {
1841             final int id = (int) invocation.getArguments()[0];
1842             return userMap.get(id);
1843         }).when(mUserManager).getUserInfo(anyInt());
1844     }
1845 
1846     /**
1847      * Populate {@link #mPackageManager} with a fake packageName-to-UID mapping.
1848      */
setMockedPackages(final Map<String, Integer> packages)1849     private void setMockedPackages(final Map<String, Integer> packages) {
1850         try {
1851             doAnswer(invocation -> {
1852                 final String appName = (String) invocation.getArguments()[0];
1853                 final int userId = (int) invocation.getArguments()[1];
1854                 Integer appId = packages.get(appName);
1855                 if (appId == null) throw new PackageManager.NameNotFoundException(appName);
1856                 return UserHandle.getUid(userId, appId);
1857             }).when(mPackageManager).getPackageUidAsUser(anyString(), anyInt());
1858         } catch (Exception e) {
1859         }
1860     }
1861 
setMockedNetworks(final Map<Network, NetworkCapabilities> networks)1862     private void setMockedNetworks(final Map<Network, NetworkCapabilities> networks) {
1863         doAnswer(invocation -> {
1864             final Network network = (Network) invocation.getArguments()[0];
1865             return networks.get(network);
1866         }).when(mConnectivityManager).getNetworkCapabilities(any());
1867     }
1868 
1869     // Need multiple copies of this, but Java's Stream objects can't be reused or
1870     // duplicated.
publicIpV4Routes()1871     private Stream<String> publicIpV4Routes() {
1872         return Stream.of(
1873                 "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",
1874                 "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",
1875                 "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9",
1876                 "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",
1877                 "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14",
1878                 "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7",
1879                 "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4");
1880     }
1881 
publicIpV6Routes()1882     private Stream<String> publicIpV6Routes() {
1883         return Stream.of(
1884                 "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6",
1885                 "fe00::/8", "2605:ef80:e:af1d::/64");
1886     }
1887 }
1888