diff options
Diffstat (limited to 'tests')
40 files changed, 2854 insertions, 586 deletions
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp index 025ac420fd4f..f7dda5798a83 100644 --- a/tests/RollbackTest/Android.bp +++ b/tests/RollbackTest/Android.bp @@ -104,6 +104,7 @@ apex { key: "com.android.apex.apkrollback.test.key", apps: ["TestAppAv1"], installable: false, + updatable: false, } apex { @@ -114,6 +115,7 @@ apex { key: "com.android.apex.apkrollback.test.key", apps: ["TestAppAv2"], installable: false, + updatable: false, } apex { @@ -124,4 +126,5 @@ apex { key: "com.android.apex.apkrollback.test.key", apps: ["TestAppACrashingV2"], installable: false, + updatable: false, } diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java index 1b5e6dd65540..dddb317f31e5 100644 --- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java +++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java @@ -28,6 +28,7 @@ import android.platform.test.annotations.LargeTest; import com.android.ddmlib.Log; import com.android.tests.rollback.host.AbandonSessionsRule; +import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; import com.android.tradefed.util.ProcessInfo; @@ -39,6 +40,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; @RunWith(DeviceJUnit4ClassRunner.class) public class StagedInstallInternalTest extends BaseHostJUnit4Test { @@ -182,9 +186,55 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test { assertThat(sessionIds.length).isEqualTo(3); } + @Test + public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception { + List<String> before = getStagingDirectories(); + runPhase("testStagedInstallationShouldCleanUpOnValidationFailure"); + List<String> after = getStagingDirectories(); + assertThat(after).isEqualTo(before); + } + + @Test + public void testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage() + throws Exception { + List<String> before = getStagingDirectories(); + runPhase("testStagedInstallationShouldCleanUpOnValidationFailureMultiPackage"); + List<String> after = getStagingDirectories(); + assertThat(after).isEqualTo(before); + } + + @Test + public void testOrphanedStagingDirectoryGetsCleanedUpOnReboot() throws Exception { + //create random directories in /data/app-staging folder + getDevice().enableAdbRoot(); + getDevice().executeShellCommand("mkdir /data/app-staging/session_123"); + getDevice().executeShellCommand("mkdir /data/app-staging/random_name"); + getDevice().disableAdbRoot(); + + assertThat(getStagingDirectories()).isNotEmpty(); + getDevice().reboot(); + assertThat(getStagingDirectories()).isEmpty(); + } + + private List<String> getStagingDirectories() throws DeviceNotAvailableException { + String baseDir = "/data/app-staging"; + try { + getDevice().enableAdbRoot(); + return getDevice().getFileEntry(baseDir).getChildren(false) + .stream().filter(entry -> entry.getName().matches("session_\\d+")) + .map(entry -> entry.getName()) + .collect(Collectors.toList()); + } catch (Exception e) { + // Return an empty list if any error + return Collections.EMPTY_LIST; + } finally { + getDevice().disableAdbRoot(); + } + } + private void restartSystemServer() throws Exception { // Restart the system server - final long oldStartTime = getDevice().getProcessByName("system_server").getStartTime(); + long oldStartTime = getDevice().getProcessByName("system_server").getStartTime(); getDevice().enableAdbRoot(); // Need root to restart system server assertThat(getDevice().executeShellCommand("am restart")).contains("Restart the system"); diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt index ad5bbf220d57..18a93319b271 100644 --- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt +++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt @@ -55,14 +55,14 @@ class CaptivePortalDataTest { .build() private val dataFromPasspoint = CaptivePortalData.Builder() - .setUserPortalUrl(Uri.parse("https://tc.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) - .setVenueInfoUrl(Uri.parse("https://venue.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) .setCaptive(true) .apply { if (SdkLevel.isAtLeastS()) { setVenueFriendlyName("venue friendly name") + setUserPortalUrl(Uri.parse("https://tc.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) + setVenueInfoUrl(Uri.parse("https://venue.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } } .build() @@ -96,28 +96,28 @@ class CaptivePortalDataTest { if (SdkLevel.isAtLeastS()) { assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } - } - assertEquals(dataFromPasspoint, CaptivePortalData.Builder(dataFromPasspoint).build()) - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/passpoint")) } - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/other"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } - assertNotEqualsAfterChange { it.setUserPortalUrl( - Uri.parse("https://tc.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } - assertNotEqualsAfterChange { it.setVenueInfoUrl( - Uri.parse("https://venue.example.com/passpoint")) } - assertNotEqualsAfterChange { it.setVenueInfoUrl( - Uri.parse("https://venue.example.com/other"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } - assertNotEqualsAfterChange { it.setVenueInfoUrl( - Uri.parse("https://venue.example.com/passpoint"), - CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } + assertEquals(dataFromPasspoint, CaptivePortalData.Builder(dataFromPasspoint).build()) + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/passpoint")) } + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/other"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } + assertNotEqualsAfterChange { it.setUserPortalUrl( + Uri.parse("https://tc.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } + assertNotEqualsAfterChange { it.setVenueInfoUrl( + Uri.parse("https://venue.example.com/passpoint")) } + assertNotEqualsAfterChange { it.setVenueInfoUrl( + Uri.parse("https://venue.example.com/other"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT) } + assertNotEqualsAfterChange { it.setVenueInfoUrl( + Uri.parse("https://venue.example.com/passpoint"), + CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_OTHER) } + } } @Test diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java index 7a60cc105a26..15d3398d43c0 100644 --- a/tests/net/common/java/android/net/CaptivePortalTest.java +++ b/tests/net/common/java/android/net/CaptivePortalTest.java @@ -24,8 +24,8 @@ import android.os.RemoteException; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import org.junit.Rule; @@ -55,7 +55,7 @@ public class CaptivePortalTest { mCode = request; } - @Override + // This is only @Override on R- public void logEvent(int eventId, String packageName) throws RemoteException { mCode = eventId; mPackageName = packageName; @@ -98,12 +98,24 @@ public class CaptivePortalTest { assertEquals(result.mCode, CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED); } + @IgnoreUpTo(Build.VERSION_CODES.R) @Test public void testLogEvent() { + /** + * From S testLogEvent is expected to do nothing but shouldn't crash (the API + * logEvent has been deprecated). + */ final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent( - MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY, + 0, TEST_PACKAGE_NAME)); - assertEquals(result.mCode, MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY); + } + + @IgnoreAfter(Build.VERSION_CODES.R) + @Test + public void testLogEvent_UntilR() { + final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.logEvent( + 42, TEST_PACKAGE_NAME)); + assertEquals(result.mCode, 42); assertEquals(result.mPackageName, TEST_PACKAGE_NAME); } } diff --git a/tests/net/common/java/android/net/NetworkStackTest.java b/tests/net/common/java/android/net/NetworkStackTest.java index a99aa0106655..f8f9c72374ad 100644 --- a/tests/net/common/java/android/net/NetworkStackTest.java +++ b/tests/net/common/java/android/net/NetworkStackTest.java @@ -15,20 +15,8 @@ */ package android.net; -import static android.Manifest.permission.NETWORK_STACK; -import static android.content.pm.PackageManager.PERMISSION_DENIED; -import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; -import static android.net.NetworkStack.checkNetworkStackPermission; -import static android.net.NetworkStack.checkNetworkStackPermissionOr; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.when; -import android.content.Context; import android.os.Build; import android.os.IBinder; @@ -46,44 +34,15 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class NetworkStackTest { - private static final String [] OTHER_PERMISSION = {"otherpermission1", "otherpermission2"}; - @Rule public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); - @Mock Context mCtx; @Mock private IBinder mConnectorBinder; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); } - @Test - public void testCheckNetworkStackPermission() throws Exception { - when(mCtx.checkCallingOrSelfPermission(eq(NETWORK_STACK))).thenReturn(PERMISSION_GRANTED); - when(mCtx.checkCallingOrSelfPermission(eq(PERMISSION_MAINLINE_NETWORK_STACK))) - .thenReturn(PERMISSION_DENIED); - checkNetworkStackPermission(mCtx); - checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION); - - when(mCtx.checkCallingOrSelfPermission(eq(NETWORK_STACK))).thenReturn(PERMISSION_DENIED); - when(mCtx.checkCallingOrSelfPermission(eq(PERMISSION_MAINLINE_NETWORK_STACK))) - .thenReturn(PERMISSION_GRANTED); - checkNetworkStackPermission(mCtx); - checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION); - - when(mCtx.checkCallingOrSelfPermission(any())).thenReturn(PERMISSION_DENIED); - - try { - checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION); - } catch (SecurityException e) { - // Expect to get a SecurityException - return; - } - - fail("Expect fail but permission granted."); - } - @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testGetService() { NetworkStack.setServiceForTest(mConnectorBinder); diff --git a/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt b/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt new file mode 100644 index 000000000000..0ca4d9551f39 --- /dev/null +++ b/tests/net/common/java/android/net/NetworkStateSnapshotTest.kt @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net + +import android.net.ConnectivityManager.TYPE_NONE +import android.net.ConnectivityManager.TYPE_WIFI +import android.net.InetAddresses.parseNumericAddress +import android.net.NetworkCapabilities.TRANSPORT_WIFI +import android.os.Build +import androidx.test.filters.SmallTest +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRunner +import com.android.testutils.assertParcelSane +import org.junit.Test +import org.junit.runner.RunWith +import java.net.Inet4Address +import java.net.Inet6Address + +private const val TEST_IMSI = "imsi1" +private const val TEST_SSID = "SSID1" +private const val TEST_NETID = 123 + +private val TEST_IPV4_GATEWAY = parseNumericAddress("192.168.222.3") as Inet4Address +private val TEST_IPV6_GATEWAY = parseNumericAddress("2001:db8::1") as Inet6Address +private val TEST_IPV4_LINKADDR = LinkAddress("192.168.222.123/24") +private val TEST_IPV6_LINKADDR = LinkAddress("2001:db8::123/64") +private val TEST_IFACE = "fake0" +private val TEST_LINK_PROPERTIES = LinkProperties().apply { + interfaceName = TEST_IFACE + addLinkAddress(TEST_IPV4_LINKADDR) + addLinkAddress(TEST_IPV6_LINKADDR) + + // Add default routes + addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY)) + addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_GATEWAY)) +} + +private val TEST_CAPABILITIES = NetworkCapabilities().apply { + addTransportType(TRANSPORT_WIFI) + setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false) + setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) + setSSID(TEST_SSID) +} + +@SmallTest +@RunWith(DevSdkIgnoreRunner::class) +@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) +class NetworkStateSnapshotTest { + + @Test + fun testParcelUnparcel() { + val emptySnapshot = NetworkStateSnapshot(Network(TEST_NETID), NetworkCapabilities(), + LinkProperties(), null, TYPE_NONE) + val snapshot = NetworkStateSnapshot( + Network(TEST_NETID), TEST_CAPABILITIES, TEST_LINK_PROPERTIES, TEST_IMSI, TYPE_WIFI) + assertParcelSane(emptySnapshot, 5) + assertParcelSane(snapshot, 5) + } +} diff --git a/tests/net/common/java/android/net/UidRangeTest.java b/tests/net/common/java/android/net/UidRangeTest.java new file mode 100644 index 000000000000..1b1c95431d6f --- /dev/null +++ b/tests/net/common/java/android/net/UidRangeTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.os.UserHandle.MIN_SECONDARY_USER_ID; +import static android.os.UserHandle.SYSTEM; +import static android.os.UserHandle.USER_SYSTEM; +import static android.os.UserHandle.getUid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import android.os.Build; +import android.os.UserHandle; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class UidRangeTest { + + /* + * UidRange is no longer passed to netd. UID ranges between the framework and netd are passed as + * UidRangeParcel objects. + */ + + @Rule + public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); + + @Test + public void testSingleItemUidRangeAllowed() { + new UidRange(123, 123); + new UidRange(0, 0); + new UidRange(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + @Test + public void testNegativeUidsDisallowed() { + try { + new UidRange(-2, 100); + fail("Exception not thrown for negative start UID"); + } catch (IllegalArgumentException expected) { + } + + try { + new UidRange(-200, -100); + fail("Exception not thrown for negative stop UID"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testStopLessThanStartDisallowed() { + final int x = 4195000; + try { + new UidRange(x, x - 1); + fail("Exception not thrown for negative-length UID range"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testGetStartAndEndUser() throws Exception { + final UidRange uidRangeOfPrimaryUser = new UidRange( + getUid(USER_SYSTEM, 10000), getUid(USER_SYSTEM, 10100)); + final UidRange uidRangeOfSecondaryUser = new UidRange( + getUid(MIN_SECONDARY_USER_ID, 10000), getUid(MIN_SECONDARY_USER_ID, 10100)); + assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getStartUser()); + assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getEndUser()); + assertEquals(MIN_SECONDARY_USER_ID, uidRangeOfSecondaryUser.getStartUser()); + assertEquals(MIN_SECONDARY_USER_ID, uidRangeOfSecondaryUser.getEndUser()); + + final UidRange uidRangeForDifferentUsers = new UidRange( + getUid(USER_SYSTEM, 10000), getUid(MIN_SECONDARY_USER_ID, 10100)); + assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getStartUser()); + assertEquals(MIN_SECONDARY_USER_ID, uidRangeOfSecondaryUser.getEndUser()); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testCreateForUser() throws Exception { + final UidRange uidRangeOfPrimaryUser = UidRange.createForUser(SYSTEM); + final UidRange uidRangeOfSecondaryUser = UidRange.createForUser( + UserHandle.of(USER_SYSTEM + 1)); + assertTrue(uidRangeOfPrimaryUser.stop < uidRangeOfSecondaryUser.start); + assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getStartUser()); + assertEquals(USER_SYSTEM, uidRangeOfPrimaryUser.getEndUser()); + assertEquals(USER_SYSTEM + 1, uidRangeOfSecondaryUser.getStartUser()); + assertEquals(USER_SYSTEM + 1, uidRangeOfSecondaryUser.getEndUser()); + } +} diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp index 4d1e3371e0a7..56f9df78c83e 100644 --- a/tests/net/integration/Android.bp +++ b/tests/net/integration/Android.bp @@ -35,7 +35,7 @@ android_test { "android.test.mock", ], static_libs: [ - "TestNetworkStackLib", + "NetworkStackApiStableLib", "androidx.test.ext.junit", "frameworks-net-integration-testutils", "kotlin-reflect", diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index 083c8c8741da..2a2dc5628ecd 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt @@ -16,6 +16,7 @@ package com.android.server.net.integrationtests +import android.app.usage.NetworkStatsManager import android.content.ComponentName import android.content.Context import android.content.Context.BIND_AUTO_CREATE @@ -25,7 +26,6 @@ import android.content.ServiceConnection import android.net.ConnectivityManager import android.net.IDnsResolver import android.net.INetd -import android.net.INetworkStatsService import android.net.LinkProperties import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET @@ -37,7 +37,7 @@ import android.net.Uri import android.net.metrics.IpConnectivityLog import android.os.ConditionVariable import android.os.IBinder -import android.os.INetworkManagementService +import android.os.SystemConfigManager import android.os.UserHandle import android.testing.TestableContext import android.util.Log @@ -57,6 +57,7 @@ import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith import org.mockito.AdditionalAnswers +import org.mockito.ArgumentMatchers.anyString import org.mockito.Mock import org.mockito.Mockito.any import org.mockito.Mockito.anyInt @@ -85,15 +86,15 @@ class ConnectivityServiceIntegrationTest { // lateinit used here for mocks as they need to be reinitialized between each test and the test // should crash if they are used before being initialized. @Mock - private lateinit var netManager: INetworkManagementService - @Mock - private lateinit var statsService: INetworkStatsService + private lateinit var statsManager: NetworkStatsManager @Mock private lateinit var log: IpConnectivityLog @Mock private lateinit var netd: INetd @Mock private lateinit var dnsResolver: IDnsResolver + @Mock + private lateinit var systemConfigManager: SystemConfigManager @Spy private var context = TestableContext(realContext) @@ -151,6 +152,11 @@ class ConnectivityServiceIntegrationTest { doReturn(UserHandle.ALL).`when`(asUserCtx).user doReturn(asUserCtx).`when`(context).createContextAsUser(eq(UserHandle.ALL), anyInt()) doNothing().`when`(context).sendStickyBroadcast(any(), any()) + doReturn(Context.SYSTEM_CONFIG_SERVICE).`when`(context) + .getSystemServiceName(SystemConfigManager::class.java) + doReturn(systemConfigManager).`when`(context) + .getSystemService(Context.SYSTEM_CONFIG_SERVICE) + doReturn(IntArray(0)).`when`(systemConfigManager).getSystemPermissionUids(anyString()) networkStackClient = TestNetworkStackClient(realContext) networkStackClient.init() @@ -163,12 +169,13 @@ class ConnectivityServiceIntegrationTest { service = TestConnectivityService(makeDependencies()) cm = ConnectivityManager(context, service) context.addMockSystemService(Context.CONNECTIVITY_SERVICE, cm) + context.addMockSystemService(Context.NETWORK_STATS_SERVICE, statsManager) service.systemReadyInternal() } private inner class TestConnectivityService(deps: Dependencies) : ConnectivityService( - context, netManager, statsService, dnsResolver, log, netd, deps) + context, dnsResolver, log, netd, deps) private fun makeDependencies(): ConnectivityService.Dependencies { val deps = spy(ConnectivityService.Dependencies()) diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index dc9e587332cb..e1da3d0ae2b3 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -17,6 +17,7 @@ package com.android.server; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; @@ -84,6 +85,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { final String typeName = ConnectivityManager.getNetworkTypeName(type); mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities(); mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); mNetworkCapabilities.addTransportType(transport); switch (transport) { case TRANSPORT_ETHERNET: diff --git a/tests/net/java/android/net/IpSecAlgorithmTest.java b/tests/net/java/android/net/IpSecAlgorithmTest.java index 2e1c29a2e405..3a8d6004f66f 100644 --- a/tests/net/java/android/net/IpSecAlgorithmTest.java +++ b/tests/net/java/android/net/IpSecAlgorithmTest.java @@ -129,6 +129,7 @@ public class IpSecAlgorithmTest { checkCryptKeyLenValidation(IpSecAlgorithm.CRYPT_AES_CTR, len); } checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_AES_XCBC, 128, 96); + checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_AES_CMAC, 128, 96); checkAuthKeyAndTruncLenValidation(IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305, 288, 128); } diff --git a/tests/net/java/android/net/NetworkIdentityTest.kt b/tests/net/java/android/net/NetworkIdentityTest.kt new file mode 100644 index 000000000000..eb2b85c14578 --- /dev/null +++ b/tests/net/java/android/net/NetworkIdentityTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net + +import android.net.NetworkIdentity.OEM_NONE +import android.net.NetworkIdentity.OEM_PAID +import android.net.NetworkIdentity.OEM_PRIVATE +import android.net.NetworkIdentity.getOemBitfield +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import kotlin.test.assertEquals + +@RunWith(JUnit4::class) +class NetworkIdentityTest { + @Test + fun testGetOemBitfield() { + val oemNone = NetworkCapabilities().apply { + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, false) + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, false) + } + val oemPaid = NetworkCapabilities().apply { + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, true) + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, false) + } + val oemPrivate = NetworkCapabilities().apply { + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, false) + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, true) + } + val oemAll = NetworkCapabilities().apply { + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, true) + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, true) + } + + assertEquals(getOemBitfield(oemNone), OEM_NONE) + assertEquals(getOemBitfield(oemPaid), OEM_PAID) + assertEquals(getOemBitfield(oemPrivate), OEM_PRIVATE) + assertEquals(getOemBitfield(oemAll), OEM_PAID or OEM_PRIVATE) + } +} diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt index 1f8f6f311069..64b774cc4340 100644 --- a/tests/net/java/android/net/NetworkTemplateTest.kt +++ b/tests/net/java/android/net/NetworkTemplateTest.kt @@ -20,14 +20,22 @@ import android.content.Context import android.net.ConnectivityManager.TYPE_MOBILE import android.net.ConnectivityManager.TYPE_WIFI import android.net.NetworkIdentity.SUBTYPE_COMBINED +import android.net.NetworkIdentity.OEM_NONE +import android.net.NetworkIdentity.OEM_PAID +import android.net.NetworkIdentity.OEM_PRIVATE import android.net.NetworkIdentity.buildNetworkIdentity import android.net.NetworkStats.DEFAULT_NETWORK_ALL import android.net.NetworkStats.METERED_ALL import android.net.NetworkStats.ROAMING_ALL import android.net.NetworkTemplate.MATCH_MOBILE +import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD import android.net.NetworkTemplate.MATCH_WIFI +import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA import android.net.NetworkTemplate.NETWORK_TYPE_ALL +import android.net.NetworkTemplate.OEM_MANAGED_ALL +import android.net.NetworkTemplate.OEM_MANAGED_NO +import android.net.NetworkTemplate.OEM_MANAGED_YES import android.net.NetworkTemplate.buildTemplateMobileWithRatType import android.telephony.TelephonyManager import com.android.testutils.assertParcelSane @@ -37,6 +45,7 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations +import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertNotEquals import kotlin.test.assertTrue @@ -49,23 +58,28 @@ private const val TEST_SSID1 = "ssid1" class NetworkTemplateTest { private val mockContext = mock(Context::class.java) - private fun buildMobileNetworkState(subscriberId: String): NetworkState = + private fun buildMobileNetworkState(subscriberId: String): NetworkStateSnapshot = buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId) - private fun buildWifiNetworkState(ssid: String): NetworkState = + private fun buildWifiNetworkState(ssid: String): NetworkStateSnapshot = buildNetworkState(TYPE_WIFI, ssid = ssid) private fun buildNetworkState( type: Int, subscriberId: String? = null, - ssid: String? = null - ): NetworkState { + ssid: String? = null, + oemManaged: Int = OEM_NONE + ): NetworkStateSnapshot { val lp = LinkProperties() val caps = NetworkCapabilities().apply { setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false) setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) setSSID(ssid) + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID, + (oemManaged and OEM_PAID) == OEM_PAID) + setCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, + (oemManaged and OEM_PRIVATE) == OEM_PRIVATE) } - return NetworkState(type, lp, caps, mock(Network::class.java), subscriberId, ssid) + return NetworkStateSnapshot(mock(Network::class.java), caps, lp, subscriberId, type) } private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) = @@ -136,11 +150,15 @@ class NetworkTemplateTest { @Test fun testParcelUnparcel() { val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE) + ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE, + OEM_MANAGED_ALL) val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL, - ROAMING_ALL, DEFAULT_NETWORK_ALL, 0) - assertParcelSane(templateMobile, 8) - assertParcelSane(templateWifi, 8) + ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_ALL) + val templateOem = NetworkTemplate(MATCH_MOBILE, null, null, null, METERED_ALL, + ROAMING_ALL, DEFAULT_NETWORK_ALL, 0, OEM_MANAGED_YES) + assertParcelSane(templateMobile, 9) + assertParcelSane(templateWifi, 9) + assertParcelSane(templateOem, 9) } // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with @@ -152,4 +170,86 @@ class NetworkTemplateTest { assertNotEquals(NETWORK_TYPE_5G_NSA, ratType) } } + + @Test + fun testOemNetworkConstants() { + val constantValues = arrayOf(OEM_MANAGED_YES, OEM_MANAGED_ALL, OEM_MANAGED_NO, + OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE) + + // Verify that "not OEM managed network" constants are equal. + assertEquals(OEM_MANAGED_NO, OEM_NONE) + + // Verify the constants don't conflict. + assertEquals(constantValues.size, constantValues.distinct().count()) + } + + /** + * Helper to enumerate and assert OEM managed wifi and mobile {@code NetworkTemplate}s match + * their the appropriate OEM managed {@code NetworkIdentity}s. + * + * @param networkType {@code TYPE_MOBILE} or {@code TYPE_WIFI} + * @param matchType A match rule from {@code NetworkTemplate.MATCH_*} corresponding to the + * networkType. + * @param subscriberId To be populated with {@code TEST_IMSI*} only if networkType is + * {@code TYPE_MOBILE}. May be left as null when matchType is + * {@link NetworkTemplate.MATCH_MOBILE_WILDCARD}. + * @param templateSsid Top be populated with {@code TEST_SSID*} only if networkType is + * {@code TYPE_WIFI}. May be left as null when matchType is + * {@link NetworkTemplate.MATCH_WIFI_WILDCARD}. + * @param identSsid If networkType is {@code TYPE_WIFI}, this value must *NOT* be null. Provide + * one of {@code TEST_SSID*}. + */ + private fun matchOemManagedIdent( + networkType: Int, + matchType: Int, + subscriberId: String? = null, + templateSsid: String? = null, + identSsid: String? = null + ) { + val oemManagedStates = arrayOf(OEM_NONE, OEM_PAID, OEM_PRIVATE, OEM_PAID or OEM_PRIVATE) + // A null subscriberId needs a null matchSubscriberIds argument as well. + val matchSubscriberIds = if (subscriberId == null) null else arrayOf(subscriberId) + + val templateOemYes = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, + templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, + OEM_MANAGED_YES) + val templateOemAll = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, + templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, + OEM_MANAGED_ALL) + + for (identityOemManagedState in oemManagedStates) { + val ident = buildNetworkIdentity(mockContext, buildNetworkState(networkType, + subscriberId, identSsid, identityOemManagedState), /*defaultNetwork=*/false, + /*subType=*/0) + + // Create a template with each OEM managed type and match it against the NetworkIdentity + for (templateOemManagedState in oemManagedStates) { + val template = NetworkTemplate(matchType, subscriberId, matchSubscriberIds, + templateSsid, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, + NETWORK_TYPE_ALL, templateOemManagedState) + if (identityOemManagedState == templateOemManagedState) { + template.assertMatches(ident) + } else { + template.assertDoesNotMatch(ident) + } + } + // OEM_MANAGED_ALL ignores OEM state. + templateOemAll.assertMatches(ident) + if (identityOemManagedState == OEM_NONE) { + // OEM_MANAGED_YES matches everything except OEM_NONE. + templateOemYes.assertDoesNotMatch(ident) + } else { + templateOemYes.assertMatches(ident) + } + } + } + + @Test + fun testOemManagedMatchesIdent() { + matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE, subscriberId = TEST_IMSI1) + matchOemManagedIdent(TYPE_MOBILE, MATCH_MOBILE_WILDCARD) + matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI, templateSsid = TEST_SSID1, + identSsid = TEST_SSID1) + matchOemManagedIdent(TYPE_WIFI, MATCH_WIFI_WILDCARD, identSsid = TEST_SSID1) + } } diff --git a/tests/net/java/android/net/UidRangeTest.java b/tests/net/java/android/net/UidRangeTest.java deleted file mode 100644 index ea1df096e208..000000000000 --- a/tests/net/java/android/net/UidRangeTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static org.junit.Assert.fail; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class UidRangeTest { - - /* - * UidRange is no longer passed to netd. UID ranges between the framework and netd are passed as - * UidRangeParcel objects. - */ - - @Test - public void testSingleItemUidRangeAllowed() { - new UidRange(123, 123); - new UidRange(0, 0); - new UidRange(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - @Test - public void testNegativeUidsDisallowed() { - try { - new UidRange(-2, 100); - fail("Exception not thrown for negative start UID"); - } catch (IllegalArgumentException expected) { - } - - try { - new UidRange(-200, -100); - fail("Exception not thrown for negative stop UID"); - } catch (IllegalArgumentException expected) { - } - } - - @Test - public void testStopLessThanStartDisallowed() { - final int x = 4195000; - try { - new UidRange(x, x - 1); - fail("Exception not thrown for negative-length UID range"); - } catch (IllegalArgumentException expected) { - } - } -}
\ No newline at end of file diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java index 866f38c84333..d04c87b29c25 100644 --- a/tests/net/java/android/net/VpnTransportInfoTest.java +++ b/tests/net/java/android/net/VpnTransportInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt new file mode 100644 index 000000000000..c1315f64c56b --- /dev/null +++ b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.util + +import android.content.Context +import android.content.res.Resources +import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER +import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE +import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY +import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener +import android.provider.Settings +import android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI +import android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE +import android.telephony.SubscriptionInfo +import android.telephony.SubscriptionManager +import android.telephony.TelephonyManager +import android.test.mock.MockContentResolver +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.internal.R +import com.android.internal.util.test.FakeSettingsProvider +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.argThat +import org.mockito.Mockito.any +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +/** + * Tests for [MultinetworkPolicyTracker]. + * + * Build, install and run with: + * atest android.net.util.MultinetworkPolicyTrackerTest + */ +@RunWith(AndroidJUnit4::class) +@SmallTest +class MultinetworkPolicyTrackerTest { + private val resources = mock(Resources::class.java).also { + doReturn(0).`when`(it).getInteger(R.integer.config_networkAvoidBadWifi) + } + private val telephonyManager = mock(TelephonyManager::class.java) + private val subscriptionManager = mock(SubscriptionManager::class.java).also { + doReturn(null).`when`(it).getActiveSubscriptionInfo(anyInt()) + } + private val resolver = MockContentResolver().apply { + addProvider(Settings.AUTHORITY, FakeSettingsProvider()) } + private val context = mock(Context::class.java).also { + doReturn(Context.TELEPHONY_SERVICE).`when`(it) + .getSystemServiceName(TelephonyManager::class.java) + doReturn(telephonyManager).`when`(it).getSystemService(Context.TELEPHONY_SERVICE) + doReturn(subscriptionManager).`when`(it) + .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) + doReturn(resolver).`when`(it).contentResolver + doReturn(resources).`when`(it).resources + doReturn(it).`when`(it).createConfigurationContext(any()) + Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1") + } + private val tracker = MultinetworkPolicyTracker(context, null /* handler */) + + private fun assertMultipathPreference(preference: Int) { + Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, + preference.toString()) + tracker.updateMeteredMultipathPreference() + assertEquals(preference, tracker.meteredMultipathPreference) + } + + @Test + fun testUpdateMeteredMultipathPreference() { + assertMultipathPreference(MULTIPATH_PREFERENCE_HANDOVER) + assertMultipathPreference(MULTIPATH_PREFERENCE_RELIABILITY) + assertMultipathPreference(MULTIPATH_PREFERENCE_PERFORMANCE) + } + + @Test + fun testUpdateAvoidBadWifi() { + Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0") + assertTrue(tracker.updateAvoidBadWifi()) + assertFalse(tracker.avoidBadWifi) + + doReturn(1).`when`(resources).getInteger(R.integer.config_networkAvoidBadWifi) + assertTrue(tracker.updateAvoidBadWifi()) + assertTrue(tracker.avoidBadWifi) + } + + @Test + fun testOnActiveDataSubscriptionIdChanged() { + val testSubId = 1000 + val subscriptionInfo = SubscriptionInfo(testSubId, ""/* iccId */, 1/* iccId */, + "TMO"/* displayName */, "TMO"/* carrierName */, 1/* nameSource */, 1/* iconTint */, + "123"/* number */, 1/* roaming */, null/* icon */, "310"/* mcc */, "210"/* mnc */, + ""/* countryIso */, false/* isEmbedded */, null/* nativeAccessRules */, + "1"/* cardString */) + doReturn(subscriptionInfo).`when`(subscriptionManager).getActiveSubscriptionInfo(testSubId) + + // Modify avoidBadWifi and meteredMultipathPreference settings value and local variables in + // MultinetworkPolicyTracker should be also updated after subId changed. + Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0") + Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE, + MULTIPATH_PREFERENCE_PERFORMANCE.toString()) + + val listenerCaptor = ArgumentCaptor.forClass( + ActiveDataSubscriptionIdListener::class.java) + verify(telephonyManager, times(1)) + .registerTelephonyCallback(any(), listenerCaptor.capture()) + val listener = listenerCaptor.value + listener.onActiveDataSubscriptionIdChanged(testSubId) + + // Check it get resource value with test sub id. + verify(subscriptionManager, times(1)).getActiveSubscriptionInfo(testSubId) + verify(context).createConfigurationContext(argThat { it.mcc == 310 && it.mnc == 210 }) + + // Check if avoidBadWifi and meteredMultipathPreference values have been updated. + assertFalse(tracker.avoidBadWifi) + assertEquals(MULTIPATH_PREFERENCE_PERFORMANCE, tracker.meteredMultipathPreference) + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 182897e37e0a..a643bc8a94c0 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -53,6 +53,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; +import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA; import static android.net.NetworkCapabilities.NET_CAPABILITY_IA; @@ -71,6 +72,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS; import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; @@ -84,7 +86,16 @@ import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; +import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED; import static android.net.RouteInfo.RTN_UNREACHABLE; +import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_ADDED; +import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.PREFIX_OPERATION_REMOVED; +import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; +import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; @@ -93,6 +104,7 @@ import static com.android.testutils.ConcurrentUtils.await; import static com.android.testutils.ConcurrentUtils.durationOf; import static com.android.testutils.ExceptionUtils.ignoreExceptions; import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor; +import static com.android.testutils.MiscAsserts.assertContainsAll; import static com.android.testutils.MiscAsserts.assertContainsExactly; import static com.android.testutils.MiscAsserts.assertEmpty; import static com.android.testutils.MiscAsserts.assertLength; @@ -139,6 +151,7 @@ import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.usage.NetworkStatsManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; @@ -170,7 +183,6 @@ import android.net.INetd; import android.net.INetworkMonitor; import android.net.INetworkMonitorCallbacks; import android.net.INetworkPolicyListener; -import android.net.INetworkStatsService; import android.net.IOnSetOemNetworkPreferenceListener; import android.net.IQosCallback; import android.net.InetAddresses; @@ -193,7 +205,7 @@ import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; -import android.net.NetworkState; +import android.net.NetworkStateSnapshot; import android.net.NetworkTestResultParcelable; import android.net.OemNetworkPreferences; import android.net.ProxyInfo; @@ -212,6 +224,8 @@ import android.net.Uri; import android.net.VpnManager; import android.net.VpnTransportInfo; import android.net.metrics.IpConnectivityLog; +import android.net.resolv.aidl.Nat64PrefixEventParcel; +import android.net.resolv.aidl.PrivateDnsValidationEventParcel; import android.net.shared.NetworkMonitorUtils; import android.net.shared.PrivateDnsConfig; import android.net.util.MultinetworkPolicyTracker; @@ -233,11 +247,11 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.SystemClock; +import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.security.Credentials; -import android.security.KeyStore; import android.system.Os; import android.telephony.TelephonyManager; import android.telephony.data.EpsBearerQosSessionAttributes; @@ -269,6 +283,7 @@ import com.android.server.connectivity.NetworkNotificationManager.NotificationTy import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.QosCallbackTracker; import com.android.server.connectivity.Vpn; +import com.android.server.connectivity.VpnProfileStore; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; import com.android.testutils.ExceptionUtils; @@ -338,6 +353,9 @@ public class ConnectivityServiceTest { private static final String TAG = "ConnectivityServiceTest"; private static final int TIMEOUT_MS = 500; + // Broadcasts can take a long time to be delivered. The test will not wait for that long unless + // there is a failure, so use a long timeout. + private static final int BROADCAST_TIMEOUT_MS = 30_000; private static final int TEST_LINGER_DELAY_MS = 400; private static final int TEST_NASCENT_DELAY_MS = 300; // Chosen to be less than the linger and nascent timeout. This ensures that we can distinguish @@ -355,6 +373,7 @@ public class ConnectivityServiceTest { private static final long TIMESTAMP = 1234L; private static final int NET_ID = 110; + private static final int OEM_PREF_ANY_NET_ID = -1; // Set a non-zero value to verify the flow to set tcp init rwnd value. private static final int TEST_TCP_INIT_RWND = 60; @@ -399,6 +418,8 @@ public class ConnectivityServiceTest { private QosCallbackMockHelper mQosCallbackMockHelper; private QosCallbackTracker mQosCallbackTracker; private VpnManagerService mVpnManagerService; + private TestNetworkCallback mDefaultNetworkCallback; + private TestNetworkCallback mSystemDefaultNetworkCallback; // State variables required to emulate NetworkPolicyManagerService behaviour. private int mUidRules = RULE_NONE; @@ -406,7 +427,7 @@ public class ConnectivityServiceTest { @Mock DeviceIdleInternal mDeviceIdleInternal; @Mock INetworkManagementService mNetworkManagementService; - @Mock INetworkStatsService mStatsService; + @Mock NetworkStatsManager mStatsManager; @Mock IBatteryStats mBatteryStatsService; @Mock IDnsResolver mMockDnsResolver; @Mock INetd mMockNetd; @@ -423,8 +444,8 @@ public class ConnectivityServiceTest { @Mock MockableSystemProperties mSystemProperties; @Mock EthernetManager mEthernetManager; @Mock NetworkPolicyManager mNetworkPolicyManager; - @Mock KeyStore mKeyStore; - @Mock IOnSetOemNetworkPreferenceListener mOnSetOemNetworkPreferenceListener; + @Mock VpnProfileStore mVpnProfileStore; + @Mock SystemConfigManager mSystemConfigManager; private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -521,6 +542,8 @@ public class ConnectivityServiceTest { if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager; if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager; + if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager; + if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager; return super.getSystemService(name); } @@ -994,10 +1017,12 @@ public class ConnectivityServiceTest { // Used to collect the networks requests managed by this factory. This is a duplicate of // the internal information stored in the NetworkFactory (which is private). private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>(); + private final HandlerThread mHandlerSendingRequests; public MockNetworkFactory(Looper looper, Context context, String logTag, - NetworkCapabilities filter) { + NetworkCapabilities filter, HandlerThread threadSendingRequests) { super(looper, context, logTag, filter); + mHandlerSendingRequests = threadSendingRequests; } public int getMyRequestCount() { @@ -1051,7 +1076,8 @@ public class ConnectivityServiceTest { public void terminate() { super.terminate(); // Make sure there are no remaining requests unaccounted for. - assertNull(mRequestHistory.poll(TIMEOUT_MS, r -> true)); + HandlerUtils.waitForIdle(mHandlerSendingRequests, TIMEOUT_MS); + assertNull(mRequestHistory.poll(0, r -> true)); } // Trigger releasing the request as unfulfillable @@ -1060,9 +1086,11 @@ public class ConnectivityServiceTest { } } - private Set<UidRange> uidRangesForUid(int uid) { + private Set<UidRange> uidRangesForUids(int... uids) { final ArraySet<UidRange> ranges = new ArraySet<>(); - ranges.add(new UidRange(uid, uid)); + for (final int uid : uids) { + ranges.add(new UidRange(uid, uid)); + } return ranges; } @@ -1103,7 +1131,7 @@ public class ConnectivityServiceTest { return mDeviceIdleInternal; } }, - mNetworkManagementService, mMockNetd, userId, mKeyStore); + mNetworkManagementService, mMockNetd, userId, mVpnProfileStore); } public void setUids(Set<UidRange> uids) { @@ -1192,13 +1220,13 @@ public class ConnectivityServiceTest { public void establishForMyUid(LinkProperties lp) throws Exception { final int uid = Process.myUid(); - establish(lp, uid, uidRangesForUid(uid), true, true, false); + establish(lp, uid, uidRangesForUids(uid), true, true, false); } public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode) throws Exception { final int uid = Process.myUid(); - establish(makeLinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet, + establish(makeLinkProperties(), uid, uidRangesForUids(uid), validated, hasInternet, isStrictMode); } @@ -1282,8 +1310,9 @@ public class ConnectivityServiceTest { return mVMSHandlerThread; } - public KeyStore getKeyStore() { - return mKeyStore; + @Override + public VpnProfileStore getVpnProfileStore() { + return mVpnProfileStore; } public INetd getNetd() { @@ -1306,7 +1335,7 @@ public class ConnectivityServiceTest { } - private void processBroadcastForVpn(Intent intent) { + private void processBroadcast(Intent intent) { mServiceContext.sendBroadcast(intent); HandlerUtils.waitForIdle(mVMSHandlerThread, TIMEOUT_MS); waitForIdle(); @@ -1397,6 +1426,7 @@ public class ConnectivityServiceTest { private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043); private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "", UserInfo.FLAG_PRIMARY); + private static final UserHandle PRIMARY_USER_HANDLE = new UserHandle(PRIMARY_USER); private static final int RESTRICTED_USER = 1; private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "", @@ -1414,6 +1444,8 @@ public class ConnectivityServiceTest { MockitoAnnotations.initMocks(this); when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO)); + when(mUserManager.getUserHandles(anyBoolean())).thenReturn( + Arrays.asList(PRIMARY_USER_HANDLE)); when(mUserManager.getUserInfo(PRIMARY_USER)).thenReturn(PRIMARY_USER_INFO); // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context // it was started from, i.e., PRIMARY_USER. @@ -1424,6 +1456,7 @@ public class ConnectivityServiceTest { applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) .thenReturn(applicationInfo); + when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not. // http://b/25897652 . @@ -1449,8 +1482,6 @@ public class ConnectivityServiceTest { mDeps = makeDependencies(); returnRealCallingUid(); mService = new ConnectivityService(mServiceContext, - mNetworkManagementService, - mStatsService, mMockDnsResolver, mock(IpConnectivityLog.class), mMockNetd, @@ -1534,6 +1565,7 @@ public class ConnectivityServiceTest { @After public void tearDown() throws Exception { + unregisterDefaultNetworkCallbacks(); setAlwaysOnNetworks(false); if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); @@ -1609,10 +1641,13 @@ public class ConnectivityServiceTest { } switch (transport) { case TRANSPORT_WIFI: - assertEquals(mCm.getActiveNetwork(), mWiFiNetworkAgent.getNetwork()); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); break; case TRANSPORT_CELLULAR: - assertEquals(mCm.getActiveNetwork(), mCellNetworkAgent.getNetwork()); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + break; + case TRANSPORT_ETHERNET: + assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork()); break; default: break; @@ -1621,6 +1656,7 @@ public class ConnectivityServiceTest { assertNotNull(mCm.getNetworkInfo(mCm.getActiveNetwork())); assertEquals(transportToLegacyType(transport), mCm.getNetworkInfo(mCm.getActiveNetwork()).getType()); + assertNotNull(mCm.getActiveNetworkInfoForUid(Process.myUid())); // Test getNetworkCapabilities(Network) assertNotNull(mCm.getNetworkCapabilities(mCm.getActiveNetwork())); assertTrue(mCm.getNetworkCapabilities(mCm.getActiveNetwork()).hasTransport(transport)); @@ -1635,6 +1671,7 @@ public class ConnectivityServiceTest { assertNull(mCm.getActiveNetworkForUid(Process.myUid())); // Test getAllNetworks() assertEmpty(mCm.getAllNetworks()); + assertEmpty(mCm.getAllNetworkStateSnapshot()); } /** @@ -1663,7 +1700,7 @@ public class ConnectivityServiceTest { } public Intent expectBroadcast() throws Exception { - return expectBroadcast(TIMEOUT_MS); + return expectBroadcast(BROADCAST_TIMEOUT_MS); } public void expectNoBroadcast(int timeoutMs) throws Exception { @@ -2158,6 +2195,24 @@ public class ConnectivityServiceTest { } } + static void expectOnLost(TestNetworkAgentWrapper network, TestNetworkCallback ... callbacks) { + for (TestNetworkCallback c : callbacks) { + c.expectCallback(CallbackEntry.LOST, network); + } + } + + static void expectAvailableCallbacksUnvalidatedWithSpecifier(TestNetworkAgentWrapper network, + NetworkSpecifier specifier, TestNetworkCallback ... callbacks) { + for (TestNetworkCallback c : callbacks) { + c.expectCallback(CallbackEntry.AVAILABLE, network); + c.expectCapabilitiesThat(network, (nc) -> + !nc.hasCapability(NET_CAPABILITY_VALIDATED) + && Objects.equals(specifier, nc.getNetworkSpecifier())); + c.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, network); + c.expectCallback(CallbackEntry.BLOCKED_STATUS, network); + } + } + @Test public void testStateChangeNetworkCallbacks() throws Exception { final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); @@ -2753,7 +2808,8 @@ public class ConnectivityServiceTest { if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS || - capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) { + capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP + || capability == NET_CAPABILITY_ENTERPRISE) { assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); } else { assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)); @@ -2761,10 +2817,14 @@ public class ConnectivityServiceTest { NetworkCapabilities filter = new NetworkCapabilities(); filter.addCapability(capability); + // Add NOT_VCN_MANAGED capability into filter unconditionally since some request will add + // NOT_VCN_MANAGED automatically but not for NetworkCapabilities, + // see {@code NetworkCapabilities#deduceNotVcnManagedCapability} for more details. + filter.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); handlerThread.start(); final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); testFactory.setScoreFilter(40); ConditionVariable cv = testFactory.getNetworkStartedCV(); testFactory.register(); @@ -2852,6 +2912,7 @@ public class ConnectivityServiceTest { tryNetworkFactoryRequests(NET_CAPABILITY_IA); tryNetworkFactoryRequests(NET_CAPABILITY_RCS); tryNetworkFactoryRequests(NET_CAPABILITY_XCAP); + tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE); tryNetworkFactoryRequests(NET_CAPABILITY_EIMS); tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED); tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET); @@ -2872,7 +2933,7 @@ public class ConnectivityServiceTest { // does not crash. for (int i = 0; i < 100; i++) { final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); // Register the factory and don't be surprised when the default request arrives. testFactory.register(); testFactory.expectRequestAdd(); @@ -3521,11 +3582,9 @@ public class ConnectivityServiceTest { /** * Verify request matching behavior with network specifiers. * - * Note: this test is somewhat problematic since it involves removing capabilities from - * agents - i.e. agents rejecting requests which they previously accepted. This is flagged - * as a WTF bug in - * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but - * does work. + * This test does not check updating the specifier on a live network because the specifier is + * immutable and this triggers a WTF in + * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)}. */ @Test public void testNetworkSpecifier() throws Exception { @@ -3610,60 +3669,49 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); - cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - cEmpty2.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - cEmpty3.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */, + cEmpty1, cEmpty2, cEmpty3, cEmpty4); assertNoCallbacks(cFoo, cBar); + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); - cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - for (TestNetworkCallback c: emptyCallbacks) { - c.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsFoo)); - } - cFoo.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsFoo)); + mWiFiNetworkAgent.connect(false); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsFoo, + cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); + cBar.assertNoCallback(); assertEquals(nsFoo, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - cFoo.assertNoCallback(); + assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); + + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo); + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.setNetworkSpecifier(nsBar); - cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - for (TestNetworkCallback c: emptyCallbacks) { - c.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsBar)); - } - cBar.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier().equals(nsBar)); + mWiFiNetworkAgent.connect(false); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, nsBar, + cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar); + cFoo.assertNoCallback(); assertEquals(nsBar, mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - cBar.assertNoCallback(); + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cBar); + cFoo.assertNoCallback(); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); - cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - for (TestNetworkCallback c : emptyCallbacks) { - c.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier() == null); - } - cFoo.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier() == null); - cBar.expectCapabilitiesThat(mWiFiNetworkAgent, - (caps) -> caps.getNetworkSpecifier() == null); + mWiFiNetworkAgent.connect(false); + expectAvailableCallbacksUnvalidatedWithSpecifier(mWiFiNetworkAgent, null /* specifier */, + cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); assertNull( mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); - cFoo.assertNoCallback(); - cBar.assertNoCallback(); - - mWiFiNetworkAgent.setNetworkSpecifier(null); - cFoo.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - cBar.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - for (TestNetworkCallback c: emptyCallbacks) { - c.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent); - } - assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); + mWiFiNetworkAgent.disconnect(); + expectOnLost(mWiFiNetworkAgent, cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); } /** @@ -4120,9 +4168,10 @@ public class ConnectivityServiceTest { handlerThread.start(); NetworkCapabilities filter = new NetworkCapabilities() .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .addCapability(NET_CAPABILITY_INTERNET); final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); testFactory.setScoreFilter(40); // Register the factory and expect it to start looking for a network. @@ -4170,6 +4219,7 @@ public class ConnectivityServiceTest { // ... and cell data to be torn down after nascent network timeout. cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent, mService.mNascentDelayMs + TEST_CALLBACK_TIMEOUT_MS); + waitForIdle(); assertLength(1, mCm.getAllNetworks()); } finally { testFactory.terminate(); @@ -4469,7 +4519,7 @@ public class ConnectivityServiceTest { .addTransportType(TRANSPORT_WIFI) .addCapability(NET_CAPABILITY_INTERNET); final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), - mServiceContext, "testFactory", filter); + mServiceContext, "testFactory", filter, mCsHandlerThread); testFactory.setScoreFilter(40); // Register the factory and expect it to receive the default request. @@ -5448,18 +5498,19 @@ public class ConnectivityServiceTest { assertEquals(expectedSet, actualSet); } - private void expectForceUpdateIfaces(Network[] networks, String defaultIface, + private void expectNetworkStatus(Network[] networks, String defaultIface, Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception { - ArgumentCaptor<Network[]> networksCaptor = ArgumentCaptor.forClass(Network[].class); - ArgumentCaptor<UnderlyingNetworkInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass( - UnderlyingNetworkInfo[].class); + ArgumentCaptor<List<Network>> networksCaptor = ArgumentCaptor.forClass(List.class); + ArgumentCaptor<List<UnderlyingNetworkInfo>> vpnInfosCaptor = + ArgumentCaptor.forClass(List.class); - verify(mStatsService, atLeastOnce()).forceUpdateIfaces(networksCaptor.capture(), - any(NetworkState[].class), eq(defaultIface), vpnInfosCaptor.capture()); + verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(), + any(List.class), eq(defaultIface), vpnInfosCaptor.capture()); - assertSameElementsNoDuplicates(networksCaptor.getValue(), networks); + assertSameElementsNoDuplicates(networksCaptor.getValue().toArray(), networks); - UnderlyingNetworkInfo[] infos = vpnInfosCaptor.getValue(); + UnderlyingNetworkInfo[] infos = + vpnInfosCaptor.getValue().toArray(new UnderlyingNetworkInfo[0]); if (vpnUid != null) { assertEquals("Should have exactly one VPN:", 1, infos.length); UnderlyingNetworkInfo info = infos[0]; @@ -5473,8 +5524,9 @@ public class ConnectivityServiceTest { } } - private void expectForceUpdateIfaces(Network[] networks, String defaultIface) throws Exception { - expectForceUpdateIfaces(networks, defaultIface, null, null, new String[0]); + private void expectNetworkStatus( + Network[] networks, String defaultIface) throws Exception { + expectNetworkStatus(networks, defaultIface, null, null, new String[0]); } @Test @@ -5494,47 +5546,46 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(false); mCellNetworkAgent.sendLinkProperties(cellLp); waitForIdle(); - expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME); - reset(mStatsService); + expectNetworkStatus(onlyCell, MOBILE_IFNAME); + reset(mStatsManager); // Default network switch should update ifaces. mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.sendLinkProperties(wifiLp); waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); - expectForceUpdateIfaces(onlyWifi, WIFI_IFNAME); - reset(mStatsService); + expectNetworkStatus(onlyWifi, WIFI_IFNAME); + reset(mStatsManager); // Disconnect should update ifaces. mWiFiNetworkAgent.disconnect(); waitForIdle(); - expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME); - reset(mStatsService); + expectNetworkStatus(onlyCell, MOBILE_IFNAME); + reset(mStatsManager); // Metered change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); - expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME); - reset(mStatsService); + expectNetworkStatus(onlyCell, MOBILE_IFNAME); + reset(mStatsManager); mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); waitForIdle(); - expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME); - reset(mStatsService); + expectNetworkStatus(onlyCell, MOBILE_IFNAME); + reset(mStatsManager); // Temp metered change shouldn't update ifaces - mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); waitForIdle(); - verify(mStatsService, never()) - .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), - eq(new UnderlyingNetworkInfo[0])); - reset(mStatsService); + verify(mStatsManager, never()).notifyNetworkStatus(eq(Arrays.asList(onlyCell)), + any(List.class), eq(MOBILE_IFNAME), any(List.class)); + reset(mStatsManager); // Roaming change should update ifaces mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); waitForIdle(); - expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME); - reset(mStatsService); + expectNetworkStatus(onlyCell, MOBILE_IFNAME); + reset(mStatsManager); // Test VPNs. final LinkProperties lp = new LinkProperties(); @@ -5547,7 +5598,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()}; // A VPN with default (null) underlying networks sets the underlying network's interfaces... - expectForceUpdateIfaces(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{MOBILE_IFNAME}); // ...and updates them as the default network switches. @@ -5564,9 +5615,9 @@ public class ConnectivityServiceTest { waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); - expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{WIFI_IFNAME}); - reset(mStatsService); + reset(mStatsManager); // A VPN that sets its underlying networks passes the underlying interfaces, and influences // the default interface sent to NetworkStatsService by virtue of applying to the system @@ -5576,22 +5627,22 @@ public class ConnectivityServiceTest { // applies to the system server UID should not have any bearing on network stats. mMockVpn.setUnderlyingNetworks(onlyCell); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{MOBILE_IFNAME}); - reset(mStatsService); + reset(mStatsManager); mMockVpn.setUnderlyingNetworks(cellAndWifi); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{MOBILE_IFNAME, WIFI_IFNAME}); - reset(mStatsService); + reset(mStatsManager); // Null underlying networks are ignored. mMockVpn.setUnderlyingNetworks(cellNullAndWifi); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{MOBILE_IFNAME, WIFI_IFNAME}); - reset(mStatsService); + reset(mStatsManager); // If an underlying network disconnects, that interface should no longer be underlying. // This doesn't actually work because disconnectAndDestroyNetwork only notifies @@ -5603,17 +5654,17 @@ public class ConnectivityServiceTest { mCellNetworkAgent.disconnect(); waitForIdle(); assertNull(mService.getLinkProperties(mCellNetworkAgent.getNetwork())); - expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{MOBILE_IFNAME, WIFI_IFNAME}); // Confirm that we never tell NetworkStatsService that cell is no longer the underlying // network for the VPN... - verify(mStatsService, never()).forceUpdateIfaces(any(Network[].class), - any(NetworkState[].class), any() /* anyString() doesn't match null */, - argThat(infos -> infos[0].underlyingIfaces.size() == 1 - && WIFI_IFNAME.equals(infos[0].underlyingIfaces.get(0)))); - verifyNoMoreInteractions(mStatsService); - reset(mStatsService); + verify(mStatsManager, never()).notifyNetworkStatus(any(List.class), + any(List.class), any() /* anyString() doesn't match null */, + argThat(infos -> infos.get(0).underlyingIfaces.size() == 1 + && WIFI_IFNAME.equals(infos.get(0).underlyingIfaces.get(0)))); + verifyNoMoreInteractions(mStatsManager); + reset(mStatsManager); // ... but if something else happens that causes notifyIfacesChangedForNetworkStats to be // called again, it does. For example, connect Ethernet, but with a low score, such that it @@ -5622,13 +5673,13 @@ public class ConnectivityServiceTest { mEthernetNetworkAgent.adjustScore(-40); mEthernetNetworkAgent.connect(false); waitForIdle(); - verify(mStatsService).forceUpdateIfaces(any(Network[].class), - any(NetworkState[].class), any() /* anyString() doesn't match null */, - argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.size() == 1 - && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces.get(0)))); + verify(mStatsManager).notifyNetworkStatus(any(List.class), + any(List.class), any() /* anyString() doesn't match null */, + argThat(vpnInfos -> vpnInfos.get(0).underlyingIfaces.size() == 1 + && WIFI_IFNAME.equals(vpnInfos.get(0).underlyingIfaces.get(0)))); mEthernetNetworkAgent.disconnect(); waitForIdle(); - reset(mStatsService); + reset(mStatsManager); // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo // does not return the VPN, so CS does not pass it to NetworkStatsService. This causes @@ -5638,27 +5689,27 @@ public class ConnectivityServiceTest { // Also, for the same reason as above, the active interface passed in is null. mMockVpn.setUnderlyingNetworks(new Network[0]); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, null); - reset(mStatsService); + expectNetworkStatus(wifiAndVpn, null); + reset(mStatsManager); // Specifying only a null underlying network is the same as no networks. mMockVpn.setUnderlyingNetworks(onlyNull); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, null); - reset(mStatsService); + expectNetworkStatus(wifiAndVpn, null); + reset(mStatsManager); // Specifying networks that are all disconnected is the same as specifying no networks. mMockVpn.setUnderlyingNetworks(onlyCell); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, null); - reset(mStatsService); + expectNetworkStatus(wifiAndVpn, null); + reset(mStatsManager); // Passing in null again means follow the default network again. mMockVpn.setUnderlyingNetworks(null); waitForIdle(); - expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, + expectNetworkStatus(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, new String[]{WIFI_IFNAME}); - reset(mStatsService); + reset(mStatsManager); } @Test @@ -5891,6 +5942,16 @@ public class ConnectivityServiceTest { assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName()); } + private PrivateDnsValidationEventParcel makePrivateDnsValidationEvent( + final int netId, final String ipAddress, final String hostname, final int validation) { + final PrivateDnsValidationEventParcel event = new PrivateDnsValidationEventParcel(); + event.netId = netId; + event.ipAddress = ipAddress; + event.hostname = hostname; + event.validation = validation; + return event; + } + @Test public void testLinkPropertiesWithPrivateDnsValidationEvents() throws Exception { // The default on Android is opportunistic mode ("Automatic"). @@ -5921,8 +5982,9 @@ public class ConnectivityServiceTest { // Send a validation event for a server that is not part of the current // resolver config. The validation event should be ignored. - mService.mNetdEventCallback.onPrivateDnsValidationEvent( - mCellNetworkAgent.getNetwork().netId, "", "145.100.185.18", true); + mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( + makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, "", + "145.100.185.18", VALIDATION_RESULT_SUCCESS)); cellNetworkCallback.assertNoCallback(); // Add a dns server to the LinkProperties. @@ -5939,20 +6001,23 @@ public class ConnectivityServiceTest { // Send a validation event containing a hostname that is not part of // the current resolver config. The validation event should be ignored. - mService.mNetdEventCallback.onPrivateDnsValidationEvent( - mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "hostname", true); + mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( + makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, + "145.100.185.16", "hostname", VALIDATION_RESULT_SUCCESS)); cellNetworkCallback.assertNoCallback(); // Send a validation event where validation failed. - mService.mNetdEventCallback.onPrivateDnsValidationEvent( - mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", false); + mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( + makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, + "145.100.185.16", "", VALIDATION_RESULT_FAILURE)); cellNetworkCallback.assertNoCallback(); // Send a validation event where validation succeeded for a server in // the current resolver config. A LinkProperties callback with updated // private dns fields should be sent. - mService.mNetdEventCallback.onPrivateDnsValidationEvent( - mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true); + mService.mResolverUnsolEventCallback.onPrivateDnsValidationEvent( + makePrivateDnsValidationEvent(mCellNetworkAgent.getNetwork().netId, + "145.100.185.16", "", VALIDATION_RESULT_SUCCESS)); cbi = cellNetworkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); cellNetworkCallback.assertNoCallback(); @@ -6023,6 +6088,7 @@ public class ConnectivityServiceTest { .addTransportType(TRANSPORT_CELLULAR) .addCapability(NET_CAPABILITY_INTERNET) .addCapability(NET_CAPABILITY_NOT_CONGESTED) + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .setLinkDownstreamBandwidthKbps(10); final NetworkCapabilities wifiNc = new NetworkCapabilities() .addTransportType(TRANSPORT_WIFI) @@ -6031,6 +6097,7 @@ public class ConnectivityServiceTest { .addCapability(NET_CAPABILITY_NOT_ROAMING) .addCapability(NET_CAPABILITY_NOT_CONGESTED) .addCapability(NET_CAPABILITY_NOT_SUSPENDED) + .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) .setLinkUpstreamBandwidthKbps(20); mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */); mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */); @@ -6329,7 +6396,7 @@ public class ConnectivityServiceTest { vpnNetworkCallback.assertNoCallback(); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - final Set<UidRange> ranges = uidRangesForUid(uid); + final Set<UidRange> ranges = uidRangesForUids(uid); mMockVpn.registerAgent(ranges); mMockVpn.setUnderlyingNetworks(new Network[0]); @@ -6801,7 +6868,7 @@ public class ConnectivityServiceTest { final int uid = Process.myUid(); NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); assertNotNull("nc=" + nc, nc.getUids()); - assertEquals(nc.getUids(), uidRangesForUid(uid)); + assertEquals(nc.getUids(), uidRangesForUids(uid)); assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE); // Set an underlying network and expect to see the VPN transports change. @@ -6818,17 +6885,18 @@ public class ConnectivityServiceTest { .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID)); final Intent addedIntent = new Intent(ACTION_USER_ADDED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); // Send a USER_ADDED broadcast for it. - processBroadcastForVpn(addedIntent); + processBroadcast(addedIntent); // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added // restricted user. callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 2 && caps.getUids().contains(new UidRange(uid, uid)) - && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER)) + && caps.getUids().contains(createUidRange(RESTRICTED_USER)) && caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_WIFI)); @@ -6838,14 +6906,15 @@ public class ConnectivityServiceTest { callback.expectCapabilitiesThat(mMockVpn, (caps) -> caps.getUids().size() == 2 && caps.getUids().contains(new UidRange(uid, uid)) - && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER)) + && caps.getUids().contains(createUidRange(RESTRICTED_USER)) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - processBroadcastForVpn(removedIntent); + processBroadcast(removedIntent); // Expect that the VPN gains the UID range for the restricted user, and that the capability // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved. @@ -6901,8 +6970,9 @@ public class ConnectivityServiceTest { RESTRICTED_USER_INFO)); // TODO: check that VPN app within restricted profile still has access, etc. final Intent addedIntent = new Intent(ACTION_USER_ADDED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - processBroadcastForVpn(addedIntent); + processBroadcast(addedIntent); assertNull(mCm.getActiveNetworkForUid(uid)); assertNull(mCm.getActiveNetworkForUid(restrictedUid)); @@ -6911,8 +6981,9 @@ public class ConnectivityServiceTest { // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(RESTRICTED_USER)); removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER); - processBroadcastForVpn(removedIntent); + processBroadcast(removedIntent); assertNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); @@ -7067,7 +7138,7 @@ public class ConnectivityServiceTest { assertFalse(mCm.isActiveNetworkMetered()); // Connect VPN network. - mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUid(Process.myUid()), + mMockVpn.registerAgent(true /* isAlwaysMetered */, uidRangesForUids(Process.myUid()), new LinkProperties()); mMockVpn.connect(true); waitForIdle(); @@ -7452,8 +7523,7 @@ public class ConnectivityServiceTest { private void setupLegacyLockdownVpn() { final String profileName = "testVpnProfile"; final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8); - when(mKeyStore.contains(Credentials.LOCKDOWN_VPN)).thenReturn(true); - when(mKeyStore.get(Credentials.LOCKDOWN_VPN)).thenReturn(profileTag); + when(mVpnProfileStore.get(Credentials.LOCKDOWN_VPN)).thenReturn(profileTag); final VpnProfile profile = new VpnProfile(profileName); profile.name = "My VPN"; @@ -7461,7 +7531,7 @@ public class ConnectivityServiceTest { profile.dnsServers = "8.8.8.8"; profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK; final byte[] encodedProfile = profile.encode(); - when(mKeyStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile); + when(mVpnProfileStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile); } private void establishLegacyLockdownVpn(Network underlying) throws Exception { @@ -7469,7 +7539,7 @@ public class ConnectivityServiceTest { assertNotNull(underlying); mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY); // The legacy lockdown VPN only supports userId 0. - final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); + final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER)); mMockVpn.registerAgent(ranges); mMockVpn.setUnderlyingNetworks(new Network[]{underlying}); mMockVpn.connect(true); @@ -7505,8 +7575,9 @@ public class ConnectivityServiceTest { // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker. final int userId = UserHandle.getUserId(Process.myUid()); final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId)); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - processBroadcastForVpn(addedIntent); + processBroadcast(addedIntent); // Lockdown VPN disables teardown and enables lockdown. assertFalse(mMockVpn.getEnableTeardown()); @@ -7718,19 +7789,13 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.removeCapability(testCap); callbackWithCap.expectAvailableCallbacksValidated(mCellNetworkAgent); callbackWithoutCap.expectCapabilitiesWithout(testCap, mWiFiNetworkAgent); - // TODO: Test default network changes for NOT_VCN_MANAGED once the default request has - // it. - if (testCap == NET_CAPABILITY_TRUSTED) { - verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); - reset(mMockNetd); - } + verify(mMockNetd).networkSetDefault(eq(mCellNetworkAgent.getNetwork().netId)); + reset(mMockNetd); mCellNetworkAgent.removeCapability(testCap); callbackWithCap.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); callbackWithoutCap.assertNoCallback(); - if (testCap == NET_CAPABILITY_TRUSTED) { - verify(mMockNetd).networkClearDefault(); - } + verify(mMockNetd).networkClearDefault(); mCm.unregisterNetworkCallback(callbackWithCap); mCm.unregisterNetworkCallback(callbackWithoutCap); @@ -7744,7 +7809,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); mCellNetworkAgent.connect(true); waitForIdle(); - verify(mBatteryStatsService).noteNetworkInterfaceForTransports(cellLp.getInterfaceName(), + verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, + cellLp.getInterfaceName(), new int[] { TRANSPORT_CELLULAR }); reset(mBatteryStatsService); @@ -7753,7 +7819,8 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp); mWiFiNetworkAgent.connect(true); waitForIdle(); - verify(mBatteryStatsService).noteNetworkInterfaceForTransports(wifiLp.getInterfaceName(), + verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, + wifiLp.getInterfaceName(), new int[] { TRANSPORT_WIFI }); reset(mBatteryStatsService); @@ -7764,7 +7831,8 @@ public class ConnectivityServiceTest { mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); mCellNetworkAgent.connect(true); waitForIdle(); - verify(mBatteryStatsService).noteNetworkInterfaceForTransports(cellLp.getInterfaceName(), + verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, + cellLp.getInterfaceName(), new int[] { TRANSPORT_CELLULAR }); mCellNetworkAgent.disconnect(); } @@ -7795,6 +7863,16 @@ public class ConnectivityServiceTest { return stacked; } + private Nat64PrefixEventParcel makeNat64PrefixEvent(final int netId, final int prefixOperation, + final String prefixAddress, final int prefixLength) { + final Nat64PrefixEventParcel event = new Nat64PrefixEventParcel(); + event.netId = netId; + event.prefixOperation = prefixOperation; + event.prefixAddress = prefixAddress; + event.prefixLength = prefixLength; + return event; + } + @Test public void testStackedLinkProperties() throws Exception { final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24"); @@ -7825,7 +7903,6 @@ public class ConnectivityServiceTest { cellLp.addRoute(defaultRoute); cellLp.addRoute(ipv6Subnet); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); - reset(mNetworkManagementService); reset(mMockDnsResolver); reset(mMockNetd); reset(mBatteryStatsService); @@ -7839,7 +7916,8 @@ public class ConnectivityServiceTest { assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute); verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME); - verify(mBatteryStatsService).noteNetworkInterfaceForTransports(cellLp.getInterfaceName(), + verify(mDeps).reportNetworkInterfaceForTransports(mServiceContext, + cellLp.getInterfaceName(), new int[] { TRANSPORT_CELLULAR }); networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); @@ -7860,12 +7938,11 @@ public class ConnectivityServiceTest { // Make sure BatteryStats was not told about any v4- interfaces, as none should have // come online yet. waitForIdle(); - verify(mBatteryStatsService, never()).noteNetworkInterfaceForTransports(startsWith("v4-"), - any()); + verify(mDeps, never()) + .reportNetworkInterfaceForTransports(eq(mServiceContext), startsWith("v4-"), any()); verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mMockDnsResolver); - reset(mNetworkManagementService); reset(mMockNetd); reset(mMockDnsResolver); when(mMockNetd.interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME)) @@ -7881,8 +7958,8 @@ public class ConnectivityServiceTest { // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started. Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent); assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix()); - mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, - kNat64PrefixString, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent( + makeNat64PrefixEvent(cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96)); LinkProperties lpBeforeClat = networkCallback.expectCallback( CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp(); assertEquals(0, lpBeforeClat.getStackedLinks().size()); @@ -7914,16 +7991,17 @@ public class ConnectivityServiceTest { assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8")); for (final LinkProperties stackedLp : stackedLpsAfterChange) { - verify(mBatteryStatsService).noteNetworkInterfaceForTransports( - stackedLp.getInterfaceName(), new int[] { TRANSPORT_CELLULAR }); + verify(mDeps).reportNetworkInterfaceForTransports( + mServiceContext, stackedLp.getInterfaceName(), + new int[] { TRANSPORT_CELLULAR }); } reset(mMockNetd); when(mMockNetd.interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME)) .thenReturn(getClatInterfaceConfigParcel(myIpv4)); // Change the NAT64 prefix without first removing it. // Expect clatd to be stopped and started with the new prefix. - mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, - kOtherNat64PrefixString, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( + cellNetId, PREFIX_OPERATION_ADDED, kOtherNat64PrefixString, 96)); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 0); verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); @@ -7965,15 +8043,14 @@ public class ConnectivityServiceTest { verify(mMockNetd, times(1)).networkRemoveInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mMockDnsResolver); - reset(mNetworkManagementService); reset(mMockNetd); reset(mMockDnsResolver); when(mMockNetd.interfaceGetCfg(CLAT_PREFIX + MOBILE_IFNAME)) .thenReturn(getClatInterfaceConfigParcel(myIpv4)); // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. - mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, - kOtherNat64PrefixString, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( + cellNetId, PREFIX_OPERATION_REMOVED, kOtherNat64PrefixString, 96)); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getNat64Prefix() == null); @@ -7985,8 +8062,8 @@ public class ConnectivityServiceTest { networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added. verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); - mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, - kNat64PrefixString, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( + cellNetId, PREFIX_OPERATION_ADDED, kNat64PrefixString, 96)); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString()); @@ -7998,8 +8075,8 @@ public class ConnectivityServiceTest { verify(mMockNetd, times(1)).networkAddInterface(cellNetId, CLAT_PREFIX + MOBILE_IFNAME); // NAT64 prefix is removed. Expect that clat is stopped. - mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, - kNat64PrefixString, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent(makeNat64PrefixEvent( + cellNetId, PREFIX_OPERATION_REMOVED, kNat64PrefixString, 96)); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null); assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault); @@ -8087,8 +8164,8 @@ public class ConnectivityServiceTest { inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); - mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, - pref64FromDnsStr, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent( + makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96)); expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); @@ -8121,8 +8198,8 @@ public class ConnectivityServiceTest { inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); // Stopping prefix discovery results in a prefix removed notification. - mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */, - pref64FromDnsStr, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent( + makeNat64PrefixEvent(netId, PREFIX_OPERATION_REMOVED, pref64FromDnsStr, 96)); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); @@ -8160,8 +8237,8 @@ public class ConnectivityServiceTest { inOrder.verify(mMockNetd).clatdStop(iface); inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); - mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, - pref64FromDnsStr, 96); + mService.mResolverUnsolEventCallback.onNat64PrefixEvent( + makeNat64PrefixEvent(netId, PREFIX_OPERATION_ADDED, pref64FromDnsStr, 96)); expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any()); @@ -8202,11 +8279,10 @@ public class ConnectivityServiceTest { final LinkProperties cellLp = new LinkProperties(); cellLp.setInterfaceName(MOBILE_IFNAME); mCellNetworkAgent.sendLinkProperties(cellLp); - reset(mNetworkManagementService); mCellNetworkAgent.connect(true); networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), - eq(NetworkCapabilities.TRANSPORT_CELLULAR)); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); final LinkProperties wifiLp = new LinkProperties(); @@ -8214,25 +8290,27 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.sendLinkProperties(wifiLp); // Network switch - reset(mNetworkManagementService); mWiFiNetworkAgent.connect(true); networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(), - eq(NetworkCapabilities.TRANSPORT_WIFI)); - verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME)); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); // Disconnect wifi and switch back to cell - reset(mNetworkManagementService); + reset(mMockNetd); mWiFiNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); assertNoCallbacks(networkCallback); - verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); - verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(), - eq(NetworkCapabilities.TRANSPORT_CELLULAR)); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); // reconnect wifi + reset(mMockNetd); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); wifiLp.setInterfaceName(WIFI_IFNAME); mWiFiNetworkAgent.sendLinkProperties(wifiLp); @@ -8240,9 +8318,12 @@ public class ConnectivityServiceTest { networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + verify(mMockNetd, times(1)).idletimerAddInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); // Disconnect cell - reset(mNetworkManagementService); reset(mMockNetd); mCellNetworkAgent.disconnect(); networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); @@ -8250,17 +8331,18 @@ public class ConnectivityServiceTest { // sent as network being switched. Ensure rule removal for cell will not be triggered // unexpectedly before network being removed. waitForIdle(); - verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME)); + verify(mMockNetd, times(0)).idletimerRemoveInterface(eq(MOBILE_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_CELLULAR))); verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId)); verify(mMockDnsResolver, times(1)) .destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId)); // Disconnect wifi ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED); - reset(mNetworkManagementService); mWiFiNetworkAgent.disconnect(); b.expectBroadcast(); - verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME)); + verify(mMockNetd, times(1)).idletimerRemoveInterface(eq(WIFI_IFNAME), anyInt(), + eq(Integer.toString(TRANSPORT_WIFI))); // Clean up mCm.unregisterNetworkCallback(networkCallback); @@ -8381,7 +8463,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); mMockVpn.establish(lp, VPN_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); @@ -8409,7 +8491,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); @@ -8425,7 +8507,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0")); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID); @@ -8440,7 +8522,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); mMockVpn.establish(lp, VPN_UID, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, VPN_UID); @@ -8492,7 +8574,7 @@ public class ConnectivityServiceTest { lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); // The uid range needs to cover the test app so the network is visible to it. - final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER); + final UidRange vpnRange = createUidRange(PRIMARY_USER); final Set<UidRange> vpnRanges = Collections.singleton(vpnRange); mMockVpn.establish(lp, VPN_UID, vpnRanges); assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); @@ -8691,7 +8773,7 @@ public class ConnectivityServiceTest { private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) throws Exception { - final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER)); + final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER)); mMockVpn.setVpnType(vpnType); mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange); assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid); @@ -8890,8 +8972,8 @@ public class ConnectivityServiceTest { ConnectivityManager.getNetworkTypeName(TYPE_MOBILE), TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE)); return new NetworkAgentInfo(null, new Network(NET_ID), info, new LinkProperties(), - nc, 0, mServiceContext, null, new NetworkAgentConfig(), mService, null, null, null, - 0, INVALID_UID, mQosCallbackTracker); + nc, 0, mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0, + INVALID_UID, mQosCallbackTracker); } @Test @@ -9219,7 +9301,7 @@ public class ConnectivityServiceTest { private void assertUidRangesUpdatedForMyUid(boolean add) throws Exception { final int uid = Process.myUid(); - assertVpnUidRangesUpdated(add, uidRangesForUid(uid), uid); + assertVpnUidRangesUpdated(add, uidRangesForUids(uid), uid); } private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid) @@ -9250,7 +9332,7 @@ public class ConnectivityServiceTest { lp.setInterfaceName("tun0"); lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); - final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER); + final UidRange vpnRange = createUidRange(PRIMARY_USER); Set<UidRange> vpnRanges = Collections.singleton(vpnRange); mMockVpn.establish(lp, VPN_UID, vpnRanges); assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID); @@ -9430,8 +9512,12 @@ public class ConnectivityServiceTest { fail("TOO_MANY_REQUESTS never thrown"); } + private UidRange createUidRange(int userId) { + return UidRange.createForUser(UserHandle.of(userId)); + } + private void mockGetApplicationInfo(@NonNull final String packageName, @NonNull final int uid) - throws PackageManager.NameNotFoundException { + throws Exception { final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.uid = uid; when(mPackageManager.getApplicationInfo(eq(packageName), anyInt())) @@ -9451,7 +9537,7 @@ public class ConnectivityServiceTest { private OemNetworkPreferences createDefaultOemNetworkPreferences( @OemNetworkPreferences.OemNetworkPreference final int preference) - throws PackageManager.NameNotFoundException { + throws Exception { // Arrange PackageManager mocks mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); @@ -9465,7 +9551,7 @@ public class ConnectivityServiceTest { public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() throws PackageManager.NameNotFoundException { @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED; + OEM_NETWORK_PREFERENCE_UNINITIALIZED; // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() assertThrows(IllegalArgumentException.class, @@ -9476,13 +9562,13 @@ public class ConnectivityServiceTest { @Test public void testOemNetworkRequestFactoryPreferenceOemPaid() - throws PackageManager.NameNotFoundException { + throws Exception { // Expectations final int expectedNumOfNris = 1; final int expectedNumOfRequests = 3; @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; + OEM_NETWORK_PREFERENCE_OEM_PAID; // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() final ArraySet<ConnectivityService.NetworkRequestInfo> nris = @@ -9505,13 +9591,13 @@ public class ConnectivityServiceTest { @Test public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback() - throws PackageManager.NameNotFoundException { + throws Exception { // Expectations final int expectedNumOfNris = 1; final int expectedNumOfRequests = 2; @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() final ArraySet<ConnectivityService.NetworkRequestInfo> nris = @@ -9531,13 +9617,13 @@ public class ConnectivityServiceTest { @Test public void testOemNetworkRequestFactoryPreferenceOemPaidOnly() - throws PackageManager.NameNotFoundException { + throws Exception { // Expectations final int expectedNumOfNris = 1; final int expectedNumOfRequests = 1; @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() final ArraySet<ConnectivityService.NetworkRequestInfo> nris = @@ -9554,13 +9640,13 @@ public class ConnectivityServiceTest { @Test public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly() - throws PackageManager.NameNotFoundException { + throws Exception { // Expectations final int expectedNumOfNris = 1; final int expectedNumOfRequests = 1; @OemNetworkPreferences.OemNetworkPreference final int prefToTest = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() final ArraySet<ConnectivityService.NetworkRequestInfo> nris = @@ -9578,7 +9664,7 @@ public class ConnectivityServiceTest { @Test public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris() - throws PackageManager.NameNotFoundException { + throws Exception { // Expectations final int expectedNumOfNris = 2; @@ -9588,8 +9674,8 @@ public class ConnectivityServiceTest { mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID); // Build OemNetworkPreferences object - final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; - final int testOemPref2 = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) .addNetworkPreference(testPackageName2, testOemPref2) @@ -9604,8 +9690,8 @@ public class ConnectivityServiceTest { } @Test - public void testOemNetworkRequestFactoryCorrectlySetsUids() - throws PackageManager.NameNotFoundException { + public void testOemNetworkRequestFactoryMultiplePrefsCorrectlySetsUids() + throws Exception { // Arrange PackageManager mocks final String testPackageName2 = "com.google.apps.dialer"; final int testPackageNameUid2 = 456; @@ -9613,8 +9699,8 @@ public class ConnectivityServiceTest { mockGetApplicationInfo(testPackageName2, testPackageNameUid2); // Build OemNetworkPreferences object - final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; - final int testOemPref2 = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testOemPref2 = OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) .addNetworkPreference(testPackageName2, testOemPref2) @@ -9635,8 +9721,48 @@ public class ConnectivityServiceTest { } @Test + public void testOemNetworkRequestFactoryMultipleUsersCorrectlySetsUids() + throws Exception { + // Arrange users + final int secondUser = 10; + final UserHandle secondUserHandle = new UserHandle(secondUser); + when(mUserManager.getUserHandles(anyBoolean())).thenReturn( + Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle)); + + // Arrange PackageManager mocks + mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID); + + // Build OemNetworkPreferences object + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; + final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() + .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) + .build(); + + // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences() + final List<ConnectivityService.NetworkRequestInfo> nris = + new ArrayList<>( + mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences( + pref)); + + // UIDs for all users and all managed packages should be present. + // Two users each with two packages. + final int expectedUidSize = 2; + final List<UidRange> uids = + new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids()); + assertEquals(expectedUidSize, uids.size()); + + // Sort by uid to access nris by index + uids.sort(Comparator.comparingInt(uid -> uid.start)); + final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); + assertEquals(TEST_PACKAGE_UID, uids.get(0).start); + assertEquals(TEST_PACKAGE_UID, uids.get(0).stop); + assertEquals(secondUserTestPackageUid, uids.get(1).start); + assertEquals(secondUserTestPackageUid, uids.get(1).stop); + } + + @Test public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference() - throws PackageManager.NameNotFoundException { + throws Exception { // Expectations final int expectedNumOfNris = 1; final int expectedNumOfAppUids = 2; @@ -9648,7 +9774,7 @@ public class ConnectivityServiceTest { mockGetApplicationInfo(testPackageName2, testPackageNameUid2); // Build OemNetworkPreferences object - final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testOemPref = OEM_NETWORK_PREFERENCE_OEM_PAID; final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref) .addNetworkPreference(testPackageName2, testOemPref) @@ -9666,8 +9792,6 @@ public class ConnectivityServiceTest { @Test public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() { mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); - @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; // Act on ConnectivityService.setOemNetworkPreference() assertThrows(NullPointerException.class, @@ -9678,15 +9802,1132 @@ public class ConnectivityServiceTest { @Test public void testSetOemNetworkPreferenceFailsForNonAutomotive() - throws PackageManager.NameNotFoundException, RemoteException { + throws Exception { mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false); @OemNetworkPreferences.OemNetworkPreference final int networkPref = - OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; // Act on ConnectivityService.setOemNetworkPreference() assertThrows(UnsupportedOperationException.class, () -> mService.setOemNetworkPreference( createDefaultOemNetworkPreferences(networkPref), - mOnSetOemNetworkPreferenceListener)); + new TestOemListenerCallback())); + } + + private void setOemNetworkPreferenceAgentConnected(final int transportType, + final boolean connectAgent) throws Exception { + switch(transportType) { + // Corresponds to a metered cellular network. Will be used for the default network. + case TRANSPORT_CELLULAR: + if (!connectAgent) { + mCellNetworkAgent.disconnect(); + break; + } + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_METERED); + mCellNetworkAgent.connect(true); + break; + // Corresponds to a restricted ethernet network with OEM_PAID/OEM_PRIVATE. + case TRANSPORT_ETHERNET: + if (!connectAgent) { + stopOemManagedNetwork(); + break; + } + startOemManagedNetwork(true); + break; + // Corresponds to unmetered Wi-Fi. + case TRANSPORT_WIFI: + if (!connectAgent) { + mWiFiNetworkAgent.disconnect(); + break; + } + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mWiFiNetworkAgent.connect(true); + break; + default: + throw new AssertionError("Unsupported transport type passed in."); + + } + waitForIdle(); + } + + private void startOemManagedNetwork(final boolean isOemPaid) throws Exception { + mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); + mEthernetNetworkAgent.addCapability( + isOemPaid ? NET_CAPABILITY_OEM_PAID : NET_CAPABILITY_OEM_PRIVATE); + mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + mEthernetNetworkAgent.connect(true); + } + + private void stopOemManagedNetwork() { + mEthernetNetworkAgent.disconnect(); + waitForIdle(); + } + + private void verifyMultipleDefaultNetworksTracksCorrectly( + final int expectedOemRequestsSize, + @NonNull final Network expectedDefaultNetwork, + @NonNull final Network expectedPerAppNetwork) { + // The current test setup assumes two tracked default network requests; one for the default + // network and the other for the OEM network preference being tested. This will be validated + // each time to confirm it doesn't change under test. + final int expectedDefaultNetworkRequestsSize = 2; + assertEquals(expectedDefaultNetworkRequestsSize, mService.mDefaultNetworkRequests.size()); + for (final ConnectivityService.NetworkRequestInfo defaultRequest + : mService.mDefaultNetworkRequests) { + final Network defaultNetwork = defaultRequest.getSatisfier() == null + ? null : defaultRequest.getSatisfier().network(); + // If this is the default request. + if (defaultRequest == mService.mDefaultRequest) { + assertEquals( + expectedDefaultNetwork, + defaultNetwork); + // Make sure this value doesn't change. + assertEquals(1, defaultRequest.mRequests.size()); + continue; + } + assertEquals(expectedPerAppNetwork, defaultNetwork); + assertEquals(expectedOemRequestsSize, defaultRequest.mRequests.size()); + } + verifyMultipleDefaultCallbacks(expectedDefaultNetwork, expectedPerAppNetwork); + } + + /** + * Verify default callbacks for 'available' fire as expected. This will only run if + * registerDefaultNetworkCallbacks() was executed prior and will only be different if the + * setOemNetworkPreference() per-app API was used for the current process. + * @param expectedSystemDefault the expected network for the system default. + * @param expectedPerAppDefault the expected network for the current process's default. + */ + private void verifyMultipleDefaultCallbacks( + @NonNull final Network expectedSystemDefault, + @NonNull final Network expectedPerAppDefault) { + if (null != mSystemDefaultNetworkCallback && null != expectedSystemDefault + && mService.mNoServiceNetwork.network() != expectedSystemDefault) { + // getLastAvailableNetwork() is used as this method can be called successively with + // the same network to validate therefore expectAvailableThenValidatedCallbacks + // can't be used. + assertEquals(mSystemDefaultNetworkCallback.getLastAvailableNetwork(), + expectedSystemDefault); + } + if (null != mDefaultNetworkCallback && null != expectedPerAppDefault + && mService.mNoServiceNetwork.network() != expectedPerAppDefault) { + assertEquals(mDefaultNetworkCallback.getLastAvailableNetwork(), + expectedPerAppDefault); + } + } + + private void registerDefaultNetworkCallbacks() { + // Using Manifest.permission.NETWORK_SETTINGS for registerSystemDefaultNetworkCallback() + mServiceContext.setPermission( + Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); + mSystemDefaultNetworkCallback = new TestNetworkCallback(); + mDefaultNetworkCallback = new TestNetworkCallback(); + mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback, + new Handler(ConnectivityThread.getInstanceLooper())); + mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback); + mServiceContext.setPermission( + Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED); + } + + private void unregisterDefaultNetworkCallbacks() { + if (null != mDefaultNetworkCallback) { + mCm.unregisterNetworkCallback(mDefaultNetworkCallback); + } + if (null != mSystemDefaultNetworkCallback) { + mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback); + } + } + + private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup) + throws Exception { + final int testPackageNameUid = 123; + final String testPackageName = "per.app.defaults.package"; + setupMultipleDefaultNetworksForOemNetworkPreferenceTest( + networkPrefToSetup, testPackageNameUid, testPackageName); + } + + private void setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup) + throws Exception { + final int testPackageNameUid = Process.myUid(); + final String testPackageName = "per.app.defaults.package"; + setupMultipleDefaultNetworksForOemNetworkPreferenceTest( + networkPrefToSetup, testPackageNameUid, testPackageName); + } + + private void setupMultipleDefaultNetworksForOemNetworkPreferenceTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup, + final int testPackageUid, @NonNull final String testPackageName) throws Exception { + // Only the default request should be included at start. + assertEquals(1, mService.mDefaultNetworkRequests.size()); + + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUids(testPackageUid)); + setupSetOemNetworkPreferenceForPreferenceTest( + networkPrefToSetup, uidRanges, testPackageName); + } + + private void setupSetOemNetworkPreferenceForPreferenceTest( + @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup, + @NonNull final UidRangeParcel[] uidRanges, + @NonNull final String testPackageName) + throws Exception { + mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true); + + // These tests work off a single UID therefore using 'start' is valid. + mockGetApplicationInfo(testPackageName, uidRanges[0].start); + + // Build OemNetworkPreferences object + final OemNetworkPreferences pref = new OemNetworkPreferences.Builder() + .addNetworkPreference(testPackageName, networkPrefToSetup) + .build(); + + // Act on ConnectivityService.setOemNetworkPreference() + final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback(); + mService.setOemNetworkPreference(pref, oemPrefListener); + + // Verify call returned successfully + oemPrefListener.expectOnComplete(); + } + + private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener { + final CompletableFuture<Object> mDone = new CompletableFuture<>(); + + @Override + public void onComplete() { + mDone.complete(new Object()); + } + + void expectOnComplete() throws Exception { + try { + mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + fail("Expected onComplete() not received after " + TIMEOUT_MS + " ms"); + } + } + + @Override + public IBinder asBinder() { + return null; + } + } + + @Test + public void testMultiDefaultGetActiveNetworkIsCorrect() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + registerDefaultNetworkCallbacks(); + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active network for the default should be null at this point as this is a retricted + // network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // Verify that the active network is correct + verifyActiveNetwork(TRANSPORT_ETHERNET); + // default NCs will be unregistered in tearDown + } + + @Test + public void testMultiDefaultIsActiveNetworkMeteredIsCorrect() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + registerDefaultNetworkCallbacks(); + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Returns true by default when no network is available. + assertTrue(mCm.isActiveNetworkMetered()); + + // Connect to an unmetered restricted network that will only be available to the OEM pref. + mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); + mEthernetNetworkAgent.addCapability(NET_CAPABILITY_OEM_PAID); + mEthernetNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mEthernetNetworkAgent.removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + mEthernetNetworkAgent.connect(true); + waitForIdle(); + + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + assertFalse(mCm.isActiveNetworkMetered()); + // default NCs will be unregistered in tearDown + } + + @Test + public void testPerAppDefaultRegisterDefaultNetworkCallback() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); + + // Register the default network callback before the pref is already set. This means that + // the policy will be applied to the callback on setOemNetworkPreference(). + mCm.registerDefaultNetworkCallback(defaultNetworkCallback); + defaultNetworkCallback.assertNoCallback(); + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active nai for the default is null at this point as this is a restricted network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // At this point with a restricted network used, the available callback should trigger + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); + assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Now bring down the default network which should trigger a LOST callback. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + + // At this point, with no network is available, the lost callback should trigger + defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); + + // Confirm we can unregister without issues. + mCm.unregisterNetworkCallback(defaultNetworkCallback); + } + + @Test + public void testPerAppDefaultRegisterDefaultNetworkCallbackAfterPrefSet() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); + + // Setup the test process to use networkPref for their default network. + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + + // Register the default network callback after the pref is already set. This means that + // the policy will be applied to the callback on requestNetwork(). + mCm.registerDefaultNetworkCallback(defaultNetworkCallback); + defaultNetworkCallback.assertNoCallback(); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active nai for the default is null at this point as this is a restricted network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // At this point with a restricted network used, the available callback should trigger + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent); + assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Now bring down the default network which should trigger a LOST callback. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + + // At this point, with no network is available, the lost callback should trigger + defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); + + // Confirm we can unregister without issues. + mCm.unregisterNetworkCallback(defaultNetworkCallback); + } + + @Test + public void testPerAppDefaultRegisterDefaultNetworkCallbackDoesNotFire() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + final int expectedOemPrefRequestSize = 1; + final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback(); + final int userId = UserHandle.getUserId(Process.myUid()); + + mCm.registerDefaultNetworkCallback(defaultNetworkCallback); + defaultNetworkCallback.assertNoCallback(); + + // Setup a process different than the test process to use the default network. This means + // that the defaultNetworkCallback won't be tracked by the per-app policy. + setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + // The active nai for the default is null at this point as this is a restricted network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // As this callback does not have access to the OEM_PAID network, it will not fire. + defaultNetworkCallback.assertNoCallback(); + assertDefaultNetworkCapabilities(userId /* no networks */); + + // Bring up unrestricted cellular. This should now satisfy the default network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // At this point with an unrestricted network used, the available callback should trigger + defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), + mCellNetworkAgent.getNetwork()); + assertDefaultNetworkCapabilities(userId, mCellNetworkAgent); + + // Now bring down the per-app network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + + // Since the callback didn't use the per-app network, no callback should fire. + defaultNetworkCallback.assertNoCallback(); + + // Now bring down the default network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + + // As this callback was tracking the default, this should now trigger. + defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + + // Confirm we can unregister without issues. + mCm.unregisterNetworkCallback(defaultNetworkCallback); + } + + /** + * This method assumes that the same uidRanges input will be used to verify that dependencies + * are called as expected. + */ + private void verifySetOemNetworkPreferenceForPreference( + @NonNull final UidRangeParcel[] uidRanges, + final int addUidRangesNetId, + final int addUidRangesTimes, + final int removeUidRangesNetId, + final int removeUidRangesTimes, + final boolean shouldDestroyNetwork) throws RemoteException { + verifySetOemNetworkPreferenceForPreference(uidRanges, uidRanges, + addUidRangesNetId, addUidRangesTimes, removeUidRangesNetId, removeUidRangesTimes, + shouldDestroyNetwork); + } + + private void verifySetOemNetworkPreferenceForPreference( + @NonNull final UidRangeParcel[] addedUidRanges, + @NonNull final UidRangeParcel[] removedUidRanges, + final int addUidRangesNetId, + final int addUidRangesTimes, + final int removeUidRangesNetId, + final int removeUidRangesTimes, + final boolean shouldDestroyNetwork) throws RemoteException { + final boolean useAnyIdForAdd = OEM_PREF_ANY_NET_ID == addUidRangesNetId; + final boolean useAnyIdForRemove = OEM_PREF_ANY_NET_ID == removeUidRangesNetId; + + // Validate netd. + verify(mMockNetd, times(addUidRangesTimes)) + .networkAddUidRanges( + (useAnyIdForAdd ? anyInt() : eq(addUidRangesNetId)), eq(addedUidRanges)); + verify(mMockNetd, times(removeUidRangesTimes)) + .networkRemoveUidRanges( + (useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId)), + eq(removedUidRanges)); + if (shouldDestroyNetwork) { + verify(mMockNetd, times(1)) + .networkDestroy((useAnyIdForRemove ? anyInt() : eq(removeUidRangesNetId))); + } + reset(mMockNetd); + } + + /** + * Test the tracked default requests clear previous OEM requests on setOemNetworkPreference(). + */ + @Test + public void testSetOemNetworkPreferenceClearPreviousOemValues() throws Exception { + @OemNetworkPreferences.OemNetworkPreference int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID; + final int testPackageUid = 123; + final String testPackageName = "com.google.apps.contacts"; + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUids(testPackageUid)); + + // Validate the starting requests only includes the fallback request. + assertEquals(1, mService.mDefaultNetworkRequests.size()); + + // Add an OEM default network request to track. + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName); + + // Two requests should exist, one for the fallback and one for the pref. + assertEquals(2, mService.mDefaultNetworkRequests.size()); + + networkPref = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, testPackageName); + + // Two requests should still exist validating the previous per-app request was replaced. + assertEquals(2, mService.mDefaultNetworkRequests.size()); + } + + /** + * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order: + * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback + */ + @Test + public void testMultilayerForPreferenceOemPaidEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID; + + // Arrange PackageManager mocks + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. No networks should be connected. + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mWiFiNetworkAgent.getNetwork().netId, 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting OEM_PAID should have no effect as it is lower in priority then unmetered. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + // netd should not be called as default networks haven't changed. + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting unmetered should put PANS on lowest priority fallback request. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + mWiFiNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + + // Disconnecting the fallback network should result in no connectivity. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + mCellNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order: + * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID + */ + @Test + public void testMultilayerForPreferenceOemPaidNoFallbackEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + + // Arrange PackageManager mocks + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. This preference doesn't support using the fallback network + // therefore should be on the disconnected network as it has no networks to connect to. + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + // This preference should not use this network as it doesn't support fallback usage. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mWiFiNetworkAgent.getNetwork().netId, 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting unmetered should put PANS on OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mWiFiNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + + // Disconnecting OEM_PAID should result in no connectivity. + // OEM_PAID_NO_FALLBACK not supporting a fallback now uses the disconnected network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order: + * NET_CAPABILITY_OEM_PAID + * This preference should only apply to OEM_PAID networks. + */ + @Test + public void testMultilayerForPreferenceOemPaidOnlyEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + + // Arrange PackageManager mocks + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. This preference doesn't support using the fallback network + // therefore should be on the disconnected network as it has no networks to connect to. + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up metered cellular. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting OEM_PAID should result in no connectivity. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order: + * NET_CAPABILITY_OEM_PRIVATE + * This preference should only apply to OEM_PRIVATE networks. + */ + @Test + public void testMultilayerForPreferenceOemPrivateOnlyEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + + // Arrange PackageManager mocks + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. This preference doesn't support using the fallback network + // therefore should be on the disconnected network as it has no networks to connect to. + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up metered cellular. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up unmetered Wi-Fi. This should not apply to this preference. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE. + startOemManagedNetwork(false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mEthernetNetworkAgent.getNetwork().netId, 1 /* times */, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + false /* shouldDestroyNetwork */); + + // Disconnecting OEM_PRIVATE should result in no connectivity. + stopOemManagedNetwork(); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mService.mNoServiceNetwork.network.getNetId(), 1 /* times */, + mEthernetNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + @Test + public void testMultilayerForMultipleUsersEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID; + + // Arrange users + final int secondUser = 10; + final UserHandle secondUserHandle = new UserHandle(secondUser); + when(mUserManager.getUserHandles(anyBoolean())).thenReturn( + Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle)); + + // Arrange PackageManager mocks + final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); + final UidRangeParcel[] uidRanges = + toUidRangeStableParcels( + uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid)); + setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME); + + // Verify the starting state. No networks should be connected. + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test that we correctly add the expected values for multiple users. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRanges, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test that we correctly remove the expected values for multiple users. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifySetOemNetworkPreferenceForPreference(uidRanges, + OEM_PREF_ANY_NET_ID, 0 /* times */, + mCellNetworkAgent.getNetwork().netId, 0 /* times */, + true /* shouldDestroyNetwork */); + } + + @Test + public void testMultilayerForBroadcastedUsersEvaluatesCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OEM_NETWORK_PREFERENCE_OEM_PAID; + + // Arrange users + final int secondUser = 10; + final UserHandle secondUserHandle = new UserHandle(secondUser); + when(mUserManager.getUserHandles(anyBoolean())).thenReturn( + Arrays.asList(PRIMARY_USER_HANDLE)); + + // Arrange PackageManager mocks + final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID); + final UidRangeParcel[] uidRangesSingleUser = + toUidRangeStableParcels( + uidRangesForUids(TEST_PACKAGE_UID)); + final UidRangeParcel[] uidRangesBothUsers = + toUidRangeStableParcels( + uidRangesForUids(TEST_PACKAGE_UID, secondUserTestPackageUid)); + setupSetOemNetworkPreferenceForPreferenceTest( + networkPref, uidRangesSingleUser, TEST_PACKAGE_NAME); + + // Verify the starting state. No networks should be connected. + verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, + OEM_PREF_ANY_NET_ID, 0 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Test that we correctly add the expected values for multiple users. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + OEM_PREF_ANY_NET_ID, 0 /* times */, + false /* shouldDestroyNetwork */); + + // Send a broadcast indicating a user was added. + when(mUserManager.getUserHandles(anyBoolean())).thenReturn( + Arrays.asList(PRIMARY_USER_HANDLE, secondUserHandle)); + final Intent addedIntent = new Intent(ACTION_USER_ADDED); + addedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser)); + processBroadcast(addedIntent); + + // Test that we correctly add values for all users and remove for the single user. + verifySetOemNetworkPreferenceForPreference(uidRangesBothUsers, uidRangesSingleUser, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + + // Send a broadcast indicating a user was removed. + when(mUserManager.getUserHandles(anyBoolean())).thenReturn( + Arrays.asList(PRIMARY_USER_HANDLE)); + final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(secondUser)); + processBroadcast(removedIntent); + + // Test that we correctly add values for the single user and remove for the all users. + verifySetOemNetworkPreferenceForPreference(uidRangesSingleUser, uidRangesBothUsers, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + mCellNetworkAgent.getNetwork().netId, 1 /* times */, + false /* shouldDestroyNetwork */); + } + + /** + * Test network priority for preference OEM_NETWORK_PREFERENCE_OEM_PAID in the following order: + * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID -> fallback + */ + @Test + public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID; + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + final int expectedDefaultRequestSize = 2; + final int expectedOemPrefRequestSize = 3; + registerDefaultNetworkCallbacks(); + + // The fallback as well as the OEM preference should now be tracked. + assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mCellNetworkAgent.getNetwork()); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mWiFiNetworkAgent.getNetwork(), + mWiFiNetworkAgent.getNetwork()); + + // Disconnecting unmetered Wi-Fi will put the pref on OEM_PAID and fallback on cellular. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting OEM_PAID will put both on null as it is the last network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + null); + + // default callbacks will be unregistered in tearDown + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK in the following order: + * NET_CAPABILITY_NOT_METERED -> NET_CAPABILITY_OEM_PAID + */ + @Test + public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidNoFallbackCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK; + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + final int expectedDefaultRequestSize = 2; + final int expectedOemPrefRequestSize = 2; + registerDefaultNetworkCallbacks(); + + // The fallback as well as the OEM preference should now be tracked. + assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network but not the pref. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mService.mNoServiceNetwork.network()); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Bring up unmetered Wi-Fi. This will satisfy NET_CAPABILITY_NOT_METERED. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mWiFiNetworkAgent.getNetwork(), + mWiFiNetworkAgent.getNetwork()); + + // Disconnecting unmetered Wi-Fi will put the OEM pref on OEM_PAID and fallback on cellular. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting cellular should keep OEM network on OEM_PAID and fallback will be null. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting OEM_PAID puts the fallback on null and the pref on the disconnected net. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mService.mNoServiceNetwork.network()); + + // default callbacks will be unregistered in tearDown + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY in the following order: + * NET_CAPABILITY_OEM_PAID + * This preference should only apply to OEM_PAID networks. + */ + @Test + public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPaidOnlyCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY; + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + final int expectedDefaultRequestSize = 2; + final int expectedOemPrefRequestSize = 1; + registerDefaultNetworkCallbacks(); + + // The fallback as well as the OEM preference should now be tracked. + assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mService.mNoServiceNetwork.network()); + + // Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mWiFiNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting OEM_PAID will keep the fallback on cellular and nothing for OEM_PAID. + // OEM_PAID_ONLY not supporting a fallback now uses the disconnected network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mService.mNoServiceNetwork.network()); + + // Disconnecting cellular will put the fallback on null and the pref on disconnected. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mService.mNoServiceNetwork.network()); + + // default callbacks will be unregistered in tearDown + } + + /** + * Test network priority for OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY in the following order: + * NET_CAPABILITY_OEM_PRIVATE + * This preference should only apply to OEM_PRIVATE networks. + */ + @Test + public void testMultipleDefaultNetworksTracksOemNetworkPreferenceOemPrivateOnlyCorrectly() + throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref); + final int expectedDefaultRequestSize = 2; + final int expectedOemPrefRequestSize = 1; + registerDefaultNetworkCallbacks(); + + // The fallback as well as the OEM preference should now be tracked. + assertEquals(expectedDefaultRequestSize, mService.mDefaultNetworkRequests.size()); + + // Test lowest to highest priority requests. + // Bring up metered cellular. This will satisfy the fallback network. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mService.mNoServiceNetwork.network()); + + // Bring up ethernet with OEM_PRIVATE. This will satisfy NET_CAPABILITY_OEM_PRIVATE. + startOemManagedNetwork(false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Bring up unmetered Wi-Fi. The OEM network shouldn't change, the fallback will take Wi-Fi. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, true); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mWiFiNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting unmetered Wi-Fi shouldn't change the OEM network with fallback on cellular. + setOemNetworkPreferenceAgentConnected(TRANSPORT_WIFI, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mEthernetNetworkAgent.getNetwork()); + + // Disconnecting OEM_PRIVATE will keep the fallback on cellular. + // OEM_PRIVATE_ONLY not supporting a fallback now uses to the disconnected network. + stopOemManagedNetwork(); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + mCellNetworkAgent.getNetwork(), + mService.mNoServiceNetwork.network()); + + // Disconnecting cellular will put the fallback on null and pref on disconnected. + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false); + verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize, + null, + mService.mNoServiceNetwork.network()); + + // default callbacks will be unregistered in tearDown + } + + @Test + public void testCapabilityWithOemNetworkPreference() throws Exception { + @OemNetworkPreferences.OemNetworkPreference final int networkPref = + OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY; + setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref); + registerDefaultNetworkCallbacks(); + + setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true); + + mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + + mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED); + mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc -> + nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); + + // default callbacks will be unregistered in tearDown + } + + @Test + public void testGetAllNetworkStateSnapshot() throws Exception { + verifyNoNetwork(); + + // Setup test cellular network with specified LinkProperties and NetworkCapabilities, + // verify the content of the snapshot matches. + final LinkProperties cellLp = new LinkProperties(); + final LinkAddress myIpv4Addr = new LinkAddress(InetAddress.getByName("192.0.2.129"), 25); + final LinkAddress myIpv6Addr = new LinkAddress(InetAddress.getByName("2001:db8::1"), 64); + cellLp.setInterfaceName("test01"); + cellLp.addLinkAddress(myIpv4Addr); + cellLp.addLinkAddress(myIpv6Addr); + cellLp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234"))); + cellLp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); + cellLp.addRoute(new RouteInfo(myIpv4Addr, null)); + cellLp.addRoute(new RouteInfo(myIpv6Addr, null)); + final NetworkCapabilities cellNcTemplate = new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_MMS).build(); + + final TestNetworkCallback cellCb = new TestNetworkCallback(); + mCm.requestNetwork(new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(), + cellCb); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp, cellNcTemplate); + mCellNetworkAgent.connect(true); + cellCb.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + List<NetworkStateSnapshot> snapshots = mCm.getAllNetworkStateSnapshot(); + assertLength(1, snapshots); + + // Compose the expected cellular snapshot for verification. + final NetworkCapabilities cellNc = + mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()); + final NetworkStateSnapshot cellSnapshot = new NetworkStateSnapshot( + mCellNetworkAgent.getNetwork(), cellNc, cellLp, + null, ConnectivityManager.TYPE_MOBILE); + assertEquals(cellSnapshot, snapshots.get(0)); + + // Connect wifi and verify the snapshots. + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + waitForIdle(); + // Compose the expected wifi snapshot for verification. + final NetworkCapabilities wifiNc = + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()); + final NetworkStateSnapshot wifiSnapshot = new NetworkStateSnapshot( + mWiFiNetworkAgent.getNetwork(), wifiNc, new LinkProperties(), null, + ConnectivityManager.TYPE_WIFI); + + snapshots = mCm.getAllNetworkStateSnapshot(); + assertLength(2, snapshots); + assertContainsAll(snapshots, cellSnapshot, wifiSnapshot); + + // Set cellular as suspended, verify the snapshots will not contain suspended networks. + // TODO: Consider include SUSPENDED networks, which should be considered as + // temporary shortage of connectivity of a connected network. + mCellNetworkAgent.suspend(); + waitForIdle(); + snapshots = mCm.getAllNetworkStateSnapshot(); + assertLength(1, snapshots); + assertEquals(wifiSnapshot, snapshots.get(0)); + + // Disconnect wifi, verify the snapshots contain nothing. + mWiFiNetworkAgent.disconnect(); + waitForIdle(); + snapshots = mCm.getAllNetworkStateSnapshot(); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + assertLength(0, snapshots); + + mCellNetworkAgent.resume(); + waitForIdle(); + snapshots = mCm.getAllNetworkStateSnapshot(); + assertLength(1, snapshots); + assertEquals(cellSnapshot, snapshots.get(0)); + + mCellNetworkAgent.disconnect(); + waitForIdle(); + verifyNoNetwork(); + mCm.unregisterNetworkCallback(cellCb); } } diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index c86224a71978..32c95f149979 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -16,12 +16,16 @@ package com.android.server; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.INetd.IF_STATE_DOWN; +import static android.net.INetd.IF_STATE_UP; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; @@ -36,6 +40,7 @@ import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.INetd; import android.net.InetAddresses; +import android.net.InterfaceConfigurationParcel; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; @@ -48,7 +53,6 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.os.Binder; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.system.Os; import android.test.mock.MockContext; @@ -148,10 +152,17 @@ public class IpSecServiceParameterizedTest { } throw new SecurityException("Unavailable permission requested"); } + + @Override + public int checkCallingOrSelfPermission(String permission) { + if (android.Manifest.permission.NETWORK_STACK.equals(permission)) { + return PERMISSION_GRANTED; + } + throw new UnsupportedOperationException(); + } }; INetd mMockNetd; - INetworkManagementService mNetworkManager; PackageManager mMockPkgMgr; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -181,10 +192,9 @@ public class IpSecServiceParameterizedTest { @Before public void setUp() throws Exception { mMockNetd = mock(INetd.class); - mNetworkManager = mock(INetworkManagementService.class); mMockPkgMgr = mock(PackageManager.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mNetworkManager, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -644,7 +654,10 @@ public class IpSecServiceParameterizedTest { } private IpSecTunnelInterfaceResponse createAndValidateTunnel( - String localAddr, String remoteAddr, String pkgName) { + String localAddr, String remoteAddr, String pkgName) throws Exception { + final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); + config.flags = new String[] {IF_STATE_DOWN}; + when(mMockNetd.interfaceGetCfg(anyString())).thenReturn(config); IpSecTunnelInterfaceResponse createTunnelResp = mIpSecService.createTunnelInterface( mSourceAddr, mDestinationAddr, fakeNetwork, new Binder(), pkgName); @@ -674,7 +687,8 @@ public class IpSecServiceParameterizedTest { anyInt(), anyInt(), anyInt()); - verify(mNetworkManager).setInterfaceUp(createTunnelResp.interfaceName); + verify(mMockNetd).interfaceSetCfg(argThat( + config -> Arrays.asList(config.flags).contains(IF_STATE_UP))); } @Test diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java index 788e4efe097e..22a2c94fc194 100644 --- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.os.Binder; import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.RemoteException; import androidx.test.filters.SmallTest; @@ -62,8 +61,7 @@ public class IpSecServiceRefcountedResourceTest { public void setUp() throws Exception { mMockContext = mock(Context.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService( - mMockContext, mock(INetworkManagementService.class), mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); } private void assertResourceState( diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 536e98327e1f..f97eabf6366d 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -42,7 +42,6 @@ import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecUdpEncapResponse; import android.os.Binder; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.Process; import android.system.ErrnoException; @@ -116,7 +115,6 @@ public class IpSecServiceTest { } Context mMockContext; - INetworkManagementService mMockNetworkManager; INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -124,10 +122,9 @@ public class IpSecServiceTest { @Before public void setUp() throws Exception { mMockContext = mock(Context.class); - mMockNetworkManager = mock(INetworkManagementService.class); mMockNetd = mock(INetd.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockNetworkManager, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -135,7 +132,7 @@ public class IpSecServiceTest { @Test public void testIpSecServiceCreate() throws InterruptedException { - IpSecService ipSecSrv = IpSecService.create(mMockContext, mMockNetworkManager); + IpSecService ipSecSrv = IpSecService.create(mMockContext); assertNotNull(ipSecSrv); } @@ -608,7 +605,7 @@ public class IpSecServiceTest { public void testOpenUdpEncapSocketTagsSocket() throws Exception { IpSecService.UidFdTagger mockTagger = mock(IpSecService.UidFdTagger.class); IpSecService testIpSecService = new IpSecService( - mMockContext, mMockNetworkManager, mMockIpSecSrvConfig, mockTagger); + mMockContext, mMockIpSecSrvConfig, mockTagger); IpSecUdpEncapResponse udpEncapResp = testIpSecService.openUdpEncapsulationSocket(0, new Binder()); diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index f5b85ca06f92..5760211d9a27 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -22,6 +22,8 @@ import static android.net.NetworkCapabilities.MAX_TRANSPORT; import static android.net.NetworkCapabilities.MIN_TRANSPORT; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE; +import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS; import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER; @@ -164,7 +166,8 @@ public class DnsManagerTest { mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_ALTERNATE, - InetAddress.parseNumericAddress("4.4.4.4"), "", true)); + InetAddress.parseNumericAddress("4.4.4.4"), "", + VALIDATION_RESULT_SUCCESS)); LinkProperties fixedLp = new LinkProperties(lp); mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); assertFalse(fixedLp.isPrivateDnsActive()); @@ -204,7 +207,8 @@ public class DnsManagerTest { // Validate one. mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("6.6.6.6"), "strictmode.com", true)); + InetAddress.parseNumericAddress("6.6.6.6"), "strictmode.com", + VALIDATION_RESULT_SUCCESS)); fixedLp = new LinkProperties(lp); mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); assertEquals(Arrays.asList(InetAddress.parseNumericAddress("6.6.6.6")), @@ -212,7 +216,8 @@ public class DnsManagerTest { // Validate the 2nd one. mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("2001:db8:66:66::1"), "strictmode.com", true)); + InetAddress.parseNumericAddress("2001:db8:66:66::1"), "strictmode.com", + VALIDATION_RESULT_SUCCESS)); fixedLp = new LinkProperties(lp); mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); assertEquals(Arrays.asList( @@ -232,7 +237,8 @@ public class DnsManagerTest { mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", true)); + InetAddress.parseNumericAddress("3.3.3.3"), "", + VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -245,7 +251,8 @@ public class DnsManagerTest { mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_UNTRACKED, - InetAddress.parseNumericAddress("3.3.3.3"), "", true)); + InetAddress.parseNumericAddress("3.3.3.3"), "", + VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -253,7 +260,8 @@ public class DnsManagerTest { // Validation event has untracked ipAddress mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("4.4.4.4"), "", true)); + InetAddress.parseNumericAddress("4.4.4.4"), "", + VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -261,8 +269,8 @@ public class DnsManagerTest { // Validation event has untracked hostname mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "hostname", - true)); + InetAddress.parseNumericAddress("3.3.3.3"), "hostname", + VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -270,7 +278,8 @@ public class DnsManagerTest { // Validation event failed mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", false)); + InetAddress.parseNumericAddress("3.3.3.3"), "", + VALIDATION_RESULT_FAILURE)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -279,7 +288,7 @@ public class DnsManagerTest { mDnsManager.removeNetwork(new Network(TEST_NETID)); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", true)); + InetAddress.parseNumericAddress("3.3.3.3"), "", VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -293,7 +302,8 @@ public class DnsManagerTest { mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, - InetAddress.parseNumericAddress("3.3.3.3"), "", true)); + InetAddress.parseNumericAddress("3.3.3.3"), "", + VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); assertFalse(lp.isPrivateDnsActive()); assertNull(lp.getPrivateDnsServerName()); @@ -398,7 +408,8 @@ public class DnsManagerTest { mDnsManager.updatePrivateDns(network, mDnsManager.getPrivateDnsConfig()); mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); mDnsManager.updatePrivateDnsValidation( - new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, dnsAddr, "", true)); + new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, dnsAddr, "", + VALIDATION_RESULT_SUCCESS)); mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); assertTrue(privateDnsCfg.useTls); diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 52cb836e19c8..a913673c2a1e 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -41,7 +41,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; import android.os.Binder; -import android.os.INetworkManagementService; import android.text.format.DateUtils; import androidx.test.filters.SmallTest; @@ -74,7 +73,6 @@ public class LingerMonitorTest { @Mock ConnectivityService mConnService; @Mock IDnsResolver mDnsResolver; @Mock INetd mNetd; - @Mock INetworkManagementService mNMS; @Mock Context mCtx; @Mock NetworkNotificationManager mNotifier; @Mock Resources mResources; @@ -358,8 +356,8 @@ public class LingerMonitorTest { caps.addTransportType(transport); NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info, new LinkProperties(), caps, 50, mCtx, null, new NetworkAgentConfig() /* config */, - mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE, - Binder.getCallingUid(), mQosCallbackTracker); + mConnService, mNetd, mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), + mQosCallbackTracker); nai.everValidated = true; return nai; } diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index 4f65b67fa3da..5f56e25356c2 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -36,7 +36,6 @@ import android.net.LinkProperties; import android.net.NetworkAgentConfig; import android.net.NetworkInfo; import android.os.Handler; -import android.os.INetworkManagementService; import android.os.test.TestLooper; import androidx.test.filters.SmallTest; @@ -67,7 +66,6 @@ public class Nat464XlatTest { @Mock ConnectivityService mConnectivity; @Mock IDnsResolver mDnsResolver; @Mock INetd mNetd; - @Mock INetworkManagementService mNms; @Mock NetworkAgentInfo mNai; TestLooper mLooper; @@ -75,7 +73,7 @@ public class Nat464XlatTest { NetworkAgentConfig mAgentConfig = new NetworkAgentConfig(); Nat464Xlat makeNat464Xlat() { - return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) { + return new Nat464Xlat(mNai, mNetd, mDnsResolver) { @Override protected int getNetId() { return NETID; } @@ -206,7 +204,6 @@ public class Nat464XlatTest { // Start clat. nat.start(); - verify(mNms).registerObserver(eq(nat)); verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); // Stacked interface up notification arrives. @@ -225,7 +222,6 @@ public class Nat464XlatTest { verify(mNetd).clatdStop(eq(BASE_IFACE)); verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); - verify(mNms).unregisterObserver(eq(nat)); assertTrue(c.getValue().getStackedLinks().isEmpty()); assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); @@ -235,7 +231,7 @@ public class Nat464XlatTest { nat.interfaceRemoved(STACKED_IFACE); mLooper.dispatchNext(); - verifyNoMoreInteractions(mNetd, mNms, mConnectivity); + verifyNoMoreInteractions(mNetd, mConnectivity); } @Test @@ -346,7 +342,6 @@ public class Nat464XlatTest { nat.start(); - verify(mNms).registerObserver(eq(nat)); verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); // Stacked interface up notification arrives. @@ -365,7 +360,6 @@ public class Nat464XlatTest { verify(mNetd).clatdStop(eq(BASE_IFACE)); verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); - verify(mNms).unregisterObserver(eq(nat)); verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertTrue(c.getValue().getStackedLinks().isEmpty()); assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); @@ -374,7 +368,7 @@ public class Nat464XlatTest { // ConnectivityService stops clat: no-op. nat.stop(); - verifyNoMoreInteractions(mNetd, mNms, mConnectivity); + verifyNoMoreInteractions(mNetd, mConnectivity); } private void checkStopBeforeClatdStarts(boolean dueToDisconnect) throws Exception { @@ -386,7 +380,6 @@ public class Nat464XlatTest { nat.start(); - verify(mNms).registerObserver(eq(nat)); verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) @@ -394,7 +387,6 @@ public class Nat464XlatTest { nat.stop(); verify(mNetd).clatdStop(eq(BASE_IFACE)); - verify(mNms).unregisterObserver(eq(nat)); verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertIdle(nat); @@ -408,7 +400,7 @@ public class Nat464XlatTest { assertIdle(nat); - verifyNoMoreInteractions(mNetd, mNms, mConnectivity); + verifyNoMoreInteractions(mNetd, mConnectivity); } @Test @@ -430,7 +422,6 @@ public class Nat464XlatTest { nat.start(); - verify(mNms).registerObserver(eq(nat)); verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) @@ -438,11 +429,10 @@ public class Nat464XlatTest { nat.stop(); verify(mNetd).clatdStop(eq(BASE_IFACE)); - verify(mNms).unregisterObserver(eq(nat)); verify(mDnsResolver).stopPrefix64Discovery(eq(NETID)); assertIdle(nat); - verifyNoMoreInteractions(mNetd, mNms, mConnectivity); + verifyNoMoreInteractions(mNetd, mConnectivity); } @Test diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index 697dbc48880c..ff8c632833f2 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java @@ -49,6 +49,7 @@ import com.android.server.connectivity.NetworkNotificationManager.NotificationTy import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.AdditionalAnswers; @@ -183,6 +184,9 @@ public class NetworkNotificationManagerTest { } @Test + @Ignore + // Ignored because the code under test calls Log.wtf, which crashes the tests on eng builds. + // TODO: re-enable after fixing this (e.g., turn Log.wtf into exceptions that this test catches) public void testNoInternetNotificationsNotShownForCellular() { mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false); mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false); diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index 8f5ae97bc4c5..e4e24b464838 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -61,6 +61,7 @@ import android.content.pm.PackageManagerInternal; import android.net.INetd; import android.net.UidRange; import android.os.Build; +import android.os.SystemConfigManager; import android.os.UserHandle; import android.os.UserManager; import android.util.SparseIntArray; @@ -114,6 +115,7 @@ public class PermissionMonitorTest { @Mock private PackageManagerInternal mMockPmi; @Mock private UserManager mUserManager; @Mock private PermissionMonitor.Dependencies mDeps; + @Mock private SystemConfigManager mSystemConfigManager; private PermissionMonitor mPermissionMonitor; @@ -124,6 +126,11 @@ public class PermissionMonitorTest { when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); when(mUserManager.getUserHandles(eq(true))).thenReturn( Arrays.asList(new UserHandle[] { MOCK_USER1, MOCK_USER2 })); + when(mContext.getSystemServiceName(SystemConfigManager.class)) + .thenReturn(Context.SYSTEM_CONFIG_SERVICE); + when(mContext.getSystemService(Context.SYSTEM_CONFIG_SERVICE)) + .thenReturn(mSystemConfigManager); + when(mSystemConfigManager.getSystemPermissionUids(anyString())).thenReturn(new int[0]); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); @@ -747,4 +754,20 @@ public class PermissionMonitorTest { GET_PERMISSIONS | MATCH_ANY_USER); assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); } + + @Test + public void testUpdateUidPermissionsFromSystemConfig() throws Exception { + final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); + when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(new ArrayList<>()); + when(mSystemConfigManager.getSystemPermissionUids(eq(INTERNET))) + .thenReturn(new int[]{ MOCK_UID1, MOCK_UID2 }); + when(mSystemConfigManager.getSystemPermissionUids(eq(UPDATE_DEVICE_STATS))) + .thenReturn(new int[]{ MOCK_UID2 }); + + mPermissionMonitor.startMonitoring(); + mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{ MOCK_UID1 }); + mNetdServiceMonitor.expectPermission( + INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, + new int[]{ MOCK_UID2 }); + } } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index cffd2d1d428f..b8f7fbca3983 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -21,6 +21,8 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; import static android.content.pm.UserInfo.FLAG_PRIMARY; import static android.content.pm.UserInfo.FLAG_RESTRICTED; import static android.net.ConnectivityManager.NetworkCallback; +import static android.net.INetd.IF_STATE_DOWN; +import static android.net.INetd.IF_STATE_UP; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -62,6 +64,7 @@ import android.net.ConnectivityManager; import android.net.INetd; import android.net.Ikev2VpnProfile; import android.net.InetAddresses; +import android.net.InterfaceConfigurationParcel; import android.net.IpPrefix; import android.net.IpSecManager; import android.net.IpSecTunnelInterfaceResponse; @@ -88,7 +91,6 @@ import android.os.UserManager; import android.os.test.TestLooper; import android.provider.Settings; import android.security.Credentials; -import android.security.KeyStore; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Range; @@ -179,7 +181,8 @@ public class VpnTest { mPackages.put(PKGS[i], PKG_UIDS[i]); } } - private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id); + private static final UidRange PRI_USER_RANGE = + UidRange.createForUser(UserHandle.of(primaryUser.id)); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; @Mock private UserManager mUserManager; @@ -192,7 +195,7 @@ public class VpnTest { @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator; @Mock private ConnectivityManager mConnectivityManager; @Mock private IpSecService mIpSecService; - @Mock private KeyStore mKeyStore; + @Mock private VpnProfileStore mVpnProfileStore; private final VpnProfile mVpnProfile; private IpSecManager mIpSecManager; @@ -269,7 +272,7 @@ public class VpnTest { vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id) + PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id)) })), ranges); } @@ -329,17 +332,17 @@ public class VpnTest { assertFalse(vpn.getLockdown()); // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList(), mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList())); assertTrue(vpn.getAlwaysOn()); assertFalse(vpn.getLockdown()); // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList(), mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList())); assertTrue(vpn.getAlwaysOn()); assertTrue(vpn.getLockdown()); // Remove always-on configuration. - assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList(), mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList())); assertFalse(vpn.getAlwaysOn()); assertFalse(vpn.getLockdown()); } @@ -350,17 +353,17 @@ public class VpnTest { final UidRange user = PRI_USER_RANGE; // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); // Switch to another app. - assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) @@ -378,14 +381,14 @@ public class VpnTest { // Set always-on with lockdown and allow app PKGS[2] from lockdown. assertTrue(vpn.setAlwaysOnPackage( - PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore)); + PKGS[1], true, Collections.singletonList(PKGS[2]))); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( - PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); + PKGS[1], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); @@ -396,7 +399,7 @@ public class VpnTest { // Change the VPN app. assertTrue(vpn.setAlwaysOnPackage( - PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore)); + PKGS[0], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) @@ -407,7 +410,7 @@ public class VpnTest { })); // Remove the list of allowed packages. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) @@ -418,7 +421,7 @@ public class VpnTest { // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( - PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore)); + PKGS[0], true, Collections.singletonList(PKGS[1]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop) })); @@ -429,12 +432,12 @@ public class VpnTest { // Try allowing a package with a comma, should be rejected. assertFalse(vpn.setAlwaysOnPackage( - PKGS[0], true, Collections.singletonList("a.b,c.d"), mKeyStore)); + PKGS[0], true, Collections.singletonList("a.b,c.d"))); // Pass a non-existent packages in the allowlist, they (and only they) should be ignored. // allowed package should change from PGKS[1] to PKGS[2]. assertTrue(vpn.setAlwaysOnPackage( - PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore)); + PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) @@ -521,22 +524,22 @@ public class VpnTest { .thenReturn(Collections.singletonList(resInfo)); // null package name should return false - assertFalse(vpn.isAlwaysOnPackageSupported(null, mKeyStore)); + assertFalse(vpn.isAlwaysOnPackageSupported(null)); // Pre-N apps are not supported appInfo.targetSdkVersion = VERSION_CODES.M; - assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore)); + assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); // N+ apps are supported by default appInfo.targetSdkVersion = VERSION_CODES.N; - assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore)); + assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0])); // Apps that opt out explicitly are not supported appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; Bundle metaData = new Bundle(); metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); svcInfo.metaData = metaData; - assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore)); + assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); } @Test @@ -552,7 +555,7 @@ public class VpnTest { order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt()); // Start showing a notification for disconnected once always-on. - vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore); + vpn.setAlwaysOnPackage(PKGS[0], false, null); order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); // Stop showing the notification once connected. @@ -564,7 +567,7 @@ public class VpnTest { order.verify(mNotificationManager).notify(anyString(), anyInt(), any()); // Notification should be cleared after unsetting always-on package. - vpn.setAlwaysOnPackage(null, false, null, mKeyStore); + vpn.setAlwaysOnPackage(null, false, null); order.verify(mNotificationManager).cancel(anyString(), anyInt()); } @@ -604,15 +607,13 @@ public class VpnTest { } private void checkProvisionVpnProfile(Vpn vpn, boolean expectedResult, String... checkedOps) { - assertEquals(expectedResult, vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile, mKeyStore)); + assertEquals(expectedResult, vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile)); // The profile should always be stored, whether or not consent has been previously granted. - verify(mKeyStore) + verify(mVpnProfileStore) .put( eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)), - eq(mVpnProfile.encode()), - eq(Process.SYSTEM_UID), - eq(0)); + eq(mVpnProfile.encode())); for (final String checkedOpStr : checkedOps) { verify(mAppOps).noteOpNoThrow(checkedOpStr, Process.myUid(), TEST_VPN_PKG, @@ -667,7 +668,7 @@ public class VpnTest { bigProfile.name = new String(new byte[Vpn.MAX_VPN_PROFILE_SIZE_BYTES + 1]); try { - vpn.provisionVpnProfile(TEST_VPN_PKG, bigProfile, mKeyStore); + vpn.provisionVpnProfile(TEST_VPN_PKG, bigProfile); fail("Expected IAE due to profile size"); } catch (IllegalArgumentException expected) { } @@ -680,7 +681,7 @@ public class VpnTest { restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); try { - vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile, mKeyStore); + vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile); fail("Expected SecurityException due to restricted user"); } catch (SecurityException expected) { } @@ -690,10 +691,10 @@ public class VpnTest { public void testDeleteVpnProfile() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(); - vpn.deleteVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.deleteVpnProfile(TEST_VPN_PKG); - verify(mKeyStore) - .delete(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)), eq(Process.SYSTEM_UID)); + verify(mVpnProfileStore) + .remove(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); } @Test @@ -703,7 +704,7 @@ public class VpnTest { restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); try { - vpn.deleteVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.deleteVpnProfile(TEST_VPN_PKG); fail("Expected SecurityException due to restricted user"); } catch (SecurityException expected) { } @@ -713,24 +714,24 @@ public class VpnTest { public void testGetVpnProfilePrivileged() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(); - when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) .thenReturn(new VpnProfile("").encode()); - vpn.getVpnProfilePrivileged(TEST_VPN_PKG, mKeyStore); + vpn.getVpnProfilePrivileged(TEST_VPN_PKG); - verify(mKeyStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); + verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); } @Test public void testStartVpnProfile() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) .thenReturn(mVpnProfile.encode()); - vpn.startVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.startVpnProfile(TEST_VPN_PKG); - verify(mKeyStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); + verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); verify(mAppOps) .noteOpNoThrow( eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), @@ -744,10 +745,10 @@ public class VpnTest { public void testStartVpnProfileVpnServicePreconsented() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); - when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) .thenReturn(mVpnProfile.encode()); - vpn.startVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.startVpnProfile(TEST_VPN_PKG); // Verify that the the ACTIVATE_VPN appop was checked, but no error was thrown. verify(mAppOps).noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_VPN, Process.myUid(), @@ -759,7 +760,7 @@ public class VpnTest { final Vpn vpn = createVpnAndSetupUidChecks(); try { - vpn.startVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.startVpnProfile(TEST_VPN_PKG); fail("Expected failure due to no user consent"); } catch (SecurityException expected) { } @@ -776,22 +777,22 @@ public class VpnTest { TEST_VPN_PKG, null /* attributionTag */, null /* message */); // Keystore should never have been accessed. - verify(mKeyStore, never()).get(any()); + verify(mVpnProfileStore, never()).get(any()); } @Test public void testStartVpnProfileMissingProfile() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); - when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null); + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))).thenReturn(null); try { - vpn.startVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.startVpnProfile(TEST_VPN_PKG); fail("Expected failure due to missing profile"); } catch (IllegalArgumentException expected) { } - verify(mKeyStore).get(vpn.getProfileNameForPackage(TEST_VPN_PKG)); + verify(mVpnProfileStore).get(vpn.getProfileNameForPackage(TEST_VPN_PKG)); verify(mAppOps) .noteOpNoThrow( eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), @@ -808,7 +809,7 @@ public class VpnTest { restrictedProfileA, AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); try { - vpn.startVpnProfile(TEST_VPN_PKG, mKeyStore); + vpn.startVpnProfile(TEST_VPN_PKG); fail("Expected SecurityException due to restricted user"); } catch (SecurityException expected) { } @@ -872,17 +873,28 @@ public class VpnTest { eq(AppOpsManager.MODE_IGNORED)); } - private NetworkCallback triggerOnAvailableAndGetCallback() { + private NetworkCallback triggerOnAvailableAndGetCallback() throws Exception { final ArgumentCaptor<NetworkCallback> networkCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class); verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)) .requestNetwork(any(), networkCallbackCaptor.capture()); + // onAvailable() will trigger onDefaultNetworkChanged(), so NetdUtils#setInterfaceUp will be + // invoked. Set the return value of INetd#interfaceGetCfg to prevent NullPointerException. + final InterfaceConfigurationParcel config = new InterfaceConfigurationParcel(); + config.flags = new String[] {IF_STATE_DOWN}; + when(mNetd.interfaceGetCfg(anyString())).thenReturn(config); final NetworkCallback cb = networkCallbackCaptor.getValue(); cb.onAvailable(TEST_NETWORK); return cb; } + private void verifyInterfaceSetCfgWithFlags(String flag) throws Exception { + // Add a timeout for waiting for interfaceSetCfg to be called. + verify(mNetd, timeout(TEST_TIMEOUT_MS)).interfaceSetCfg(argThat( + config -> Arrays.asList(config.flags).contains(flag))); + } + @Test public void testStartPlatformVpnAuthenticationFailed() throws Exception { final ArgumentCaptor<IkeSessionCallback> captor = @@ -894,6 +906,8 @@ public class VpnTest { final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile)); final NetworkCallback cb = triggerOnAvailableAndGetCallback(); + verifyInterfaceSetCfgWithFlags(IF_STATE_UP); + // Wait for createIkeSession() to be called before proceeding in order to ensure consistent // state verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS)) @@ -912,6 +926,8 @@ public class VpnTest { final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); final NetworkCallback cb = triggerOnAvailableAndGetCallback(); + verifyInterfaceSetCfgWithFlags(IF_STATE_UP); + // Wait for createIkeSession() to be called before proceeding in order to ensure consistent // state verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); @@ -919,9 +935,9 @@ public class VpnTest { } private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) { - assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null, mKeyStore)); + assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null)); - verify(mKeyStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); + verify(mVpnProfileStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); verify(mAppOps).setMode( eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG), eq(AppOpsManager.MODE_ALLOWED)); @@ -944,11 +960,11 @@ public class VpnTest { final int uid = Process.myUid() + 1; when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) .thenReturn(uid); - when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) .thenReturn(mVpnProfile.encode()); setAndVerifyAlwaysOnPackage(vpn, uid, false); - assertTrue(vpn.startAlwaysOnVpn(mKeyStore)); + assertTrue(vpn.startAlwaysOnVpn()); // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in // a subsequent CL. @@ -965,7 +981,7 @@ public class VpnTest { InetAddresses.parseNumericAddress("192.0.2.0"), EGRESS_IFACE); lp.addRoute(defaultRoute); - vpn.startLegacyVpn(vpnProfile, mKeyStore, EGRESS_NETWORK, lp); + vpn.startLegacyVpn(vpnProfile, EGRESS_NETWORK, lp); return vpn; } @@ -1167,7 +1183,7 @@ public class VpnTest { .thenReturn(asUserContext); final TestLooper testLooper = new TestLooper(); final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService, - mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator); + mNetd, userId, mVpnProfileStore, mSystemServices, mIkev2SessionCreator); verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( provider -> provider.getName().contains("VpnNetworkProvider") )); diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java index 435c3c0af817..505ff9b6a34b 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.NetworkIdentity.OEM_NONE; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; @@ -213,7 +214,7 @@ public class NetworkStatsCollectionTest { final NetworkStats.Entry entry = new NetworkStats.Entry(); final NetworkIdentitySet identSet = new NetworkIdentitySet(); identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, - TEST_IMSI, null, false, true, true)); + TEST_IMSI, null, false, true, true, OEM_NONE)); int myUid = Process.myUid(); int otherUidInSameUser = Process.myUid() + 1; @@ -468,7 +469,7 @@ public class NetworkStatsCollectionTest { final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS); final NetworkIdentitySet ident = new NetworkIdentitySet(); ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null, - false, true, true)); + false, true, true, OEM_NONE)); large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B, new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0)); diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java index 291efc74aa47..9fa1c50423d9 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.NetworkIdentity.OEM_NONE; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.METERED_NO; @@ -220,7 +221,7 @@ public class NetworkStatsObserversTest { identSet.add(new NetworkIdentity( TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, IMSI_1, null /* networkId */, false /* roaming */, true /* metered */, - true /* defaultNetwork */)); + true /* defaultNetwork */, OEM_NONE)); return identSet; } diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 214c82da17dc..9334e2c4ad77 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -19,8 +19,9 @@ package com.android.server.net; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.TYPE_MOBILE; -import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.NetworkIdentity.OEM_PAID; +import static android.net.NetworkIdentity.OEM_PRIVATE; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; @@ -40,7 +41,10 @@ import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; +import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; +import static android.net.NetworkTemplate.OEM_MANAGED_NO; +import static android.net.NetworkTemplate.OEM_MANAGED_YES; import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateMobileWithRatType; import static android.net.NetworkTemplate.buildTemplateWifi; @@ -80,7 +84,7 @@ import android.net.INetworkStatsSession; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkState; +import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; @@ -280,7 +284,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -323,7 +327,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -397,7 +401,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -438,7 +442,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testUidStatsAcrossNetworks() throws Exception { // pretend first mobile network comes online expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildMobile3gState(IMSI_1)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -469,7 +473,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // disappearing, to verify we don't count backwards. incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); - states = new NetworkState[] {buildMobile3gState(IMSI_2)}; + states = new NetworkStateSnapshot[] {buildMobile3gState(IMSI_2)}; expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) @@ -513,7 +517,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testUidRemovedIsMoved() throws Exception { // pretend that network comes online expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -577,7 +581,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_LTE); final NetworkTemplate template5g = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_NR); - final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)}; + final NetworkStateSnapshot[] states = + new NetworkStateSnapshot[]{buildMobile3gState(IMSI_1)}; // 3G network comes online. expectNetworkStatsSummary(buildEmptyStats()); @@ -643,6 +648,117 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2); } + @Test + public void testMobileStatsOemManaged() throws Exception { + final NetworkTemplate templateOemPaid = new NetworkTemplate(MATCH_MOBILE_WILDCARD, + /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_PAID); + + final NetworkTemplate templateOemPrivate = new NetworkTemplate(MATCH_MOBILE_WILDCARD, + /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_PRIVATE); + + final NetworkTemplate templateOemAll = new NetworkTemplate(MATCH_MOBILE_WILDCARD, + /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, + OEM_PAID | OEM_PRIVATE); + + final NetworkTemplate templateOemYes = new NetworkTemplate(MATCH_MOBILE_WILDCARD, + /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_YES); + + final NetworkTemplate templateOemNone = new NetworkTemplate(MATCH_MOBILE_WILDCARD, + /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_NO); + + // OEM_PAID network comes online. + NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{ + buildOemManagedMobileState(IMSI_1, false, + new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PAID})}; + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + new UnderlyingNetworkInfo[0]); + + // Create some traffic. + incrementCurrentTime(MINUTE_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 36L, 41L, 24L, 96L, 0L))); + forcePollAndWaitForIdle(); + + // OEM_PRIVATE network comes online. + states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, + new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE})}; + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + new UnderlyingNetworkInfo[0]); + + // Create some traffic. + incrementCurrentTime(MINUTE_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 49L, 71L, 72L, 48L, 0L))); + forcePollAndWaitForIdle(); + + // OEM_PAID + OEM_PRIVATE network comes online. + states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, + new int[]{NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE, + NetworkCapabilities.NET_CAPABILITY_OEM_PAID})}; + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + new UnderlyingNetworkInfo[0]); + + // Create some traffic. + incrementCurrentTime(MINUTE_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 57L, 86L, 83L, 93L, 0L))); + forcePollAndWaitForIdle(); + + // OEM_NONE network comes online. + states = new NetworkStateSnapshot[]{buildOemManagedMobileState(IMSI_1, false, new int[]{})}; + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + new UnderlyingNetworkInfo[0]); + + // Create some traffic. + incrementCurrentTime(MINUTE_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 29L, 73L, 34L, 31L, 0L))); + forcePollAndWaitForIdle(); + + // Verify OEM_PAID template gets only relevant stats. + assertUidTotal(templateOemPaid, UID_RED, 36L, 41L, 24L, 96L, 0); + + // Verify OEM_PRIVATE template gets only relevant stats. + assertUidTotal(templateOemPrivate, UID_RED, 49L, 71L, 72L, 48L, 0); + + // Verify OEM_PAID + OEM_PRIVATE template gets only relevant stats. + assertUidTotal(templateOemAll, UID_RED, 57L, 86L, 83L, 93L, 0); + + // Verify OEM_NONE sees only non-OEM managed stats. + assertUidTotal(templateOemNone, UID_RED, 29L, 73L, 34L, 31L, 0); + + // Verify OEM_MANAGED_YES sees all OEM managed stats. + assertUidTotal(templateOemYes, UID_RED, + 36L + 49L + 57L, + 41L + 71L + 86L, + 24L + 72L + 83L, + 96L + 48L + 93L, 0); + + // Verify ALL_MOBILE template gets both OEM managed and non-OEM managed stats. + assertUidTotal(sTemplateImsi1, UID_RED, + 36L + 49L + 57L + 29L, + 41L + 71L + 86L + 73L, + 24L + 72L + 83L + 34L, + 96L + 48L + 93L + 31L, 0); + } + // TODO: support per IMSI state private void setMobileRatTypeAndWaitForIdle(int ratType) { when(mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(anyString())) @@ -655,7 +771,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testSummaryForAllUid() throws Exception { // pretend that network comes online expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -714,7 +830,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testDetailedUidStats() throws Exception { // pretend that network comes online expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -755,9 +871,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { final String stackedIface = "stacked-test0"; final LinkProperties stackedProp = new LinkProperties(); stackedProp.setInterfaceName(stackedIface); - final NetworkState wifiState = buildWifiState(); + final NetworkStateSnapshot wifiState = buildWifiState(); wifiState.linkProperties.addStackedLink(stackedProp); - NetworkState[] states = new NetworkState[] {wifiState}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {wifiState}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -813,7 +929,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testForegroundBackground() throws Exception { // pretend that network comes online expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -870,8 +986,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testMetered() throws Exception { // pretend that network comes online expectDefaultSettings(); - NetworkState[] states = - new NetworkState[] {buildWifiState(true /* isMetered */, TEST_IFACE)}; + NetworkStateSnapshot[] states = + new NetworkStateSnapshot[] {buildWifiState(true /* isMetered */, TEST_IFACE)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -910,8 +1026,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testRoaming() throws Exception { // pretend that network comes online expectDefaultSettings(); - NetworkState[] states = - new NetworkState[] {buildMobile3gState(IMSI_1, true /* isRoaming */)}; + NetworkStateSnapshot[] states = + new NetworkStateSnapshot[] {buildMobile3gState(IMSI_1, true /* isRoaming */)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -949,7 +1065,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testTethering() throws Exception { // pretend first mobile network comes online expectDefaultSettings(); - final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)}; + final NetworkStateSnapshot[] states = + new NetworkStateSnapshot[]{buildMobile3gState(IMSI_1)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -1006,7 +1123,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // pretend that wifi network comes online; service should ask about full // network state, and poll any existing interfaces before updating. expectDefaultSettings(); - NetworkState[] states = new NetworkState[] {buildWifiState()}; + NetworkStateSnapshot[] states = new NetworkStateSnapshot[] {buildWifiState()}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -1104,8 +1221,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testStatsProviderUpdateStats() throws Exception { // Pretend that network comes online. expectDefaultSettings(); - final NetworkState[] states = - new NetworkState[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; + final NetworkStateSnapshot[] states = + new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -1166,8 +1283,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testStatsProviderSetAlert() throws Exception { // Pretend that network comes online. expectDefaultSettings(); - NetworkState[] states = - new NetworkState[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; + NetworkStateSnapshot[] states = + new NetworkStateSnapshot[]{buildWifiState(true /* isMetered */, TEST_IFACE)}; mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new UnderlyingNetworkInfo[0]); @@ -1210,7 +1327,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN); final NetworkTemplate templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); - final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)}; + final NetworkStateSnapshot[] states = + new NetworkStateSnapshot[]{buildMobile3gState(IMSI_1)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); @@ -1285,7 +1403,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public void testOperationCount_nonDefault_traffic() throws Exception { // Pretend mobile network comes online, but wifi is the default network. expectDefaultSettings(); - NetworkState[] states = new NetworkState[]{ + NetworkStateSnapshot[] states = new NetworkStateSnapshot[]{ buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)}; expectNetworkStatsUidDetail(buildEmptyStats()); mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), @@ -1373,7 +1491,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsSummary(buildEmptyStats()); } - private String getActiveIface(NetworkState... states) throws Exception { + private String getActiveIface(NetworkStateSnapshot... states) throws Exception { if (states == null || states.length == 0 || states[0].linkProperties == null) { return null; } @@ -1449,11 +1567,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { assertEquals("unexpected operations", operations, entry.operations); } - private static NetworkState buildWifiState() { + private static NetworkStateSnapshot buildWifiState() { return buildWifiState(false, TEST_IFACE); } - private static NetworkState buildWifiState(boolean isMetered, @NonNull String iface) { + private static NetworkStateSnapshot buildWifiState(boolean isMetered, @NonNull String iface) { final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(iface); final NetworkCapabilities capabilities = new NetworkCapabilities(); @@ -1461,32 +1579,41 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true); capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); capabilities.setSSID(TEST_SSID); - return new NetworkState(TYPE_WIFI, prop, capabilities, WIFI_NETWORK, null, TEST_SSID); + return new NetworkStateSnapshot(WIFI_NETWORK, capabilities, prop, null, TYPE_WIFI); } - private static NetworkState buildMobile3gState(String subscriberId) { + private static NetworkStateSnapshot buildMobile3gState(String subscriberId) { return buildMobile3gState(subscriberId, false /* isRoaming */); } - private static NetworkState buildMobile3gState(String subscriberId, boolean isRoaming) { + private static NetworkStateSnapshot buildMobile3gState(String subscriberId, boolean isRoaming) { final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); final NetworkCapabilities capabilities = new NetworkCapabilities(); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming); capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - return new NetworkState( - TYPE_MOBILE, prop, capabilities, MOBILE_NETWORK, subscriberId, null); + return new NetworkStateSnapshot( + MOBILE_NETWORK, capabilities, prop, subscriberId, TYPE_MOBILE); } private NetworkStats buildEmptyStats() { return new NetworkStats(getElapsedRealtime(), 0); } - private static NetworkState buildVpnState() { + private static NetworkStateSnapshot buildOemManagedMobileState( + String subscriberId, boolean isRoaming, int[] oemNetCapabilities) { final LinkProperties prop = new LinkProperties(); - prop.setInterfaceName(TUN_IFACE); - return new NetworkState(TYPE_VPN, prop, new NetworkCapabilities(), VPN_NETWORK, null, null); + prop.setInterfaceName(TEST_IFACE); + final NetworkCapabilities capabilities = new NetworkCapabilities(); + capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false); + capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming); + for (int nc : oemNetCapabilities) { + capabilities.setCapability(nc, true); + } + capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); + return new NetworkStateSnapshot(MOBILE_NETWORK, capabilities, prop, subscriberId, + TYPE_MOBILE); } private long getElapsedRealtime() { diff --git a/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java index e482708e385b..a0a5a293f2e4 100644 --- a/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java +++ b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java @@ -92,6 +92,14 @@ public class FakeSettingsProvider extends MockContentProvider { } /** + * Creates a {@link org.junit.rules.TestRule} that makes sure {@link #clearSettingsProvider()} + * is triggered before and after each test. + */ + public static FakeSettingsProviderRule rule() { + return new FakeSettingsProviderRule(); + } + + /** * This needs to be called before and after using the FakeSettingsProvider class. */ public static void clearSettingsProvider() { diff --git a/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java new file mode 100644 index 000000000000..c4e9545dfde2 --- /dev/null +++ b/tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProviderRule.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util.test; + +import android.content.Context; +import android.provider.Settings; +import android.test.mock.MockContentResolver; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * JUnit Rule helps keeping test {@link FakeSettingsProvider} clean. + * + * <p>It clears {@link FakeSettingsProvider} before and after each test. Example use: + * <pre class="code"><code class="java"> + * public class ExampleTest { + * + * @Rule public FakeSettingsProviderRule rule = FakeSettingsProvider.rule(); + * + * @Test + * public void shouldDoSomething() { + * ContextResolver cr = rule.mockContentResolver(mContext); + * Settings.Global.putInt(cr, "my_setting_name", 1); + * // Test code relying on my_setting_name value using cr + * } + * } + * </code></pre> + * + * @see FakeSettingsProvider + */ +public final class FakeSettingsProviderRule implements TestRule { + + /** Prevent initialization outside {@link FakeSettingsProvider}. */ + FakeSettingsProviderRule() { + } + + /** + * Creates a {@link MockContentResolver} that uses the {@link FakeSettingsProvider} as the + * {@link Settings#AUTHORITY} provider. + */ + public MockContentResolver mockContentResolver(Context context) { + MockContentResolver contentResolver = new MockContentResolver(context); + contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); + return contentResolver; + } + + @Override + public Statement apply(Statement base, Description description) { + return new Statement() { + public void evaluate() throws Throwable { + FakeSettingsProvider.clearSettingsProvider(); + try { + base.evaluate(); + } finally { + FakeSettingsProvider.clearSettingsProvider(); + } + } + }; + } +} diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java index 708767605508..7515971b8307 100644 --- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java +++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java @@ -16,6 +16,8 @@ package android.net.vcn; +import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE; + import static androidx.test.InstrumentationRegistry.getContext; import static org.junit.Assert.assertEquals; @@ -201,13 +203,13 @@ public class VcnManagerTest { IVcnStatusCallback cbBinder = new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback); - cbBinder.onEnteredSafeMode(); - verify(mMockStatusCallback).onEnteredSafeMode(); + cbBinder.onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE); + verify(mMockStatusCallback).onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE); cbBinder.onGatewayConnectionError( UNDERLYING_NETWORK_CAPABILITIES, VcnManager.VCN_ERROR_CODE_NETWORK_ERROR, - "java.net.UnknownHostException", + UnknownHostException.class.getName(), "exception_message"); verify(mMockStatusCallback) .onGatewayConnectionError( diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java index 3ba0a1f53a9f..a674425efea3 100644 --- a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java +++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java @@ -46,6 +46,6 @@ public class VcnUnderlyingNetworkPolicyTest { @Test public void testParcelUnparcel() { - assertParcelSane(SAMPLE_NETWORK_POLICY, 2); + assertParcelSane(SAMPLE_NETWORK_POLICY, 1); } } diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java index 45b2381ce06d..11498dec8165 100644 --- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java +++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java @@ -43,7 +43,6 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -59,6 +58,7 @@ import android.net.vcn.IVcnStatusCallback; import android.net.vcn.IVcnUnderlyingNetworkPolicyListener; import android.net.vcn.VcnConfig; import android.net.vcn.VcnConfigTest; +import android.net.vcn.VcnManager; import android.net.vcn.VcnUnderlyingNetworkPolicy; import android.net.wifi.WifiInfo; import android.os.IBinder; @@ -100,6 +100,8 @@ import java.util.UUID; public class VcnManagementServiceTest { private static final String TEST_PACKAGE_NAME = VcnManagementServiceTest.class.getPackage().getName(); + private static final String TEST_CB_PACKAGE_NAME = + VcnManagementServiceTest.class.getPackage().getName() + ".callback"; private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0)); private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1)); private static final VcnConfig TEST_VCN_CONFIG; @@ -288,6 +290,14 @@ public class VcnManagementServiceTest { private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( Set<ParcelUuid> activeSubscriptionGroups, Map<Integer, ParcelUuid> subIdToGroupMap) { + return triggerSubscriptionTrackerCbAndGetSnapshot( + activeSubscriptionGroups, subIdToGroupMap, true /* hasCarrierPrivileges */); + } + + private TelephonySubscriptionSnapshot triggerSubscriptionTrackerCbAndGetSnapshot( + Set<ParcelUuid> activeSubscriptionGroups, + Map<Integer, ParcelUuid> subIdToGroupMap, + boolean hasCarrierPrivileges) { final TelephonySubscriptionSnapshot snapshot = mock(TelephonySubscriptionSnapshot.class); doReturn(activeSubscriptionGroups).when(snapshot).getActiveSubscriptionGroups(); @@ -295,7 +305,7 @@ public class VcnManagementServiceTest { (activeSubscriptionGroups == null || activeSubscriptionGroups.isEmpty()) ? Collections.emptySet() : Collections.singleton(TEST_PACKAGE_NAME); - doReturn(true) + doReturn(hasCarrierPrivileges) .when(snapshot) .packageHasPermissionsForSubscriptionGroup( argThat(val -> activeSubscriptionGroups.contains(val)), @@ -451,6 +461,34 @@ public class VcnManagementServiceTest { } @Test + public void testSetVcnConfigNotifiesStatusCallback() throws Exception { + mVcnMgmtSvc.systemReady(); + doReturn(true) + .when(mLocationPermissionChecker) + .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any()); + triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2)); + + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); + + // Use a different UUID to simulate a new VCN config. + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); + } + + @Test + public void testSetVcnConfigInSafeModeNotifiesStatusCallback() throws Exception { + setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */); + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); + + mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); + } + + @Test public void testClearVcnConfigRequiresNonSystemServer() throws Exception { doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid(); @@ -493,6 +531,17 @@ public class VcnManagementServiceTest { } @Test + public void testClearVcnConfigNotifiesStatusCallback() throws Exception { + setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */); + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME); + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); + + mVcnMgmtSvc.clearVcnConfig(TEST_UUID_2); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); + } + + @Test public void testSetVcnConfigClearVcnConfigStartsUpdatesAndTeardsDownVcns() throws Exception { // Use a different UUID to simulate a new VCN config. mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); @@ -549,13 +598,6 @@ public class VcnManagementServiceTest { mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); } - private void setUpVcnSubscription(int subId, ParcelUuid subGroup) { - mVcnMgmtSvc.setVcnConfig(subGroup, TEST_VCN_CONFIG, TEST_PACKAGE_NAME); - - triggerSubscriptionTrackerCbAndGetSnapshot( - Collections.singleton(subGroup), Collections.singletonMap(subId, subGroup)); - } - private void verifyMergedNetworkCapabilities( NetworkCapabilities mergedCapabilities, @Transport int transportType, @@ -573,9 +615,23 @@ public class VcnManagementServiceTest { } private void setupSubscriptionAndStartVcn(int subId, ParcelUuid subGrp, boolean isVcnActive) { - setUpVcnSubscription(subId, subGrp); + setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive, true /* hasCarrierPrivileges */); + } + + private void setupSubscriptionAndStartVcn( + int subId, ParcelUuid subGrp, boolean isVcnActive, boolean hasCarrierPrivileges) { + mVcnMgmtSvc.systemReady(); + triggerSubscriptionTrackerCbAndGetSnapshot( + Collections.singleton(subGrp), + Collections.singletonMap(subId, subGrp), + hasCarrierPrivileges); + final Vcn vcn = startAndGetVcnInstance(subGrp); doReturn(isVcnActive).when(vcn).isActive(); + + doReturn(true) + .when(mLocationPermissionChecker) + .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any()); } private VcnUnderlyingNetworkPolicy startVcnAndGetPolicyForTransport( @@ -721,7 +777,7 @@ public class VcnManagementServiceTest { verify(mMockPolicyListener).onPolicyChanged(); } - private void verifyVcnCallback( + private void triggerVcnSafeMode( @NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot) throws Exception { verify(mMockDeps) @@ -732,20 +788,20 @@ public class VcnManagementServiceTest { eq(snapshot), mVcnCallbackCaptor.capture()); - mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); - VcnCallback vcnCallback = mVcnCallbackCaptor.getValue(); vcnCallback.onEnteredSafeMode(); - - verify(mMockPolicyListener).onPolicyChanged(); } @Test - public void testVcnCallbackOnEnteredSafeMode() throws Exception { + public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception { TelephonySubscriptionSnapshot snapshot = triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1)); - verifyVcnCallback(TEST_UUID_1, snapshot); + mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener); + + triggerVcnSafeMode(TEST_UUID_1, snapshot); + + verify(mMockPolicyListener).onPolicyChanged(); } private void triggerVcnStatusCallbackOnEnteredSafeMode( @@ -758,6 +814,9 @@ public class VcnManagementServiceTest { TelephonySubscriptionSnapshot snapshot = triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(subGroup)); + setupSubscriptionAndStartVcn( + TEST_SUBSCRIPTION_ID, subGroup, true /* isActive */, hasPermissionsforSubGroup); + doReturn(hasPermissionsforSubGroup) .when(snapshot) .packageHasPermissionsForSubscriptionGroup(eq(subGroup), eq(pkgName)); @@ -768,10 +827,7 @@ public class VcnManagementServiceTest { mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName); - // Trigger systemReady() to set up LocationPermissionChecker - mVcnMgmtSvc.systemReady(); - - verifyVcnCallback(subGroup, snapshot); + triggerVcnSafeMode(subGroup, snapshot); } @Test @@ -783,7 +839,7 @@ public class VcnManagementServiceTest { true /* hasPermissionsforSubGroup */, true /* hasLocationPermission */); - verify(mMockStatusCallback, times(1)).onEnteredSafeMode(); + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); } @Test @@ -795,7 +851,8 @@ public class VcnManagementServiceTest { false /* hasPermissionsforSubGroup */, true /* hasLocationPermission */); - verify(mMockStatusCallback, never()).onEnteredSafeMode(); + verify(mMockStatusCallback, never()) + .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); } @Test @@ -807,7 +864,8 @@ public class VcnManagementServiceTest { true /* hasPermissionsforSubGroup */, false /* hasLocationPermission */); - verify(mMockStatusCallback, never()).onEnteredSafeMode(); + verify(mMockStatusCallback, never()) + .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); } @Test @@ -823,6 +881,83 @@ public class VcnManagementServiceTest { assertEquals(TEST_PACKAGE_NAME, cbInfo.mPkgName); assertEquals(TEST_UID, cbInfo.mUid); verify(mMockIBinder).linkToDeath(eq(cbInfo), anyInt()); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); + } + + @Test + public void testRegisterVcnStatusCallback_MissingPermission() throws Exception { + setupSubscriptionAndStartVcn( + TEST_SUBSCRIPTION_ID, + TEST_UUID_1, + true /* isActive */, + false /* hasCarrierPrivileges */); + + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED); + } + + @Test + public void testRegisterVcnStatusCallback_VcnInactive() throws Exception { + setupSubscriptionAndStartVcn( + TEST_SUBSCRIPTION_ID, + TEST_UUID_1, + true /* isActive */, + true /* hasCarrierPrivileges */); + + // VCN is currently active. Lose carrier privileges for TEST_PACKAGE and hit teardown + // timeout so the VCN goes inactive. + final TelephonySubscriptionSnapshot snapshot = + triggerSubscriptionTrackerCbAndGetSnapshot( + Collections.singleton(TEST_UUID_1), + Collections.singletonMap(TEST_SUBSCRIPTION_ID, TEST_UUID_1), + false /* hasCarrierPrivileges */); + mTestLooper.moveTimeForward(VcnManagementService.CARRIER_PRIVILEGES_LOST_TEARDOWN_DELAY_MS); + mTestLooper.dispatchAll(); + + // Giving TEST_PACKAGE privileges again will restart the VCN (which will indicate ACTIVE + // when the status callback is registered). Instead, setup permissions for TEST_CB_PACKAGE + // so that it's permissioned to receive INACTIVE (instead of NOT_CONFIGURED) without + // reactivating the VCN. + doReturn(true) + .when(snapshot) + .packageHasPermissionsForSubscriptionGroup( + eq(TEST_UUID_1), eq(TEST_CB_PACKAGE_NAME)); + doReturn(true) + .when(mLocationPermissionChecker) + .checkLocationPermission(eq(TEST_CB_PACKAGE_NAME), any(), eq(TEST_UID), any()); + + mVcnMgmtSvc.registerVcnStatusCallback( + TEST_UUID_1, mMockStatusCallback, TEST_CB_PACKAGE_NAME); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_INACTIVE); + } + + @Test + public void testRegisterVcnStatusCallback_VcnActive() throws Exception { + setupSubscriptionAndStartVcn( + TEST_SUBSCRIPTION_ID, + TEST_UUID_1, + true /* isActive */, + true /* hasCarrierPrivileges */); + + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE); + } + + @Test + public void testRegisterVcnStatusCallback_VcnSafeMode() throws Exception { + setupSubscriptionAndStartVcn( + TEST_SUBSCRIPTION_ID, + TEST_UUID_1, + false /* isActive */, + true /* hasCarrierPrivileges */); + + mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_1, mMockStatusCallback, TEST_PACKAGE_NAME); + + verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE); } @Test(expected = IllegalStateException.class) diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index 69c21b967917..4bf849111a5d 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -36,6 +36,7 @@ import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -143,11 +144,18 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform()); mTestLooper.dispatchAll(); + verify(mIpSecSvc, times(2)) + .setNetworkForTunnelInterface( + eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), + eq(TEST_UNDERLYING_NETWORK_RECORD_1.network), + any()); + for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT}) { verify(mIpSecSvc) .applyTunnelModeTransform( eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any()); } + assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); } @@ -233,7 +241,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verify(mGatewayStatusCallback) .onGatewayConnectionError( - eq(mConfig.getRequiredUnderlyingCapabilities()), + eq(mConfig.getExposedCapabilities()), eq(VCN_ERROR_CODE_INTERNAL_ERROR), any(), any()); @@ -267,10 +275,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verify(mGatewayStatusCallback) .onGatewayConnectionError( - eq(mConfig.getRequiredUnderlyingCapabilities()), - eq(expectedErrorType), - any(), - any()); + eq(mConfig.getExposedCapabilities()), eq(expectedErrorType), any(), any()); } @Test @@ -290,4 +295,22 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback( new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR); } + + @Test + public void testTeardown() throws Exception { + mGatewayConnection.teardownAsynchronously(); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertTrue(mGatewayConnection.isQuitting()); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java index 17ae19e086cf..d07d2cf4f1bb 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java @@ -19,6 +19,8 @@ package com.android.server.vcn; import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -111,4 +113,22 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio public void testSafeModeTimeoutNotifiesCallback() { verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState); } + + @Test + public void testTeardown() throws Exception { + mGatewayConnection.teardownAsynchronously(); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertTrue(mGatewayConnection.isQuitting()); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java index 9ea641f52e48..5f27fabb62b0 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java @@ -21,9 +21,12 @@ import static android.net.IpSecManager.IpSecTunnelInterface; import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.net.IpSecManager; @@ -54,7 +57,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect } @Test - public void testEnterWhileNotRunningTriggersQuit() throws Exception { + public void testEnterWhileQuittingTriggersQuit() throws Exception { final VcnGatewayConnection vgc = new VcnGatewayConnection( mVcnContext, @@ -64,7 +67,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect mGatewayStatusCallback, mDeps); - vgc.setIsRunning(false); + vgc.setIsQuitting(true); vgc.transitionTo(vgc.mDisconnectedState); mTestLooper.dispatchAll(); @@ -101,5 +104,18 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect assertNull(mGatewayConnection.getCurrentState()); verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any()); verifySafeModeTimeoutAlarmAndGetCallback(true /* expectCanceled */); + assertTrue(mGatewayConnection.isQuitting()); + verify(mGatewayStatusCallback).onQuit(); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + verify(mGatewayStatusCallback, never()).onQuit(); + // No safe mode timer changes expected. } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java index 7385204993c0..661e03af4f84 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectingStateTest.java @@ -18,6 +18,8 @@ package com.android.server.vcn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -79,10 +81,20 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec // Should do nothing; already tearing down. assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */); + assertTrue(mGatewayConnection.isQuitting()); } @Test public void testSafeModeTimeoutNotifiesCallback() { verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState); } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java index 5b0850b03f1a..85a0277f8b48 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java @@ -17,6 +17,9 @@ package com.android.server.vcn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -96,4 +99,22 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect public void testSafeModeTimeoutNotifiesCallback() { verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState); } + + @Test + public void testTeardownDisconnectRequest() throws Exception { + mGatewayConnection.teardownAsynchronously(); + mTestLooper.dispatchAll(); + + assertNull(mGatewayConnection.getCurrentState()); + assertTrue(mGatewayConnection.isQuitting()); + } + + @Test + public void testNonTeardownDisconnectRequest() throws Exception { + mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState()); + assertFalse(mGatewayConnection.isQuitting()); + } } diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java index 9d3368271243..4fa63d4ff640 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java @@ -16,9 +16,15 @@ package com.android.server.vcn; +import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -33,6 +39,7 @@ import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfigTest; import android.os.ParcelUuid; import android.os.test.TestLooper; +import android.util.ArraySet; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; @@ -43,6 +50,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; +import java.util.Arrays; import java.util.Set; import java.util.UUID; @@ -51,6 +59,11 @@ public class VcnTest { private static final ParcelUuid TEST_SUB_GROUP = new ParcelUuid(new UUID(0, 0)); private static final int NETWORK_SCORE = 0; private static final int PROVIDER_ID = 5; + private static final int[][] TEST_CAPS = + new int[][] { + new int[] {NET_CAPABILITY_MMS, NET_CAPABILITY_INTERNET}, + new int[] {NET_CAPABILITY_DUN} + }; private Context mContext; private VcnContext mVcnContext; @@ -91,13 +104,12 @@ public class VcnTest { mGatewayStatusCallbackCaptor = ArgumentCaptor.forClass(VcnGatewayStatusCallback.class); final VcnConfig.Builder configBuilder = new VcnConfig.Builder(mContext); - for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) { + for (final int[] caps : TEST_CAPS) { configBuilder.addGatewayConnectionConfig( - VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(capability)); + VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(caps)); } - configBuilder.addGatewayConnectionConfig(VcnGatewayConnectionConfigTest.buildTestConfig()); - mConfig = configBuilder.build(); + mConfig = configBuilder.build(); mVcn = new Vcn( mVcnContext, @@ -130,8 +142,7 @@ public class VcnTest { @Test public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() { final NetworkRequestListener requestListener = verifyAndGetRequestListener(); - startVcnGatewayWithCapabilities( - requestListener, VcnGatewayConnectionConfigTest.EXPOSED_CAPS); + startVcnGatewayWithCapabilities(requestListener, TEST_CAPS[0]); final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections(); assertFalse(gatewayConnections.isEmpty()); @@ -147,16 +158,17 @@ public class VcnTest { } } - @Test - public void testGatewayEnteringSafeModeNotifiesVcn() { - final NetworkRequestListener requestListener = verifyAndGetRequestListener(); - for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) { - startVcnGatewayWithCapabilities(requestListener, capability); + private void triggerVcnRequestListeners(NetworkRequestListener requestListener) { + for (final int[] caps : TEST_CAPS) { + startVcnGatewayWithCapabilities(requestListener, caps); } + } - // Each Capability in EXPOSED_CAPS was split into a separate VcnGatewayConnection in #setUp. - // Expect one VcnGatewayConnection per capability. - final int numExpectedGateways = VcnGatewayConnectionConfigTest.EXPOSED_CAPS.length; + public Set<VcnGatewayConnection> startGatewaysAndGetGatewayConnections( + NetworkRequestListener requestListener) { + triggerVcnRequestListeners(requestListener); + + final int numExpectedGateways = TEST_CAPS.length; final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections(); assertEquals(numExpectedGateways, gatewayConnections.size()); @@ -168,17 +180,95 @@ public class VcnTest { any(), mGatewayStatusCallbackCaptor.capture()); - // Doesn't matter which callback this gets - any Gateway entering safe mode should shut down - // all Gateways - final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); - statusCallback.onEnteredSafeMode(); - mTestLooper.dispatchAll(); + return gatewayConnections; + } + private void verifySafeMode( + NetworkRequestListener requestListener, + Set<VcnGatewayConnection> expectedGatewaysTornDown) { assertFalse(mVcn.isActive()); - for (final VcnGatewayConnection gatewayConnection : gatewayConnections) { + assertTrue(mVcn.getVcnGatewayConnections().isEmpty()); + for (final VcnGatewayConnection gatewayConnection : expectedGatewaysTornDown) { verify(gatewayConnection).teardownAsynchronously(); } verify(mVcnNetworkProvider).unregisterListener(requestListener); verify(mVcnCallback).onEnteredSafeMode(); } + + @Test + public void testGatewayEnteringSafeModeNotifiesVcn() { + final NetworkRequestListener requestListener = verifyAndGetRequestListener(); + final Set<VcnGatewayConnection> gatewayConnections = + startGatewaysAndGetGatewayConnections(requestListener); + + // Doesn't matter which callback this gets - any Gateway entering Safemode should shut down + // all Gateways + final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); + statusCallback.onEnteredSafeMode(); + mTestLooper.dispatchAll(); + + verifySafeMode(requestListener, gatewayConnections); + } + + @Test + public void testGatewayQuit() { + final NetworkRequestListener requestListener = verifyAndGetRequestListener(); + final Set<VcnGatewayConnection> gatewayConnections = + new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener)); + + final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); + statusCallback.onQuit(); + mTestLooper.dispatchAll(); + + // Verify that the VCN requests the networkRequests be resent + assertEquals(1, mVcn.getVcnGatewayConnections().size()); + verify(mVcnNetworkProvider).resendAllRequests(requestListener); + + // Verify that the VcnGatewayConnection is restarted + triggerVcnRequestListeners(requestListener); + mTestLooper.dispatchAll(); + assertEquals(2, mVcn.getVcnGatewayConnections().size()); + verify(mDeps, times(gatewayConnections.size() + 1)) + .newVcnGatewayConnection( + eq(mVcnContext), + eq(TEST_SUB_GROUP), + eq(mSubscriptionSnapshot), + any(), + mGatewayStatusCallbackCaptor.capture()); + } + + @Test + public void testUpdateConfigExitsSafeMode() { + final NetworkRequestListener requestListener = verifyAndGetRequestListener(); + final Set<VcnGatewayConnection> gatewayConnections = + new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener)); + + final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue(); + statusCallback.onEnteredSafeMode(); + mTestLooper.dispatchAll(); + verifySafeMode(requestListener, gatewayConnections); + + doAnswer(invocation -> { + final NetworkRequestListener listener = invocation.getArgument(0); + triggerVcnRequestListeners(listener); + return null; + }).when(mVcnNetworkProvider).registerListener(eq(requestListener)); + + mVcn.updateConfig(mConfig); + mTestLooper.dispatchAll(); + + // Registered on start, then re-registered with new configs + verify(mVcnNetworkProvider, times(2)).registerListener(eq(requestListener)); + assertTrue(mVcn.isActive()); + for (final int[] caps : TEST_CAPS) { + // Expect each gateway connection created on initial startup, and again with new configs + verify(mDeps, times(2)) + .newVcnGatewayConnection( + eq(mVcnContext), + eq(TEST_SUB_GROUP), + eq(mSubscriptionSnapshot), + argThat(config -> Arrays.equals(caps, config.getExposedCapabilities())), + any()); + } + } } |