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
This commit is contained in:
James Mattis 2021-05-31 17:11:10 -07:00
commit fa270db5f7

View file

@ -79,6 +79,8 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST;
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
"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 @@ public class ConnectivityService extends IConnectivityManager.Stub
@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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
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);
}
}
}