Merge changes from topic "per-app-cts"

* changes:
  CTS tests for setOemNetworkPreference
  Update CS so that per-app OEM APIs can be tested
This commit is contained in:
Lorenzo Colitti
2021-06-16 00:47:06 +00:00
committed by Gerrit Code Review
3 changed files with 404 additions and 67 deletions

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;
@@ -2622,6 +2624,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,
@@ -9953,8 +9961,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()) {
@@ -9966,18 +9981,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.");
}
}
}
@@ -10201,13 +10239,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));
}
@@ -10240,10 +10286,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);
}
}
}

View File

@@ -65,11 +65,13 @@ import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.AF_UNSPEC;
import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertEquals;
@@ -112,6 +114,7 @@ import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStateSnapshot;
import android.net.NetworkUtils;
import android.net.OemNetworkPreferences;
import android.net.ProxyInfo;
import android.net.SocketKeepalive;
import android.net.TelephonyNetworkSpecifier;
@@ -155,6 +158,7 @@ import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRuleKt;
import com.android.testutils.RecorderCallback.CallbackEntry;
import com.android.testutils.SkipPresubmit;
import com.android.testutils.TestNetworkTracker;
import com.android.testutils.TestableNetworkCallback;
import junit.framework.AssertionFailedError;
@@ -191,6 +195,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -518,13 +523,8 @@ public class ConnectivityManagerTest {
@Test
@SkipPresubmit(reason = "Virtual devices use a single internet connection for all networks")
public void testOpenConnection() throws Exception {
boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
&& mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
if (!canRunTest) {
Log.i(TAG,"testOpenConnection cannot execute unless device supports both WiFi "
+ "and a cellular connection");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY));
Network wifiNetwork = mCtsNetUtils.connectToWifi();
Network cellNetwork = mCtsNetUtils.connectToCell();
@@ -699,10 +699,7 @@ public class ConnectivityManagerTest {
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testRegisterNetworkCallback() {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
// We will register for a WIFI network being available or lost.
final TestNetworkCallback callback = new TestNetworkCallback();
@@ -766,10 +763,7 @@ public class ConnectivityManagerTest {
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testRegisterNetworkCallback_withPendingIntent() {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
// Create a ConnectivityActionReceiver that has an IntentFilter for our locally defined
// action, NETWORK_CALLBACK_ACTION.
@@ -940,7 +934,8 @@ public class ConnectivityManagerTest {
}
}
private void waitForActiveNetworkMetered(int targetTransportType, boolean requestedMeteredness)
private void waitForActiveNetworkMetered(final int targetTransportType,
final boolean requestedMeteredness, final boolean useSystemDefault)
throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final NetworkCallback networkCallback = new NetworkCallback() {
@@ -954,17 +949,36 @@ public class ConnectivityManagerTest {
}
}
};
// Registering a callback here guarantees onCapabilitiesChanged is called immediately
// with the current setting. Therefore, if the setting has already been changed,
// this method will return right away, and if not it will wait for the setting to change.
mCm.registerDefaultNetworkCallback(networkCallback);
// Changing meteredness on wifi involves reconnecting, which can take several seconds
// (involves re-associating, DHCP...).
if (!latch.await(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
fail("Timed out waiting for active network metered status to change to "
+ requestedMeteredness + " ; network = " + mCm.getActiveNetwork());
try {
// Registering a callback here guarantees onCapabilitiesChanged is called immediately
// with the current setting. Therefore, if the setting has already been changed,
// this method will return right away, and if not, it'll wait for the setting to change.
if (useSystemDefault) {
runWithShellPermissionIdentity(() ->
mCmShim.registerSystemDefaultNetworkCallback(networkCallback,
new Handler(Looper.getMainLooper())),
NETWORK_SETTINGS);
} else {
mCm.registerDefaultNetworkCallback(networkCallback);
}
// Changing meteredness on wifi involves reconnecting, which can take several seconds
// (involves re-associating, DHCP...).
if (!latch.await(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
fail("Timed out waiting for active network metered status to change to "
+ requestedMeteredness + " ; network = " + mCm.getActiveNetwork());
}
} finally {
mCm.unregisterNetworkCallback(networkCallback);
}
mCm.unregisterNetworkCallback(networkCallback);
}
private void setWifiMeteredStatusAndWait(String ssid, boolean isMetered) throws Exception {
setWifiMeteredStatus(ssid, Boolean.toString(isMetered) /* metered */);
waitForActiveNetworkMetered(TRANSPORT_WIFI,
isMetered /* requestedMeteredness */,
true /* useSystemDefault */);
}
private void assertMultipathPreferenceIsEventually(Network network, int oldValue,
@@ -1026,10 +1040,9 @@ public class ConnectivityManagerTest {
int newMeteredPreference = findNextPrefValue(resolver);
Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE,
Integer.toString(newMeteredPreference));
setWifiMeteredStatus(ssid, "true");
waitForActiveNetworkMetered(TRANSPORT_WIFI, true);
// Wifi meterness changes from unmetered to metered will disconnect and reconnect since
// R.
setWifiMeteredStatusAndWait(ssid, true);
final Network network = mCtsNetUtils.ensureWifiConnected();
assertEquals(ssid, unquoteSSID(mWifiManager.getConnectionInfo().getSSID()));
assertEquals(mCm.getNetworkCapabilities(network).hasCapability(
@@ -1046,9 +1059,8 @@ public class ConnectivityManagerTest {
assertMultipathPreferenceIsEventually(network,
oldMeteredPreference, newMeteredPreference);
setWifiMeteredStatus(ssid, "false");
// No disconnect from unmetered to metered.
waitForActiveNetworkMetered(TRANSPORT_WIFI, false);
setWifiMeteredStatusAndWait(ssid, false);
assertEquals(mCm.getNetworkCapabilities(network).hasCapability(
NET_CAPABILITY_NOT_METERED), true);
assertMultipathPreferenceIsEventually(network, newMeteredPreference,
@@ -1238,11 +1250,7 @@ public class ConnectivityManagerTest {
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testKeepaliveWifiUnsupported() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testKeepaliveUnsupported cannot execute unless device"
+ " supports WiFi");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
final Network network = mCtsNetUtils.ensureWifiConnected();
if (getSupportedKeepalivesForNet(network) != 0) return;
@@ -1259,10 +1267,7 @@ public class ConnectivityManagerTest {
@Test
@SkipPresubmit(reason = "Keepalive is not supported on virtual hardware")
public void testCreateTcpKeepalive() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testCreateTcpKeepalive cannot execute unless device supports WiFi");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
final Network network = mCtsNetUtils.ensureWifiConnected();
if (getSupportedKeepalivesForNet(network) == 0) return;
@@ -1469,11 +1474,7 @@ public class ConnectivityManagerTest {
@Test
@SkipPresubmit(reason = "Keepalive is not supported on virtual hardware")
public void testSocketKeepaliveLimitWifi() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testSocketKeepaliveLimitWifi cannot execute unless device"
+ " supports WiFi");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
final Network network = mCtsNetUtils.ensureWifiConnected();
final int supported = getSupportedKeepalivesForNet(network);
@@ -1566,11 +1567,7 @@ public class ConnectivityManagerTest {
@Test
@SkipPresubmit(reason = "Keepalive is not supported on virtual hardware")
public void testSocketKeepaliveUnprivileged() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testSocketKeepaliveUnprivileged cannot execute unless device"
+ " supports WiFi");
return;
}
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
final Network network = mCtsNetUtils.ensureWifiConnected();
final int supported = getSupportedKeepalivesForNet(network);
@@ -1717,6 +1714,24 @@ public class ConnectivityManagerTest {
c -> c instanceof CallbackEntry.Available);
}
private void waitForAvailable(
@NonNull final TestableNetworkCallback cb, final int expectedTransport) {
cb.eventuallyExpect(
CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
entry -> {
final NetworkCapabilities nc = mCm.getNetworkCapabilities(entry.getNetwork());
return nc.hasTransport(expectedTransport);
}
);
}
private void waitForAvailable(
@NonNull final TestableNetworkCallback cb, @NonNull final Network expectedNetwork) {
cb.expectAvailableCallbacks(expectedNetwork, false /* suspended */,
true /* validated */,
false /* blocked */, NETWORK_CALLBACK_TIMEOUT_MS);
}
private void waitForLost(@NonNull final TestableNetworkCallback cb) {
cb.eventuallyExpect(CallbackEntry.LOST, NETWORK_CALLBACK_TIMEOUT_MS,
c -> c instanceof CallbackEntry.Lost);
@@ -2102,4 +2117,172 @@ public class ConnectivityManagerTest {
startTetheringCallback.verifyTetheringStarted();
callback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI);
}
/**
* Verify that per-app OEM network preference functions as expected for network preference TEST.
* For specified apps, validate networks are prioritized in order: unmetered, TEST transport,
* default network.
*/
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testSetOemNetworkPreferenceForTestPref() throws Exception {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
assumeTrue(TestUtils.shouldTestSApis());
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
final TestNetworkTracker tnt = callWithShellPermissionIdentity(
() -> initTestNetwork(mContext, TEST_LINKADDR, NETWORK_CALLBACK_TIMEOUT_MS));
final TestableNetworkCallback defaultCallback = new TestableNetworkCallback();
final TestableNetworkCallback systemDefaultCallback = new TestableNetworkCallback();
final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
final NetworkCapabilities wifiNetworkCapabilities = callWithShellPermissionIdentity(
() -> mCm.getNetworkCapabilities(wifiNetwork));
final String ssid = unquoteSSID(wifiNetworkCapabilities.getSsid());
final boolean oldMeteredValue = wifiNetworkCapabilities.isMetered();
try {
// This network will be used for unmetered.
setWifiMeteredStatusAndWait(ssid, false /* isMetered */);
setOemNetworkPreferenceForMyPackage(OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST);
registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
// Validate that an unmetered network is used over other networks.
waitForAvailable(defaultCallback, wifiNetwork);
waitForAvailable(systemDefaultCallback, wifiNetwork);
// Validate when setting unmetered to metered, unmetered is lost and replaced by the
// network with the TEST transport.
setWifiMeteredStatusAndWait(ssid, true /* isMetered */);
defaultCallback.expectCallback(CallbackEntry.LOST, wifiNetwork);
waitForAvailable(defaultCallback, tnt.getNetwork());
// Depending on if this device has cellular connectivity or not, multiple available
// callbacks may be received. Eventually, metered Wi-Fi should be the final available
// callback in any case therefore confirm its receipt before continuing to assure the
// system is in the expected state.
waitForAvailable(systemDefaultCallback, TRANSPORT_WIFI);
} finally {
// Validate that removing the test network will fallback to the default network.
runWithShellPermissionIdentity(tnt::teardown);
defaultCallback.expectCallback(CallbackEntry.LOST, tnt.getNetwork());
waitForAvailable(defaultCallback);
setWifiMeteredStatusAndWait(ssid, oldMeteredValue);
// Cleanup any prior test state from setOemNetworkPreference
clearOemNetworkPreference();
unregisterTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
}
}
/**
* Verify that per-app OEM network preference functions as expected for network pref TEST_ONLY.
* For specified apps, validate that only TEST transport type networks are used.
*/
@Test
public void testSetOemNetworkPreferenceForTestOnlyPref() throws Exception {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
assumeTrue(TestUtils.shouldTestSApis());
final TestNetworkTracker tnt = callWithShellPermissionIdentity(
() -> initTestNetwork(mContext, TEST_LINKADDR, NETWORK_CALLBACK_TIMEOUT_MS));
final TestableNetworkCallback defaultCallback = new TestableNetworkCallback();
final TestableNetworkCallback systemDefaultCallback = new TestableNetworkCallback();
final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
try {
setOemNetworkPreferenceForMyPackage(
OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY);
registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
waitForAvailable(defaultCallback, tnt.getNetwork());
waitForAvailable(systemDefaultCallback, wifiNetwork);
} finally {
runWithShellPermissionIdentity(tnt::teardown);
defaultCallback.expectCallback(CallbackEntry.LOST, tnt.getNetwork());
// This network preference should only ever use the test network therefore available
// should not trigger when the test network goes down (e.g. switch to cellular).
defaultCallback.assertNoCallback();
// The system default should still be connected to Wi-fi
assertEquals(wifiNetwork, systemDefaultCallback.getLastAvailableNetwork());
// Cleanup any prior test state from setOemNetworkPreference
clearOemNetworkPreference();
// The default (non-test) network should be available as the network pref was cleared.
waitForAvailable(defaultCallback);
unregisterTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
}
}
private void unregisterTestOemNetworkPreferenceCallbacks(
@NonNull final TestableNetworkCallback defaultCallback,
@NonNull final TestableNetworkCallback systemDefaultCallback) {
mCm.unregisterNetworkCallback(defaultCallback);
mCm.unregisterNetworkCallback(systemDefaultCallback);
}
private void registerTestOemNetworkPreferenceCallbacks(
@NonNull final TestableNetworkCallback defaultCallback,
@NonNull final TestableNetworkCallback systemDefaultCallback) {
mCm.registerDefaultNetworkCallback(defaultCallback);
runWithShellPermissionIdentity(() ->
mCmShim.registerSystemDefaultNetworkCallback(systemDefaultCallback,
new Handler(Looper.getMainLooper())), NETWORK_SETTINGS);
}
private static final class OnCompleteListenerCallback {
final CompletableFuture<Object> mDone = new CompletableFuture<>();
public void onComplete() {
mDone.complete(new Object());
}
void expectOnComplete() throws Exception {
try {
mDone.get(NETWORK_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
fail("Expected onComplete() not received after "
+ NETWORK_CALLBACK_TIMEOUT_MS + " ms");
}
}
}
private void setOemNetworkPreferenceForMyPackage(final int networkPref) throws Exception {
final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
.addNetworkPreference(mContext.getPackageName(), networkPref)
.build();
final OnCompleteListenerCallback oemPrefListener = new OnCompleteListenerCallback();
mUiAutomation.adoptShellPermissionIdentity();
try {
mCm.setOemNetworkPreference(
pref, mContext.getMainExecutor(), oemPrefListener::onComplete);
} finally {
mUiAutomation.dropShellPermissionIdentity();
}
oemPrefListener.expectOnComplete();
}
/**
* This will clear the OEM network preference on the device. As there is currently no way of
* getting the existing preference, if this is executed while an existing preference is in
* place, that preference will need to be reapplied after executing this test.
* @throws Exception
*/
private void clearOemNetworkPreference() throws Exception {
final OemNetworkPreferences clearPref = new OemNetworkPreferences.Builder().build();
final OnCompleteListenerCallback oemPrefListener = new OnCompleteListenerCallback();
mUiAutomation.adoptShellPermissionIdentity();
try {
mCm.setOemNetworkPreference(
clearPref, mContext.getMainExecutor(), oemPrefListener::onComplete);
} finally {
mUiAutomation.dropShellPermissionIdentity();
}
oemPrefListener.expectOnComplete();
}
}

View File

@@ -109,6 +109,8 @@ 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_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;
@@ -10704,8 +10706,7 @@ public class ConnectivityServiceTest {
}
@Test
public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError()
throws PackageManager.NameNotFoundException {
public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError() {
@OemNetworkPreferences.OemNetworkPreference final int prefToTest =
OEM_NETWORK_PREFERENCE_UNINITIALIZED;
@@ -10972,7 +10973,48 @@ public class ConnectivityServiceTest {
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,
@@ -11149,8 +11191,18 @@ public class ConnectivityServiceTest {
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);
@@ -11454,6 +11506,55 @@ public class ConnectivityServiceTest {
reset(mMockNetd);
}
/**
* 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().
*/
@@ -11466,7 +11567,7 @@ public class ConnectivityServiceTest {
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.