Merge "Update APIs based on API review feedback"
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index acbfa8c..8db4cb9 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -64,6 +64,7 @@
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE;
+import static com.android.networkstack.tethering.UpstreamNetworkMonitor.isCellular;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothAdapter;
@@ -1590,6 +1591,7 @@
? mUpstreamNetworkMonitor.getCurrentPreferredUpstream()
: mUpstreamNetworkMonitor.selectPreferredUpstreamType(
config.preferredUpstreamIfaceTypes);
+
if (ns == null) {
if (tryCell) {
mUpstreamNetworkMonitor.setTryCell(true);
@@ -1597,7 +1599,10 @@
} else {
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
+ } else if (!isCellular(ns)) {
+ mUpstreamNetworkMonitor.setTryCell(false);
}
+
setUpstreamNetwork(ns);
final Network newUpstream = (ns != null) ? ns.network : null;
if (mTetherUpstream != newUpstream) {
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index f9af777..9de4c87 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -318,18 +318,6 @@
if (!mIsDefaultCellularUpstream) {
mEntitlementMgr.maybeRunProvisioning();
}
- // If we're on DUN, put our own grab on it.
- registerMobileNetworkRequest();
- break;
- case TYPE_NONE:
- // If we found NONE and mobile upstream is permitted we don't want to do this
- // as we want any previous requests to keep trying to bring up something we can use.
- if (!isCellularUpstreamPermitted()) releaseMobileNetworkRequest();
- break;
- default:
- // If we've found an active upstream connection that's not DUN/HIPRI
- // we should stop any outstanding DUN/HIPRI requests.
- releaseMobileNetworkRequest();
break;
}
@@ -647,7 +635,8 @@
return prefixSet;
}
- private static boolean isCellular(UpstreamNetworkState ns) {
+ /** Check whether upstream is cellular. */
+ static boolean isCellular(UpstreamNetworkState ns) {
return (ns != null) && isCellular(ns.networkCapabilities);
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
index d045bf1..df82d7c 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
@@ -203,9 +203,11 @@
public void requestNetwork(NetworkRequest req,
int timeoutMs, int legacyType, Handler h, NetworkCallback cb) {
assertFalse(mAllCallbacks.containsKey(cb));
- mAllCallbacks.put(cb, new NetworkRequestInfo(req, h));
+ NetworkRequest newReq = new NetworkRequest(req.networkCapabilities, legacyType,
+ -1 /** testId */, req.type);
+ mAllCallbacks.put(cb, new NetworkRequestInfo(newReq, h));
assertFalse(mRequested.containsKey(cb));
- mRequested.put(cb, new NetworkRequestInfo(req, h));
+ mRequested.put(cb, new NetworkRequestInfo(newReq, h));
assertFalse(mLegacyTypeMap.containsKey(cb));
if (legacyType != ConnectivityManager.TYPE_NONE) {
mLegacyTypeMap.put(cb, legacyType);
@@ -313,14 +315,26 @@
return matchesLegacyType(networkCapabilities, legacyType);
}
- public void fakeConnect() {
- for (NetworkRequestInfo nri : cm.mRequested.values()) {
- if (matchesLegacyType(nri.request.legacyType)) {
- cm.sendConnectivityAction(legacyType, true /* connected */);
+ private void maybeSendConnectivityBroadcast(boolean connected) {
+ for (Integer requestedLegacyType : cm.mLegacyTypeMap.values()) {
+ if (requestedLegacyType.intValue() == legacyType) {
+ cm.sendConnectivityAction(legacyType, connected /* connected */);
// In practice, a given network can match only one legacy type.
break;
}
}
+ }
+
+ public void fakeConnect() {
+ fakeConnect(BROADCAST_FIRST, null);
+ }
+
+ public void fakeConnect(boolean order, @Nullable Runnable inBetween) {
+ if (order == BROADCAST_FIRST) {
+ maybeSendConnectivityBroadcast(true /* connected */);
+ if (inBetween != null) inBetween.run();
+ }
+
for (NetworkCallback cb : cm.mListening.keySet()) {
final NetworkRequestInfo nri = cm.mListening.get(cb);
nri.handler.post(() -> cb.onAvailable(networkId));
@@ -328,19 +342,32 @@
networkId, copy(networkCapabilities)));
nri.handler.post(() -> cb.onLinkPropertiesChanged(networkId, copy(linkProperties)));
}
+
+ if (order == CALLBACKS_FIRST) {
+ if (inBetween != null) inBetween.run();
+ maybeSendConnectivityBroadcast(true /* connected */);
+ }
// mTrackingDefault will be updated if/when the caller calls makeDefaultNetwork
}
public void fakeDisconnect() {
- for (NetworkRequestInfo nri : cm.mRequested.values()) {
- if (matchesLegacyType(nri.request.legacyType)) {
- cm.sendConnectivityAction(legacyType, false /* connected */);
- break;
- }
+ fakeDisconnect(BROADCAST_FIRST, null);
+ }
+
+ public void fakeDisconnect(boolean order, @Nullable Runnable inBetween) {
+ if (order == BROADCAST_FIRST) {
+ maybeSendConnectivityBroadcast(false /* connected */);
+ if (inBetween != null) inBetween.run();
}
+
for (NetworkCallback cb : cm.mListening.keySet()) {
cb.onLost(networkId);
}
+
+ if (order == CALLBACKS_FIRST) {
+ if (inBetween != null) inBetween.run();
+ maybeSendConnectivityBroadcast(false /* connected */);
+ }
// mTrackingDefault will be updated if/when the caller calls makeDefaultNetwork
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 7c3dd23..faa5ac7 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -25,7 +25,9 @@
import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_NONE;
+import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
@@ -204,6 +206,7 @@
private static final int IFINDEX_OFFSET = 100;
private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
+ private static final String TEST_DUN_IFNAME = "test_dun0";
private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
private static final String TEST_USB_IFNAME = "test_rndis0";
private static final String TEST_WIFI_IFNAME = "test_wlan0";
@@ -343,13 +346,14 @@
|| ifName.equals(TEST_WLAN_IFNAME)
|| ifName.equals(TEST_WIFI_IFNAME)
|| ifName.equals(TEST_MOBILE_IFNAME)
+ || ifName.equals(TEST_DUN_IFNAME)
|| ifName.equals(TEST_P2P_IFNAME)
|| ifName.equals(TEST_NCM_IFNAME)
|| ifName.equals(TEST_ETH_IFNAME)
|| ifName.equals(TEST_BT_IFNAME));
final String[] ifaces = new String[] {
TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_WIFI_IFNAME, TEST_MOBILE_IFNAME,
- TEST_P2P_IFNAME, TEST_NCM_IFNAME, TEST_ETH_IFNAME};
+ TEST_DUN_IFNAME, TEST_P2P_IFNAME, TEST_NCM_IFNAME, TEST_ETH_IFNAME};
return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
MacAddress.ALL_ZEROS_ADDRESS);
}
@@ -547,8 +551,7 @@
private static NetworkCapabilities buildUpstreamCapabilities(int transport, int... otherCaps) {
// TODO: add NOT_VCN_MANAGED.
final NetworkCapabilities nc = new NetworkCapabilities()
- .addTransportType(transport)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ .addTransportType(transport);
for (int cap : otherCaps) {
nc.addCapability(cap);
}
@@ -559,7 +562,7 @@
boolean withIPv6, boolean with464xlat) {
return new UpstreamNetworkState(
buildUpstreamLinkProperties(TEST_MOBILE_IFNAME, withIPv4, withIPv6, with464xlat),
- buildUpstreamCapabilities(TRANSPORT_CELLULAR),
+ buildUpstreamCapabilities(TRANSPORT_CELLULAR, NET_CAPABILITY_INTERNET),
new Network(CELLULAR_NETID));
}
@@ -583,13 +586,13 @@
return new UpstreamNetworkState(
buildUpstreamLinkProperties(TEST_WIFI_IFNAME, true /* IPv4 */, true /* IPv6 */,
false /* 464xlat */),
- buildUpstreamCapabilities(TRANSPORT_WIFI),
+ buildUpstreamCapabilities(TRANSPORT_WIFI, NET_CAPABILITY_INTERNET),
new Network(WIFI_NETID));
}
private static UpstreamNetworkState buildDunUpstreamState() {
return new UpstreamNetworkState(
- buildUpstreamLinkProperties(TEST_MOBILE_IFNAME, true /* IPv4 */, true /* IPv6 */,
+ buildUpstreamLinkProperties(TEST_DUN_IFNAME, true /* IPv4 */, true /* IPv6 */,
false /* 464xlat */),
buildUpstreamCapabilities(TRANSPORT_CELLULAR, NET_CAPABILITY_DUN),
new Network(DUN_NETID));
@@ -688,7 +691,8 @@
.thenReturn(new String[] { "test_pan\\d" });
when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
.thenReturn(new String[] { "test_ncm\\d" });
- when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
+ new int[] { TYPE_WIFI, TYPE_MOBILE_DUN });
when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
}
@@ -1101,15 +1105,13 @@
verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
}
- @Test
- public void testAutomaticUpstreamSelection() throws Exception {
+ private void upstreamSelectionTestCommon(final boolean automatic, InOrder inOrder,
+ TestNetworkAgent mobile, TestNetworkAgent wifi) throws Exception {
// Enable automatic upstream selection.
- when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(automatic);
sendConfigurationChanged();
mLooper.dispatchAll();
- InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
-
// Start USB tethering with no current upstream.
prepareUsbTethering();
sendUsbBroadcast(true, true, true, TETHERING_USB);
@@ -1117,23 +1119,31 @@
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
// Pretend cellular connected and expect the upstream to be set.
- TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
mobile.fakeConnect();
mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
- // Switch upstreams a few times.
- TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+ // Switch upstream to wifi.
wifi.fakeConnect();
mCm.makeDefaultNetwork(wifi, BROADCAST_FIRST);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+ }
+
+ @Test
+ public void testAutomaticUpstreamSelection() throws Exception {
+ TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+ TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+ InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+ // Enable automatic upstream selection.
+ upstreamSelectionTestCommon(true, inOrder, mobile, wifi);
// This code has historically been racy, so test different orderings of CONNECTIVITY_ACTION
// broadcasts and callbacks, and add mLooper.dispatchAll() calls between the two.
final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+ // Switch upstreams a few times.
mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST, doDispatchAll);
mLooper.dispatchAll();
inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
@@ -1200,6 +1210,138 @@
mLooper.dispatchAll();
}
+ @Test
+ public void testLegacyUpstreamSelection() throws Exception {
+ TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+ TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+ InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+ // Enable legacy upstream selection.
+ upstreamSelectionTestCommon(false, inOrder, mobile, wifi);
+
+ // Wifi disconnecting and the default network switch to mobile, the upstream should also
+ // switch to mobile.
+ wifi.fakeDisconnect();
+ mLooper.dispatchAll();
+ mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST, null);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+
+ wifi.fakeConnect();
+ mLooper.dispatchAll();
+ mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST, null);
+ mLooper.dispatchAll();
+ }
+
+ @Test
+ public void testChooseDunUpstreamByAutomaticMode() throws Exception {
+ // Enable automatic upstream selection.
+ TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+ TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+ TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+ InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+ chooseDunUpstreamTestCommon(true, inOrder, mobile, wifi, dun);
+
+ // When default network switch to mobile and wifi is connected (may have low signal),
+ // automatic mode would request dun again and choose it as upstream.
+ mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
+ mLooper.dispatchAll();
+ ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
+ inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(), any());
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+ dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+
+ // Lose and regain upstream again.
+ dun.fakeDisconnect(CALLBACKS_FIRST, doDispatchAll);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ inOrder.verify(mCm, never()).unregisterNetworkCallback(any(NetworkCallback.class));
+ dun.fakeConnect(CALLBACKS_FIRST, doDispatchAll);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+ }
+
+ @Test
+ public void testChooseDunUpstreamByLegacyMode() throws Exception {
+ // Enable Legacy upstream selection.
+ TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+ TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+ TestNetworkAgent dun = new TestNetworkAgent(mCm, buildDunUpstreamState());
+ InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+ chooseDunUpstreamTestCommon(false, inOrder, mobile, wifi, dun);
+
+ // Legacy mode would keep use wifi as upstream (because it has higher priority in the
+ // list).
+ mCm.makeDefaultNetwork(mobile, CALLBACKS_FIRST);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ // BUG: when wifi disconnect, the dun request would not be filed again because wifi is
+ // no longer be default network which do not have CONNECTIVIY_ACTION broadcast.
+ wifi.fakeDisconnect();
+ mLooper.dispatchAll();
+ inOrder.verify(mCm, never()).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(),
+ any());
+
+ // Change the legacy priority list that dun is higher than wifi.
+ when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
+ new int[] { TYPE_MOBILE_DUN, TYPE_WIFI });
+ sendConfigurationChanged();
+ mLooper.dispatchAll();
+
+ // Make wifi as default network. Note: mobile also connected.
+ wifi.fakeConnect();
+ mLooper.dispatchAll();
+ mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+ mLooper.dispatchAll();
+ // BUG: dun has higher priority than wifi but tethering don't file dun request because
+ // current upstream is wifi.
+ inOrder.verify(mCm, never()).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(),
+ any());
+ }
+
+ private void chooseDunUpstreamTestCommon(final boolean automatic, InOrder inOrder,
+ TestNetworkAgent mobile, TestNetworkAgent wifi, TestNetworkAgent dun) throws Exception {
+ when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(automatic);
+ when(mTelephonyManager.isTetheringApnRequired()).thenReturn(true);
+ sendConfigurationChanged();
+ mLooper.dispatchAll();
+
+ // Start USB tethering with no current upstream.
+ prepareUsbTethering();
+ sendUsbBroadcast(true, true, true, TETHERING_USB);
+ inOrder.verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
+ inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
+ ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
+ inOrder.verify(mCm).requestNetwork(any(), eq(0), eq(TYPE_MOBILE_DUN), any(),
+ captor.capture());
+ final NetworkCallback dunNetworkCallback1 = captor.getValue();
+
+ // Pretend cellular connected and expect the upstream to be set.
+ mobile.fakeConnect();
+ mCm.makeDefaultNetwork(mobile, BROADCAST_FIRST);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(mobile.networkId);
+
+ // Pretend dun connected and expect choose dun as upstream.
+ final Runnable doDispatchAll = () -> mLooper.dispatchAll();
+ dun.fakeConnect(BROADCAST_FIRST, doDispatchAll);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(dun.networkId);
+
+ // When wifi connected, unregister dun request and choose wifi as upstream.
+ wifi.fakeConnect();
+ mCm.makeDefaultNetwork(wifi, CALLBACKS_FIRST);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setTryCell(false);
+ inOrder.verify(mCm).unregisterNetworkCallback(eq(dunNetworkCallback1));
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+ dun.fakeDisconnect(BROADCAST_FIRST, doDispatchAll);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+ }
+
private void runNcmTethering() {
prepareNcmTethering();
sendUsbBroadcast(true, true, true, TETHERING_NCM);
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
index bc21692..cee0365 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
@@ -325,16 +325,9 @@
mUNM.setUpstreamConfig(false /* autoUpstream */, false /* dunRequired */);
assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
mUNM.selectPreferredUpstreamType(preferredTypes));
- // Check to see we filed an explicit request.
- assertEquals(1, mCM.mRequested.size());
- NetworkRequest netReq = ((NetworkRequestInfo) mCM.mRequested.values().toArray()[0]).request;
- assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR));
- assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
// mobile is not permitted, we should not use HIPRI.
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false);
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
- assertEquals(0, mCM.mRequested.size());
- // mobile change back to permitted, HIRPI should come back
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
mUNM.selectPreferredUpstreamType(preferredTypes));
@@ -343,7 +336,6 @@
mLooper.dispatchAll();
// WiFi is up, and we should prefer it over cell.
assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
- assertEquals(0, mCM.mRequested.size());
preferredTypes.remove(TYPE_MOBILE_HIPRI);
preferredTypes.add(TYPE_MOBILE_DUN);
@@ -363,15 +355,9 @@
mLooper.dispatchAll();
assertSatisfiesLegacyType(TYPE_MOBILE_DUN,
mUNM.selectPreferredUpstreamType(preferredTypes));
- // Check to see we filed an explicit request.
- assertEquals(1, mCM.mRequested.size());
- netReq = ((NetworkRequestInfo) mCM.mRequested.values().toArray()[0]).request;
- assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
// mobile is not permitted, we should not use DUN.
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(false);
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
- assertEquals(0, mCM.mRequested.size());
// mobile change back to permitted, DUN should come back
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
assertSatisfiesLegacyType(TYPE_MOBILE_DUN,
@@ -647,4 +633,4 @@
expectation, prefixes.contains(new IpPrefix(expectedPrefix)));
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/cts/net/AndroidManifest.xml b/tests/cts/net/AndroidManifest.xml
index a7e2bd7..3b47100 100644
--- a/tests/cts/net/AndroidManifest.xml
+++ b/tests/cts/net/AndroidManifest.xml
@@ -36,6 +36,9 @@
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
+ <!-- TODO (b/186093901): remove after fixing resource querying -->
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+
<!-- This test also uses signature permissions through adopting the shell identity.
The permissions acquired that way include (probably not exhaustive) :
android.permission.MANAGE_TEST_NETWORKS
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index f71a6de..5edf985 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -131,9 +131,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.ArrayUtils;
-import com.android.modules.utils.build.SdkLevel;
import com.android.networkstack.apishim.ConnectivityManagerShimImpl;
-import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.common.ConnectivityManagerShim;
import com.android.testutils.CompatUtil;
import com.android.testutils.DevSdkIgnoreRule;
@@ -312,7 +310,7 @@
mCtsNetUtils.disconnectFromCell();
}
- if (shouldTestSApis()) {
+ if (TestUtils.shouldTestSApis()) {
runWithShellPermissionIdentity(
() -> mCmShim.setRequireVpnForUids(false, mVpnRequiredUidRanges),
NETWORK_SETTINGS);
@@ -605,7 +603,7 @@
final TestNetworkCallback systemDefaultCallback = new TestNetworkCallback();
final TestNetworkCallback perUidCallback = new TestNetworkCallback();
final Handler h = new Handler(Looper.getMainLooper());
- if (shouldTestSApis()) {
+ if (TestUtils.shouldTestSApis()) {
runWithShellPermissionIdentity(() -> {
mCmShim.registerSystemDefaultNetworkCallback(systemDefaultCallback, h);
mCmShim.registerDefaultNetworkCallbackForUid(Process.myUid(), perUidCallback, h);
@@ -628,7 +626,7 @@
assertNotNull("Did not receive onAvailable on default network callback",
defaultNetwork);
- if (shouldTestSApis()) {
+ if (TestUtils.shouldTestSApis()) {
assertNotNull("Did not receive onAvailable on system default network callback",
systemDefaultCallback.waitForAvailable());
final Network perUidNetwork = perUidCallback.waitForAvailable();
@@ -642,7 +640,7 @@
} finally {
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultTrackingCallback);
- if (shouldTestSApis()) {
+ if (TestUtils.shouldTestSApis()) {
mCm.unregisterNetworkCallback(systemDefaultCallback);
mCm.unregisterNetworkCallback(perUidCallback);
}
@@ -1670,7 +1668,7 @@
final Network network = mCtsNetUtils.ensureWifiConnected();
final String ssid = unquoteSSID(mWifiManager.getConnectionInfo().getSSID());
- assertNotNull("Ssid getting from WiifManager is null", ssid);
+ assertNotNull("Ssid getting from WifiManager is null", ssid);
// This package should have no NETWORK_SETTINGS permission. Verify that no ssid is contained
// in the NetworkCapabilities.
verifySsidFromQueriedNetworkCapabilities(network, ssid, false /* hasSsid */);
@@ -1721,7 +1719,7 @@
public void testRequestBackgroundNetwork() {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
- assumeTrue(shouldTestSApis());
+ assumeTrue(TestUtils.shouldTestSApis());
// Create a tun interface. Use the returned interface name as the specifier to create
// a test network request.
@@ -1866,7 +1864,7 @@
public void testBlockedStatusCallback() {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
- assumeTrue(shouldTestSApis());
+ assumeTrue(TestUtils.shouldTestSApis());
runWithShellPermissionIdentity(() -> doTestBlockedStatusCallback(), NETWORK_SETTINGS);
}
@@ -1900,15 +1898,7 @@
public void testLegacyLockdownEnabled() {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
- assumeTrue(shouldTestSApis());
+ assumeTrue(TestUtils.shouldTestSApis());
runWithShellPermissionIdentity(() -> doTestLegacyLockdownEnabled(), NETWORK_SETTINGS);
}
-
- /**
- * Whether to test S+ APIs. This requires a) that the test be running on an S+ device, and
- * b) that the code be compiled against shims new enough to access these APIs.
- */
- private boolean shouldTestSApis() {
- return SdkLevel.isAtLeastS() && ConstantsShim.VERSION > Build.VERSION_CODES.R;
- }
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
index 9906c30..1a97566 100644
--- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
@@ -28,10 +28,13 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static junit.framework.Assert.fail;
+
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.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.net.MacAddress;
@@ -396,4 +399,42 @@
.addCapability(NET_CAPABILITY_DUN).build();
assertTrue(dunRequest.hasCapability(ConstantsShim.NET_CAPABILITY_NOT_VCN_MANAGED));
}
+
+ private void verifyEqualRequestBuilt(NetworkRequest orig) {
+ try {
+ final NetworkRequestShim shim = NetworkRequestShimImpl.newInstance();
+ final NetworkRequest copy = shim.newBuilder(orig).build();
+ assertEquals(orig, copy);
+ } catch (UnsupportedApiLevelException e) {
+ fail("NetworkRequestShim.newBuilder should be supported in this SDK version");
+ }
+ }
+
+ @Test
+ public void testBuildRequestFromExistingRequestWithBuilder() {
+ assumeTrue(TestUtils.shouldTestSApis());
+ final NetworkRequest.Builder builder = new NetworkRequest.Builder();
+
+ final NetworkRequest baseRequest = builder.build();
+ verifyEqualRequestBuilt(baseRequest);
+
+ final NetworkRequest requestCellMms = builder
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_MMS)
+ .setSignalStrength(-99).build();
+ verifyEqualRequestBuilt(requestCellMms);
+
+ final WifiNetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+ .setSsidPattern(new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL))
+ .setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS)
+ .build();
+ final NetworkRequest requestWifi = builder
+ .addTransportType(TRANSPORT_WIFI)
+ .removeTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .removeCapability(NET_CAPABILITY_MMS)
+ .setNetworkSpecifier(specifier)
+ .setSignalStrength(-33).build();
+ verifyEqualRequestBuilt(requestWifi);
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/TestUtils.java b/tests/cts/net/src/android/net/cts/TestUtils.java
new file mode 100644
index 0000000..c1100b1
--- /dev/null
+++ b/tests/cts/net/src/android/net/cts/TestUtils.java
@@ -0,0 +1,36 @@
+/*
+ * 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.cts;
+
+import android.os.Build;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.networkstack.apishim.ConstantsShim;
+
+/**
+ * Utils class to provide common shared test helper methods or constants that behave differently
+ * depending on the SDK against which they are compiled.
+ */
+public class TestUtils {
+ /**
+ * Whether to test S+ APIs. This requires a) that the test be running on an S+ device, and
+ * b) that the code be compiled against shims new enough to access these APIs.
+ */
+ public static boolean shouldTestSApis() {
+ return SdkLevel.isAtLeastS() && ConstantsShim.VERSION > Build.VERSION_CODES.R;
+ }
+}