From 4d3a0c24351b36588178fe165dc72bc54a933a26 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 30 Nov 2020 16:02:54 +0900 Subject: [PATCH] Add tests for always-on VPN lockdown mode. This requires mocking lots of new things that weren't mocked before but is otherwise fairly straightforward. A few changes to MockVpn are needed as well: 1. Set the VPN's NetworkInfo to CONNECTED, so methods such as isBlockingUid will work. While I'm at it, set the interface on the LinkProperties as well to make things a bit more realistic. 2. Constructs the VpnConfig when registering the agent, not when the MockVpn is created. This is needed because starting and stopping lockdown VPN calls prepare, which nulls out mConfig. But constructing the VpnConfig when registering the agent is more realistic anyway. The production code does that in establish, but we can't do that in ConnectivityServiceTest because some of the test cases don't call establish and call registerAgent directly. Bug: 173331190 Test: atest FrameworksNetTests Change-Id: I827543751dbf5e626a24ec02cd6f50b423f5f761 --- .../com/android/server/connectivity/Vpn.java | 28 +- .../server/ConnectivityServiceTest.java | 258 ++++++++++++++++-- .../android/server/connectivity/VpnTest.java | 6 +- 3 files changed, 266 insertions(+), 26 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index cabfbc02491cd..228ad588525fa 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -246,7 +246,12 @@ public class Vpn { void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException; } - static class Dependencies { + @VisibleForTesting + public static class Dependencies { + public boolean isCallerSystem() { + return Binder.getCallingUid() == Process.SYSTEM_UID; + } + public void startService(final String serviceName) { SystemService.start(serviceName); } @@ -267,6 +272,10 @@ public class Vpn { return new File("/data/misc/vpn/state"); } + public DeviceIdleInternal getDeviceIdleInternal() { + return LocalServices.getService(DeviceIdleInternal.class); + } + public void sendArgumentsToDaemon( final String daemon, final LocalSocket socket, final String[] arguments, final RetryScheduler retryScheduler) throws IOException, InterruptedException { @@ -372,6 +381,14 @@ public class Vpn { new SystemServices(context), new Ikev2SessionCreator()); } + @VisibleForTesting + public Vpn(Looper looper, Context context, Dependencies deps, + INetworkManagementService netService, INetd netd, @UserIdInt int userId, + @NonNull KeyStore keyStore) { + this(looper, context, deps, netService, netd, userId, keyStore, + new SystemServices(context), new Ikev2SessionCreator()); + } + @VisibleForTesting protected Vpn(Looper looper, Context context, Dependencies deps, INetworkManagementService netService, INetd netd, @@ -772,8 +789,7 @@ public class Vpn { // Tell the OS that background services in this app need to be allowed for // a short time, so we can bootstrap the VPN service. - DeviceIdleInternal idleController = - LocalServices.getService(DeviceIdleInternal.class); + DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal(); idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage, VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, "vpn"); @@ -1959,10 +1975,6 @@ public class Vpn { return mContext.createContextAsUser( UserHandle.of(userId), 0 /* flags */).getContentResolver(); } - - public boolean isCallerSystem() { - return Binder.getCallingUid() == Process.SYSTEM_UID; - } } private native int jniCreate(int mtu); @@ -3112,7 +3124,7 @@ public class Vpn { @VisibleForTesting @Nullable VpnProfile getVpnProfilePrivileged(@NonNull String packageName, @NonNull KeyStore keyStore) { - if (!mSystemServices.isCallerSystem()) { + if (!mDeps.isCallerSystem()) { Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID "); return null; } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 8c403f1b6898d..43d3e4e6924c1 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -39,6 +39,7 @@ import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL; +import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS; import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK; @@ -101,6 +102,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.AdditionalMatchers.aryEq; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; @@ -132,6 +135,7 @@ import android.app.AppOpsManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; @@ -140,6 +144,8 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.content.res.Resources; import android.location.LocationManager; @@ -176,6 +182,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; +import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkStack; @@ -332,7 +339,7 @@ public class ConnectivityServiceTest { private static final String WIFI_WOL_IFNAME = "test_wlan_wol"; private static final String VPN_IFNAME = "tun10042"; private static final String TEST_PACKAGE_NAME = "com.android.test.package"; - private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn"; private static final String INTERFACE_NAME = "interface"; @@ -353,6 +360,7 @@ public class ConnectivityServiceTest { @Mock IIpConnectivityMetrics mIpConnectivityMetrics; @Mock IpConnectivityMetrics.Logger mMetricsService; @Mock DefaultNetworkMetrics mDefaultNetworkMetrics; + @Mock DeviceIdleInternal mDeviceIdleInternal; @Mock INetworkManagementService mNetworkManagementService; @Mock INetworkStatsService mStatsService; @Mock IBatteryStats mBatteryStatsService; @@ -449,6 +457,15 @@ public class ConnectivityServiceTest { } catch (InterruptedException e) {} } + @Override + public ComponentName startService(Intent service) { + final String action = service.getAction(); + if (!VpnConfig.SERVICE_INTERFACE.equals(action)) { + fail("Attempt to start unknown service, action=" + action); + } + return new ComponentName(service.getPackage(), "com.android.test.Service"); + } + @Override public Object getSystemService(String name) { if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; @@ -1055,9 +1072,19 @@ public class ConnectivityServiceTest { private VpnInfo mVpnInfo; public MockVpn(int userId) { - super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, - mMockNetd, userId, mock(KeyStore.class)); - mConfig = new VpnConfig(); + super(startHandlerThreadAndReturnLooper(), mServiceContext, + new Dependencies() { + @Override + public boolean isCallerSystem() { + return true; + } + + @Override + public DeviceIdleInternal getDeviceIdleInternal() { + return mDeviceIdleInternal; + } + }, + mNetworkManagementService, mMockNetd, userId, mock(KeyStore.class)); } public void setUids(Set uids) { @@ -1086,9 +1113,16 @@ public class ConnectivityServiceTest { return mVpnType; } + private LinkProperties makeLinkProperties() { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(VPN_IFNAME); + return lp; + } + private void registerAgent(boolean isAlwaysMetered, Set uids, LinkProperties lp) throws Exception { if (mAgentRegistered) throw new IllegalStateException("already registered"); + mConfig = new VpnConfig(); setUids(uids); if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); mInterface = VPN_IFNAME; @@ -1101,12 +1135,13 @@ public class ConnectivityServiceTest { verify(mMockNetd, never()) .networkRemoveUidRanges(eq(mMockVpn.getNetId()), any()); mAgentRegistered = true; + updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent"); mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); mNetworkAgent = mMockNetworkAgent.getNetworkAgent(); } private void registerAgent(Set uids) throws Exception { - registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties()); + registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties()); } private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) { @@ -1142,12 +1177,12 @@ public class ConnectivityServiceTest { public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode) throws Exception { final int uid = Process.myUid(); - establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet, + establish(makeLinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet, isStrictMode); } public void establishForMyUid() throws Exception { - establishForMyUid(new LinkProperties()); + establishForMyUid(makeLinkProperties()); } public void sendLinkProperties(LinkProperties lp) { @@ -1155,7 +1190,10 @@ public class ConnectivityServiceTest { } public void disconnect() { - if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect(); + if (mMockNetworkAgent != null) { + mMockNetworkAgent.disconnect(); + updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect"); + } mAgentRegistered = false; } @@ -1376,13 +1414,13 @@ public class ConnectivityServiceTest { } private void mockDefaultPackages() throws Exception { - final String testPackageName = mContext.getPackageName(); - final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo( - testPackageName, PackageManager.GET_PERMISSIONS); + final String myPackageName = mContext.getPackageName(); + final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo( + myPackageName, PackageManager.GET_PERMISSIONS); when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn( - new String[] {testPackageName}); - when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(), - eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo); + new String[] {myPackageName}); + when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(), + eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo); when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { @@ -1390,6 +1428,25 @@ public class ConnectivityServiceTest { buildPackageInfo(/* SYSTEM */ false, APP2_UID), buildPackageInfo(/* SYSTEM */ false, VPN_UID) })); + + // Create a fake always-on VPN package. + final int userId = UserHandle.getCallingUserId(); + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; // Always-on supported in N+. + when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(), + eq(userId))).thenReturn(applicationInfo); + + // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy. + ResolveInfo rInfo = new ResolveInfo(); + rInfo.serviceInfo = new ServiceInfo(); + rInfo.serviceInfo.metaData = new Bundle(); + final List services = Arrays.asList(new ResolveInfo[]{rInfo}); + when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA), + eq(userId))).thenReturn(services); + when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId)) + .thenReturn(Process.myUid()); + when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId)) + .thenReturn(VPN_UID); } private void verifyActiveNetwork(int transport) { @@ -2252,10 +2309,10 @@ public class ConnectivityServiceTest { } private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception { - final String testPackageName = mContext.getPackageName(); - when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS))) + final String myPackageName = mContext.getPackageName(); + when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS))) .thenReturn(buildPackageInfo(true, uid)); - mService.mPermissionMonitor.onPackageAdded(testPackageName, uid); + mService.mPermissionMonitor.onPackageAdded(myPackageName, uid); } @Test @@ -6389,6 +6446,173 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(defaultCallback); } + private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add, + UidRangeParcel... expected) throws Exception { + inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected)); + } + + private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) { + assertNotNull(ni); + assertEquals(type, ni.getType()); + assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState()); + } + + private void assertActiveNetworkInfo(int type, DetailedState state) { + checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state); + } + private void assertNetworkInfo(int type, DetailedState state) { + checkNetworkInfo(mCm.getNetworkInfo(type), type, state); + } + + @Test + public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception { + mServiceContext.setPermission( + Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED); + mServiceContext.setPermission( + Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); + mServiceContext.setPermission( + Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); + + final TestNetworkCallback callback = new TestNetworkCallback(); + final NetworkRequest request = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .build(); + mCm.registerNetworkCallback(request, callback); + + final TestNetworkCallback defaultCallback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(defaultCallback); + + final int uid = Process.myUid(); + final int userId = UserHandle.getUserId(uid); + final ArrayList allowList = new ArrayList<>(); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + + UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1); + UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999); + InOrder inOrder = inOrder(mMockNetd); + expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); + + // Connect a network when lockdown is active, expect to see it blocked. + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false /* validated */); + callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + // Mobile is BLOCKED even though it's not actually connected. + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + + // Disable lockdown, expect to see the network unblocked. + // There are no callbacks because they are not implemented yet. + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked. + allowList.add(TEST_PACKAGE_NAME); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + defaultCallback.assertNoCallback(); + + // The following requires that the UID of this test package is greater than VPN_UID. This + // is always true in practice because a plain AOSP build with no apps installed has almost + // 200 packages installed. + final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1); + final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1); + final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999); + expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Connect a new network, expect it to be unblocked. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(false /* validated */); + callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + defaultCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + // Cellular is DISCONNECTED because it's not the default and there are no requests for it. + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown. + // Everything should now be blocked. + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3); + allowList.clear(); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + + // Disable lockdown. Everything is unblocked. + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Enable and disable an always-on VPN package without lockdown. Expect no changes. + reset(mMockNetd); + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList); + inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); + callback.assertNoCallback(); + defaultCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); + inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any()); + callback.assertNoCallback(); + defaultCallback.assertNoCallback(); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + // Enable lockdown and connect a VPN. The VPN is not blocked. + mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); + assertNull(mCm.getActiveNetwork()); + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED); + assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED); + + mMockVpn.establishForMyUid(); + defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork()); + assertEquals(null, mCm.getActiveNetworkForUid(VPN_UID)); // BUG? + assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED); + assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED); + assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); + + mMockVpn.disconnect(); + defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn); + defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent); + assertNull(mCm.getActiveNetwork()); + + mCm.unregisterNetworkCallback(callback); + mCm.unregisterNetworkCallback(defaultCallback); + } + @Test public final void testLoseTrusted() throws Exception { final NetworkRequest trustedRequest = new NetworkRequest.Builder() diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 6e380be6c5835..cc473175540ca 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -228,7 +228,6 @@ public class VpnTest { R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) .thenReturn(true); - when(mSystemServices.isCallerSystem()).thenReturn(true); // Used by {@link Notification.Builder} ApplicationInfo applicationInfo = new ApplicationInfo(); @@ -1101,6 +1100,11 @@ public class VpnTest { } } + @Override + public boolean isCallerSystem() { + return true; + } + @Override public void startService(final String serviceName) { mRunningServices.put(serviceName, true);