Update CS so that per-app OEM APIs can be tested
Updates to ConnectivityService so that the set OEM network preference
per app APIs can be tested via CTS.
Bug: 176496580
Bug: 176494815
Test: atest FrameworksNetTests
atest FrameworksNetIntegrationTests
atest CtsNetTestCasesLatestSdk
Change-Id: I5a47dcece31749293f080af060218d827082eb67
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 15b666a..55aa56b 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -79,6 +79,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;
@@ -2596,6 +2598,12 @@
"ConnectivityService");
}
+ private void enforceManageTestNetworksPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_TEST_NETWORKS,
+ "ConnectivityService");
+ }
+
private boolean checkNetworkStackPermission() {
return checkAnyPermissionOf(
android.Manifest.permission.NETWORK_STACK,
@@ -9876,8 +9884,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()) {
@@ -9889,18 +9904,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.");
}
}
}
@@ -10124,13 +10162,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));
}
@@ -10162,10 +10208,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);
}
}
}