Merge "Add a test to check if the VPN type is set or not" into sc-dev
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 58cd7cc..48ae7a0 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -80,6 +80,8 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
@@ -2630,6 +2632,12 @@
"ConnectivityService");
}
+ private void enforceManageTestNetworksPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_TEST_NETWORKS,
+ "ConnectivityService");
+ }
+
private boolean checkNetworkStackPermission() {
return checkAnyPermissionOf(
android.Manifest.permission.NETWORK_STACK,
@@ -9926,8 +9934,15 @@
@NonNull final OemNetworkPreferences preference,
@Nullable final IOnCompleteListener listener) {
- enforceAutomotiveDevice();
- enforceOemNetworkPreferencesPermission();
+ Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
+ // Only bypass the permission/device checks if this is a valid test request.
+ if (isValidTestOemNetworkPreference(preference)) {
+ enforceManageTestNetworksPermission();
+ } else {
+ enforceAutomotiveDevice();
+ enforceOemNetworkPreferencesPermission();
+ validateOemNetworkPreferences(preference);
+ }
// TODO: Have a priority for each preference.
if (!mProfileNetworkPreferences.isEmpty() || !mMobileDataPreferredUids.isEmpty()) {
@@ -9939,18 +9954,41 @@
throwConcurrentPreferenceException();
}
- Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
- validateOemNetworkPreferences(preference);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE,
new Pair<>(preference, listener)));
}
+ /**
+ * Check the validity of an OEM network preference to be used for testing purposes.
+ * @param preference the preference to validate
+ * @return true if this is a valid OEM network preference test request.
+ */
+ private boolean isValidTestOemNetworkPreference(
+ @NonNull final OemNetworkPreferences preference) {
+ // Allow for clearing of an existing OemNetworkPreference used for testing.
+ // This isn't called on the handler thread so it is possible that mOemNetworkPreferences
+ // changes after this check is complete. This is an unlikely scenario as calling of this API
+ // is controlled by the OEM therefore the added complexity is not worth adding given those
+ // circumstances. That said, it is an edge case to be aware of hence this comment.
+ final boolean isValidTestClearPref = preference.getNetworkPreferences().size() == 0
+ && isTestOemNetworkPreference(mOemNetworkPreferences);
+ return isTestOemNetworkPreference(preference) || isValidTestClearPref;
+ }
+
+ private boolean isTestOemNetworkPreference(@NonNull final OemNetworkPreferences preference) {
+ final Map<String, Integer> prefMap = preference.getNetworkPreferences();
+ return prefMap.size() == 1
+ && (prefMap.containsValue(OEM_NETWORK_PREFERENCE_TEST)
+ || prefMap.containsValue(OEM_NETWORK_PREFERENCE_TEST_ONLY));
+ }
+
private void validateOemNetworkPreferences(@NonNull OemNetworkPreferences preference) {
for (@OemNetworkPreferences.OemNetworkPreference final int pref
: preference.getNetworkPreferences().values()) {
- if (OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED == pref) {
- final String msg = "OEM_NETWORK_PREFERENCE_UNINITIALIZED is an invalid value.";
- throw new IllegalArgumentException(msg);
+ if (pref <= 0 || OemNetworkPreferences.OEM_NETWORK_PREFERENCE_MAX < pref) {
+ throw new IllegalArgumentException(
+ OemNetworkPreferences.oemNetworkPreferenceToString(pref)
+ + " is an invalid value.");
}
}
}
@@ -10174,13 +10212,21 @@
case OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY:
requests.add(createOemPrivateNetworkRequest());
break;
+ case OEM_NETWORK_PREFERENCE_TEST:
+ requests.add(createUnmeteredNetworkRequest());
+ requests.add(createTestNetworkRequest());
+ requests.add(createDefaultRequest());
+ break;
+ case OEM_NETWORK_PREFERENCE_TEST_ONLY:
+ requests.add(createTestNetworkRequest());
+ break;
default:
// This should never happen.
throw new IllegalArgumentException("createNriFromOemNetworkPreferences()"
+ " called with invalid preference of " + preference);
}
- final ArraySet ranges = new ArraySet<Integer>();
+ final ArraySet<UidRange> ranges = new ArraySet<>();
for (final int uid : uids) {
ranges.add(new UidRange(uid, uid));
}
@@ -10213,10 +10259,17 @@
}
private NetworkCapabilities createDefaultPerAppNetCap() {
- final NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addCapability(NET_CAPABILITY_INTERNET);
- netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
- return netCap;
+ final NetworkCapabilities netcap = new NetworkCapabilities();
+ netcap.addCapability(NET_CAPABILITY_INTERNET);
+ netcap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
+ return netcap;
+ }
+
+ private NetworkRequest createTestNetworkRequest() {
+ final NetworkCapabilities netcap = new NetworkCapabilities();
+ netcap.clearAll();
+ netcap.addTransportType(TRANSPORT_TEST);
+ return createNetworkRequest(NetworkRequest.Type.REQUEST, netcap);
}
}
}
diff --git a/tests/common/java/android/net/NetworkAgentConfigTest.kt b/tests/common/java/android/net/NetworkAgentConfigTest.kt
index 2b45b3d..afaae1c 100644
--- a/tests/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/common/java/android/net/NetworkAgentConfigTest.kt
@@ -59,6 +59,7 @@
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
fun testBuilder() {
+ val testExtraInfo = "mylegacyExtraInfo"
val config = NetworkAgentConfig.Builder().apply {
setExplicitlySelected(true)
setLegacyType(ConnectivityManager.TYPE_ETHERNET)
@@ -67,6 +68,7 @@
setUnvalidatedConnectivityAcceptable(true)
setLegacyTypeName("TEST_NETWORK")
if (isAtLeastS()) {
+ setLegacyExtraInfo(testExtraInfo)
setNat64DetectionEnabled(false)
setProvisioningNotificationEnabled(false)
setBypassableVpn(true)
@@ -80,6 +82,7 @@
assertTrue(config.isUnvalidatedConnectivityAcceptable())
assertEquals("TEST_NETWORK", config.getLegacyTypeName())
if (isAtLeastS()) {
+ assertEquals(testExtraInfo, config.getLegacyExtraInfo())
assertFalse(config.isNat64DetectionEnabled())
assertFalse(config.isProvisioningNotificationEnabled())
assertTrue(config.isBypassableVpn())
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index acec9a4..ae59dc4 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -152,6 +152,7 @@
import com.android.networkstack.apishim.common.ConnectivityManagerShim;
import com.android.testutils.CompatUtil;
import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRuleKt;
import com.android.testutils.RecorderCallback.CallbackEntry;
import com.android.testutils.SkipPresubmit;
@@ -674,6 +675,31 @@
.build();
}
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testIsPrivateDnsBroken() throws InterruptedException {
+ final String invalidPrivateDnsServer = "invalidhostname.example.com";
+ final String goodPrivateDnsServer = "dns.google";
+ mCtsNetUtils.storePrivateDnsSetting();
+ final TestableNetworkCallback cb = new TestableNetworkCallback();
+ mCm.registerNetworkCallback(makeWifiNetworkRequest(), cb);
+ try {
+ // Verifying the good private DNS sever
+ mCtsNetUtils.setPrivateDnsStrictMode(goodPrivateDnsServer);
+ final Network networkForPrivateDns = mCtsNetUtils.ensureWifiConnected();
+ cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .isPrivateDnsBroken()) && networkForPrivateDns.equals(entry.getNetwork()));
+
+ // Verifying the broken private DNS sever
+ mCtsNetUtils.setPrivateDnsStrictMode(invalidPrivateDnsServer);
+ cb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED, NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> (((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .isPrivateDnsBroken()) && networkForPrivateDns.equals(entry.getNetwork()));
+ } finally {
+ mCtsNetUtils.restorePrivateDnsSetting();
+ }
+ }
+
/**
* Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to
* see if we get a callback for the TRANSPORT_WIFI transport type being available.
diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
index bca4456..637ed26 100644
--- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
@@ -30,6 +30,7 @@
import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -456,6 +457,21 @@
}
}
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testGetCapabilities() {
+ final int[] netCapabilities = new int[] {
+ NET_CAPABILITY_INTERNET,
+ NET_CAPABILITY_NOT_ROAMING };
+ final NetworkCapabilities.Builder builder = NetworkCapabilities.Builder
+ .withoutDefaultCapabilities();
+ for (int capability : netCapabilities) builder.addCapability(capability);
+ final NetworkRequest nr = new NetworkRequest.Builder()
+ .clearCapabilities()
+ .setCapabilities(builder.build())
+ .build();
+ assertArrayEquals(netCapabilities, nr.getCapabilities());
+ }
+
@Test
public void testBuildRequestFromExistingRequestWithBuilder() {
assumeTrue(TestUtils.shouldTestSApis());
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 308b038..4530650 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -109,6 +109,8 @@
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_TEST;
+import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_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;
@@ -10715,8 +10717,7 @@
}
@Test
- public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError()
- throws PackageManager.NameNotFoundException {
+ public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
@OemNetworkPreferences.OemNetworkPreference final int prefToTest =
OEM_NETWORK_PREFERENCE_UNINITIALIZED;
@@ -10983,7 +10984,48 @@
assertThrows(UnsupportedOperationException.class,
() -> mService.setOemNetworkPreference(
createDefaultOemNetworkPreferences(networkPref),
- new TestOemListenerCallback()));
+ null));
+ }
+
+ @Test
+ public void testSetOemNetworkPreferenceFailsForTestRequestWithoutPermission() {
+ // Calling setOemNetworkPreference() with a test pref requires the permission
+ // MANAGE_TEST_NETWORKS.
+ mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
+ @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+ OEM_NETWORK_PREFERENCE_TEST;
+
+ // Act on ConnectivityService.setOemNetworkPreference()
+ assertThrows(SecurityException.class,
+ () -> mService.setOemNetworkPreference(
+ createDefaultOemNetworkPreferences(networkPref),
+ null));
+ }
+
+ @Test
+ public void testSetOemNetworkPreferenceFailsForInvalidTestRequest() {
+ assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST);
+ }
+
+ @Test
+ public void testSetOemNetworkPreferenceFailsForInvalidTestOnlyRequest() {
+ assertSetOemNetworkPreferenceFailsForInvalidTestRequest(OEM_NETWORK_PREFERENCE_TEST_ONLY);
+ }
+
+ private void assertSetOemNetworkPreferenceFailsForInvalidTestRequest(
+ @OemNetworkPreferences.OemNetworkPreference final int oemNetworkPreferenceForTest) {
+ mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
+ final String secondPackage = "does.not.matter";
+
+ // A valid test request would only have a single mapping.
+ final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
+ .addNetworkPreference(TEST_PACKAGE_NAME, oemNetworkPreferenceForTest)
+ .addNetworkPreference(secondPackage, oemNetworkPreferenceForTest)
+ .build();
+
+ // Act on ConnectivityService.setOemNetworkPreference()
+ assertThrows(IllegalArgumentException.class,
+ () -> mService.setOemNetworkPreference(pref, null));
}
private void setOemNetworkPreferenceAgentConnected(final int transportType,
@@ -11160,8 +11202,18 @@
private void setupSetOemNetworkPreferenceForPreferenceTest(
@OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
@NonNull final UidRangeParcel[] uidRanges,
- @NonNull final String testPackageName)
- throws Exception {
+ @NonNull final String testPackageName) throws Exception {
+ setupSetOemNetworkPreferenceForPreferenceTest(
+ networkPrefToSetup, uidRanges, testPackageName, true);
+ }
+
+ private void setupSetOemNetworkPreferenceForPreferenceTest(
+ @OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup,
+ @NonNull final UidRangeParcel[] uidRanges,
+ @NonNull final String testPackageName,
+ final boolean hasAutomotiveFeature) throws Exception {
+ mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, hasAutomotiveFeature);
+
// These tests work off a single UID therefore using 'start' is valid.
mockGetApplicationInfo(testPackageName, uidRanges[0].start);
@@ -11466,6 +11518,55 @@
}
/**
+ * Test the tracked default requests allows test requests without standard setup.
+ */
+ @Test
+ public void testSetOemNetworkPreferenceAllowsValidTestRequestWithoutChecks() throws Exception {
+ @OemNetworkPreferences.OemNetworkPreference int networkPref =
+ OEM_NETWORK_PREFERENCE_TEST;
+ validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
+ }
+
+ /**
+ * Test the tracked default requests allows test only requests without standard setup.
+ */
+ @Test
+ public void testSetOemNetworkPreferenceAllowsValidTestOnlyRequestWithoutChecks()
+ throws Exception {
+ @OemNetworkPreferences.OemNetworkPreference int networkPref =
+ OEM_NETWORK_PREFERENCE_TEST_ONLY;
+ validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(networkPref);
+ }
+
+ private void validateSetOemNetworkPreferenceAllowsValidTestPrefRequest(int networkPref)
+ throws Exception {
+ // The caller must have the MANAGE_TEST_NETWORKS permission.
+ final int testPackageUid = 123;
+ final String validTestPackageName = "does.not.matter";
+ final UidRangeParcel[] uidRanges =
+ toUidRangeStableParcels(uidRangesForUids(testPackageUid));
+ mServiceContext.setPermission(
+ Manifest.permission.MANAGE_TEST_NETWORKS, PERMISSION_GRANTED);
+
+ // Put the system into a state in which setOemNetworkPreference() would normally fail. This
+ // will confirm that a valid test request can bypass these checks.
+ mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
+ mServiceContext.setPermission(
+ Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE, PERMISSION_DENIED);
+
+ // Validate the starting requests only includes the system default request.
+ assertEquals(1, mService.mDefaultNetworkRequests.size());
+
+ // Add an OEM default network request to track.
+ setupSetOemNetworkPreferenceForPreferenceTest(
+ networkPref, uidRanges, validTestPackageName,
+ false /* hasAutomotiveFeature */);
+
+ // Two requests should now exist; the system default and the test request.
+ assertEquals(2, mService.mDefaultNetworkRequests.size());
+ }
+
+ /**
* Test the tracked default requests clear previous OEM requests on setOemNetworkPreference().
*/
@Test
@@ -11477,7 +11578,7 @@
final UidRangeParcel[] uidRanges =
toUidRangeStableParcels(uidRangesForUids(testPackageUid));
- // Validate the starting requests only includes the fallback request.
+ // Validate the starting requests only includes the system default request.
assertEquals(1, mService.mDefaultNetworkRequests.size());
// Add an OEM default network request to track.