Merge "[VCN21.1] Verify capability is not added if specifier is present"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 4eafc2a..79c2b9d 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -30,6 +30,7 @@
":services-tethering-shared-srcs",
],
static_libs: [
+ "NetworkStackApiStableShims",
"androidx.annotation_annotation",
"modules-utils-build",
"netlink-client",
diff --git a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
index e310fb6..33f1c29 100644
--- a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
@@ -179,6 +179,18 @@
}
@Override
+ public boolean addDevMap(int ifIndex) {
+ /* no op */
+ return false;
+ }
+
+ @Override
+ public boolean removeDevMap(int ifIndex) {
+ /* no op */
+ return false;
+ }
+
+ @Override
public String toString() {
return "Netd used";
}
diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
index d7ce139..74ddcbc 100644
--- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
@@ -36,6 +36,8 @@
import com.android.networkstack.tethering.Tether4Key;
import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.Tether6Value;
+import com.android.networkstack.tethering.TetherDevKey;
+import com.android.networkstack.tethering.TetherDevValue;
import com.android.networkstack.tethering.TetherDownstream6Key;
import com.android.networkstack.tethering.TetherLimitKey;
import com.android.networkstack.tethering.TetherLimitValue;
@@ -85,6 +87,10 @@
@Nullable
private final BpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap;
+ // BPF map of interface index mapping for XDP.
+ @Nullable
+ private final BpfMap<TetherDevKey, TetherDevValue> mBpfDevMap;
+
// Tracking IPv4 rule count while any rule is using the given upstream interfaces. Used for
// reducing the BPF map iteration query. The count is increased or decreased when the rule is
// added or removed successfully on mBpfDownstream4Map. Counting the rules on downstream4 map
@@ -108,6 +114,7 @@
mBpfUpstream6Map = deps.getBpfUpstream6Map();
mBpfStatsMap = deps.getBpfStatsMap();
mBpfLimitMap = deps.getBpfLimitMap();
+ mBpfDevMap = deps.getBpfDevMap();
// Clear the stubs of the maps for handling the system service crash if any.
// Doesn't throw the exception and clear the stubs as many as possible.
@@ -141,12 +148,18 @@
} catch (ErrnoException e) {
mLog.e("Could not clear mBpfLimitMap: " + e);
}
+ try {
+ if (mBpfDevMap != null) mBpfDevMap.clear();
+ } catch (ErrnoException e) {
+ mLog.e("Could not clear mBpfDevMap: " + e);
+ }
}
@Override
public boolean isInitialized() {
return mBpfDownstream4Map != null && mBpfUpstream4Map != null && mBpfDownstream6Map != null
- && mBpfUpstream6Map != null && mBpfStatsMap != null && mBpfLimitMap != null;
+ && mBpfUpstream6Map != null && mBpfStatsMap != null && mBpfLimitMap != null
+ && mBpfDevMap != null;
}
@Override
@@ -432,6 +445,32 @@
return mRule4CountOnUpstream.get(ifIndex) != null;
}
+ @Override
+ public boolean addDevMap(int ifIndex) {
+ if (!isInitialized()) return false;
+
+ try {
+ mBpfDevMap.updateEntry(new TetherDevKey(ifIndex), new TetherDevValue(ifIndex));
+ } catch (ErrnoException e) {
+ mLog.e("Could not add interface " + ifIndex + ": " + e);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeDevMap(int ifIndex) {
+ if (!isInitialized()) return false;
+
+ try {
+ mBpfDevMap.deleteEntry(new TetherDevKey(ifIndex));
+ } catch (ErrnoException e) {
+ mLog.e("Could not delete interface " + ifIndex + ": " + e);
+ return false;
+ }
+ return true;
+ }
+
private String mapStatus(BpfMap m, String name) {
return name + "{" + (m != null ? "OK" : "ERROR") + "}";
}
@@ -444,7 +483,8 @@
mapStatus(mBpfDownstream4Map, "mBpfDownstream4Map"),
mapStatus(mBpfUpstream4Map, "mBpfUpstream4Map"),
mapStatus(mBpfStatsMap, "mBpfStatsMap"),
- mapStatus(mBpfLimitMap, "mBpfLimitMap")
+ mapStatus(mBpfLimitMap, "mBpfLimitMap"),
+ mapStatus(mBpfDevMap, "mBpfDevMap")
});
}
diff --git a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
index 79a628b..8a7a49c 100644
--- a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
+++ b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
@@ -166,5 +166,15 @@
* TODO: consider using InterfaceParams to replace interface name.
*/
public abstract boolean detachProgram(@NonNull String iface);
+
+ /**
+ * Add interface index mapping.
+ */
+ public abstract boolean addDevMap(int ifIndex);
+
+ /**
+ * Remove interface index mapping.
+ */
+ public abstract boolean removeDevMap(int ifIndex);
}
diff --git a/Tethering/bpf_progs/offload.c b/Tethering/bpf_progs/offload.c
index 36f6783..6ff370c 100644
--- a/Tethering/bpf_progs/offload.c
+++ b/Tethering/bpf_progs/offload.c
@@ -767,8 +767,7 @@
// ----- XDP Support -----
-DEFINE_BPF_MAP_GRW(tether_xdp_devmap, DEVMAP_HASH, uint32_t, uint32_t, 64,
- AID_NETWORK_STACK)
+DEFINE_BPF_MAP_GRW(tether_dev_map, DEVMAP_HASH, uint32_t, uint32_t, 64, AID_NETWORK_STACK)
static inline __always_inline int do_xdp_forward6(struct xdp_md *ctx, const bool is_ethernet,
const bool downstream) {
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 2eed968..8adcbd9 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -72,6 +72,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -104,6 +105,7 @@
private static final String TETHER_STATS_MAP_PATH = makeMapPath("stats");
private static final String TETHER_LIMIT_MAP_PATH = makeMapPath("limit");
private static final String TETHER_ERROR_MAP_PATH = makeMapPath("error");
+ private static final String TETHER_DEV_MAP_PATH = makeMapPath("dev");
/** The names of all the BPF counters defined in bpf_tethering.h. */
public static final String[] sBpfCounterNames = getBpfCounterNames();
@@ -220,6 +222,11 @@
// Map for upstream and downstream pair.
private final HashMap<String, HashSet<String>> mForwardingPairs = new HashMap<>();
+ // Set for upstream and downstream device map. Used for caching BPF dev map status and
+ // reduce duplicate adding or removing map operations. Use LinkedHashSet because the test
+ // BpfCoordinatorTest needs predictable iteration order.
+ private final Set<Integer> mDeviceMapSet = new LinkedHashSet<>();
+
// Runnable that used by scheduling next polling of stats.
private final Runnable mScheduledPollingTask = () -> {
updateForwardedStats();
@@ -336,6 +343,18 @@
return null;
}
}
+
+ /** Get dev BPF map. */
+ @Nullable public BpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() {
+ if (!isAtLeastS()) return null;
+ try {
+ return new BpfMap<>(TETHER_DEV_MAP_PATH,
+ BpfMap.BPF_F_RDWR, TetherDevKey.class, TetherDevValue.class);
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Cannot create dev map: " + e);
+ return null;
+ }
+ }
}
@VisibleForTesting
@@ -490,6 +509,9 @@
}
LinkedHashMap<Inet6Address, Ipv6ForwardingRule> rules = mIpv6ForwardingRules.get(ipServer);
+ // Add upstream and downstream interface index to dev map.
+ maybeAddDevMap(rule.upstreamIfindex, rule.downstreamIfindex);
+
// When the first rule is added to an upstream, setup upstream forwarding and data limit.
maybeSetLimit(rule.upstreamIfindex);
@@ -758,6 +780,11 @@
dumpIpv4ForwardingRules(pw);
pw.decreaseIndent();
+ pw.println("Device map:");
+ pw.increaseIndent();
+ dumpDevmap(pw);
+ pw.decreaseIndent();
+
pw.println();
pw.println("Forwarding counters:");
pw.increaseIndent();
@@ -890,6 +917,31 @@
}
}
+ private void dumpDevmap(@NonNull IndentingPrintWriter pw) {
+ try (BpfMap<TetherDevKey, TetherDevValue> map = mDeps.getBpfDevMap()) {
+ if (map == null) {
+ pw.println("No devmap support");
+ return;
+ }
+ if (map.isEmpty()) {
+ pw.println("No interface index");
+ return;
+ }
+ pw.println("ifindex (iface) -> ifindex (iface)");
+ pw.increaseIndent();
+ map.forEach((k, v) -> {
+ // Only get upstream interface name. Just do the best to make the index readable.
+ // TODO: get downstream interface name because the index is either upstrema or
+ // downstream interface in dev map.
+ pw.println(String.format("%d (%s) -> %d (%s)", k.ifIndex, getIfName(k.ifIndex),
+ v.ifIndex, getIfName(v.ifIndex)));
+ });
+ } catch (ErrnoException e) {
+ pw.println("Error dumping dev map: " + e);
+ }
+ pw.decreaseIndent();
+ }
+
/** IPv6 forwarding rule class. */
public static class Ipv6ForwardingRule {
// The upstream6 and downstream6 rules are built as the following tables. Only raw ip
@@ -1229,6 +1281,7 @@
final Tether4Value downstream4Value = makeTetherDownstream4Value(e, tetherClient,
upstreamIndex);
+ maybeAddDevMap(upstreamIndex, tetherClient.downstreamIfindex);
maybeSetLimit(upstreamIndex);
mBpfCoordinatorShim.tetherOffloadRuleAdd(UPSTREAM, upstream4Key, upstream4Value);
mBpfCoordinatorShim.tetherOffloadRuleAdd(DOWNSTREAM, downstream4Key, downstream4Value);
@@ -1357,6 +1410,15 @@
return false;
}
+ // TODO: remove the index from map while the interface has been removed because the map size
+ // is 64 entries. See packages\modules\Connectivity\Tethering\bpf_progs\offload.c.
+ private void maybeAddDevMap(int upstreamIfindex, int downstreamIfindex) {
+ for (Integer index : new Integer[] {upstreamIfindex, downstreamIfindex}) {
+ if (mDeviceMapSet.contains(index)) continue;
+ if (mBpfCoordinatorShim.addDevMap(index)) mDeviceMapSet.add(index);
+ }
+ }
+
private void forwardingPairAdd(@NonNull String intIface, @NonNull String extIface) {
if (!mForwardingPairs.containsKey(extIface)) {
mForwardingPairs.put(extIface, new HashSet<String>());
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java b/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
new file mode 100644
index 0000000..4283c1b
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.networkstack.tethering;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/** The key of BpfMap which is used for mapping interface index. */
+public class TetherDevKey extends Struct {
+ @Field(order = 0, type = Type.U32)
+ public final long ifIndex; // interface index
+
+ public TetherDevKey(final long ifIndex) {
+ this.ifIndex = ifIndex;
+ }
+}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java b/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
new file mode 100644
index 0000000..1cd99b5
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.networkstack.tethering;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/** The key of BpfMap which is used for mapping interface index. */
+public class TetherDevValue extends Struct {
+ @Field(order = 0, type = Type.U32)
+ public final long ifIndex; // interface index
+
+ public TetherDevValue(final long ifIndex) {
+ this.ifIndex = ifIndex;
+ }
+}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index df9e12a..0e8b2b5 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -2040,8 +2040,7 @@
}
private void startTrackDefaultNetwork() {
- mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(),
- mEntitlementMgr);
+ mUpstreamNetworkMonitor.startTrackDefaultNetwork(mEntitlementMgr);
}
/** Get the latest value of the tethering entitlement check. */
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
index 413b0cb..2beeeb8 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java
@@ -58,6 +58,8 @@
private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final String TETHERING_MODULE_NAME = "com.android.tethering";
+
// Default ranges used for the legacy DHCP server.
// USB is 192.168.42.1 and 255.255.255.0
// Wifi is 192.168.43.1 and 255.255.255.0
@@ -473,7 +475,8 @@
@VisibleForTesting
protected boolean isFeatureEnabled(Context ctx, String featureVersionFlag) {
- return DeviceConfigUtils.isFeatureEnabled(ctx, NAMESPACE_CONNECTIVITY, featureVersionFlag);
+ return DeviceConfigUtils.isFeatureEnabled(ctx, NAMESPACE_CONNECTIVITY, featureVersionFlag,
+ TETHERING_MODULE_NAME, false /* defaultEnabled */);
}
private Resources getResources(Context ctx, int subId) {
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 45b9141..7df9475 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -20,7 +20,6 @@
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.INetd;
-import android.net.NetworkRequest;
import android.net.ip.IpServer;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -99,11 +98,6 @@
}
/**
- * Get the NetworkRequest that should be fulfilled by the default network.
- */
- public abstract NetworkRequest getDefaultNetworkRequest();
-
- /**
* Get a reference to the EntitlementManager to be used by tethering.
*/
public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index 745ebd0..5ab3401 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -35,8 +35,6 @@
import android.net.INetworkStackConnector;
import android.net.ITetheringConnector;
import android.net.ITetheringEventCallback;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
import android.net.NetworkStack;
import android.net.TetheringRequestParcel;
import android.net.dhcp.DhcpServerCallbacks;
@@ -307,19 +305,6 @@
public TetheringDependencies makeTetheringDependencies() {
return new TetheringDependencies() {
@Override
- public NetworkRequest getDefaultNetworkRequest() {
- // TODO: b/147280869, add a proper system API to replace this.
- final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
- .clearCapabilities()
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build();
- return trackDefaultRequest;
- }
-
- @Override
public Looper getTetheringLooper() {
final HandlerThread tetherThread = new HandlerThread("android.tethering");
tetherThread.start();
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 9de4c87..e615334 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -47,6 +47,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
+import com.android.networkstack.apishim.ConnectivityManagerShimImpl;
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import java.util.HashMap;
import java.util.HashSet;
@@ -142,33 +145,28 @@
mWhat = what;
mLocalPrefixes = new HashSet<>();
mIsDefaultCellularUpstream = false;
- }
-
- @VisibleForTesting
- public UpstreamNetworkMonitor(
- ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) {
- this((Context) null, tgt, log, what);
- mCM = cm;
+ mCM = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
}
/**
- * Tracking the system default network. This method should be called when system is ready.
+ * Tracking the system default network. This method should be only called once when system is
+ * ready, and the callback is never unregistered.
*
- * @param defaultNetworkRequest should be the same as ConnectivityService default request
* @param entitle a EntitlementManager object to communicate between EntitlementManager and
* UpstreamNetworkMonitor
*/
- public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest,
- EntitlementManager entitle) {
-
- // defaultNetworkRequest is not really a "request", just a way of tracking the system
- // default network. It's guaranteed not to actually bring up any networks because it's
- // the should be the same request as the ConnectivityService default request, and thus
- // shares fate with it. We can't use registerDefaultNetworkCallback because it will not
- // track the system default network if there is a VPN that applies to our UID.
- if (mDefaultNetworkCallback == null) {
- mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
- cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler);
+ public void startTrackDefaultNetwork(EntitlementManager entitle) {
+ if (mDefaultNetworkCallback != null) {
+ Log.wtf(TAG, "default network callback is already registered");
+ return;
+ }
+ ConnectivityManagerShim mCmShim = ConnectivityManagerShimImpl.newInstance(mContext);
+ mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
+ try {
+ mCmShim.registerSystemDefaultNetworkCallback(mDefaultNetworkCallback, mHandler);
+ } catch (UnsupportedApiLevelException e) {
+ Log.wtf(TAG, "registerSystemDefaultNetworkCallback is not supported");
+ return;
}
if (mEntitlementMgr == null) {
mEntitlementMgr = entitle;
diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp
index 6999ed9..351b9f4 100644
--- a/Tethering/tests/integration/Android.bp
+++ b/Tethering/tests/integration/Android.bp
@@ -23,6 +23,7 @@
"src/**/*.java",
"src/**/*.kt",
],
+ min_sdk_version: "30",
static_libs: [
"NetworkStackApiStableLib",
"androidx.test.rules",
@@ -44,12 +45,24 @@
}
android_library {
- name: "TetheringIntegrationTestsLib",
+ name: "TetheringIntegrationTestsLatestSdkLib",
+ target_sdk_version: "30",
platform_apis: true,
defaults: ["TetheringIntegrationTestsDefaults"],
visibility: [
- "//cts/tests/tests/tethering",
"//packages/modules/Connectivity/tests/cts/tethering",
+ "//packages/modules/Connectivity/Tethering/tests/mts",
+ ]
+}
+
+android_library {
+ name: "TetheringIntegrationTestsLib",
+ target_sdk_version: "current",
+ platform_apis: true,
+ defaults: ["TetheringIntegrationTestsDefaults"],
+ visibility: [
+ "//packages/modules/Connectivity/tests/cts/tethering",
+ "//packages/modules/Connectivity/Tethering/tests/mts",
]
}
@@ -70,6 +83,8 @@
android_test {
name: "TetheringCoverageTests",
platform_apis: true,
+ min_sdk_version: "30",
+ target_sdk_version: "30",
test_suites: ["device-tests", "mts"],
test_config: "AndroidTest_Coverage.xml",
defaults: ["libnetworkstackutilsjni_deps"],
@@ -78,8 +93,8 @@
"NetdStaticLibTestsLib",
"NetworkStaticLibTestsLib",
"NetworkStackTestsLib",
- "TetheringTestsLib",
- "TetheringIntegrationTestsLib",
+ "TetheringTestsLatestSdkLib",
+ "TetheringIntegrationTestsLatestSdkLib",
],
jni_libs: [
// For mockito extended
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index fe4e696..de94cba 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.TETHER_PRIVILEGED;
@@ -121,7 +122,7 @@
// Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive
// tethered client callbacks.
mUiAutomation.adoptShellPermissionIdentity(
- MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED);
+ MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED, ACCESS_NETWORK_STATE);
mRunTests = mTm.isTetheringSupported() && mEm != null;
assumeTrue(mRunTests);
diff --git a/Tethering/tests/jarjar-rules.txt b/Tethering/tests/jarjar-rules.txt
index c99ff7f..9cb143e 100644
--- a/Tethering/tests/jarjar-rules.txt
+++ b/Tethering/tests/jarjar-rules.txt
@@ -1,8 +1,8 @@
# Don't jar-jar the entire package because this test use some
# internal classes (like ArrayUtils in com.android.internal.util)
rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
-rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
-rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
+rule com.android.internal.util.IndentingPrintWriter* com.android.networkstack.tethering.util.IndentingPrintWriter@1
+rule com.android.internal.util.IState* com.android.networkstack.tethering.util.IState@1
rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
diff --git a/Tethering/tests/mts/Android.bp b/Tethering/tests/mts/Android.bp
index edb6356..221771f 100644
--- a/Tethering/tests/mts/Android.bp
+++ b/Tethering/tests/mts/Android.bp
@@ -19,7 +19,10 @@
android_test {
// This tests for functionality that is not required for devices that
// don't use Tethering mainline module.
- name: "MtsTetheringTest",
+ name: "MtsTetheringTestLatestSdk",
+
+ min_sdk_version: "30",
+ target_sdk_version: "30",
libs: [
"android.test.base",
diff --git a/Tethering/tests/mts/AndroidTest.xml b/Tethering/tests/mts/AndroidTest.xml
index 80788df..4edd544 100644
--- a/Tethering/tests/mts/AndroidTest.xml
+++ b/Tethering/tests/mts/AndroidTest.xml
@@ -24,7 +24,7 @@
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="MtsTetheringTest.apk" />
+ <option name="test-file-name" value="MtsTetheringTestLatestSdk.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.tethering.mts" />
diff --git a/Tethering/tests/unit/Android.bp b/Tethering/tests/unit/Android.bp
index d469b37..b4b3977 100644
--- a/Tethering/tests/unit/Android.bp
+++ b/Tethering/tests/unit/Android.bp
@@ -36,13 +36,13 @@
"framework-tethering.impl",
],
visibility: [
- "//cts/tests/tests/tethering",
"//packages/modules/Connectivity/tests/cts/tethering",
],
}
java_defaults {
name: "TetheringTestsDefaults",
+ min_sdk_version: "30",
srcs: [
"src/**/*.java",
"src/**/*.kt",
@@ -81,10 +81,10 @@
// unit test code. It is not currently used by the tests themselves because all the build
// configuration needed by the tests is in the TetheringTestsDefaults rule.
android_library {
- name: "TetheringTestsLib",
+ name: "TetheringTestsLatestSdkLib",
defaults: ["TetheringTestsDefaults"],
+ target_sdk_version: "30",
visibility: [
- "//frameworks/base/packages/Tethering/tests/integration",
"//packages/modules/Connectivity/Tethering/tests/integration",
]
}
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 435cab5..ce69cb3 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -107,6 +107,8 @@
import com.android.networkstack.tethering.Tether4Key;
import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.Tether6Value;
+import com.android.networkstack.tethering.TetherDevKey;
+import com.android.networkstack.tethering.TetherDevValue;
import com.android.networkstack.tethering.TetherDownstream6Key;
import com.android.networkstack.tethering.TetherLimitKey;
import com.android.networkstack.tethering.TetherLimitValue;
@@ -182,6 +184,7 @@
@Mock private BpfMap<TetherUpstream6Key, Tether6Value> mBpfUpstream6Map;
@Mock private BpfMap<TetherStatsKey, TetherStatsValue> mBpfStatsMap;
@Mock private BpfMap<TetherLimitKey, TetherLimitValue> mBpfLimitMap;
+ @Mock private BpfMap<TetherDevKey, TetherDevValue> mBpfDevMap;
@Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
@@ -334,6 +337,11 @@
public BpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() {
return mBpfLimitMap;
}
+
+ @Nullable
+ public BpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() {
+ return mBpfDevMap;
+ }
};
mBpfCoordinator = spy(new BpfCoordinator(mBpfDeps));
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 233f6db..cc912f4 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -207,6 +207,7 @@
@Mock private BpfMap<Tether4Key, Tether4Value> mBpfUpstream4Map;
@Mock private BpfMap<TetherDownstream6Key, Tether6Value> mBpfDownstream6Map;
@Mock private BpfMap<TetherUpstream6Key, Tether6Value> mBpfUpstream6Map;
+ @Mock private BpfMap<TetherDevKey, TetherDevValue> mBpfDevMap;
// Late init since methods must be called by the thread that created this object.
private TestableNetworkStatsProviderCbBinder mTetherStatsProviderCb;
@@ -284,6 +285,11 @@
public BpfMap<TetherLimitKey, TetherLimitValue> getBpfLimitMap() {
return mBpfLimitMap;
}
+
+ @Nullable
+ public BpfMap<TetherDevKey, TetherDevValue> getBpfDevMap() {
+ return mBpfDevMap;
+ }
});
@Before public void setUp() {
@@ -1368,12 +1374,9 @@
coordinator.tetherOffloadClientAdd(mIpServer, clientInfo);
}
- // TODO: Test the IPv4 and IPv6 exist concurrently.
- // TODO: Test the IPv4 rule delete failed.
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.R)
- public void testSetDataLimitOnRule4Change() throws Exception {
- final BpfCoordinator coordinator = makeBpfCoordinator();
+ private void initBpfCoordinatorForRule4(final BpfCoordinator coordinator) throws Exception {
+ // Needed because addUpstreamIfindexToMap only updates upstream information when polling
+ // was started.
coordinator.startPolling();
// Needed because tetherOffloadRuleRemove of api31.BpfCoordinatorShimImpl only decreases
@@ -1387,6 +1390,15 @@
coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE);
setUpstreamInformationTo(coordinator);
setDownstreamAndClientInformationTo(coordinator);
+ }
+
+ // TODO: Test the IPv4 and IPv6 exist concurrently.
+ // TODO: Test the IPv4 rule delete failed.
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testSetDataLimitOnRule4Change() throws Exception {
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+ initBpfCoordinatorForRule4(coordinator);
// Applying a data limit to the current upstream does not take any immediate action.
// The data limit could be only set on an upstream which has rules.
@@ -1445,4 +1457,41 @@
verifyTetherOffloadGetAndClearStats(inOrder, UPSTREAM_IFINDEX);
inOrder.verifyNoMoreInteractions();
}
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testAddDevMapRule6() throws Exception {
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+
+ coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE);
+ final Ipv6ForwardingRule ruleA = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_A, MAC_A);
+ final Ipv6ForwardingRule ruleB = buildTestForwardingRule(UPSTREAM_IFINDEX, NEIGH_B, MAC_B);
+
+ coordinator.tetherOffloadRuleAdd(mIpServer, ruleA);
+ verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)),
+ eq(new TetherDevValue(UPSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX)),
+ eq(new TetherDevValue(DOWNSTREAM_IFINDEX)));
+ clearInvocations(mBpfDevMap);
+
+ coordinator.tetherOffloadRuleAdd(mIpServer, ruleB);
+ verify(mBpfDevMap, never()).updateEntry(any(), any());
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testAddDevMapRule4() throws Exception {
+ final BpfCoordinator coordinator = makeBpfCoordinator();
+ initBpfCoordinatorForRule4(coordinator);
+
+ mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_TCP));
+ verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)),
+ eq(new TetherDevValue(UPSTREAM_IFINDEX)));
+ verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX)),
+ eq(new TetherDevValue(DOWNSTREAM_IFINDEX)));
+ clearInvocations(mBpfDevMap);
+
+ mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_UDP));
+ verify(mBpfDevMap, never()).updateEntry(any(), any());
+ }
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
index ce52ae2..9bd82f9 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
@@ -177,87 +177,65 @@
return offload;
}
- @Test
- public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
+ @NonNull
+ private OffloadController startOffloadController(boolean expectStart)
+ throws Exception {
setupFunctioningHardwareInterface();
- when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
- assertThrows(SettingNotFoundException.class, () ->
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
-
final OffloadController offload = makeOffloadController();
offload.start();
final InOrder inOrder = inOrder(mHardware);
inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, never()).initOffloadConfig();
- inOrder.verify(mHardware, never()).initOffloadControl(
+ inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffloadConfig();
+ inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffloadControl(
any(OffloadHardwareInterface.ControlCallback.class));
inOrder.verifyNoMoreInteractions();
+ // Clear counters only instead of whole mock to preserve the mocking setup.
+ clearInvocations(mHardware);
+ return offload;
+ }
+
+ private void stopOffloadController(final OffloadController offload) throws Exception {
+ final InOrder inOrder = inOrder(mHardware);
+ offload.stop();
+ inOrder.verify(mHardware, times(1)).stopOffloadControl();
+ inOrder.verifyNoMoreInteractions();
+ reset(mHardware);
+ }
+
+ @Test
+ public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
+ when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
+ startOffloadController(false /*expectStart*/);
}
@Test
public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception {
- setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
assertThrows(SettingNotFoundException.class, () ->
Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
+ startOffloadController(true /*expectStart*/);
}
@Test
public void testSettingsAllowsStart() throws Exception {
- setupFunctioningHardwareInterface();
Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
+ startOffloadController(true /*expectStart*/);
}
@Test
public void testSettingsDisablesStart() throws Exception {
- setupFunctioningHardwareInterface();
Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1);
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, never()).initOffloadConfig();
- inOrder.verify(mHardware, never()).initOffloadControl(anyObject());
- inOrder.verifyNoMoreInteractions();
+ startOffloadController(false /*expectStart*/);
}
@Test
public void testSetUpstreamLinkPropertiesWorking() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
- final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
// In reality, the UpstreamNetworkMonitor would have passed down to us
// a covering set of local prefixes representing a minimum essential
@@ -271,6 +249,7 @@
minimumLocalPrefixes.add(new IpPrefix(s));
}
offload.setLocalPrefixes(minimumLocalPrefixes);
+ final InOrder inOrder = inOrder(mHardware);
inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
ArrayList<String> localPrefixes = mStringArrayCaptor.getValue();
assertEquals(4, localPrefixes.size());
@@ -425,11 +404,9 @@
@Test
public void testGetForwardedStats() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
final String ethernetIface = "eth1";
final String mobileIface = "rmnet_data0";
@@ -439,7 +416,7 @@
when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn(
new ForwardedStats(999, 99999));
- InOrder inOrder = inOrder(mHardware);
+ final InOrder inOrder = inOrder(mHardware);
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName(ethernetIface);
@@ -517,11 +494,9 @@
@Test
public void testSetInterfaceQuota() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
final String ethernetIface = "eth1";
final String mobileIface = "rmnet_data0";
@@ -581,11 +556,9 @@
@Test
public void testDataLimitCallback() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
callback.onStoppedLimitReached();
@@ -594,17 +567,10 @@
@Test
public void testAddRemoveDownstreams() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
-
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
final InOrder inOrder = inOrder(mHardware);
- inOrder.verify(mHardware, times(1)).initOffloadConfig();
- inOrder.verify(mHardware, times(1)).initOffloadControl(
- any(OffloadHardwareInterface.ControlCallback.class));
- inOrder.verifyNoMoreInteractions();
// Tethering makes several calls to setLocalPrefixes() before add/remove
// downstream calls are made. This is not tested here; only the behavior
@@ -668,11 +634,9 @@
@Test
public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
// Pretend to set a few different upstreams (only the interface name
// matters for this test; we're ignoring IP and route information).
@@ -701,11 +665,9 @@
@Test
public void testControlCallbackOnSupportAvailableFetchesAllStatsAndPushesAllParameters()
throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
-
- final OffloadController offload = makeOffloadController();
- offload.start();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
// Pretend to set a few different upstreams (only the interface name
// matters for this test; we're ignoring IP and route information).
@@ -780,11 +742,10 @@
@Test
public void testOnSetAlert() throws Exception {
- setupFunctioningHardwareInterface();
enableOffload();
setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
- final OffloadController offload = makeOffloadController();
- offload.start();
+ final OffloadController offload =
+ startOffloadController(true /*expectStart*/);
// Initialize with fake eth upstream.
final String ethernetIface = "eth1";
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 df82d7c..6090213 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
@@ -16,6 +16,10 @@
package com.android.networkstack.tethering;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
@@ -64,12 +68,13 @@
public static final boolean CALLBACKS_FIRST = true;
final Map<NetworkCallback, NetworkRequestInfo> mAllCallbacks = new ArrayMap<>();
+ // This contains the callbacks tracking the system default network, whether it's registered
+ // with registerSystemDefaultNetworkCallback (S+) or with a custom request (R-).
final Map<NetworkCallback, NetworkRequestInfo> mTrackingDefault = new ArrayMap<>();
final Map<NetworkCallback, NetworkRequestInfo> mListening = new ArrayMap<>();
final Map<NetworkCallback, NetworkRequestInfo> mRequested = new ArrayMap<>();
final Map<NetworkCallback, Integer> mLegacyTypeMap = new ArrayMap<>();
- private final NetworkRequest mDefaultRequest;
private final Context mContext;
private int mNetworkId = 100;
@@ -80,13 +85,10 @@
* @param ctx the context to use. Must be a fake or a mock because otherwise the test will
* attempt to send real broadcasts and resulting in permission denials.
* @param svc an IConnectivityManager. Should be a fake or a mock.
- * @param defaultRequest the default NetworkRequest that will be used by Tethering.
*/
- public TestConnectivityManager(Context ctx, IConnectivityManager svc,
- NetworkRequest defaultRequest) {
+ public TestConnectivityManager(Context ctx, IConnectivityManager svc) {
super(ctx, svc);
mContext = ctx;
- mDefaultRequest = defaultRequest;
}
class NetworkRequestInfo {
@@ -181,11 +183,19 @@
makeDefaultNetwork(agent, BROADCAST_FIRST, null /* inBetween */);
}
+ static boolean looksLikeDefaultRequest(NetworkRequest req) {
+ return req.hasCapability(NET_CAPABILITY_INTERNET)
+ && !req.hasCapability(NET_CAPABILITY_DUN)
+ && !req.hasTransport(TRANSPORT_CELLULAR);
+ }
+
@Override
public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
assertFalse(mAllCallbacks.containsKey(cb));
mAllCallbacks.put(cb, new NetworkRequestInfo(req, h));
- if (mDefaultRequest.equals(req)) {
+ // For R- devices, Tethering will invoke this function in 2 cases, one is to request mobile
+ // network, the other is to track system default network.
+ if (looksLikeDefaultRequest(req)) {
assertFalse(mTrackingDefault.containsKey(cb));
mTrackingDefault.put(cb, new NetworkRequestInfo(req, h));
} else {
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 fedeeeb..2bc7fc4 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -26,7 +26,6 @@
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;
@@ -73,7 +72,6 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.argThat;
@@ -274,8 +272,6 @@
private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
private TestConnectivityManager mCm;
- private NetworkRequest mNetworkRequest;
- private NetworkCallback mDefaultNetworkCallback;
private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) {
@@ -450,11 +446,6 @@
}
@Override
- public NetworkRequest getDefaultNetworkRequest() {
- return mNetworkRequest;
- }
-
- @Override
public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
Runnable callback) {
mEntitleMgr = spy(super.getEntitlementManager(ctx, h, log, callback));
@@ -645,15 +636,7 @@
mServiceContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(ACTION_TETHER_STATE_CHANGED));
- // TODO: add NOT_VCN_MANAGED here, but more importantly in the production code.
- // TODO: even better, change TetheringDependencies.getDefaultNetworkRequest() to use
- // registerSystemDefaultNetworkCallback() on S and above.
- NetworkCapabilities defaultCaps = new NetworkCapabilities()
- .addCapability(NET_CAPABILITY_INTERNET);
- mNetworkRequest = new NetworkRequest(defaultCaps, TYPE_NONE, 1 /* requestId */,
- NetworkRequest.Type.REQUEST);
- mCm = spy(new TestConnectivityManager(mServiceContext, mock(IConnectivityManager.class),
- mNetworkRequest));
+ mCm = spy(new TestConnectivityManager(mServiceContext, mock(IConnectivityManager.class)));
mTethering = makeTethering();
verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
@@ -793,15 +776,13 @@
}
private void verifyDefaultNetworkRequestFiled() {
- ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
- verify(mCm, times(1)).requestNetwork(eq(mNetworkRequest),
- captor.capture(), any(Handler.class));
- mDefaultNetworkCallback = captor.getValue();
- assertNotNull(mDefaultNetworkCallback);
-
+ ArgumentCaptor<NetworkRequest> reqCaptor = ArgumentCaptor.forClass(NetworkRequest.class);
+ verify(mCm, times(1)).requestNetwork(reqCaptor.capture(),
+ any(NetworkCallback.class), any(Handler.class));
+ assertTrue(TestConnectivityManager.looksLikeDefaultRequest(reqCaptor.getValue()));
// The default network request is only ever filed once.
verifyNoMoreInteractions(mCm);
- mUpstreamNetworkMonitor.startTrackDefaultNetwork(mNetworkRequest, mEntitleMgr);
+ mUpstreamNetworkMonitor.startTrackDefaultNetwork(mEntitleMgr);
verifyNoMoreInteractions(mCm);
}
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 cee0365..ce4ba85 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
@@ -29,10 +29,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -66,6 +66,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -83,10 +84,6 @@
private static final boolean INCLUDES = true;
private static final boolean EXCLUDES = false;
- // Actual contents of the request don't matter for this test. The lack of
- // any specific TRANSPORT_* is sufficient to identify this request.
- private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build();
-
private static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_INTERNET).build();
private static final NetworkCapabilities DUN_CAPABILITIES = new NetworkCapabilities.Builder()
@@ -113,9 +110,10 @@
when(mLog.forSubComponent(anyString())).thenReturn(mLog);
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
- mCM = spy(new TestConnectivityManager(mContext, mCS, sDefaultRequest));
+ mCM = spy(new TestConnectivityManager(mContext, mCS));
+ when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))).thenReturn(mCM);
mSM = new TestStateMachine(mLooper.getLooper());
- mUNM = new UpstreamNetworkMonitor(mCM, mSM, mLog, EVENT_UNM_UPDATE);
+ mUNM = new UpstreamNetworkMonitor(mContext, mSM, mLog, EVENT_UNM_UPDATE);
}
@After public void tearDown() throws Exception {
@@ -146,7 +144,7 @@
@Test
public void testDefaultNetworkIsTracked() throws Exception {
assertTrue(mCM.hasNoCallbacks());
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
assertEquals(1, mCM.mTrackingDefault.size());
@@ -159,7 +157,7 @@
public void testListensForAllNetworks() throws Exception {
assertTrue(mCM.mListening.isEmpty());
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
assertFalse(mCM.mListening.isEmpty());
assertTrue(mCM.isListeningForAll());
@@ -170,9 +168,17 @@
@Test
public void testCallbacksRegistered() {
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
+ // Verify the fired default request matches expectation.
+ final ArgumentCaptor<NetworkRequest> requestCaptor =
+ ArgumentCaptor.forClass(NetworkRequest.class);
verify(mCM, times(1)).requestNetwork(
- eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class));
+ requestCaptor.capture(), any(NetworkCallback.class), any(Handler.class));
+ // For R- devices, Tethering will invoke this function in 2 cases, one is to
+ // request mobile network, the other is to track system default network. Verify
+ // the request is the one tracks default network.
+ assertTrue(TestConnectivityManager.looksLikeDefaultRequest(requestCaptor.getValue()));
+
mUNM.startObserveAllNetworks();
verify(mCM, times(1)).registerNetworkCallback(
any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
@@ -293,7 +299,7 @@
final Collection<Integer> preferredTypes = new ArrayList<>();
preferredTypes.add(TYPE_WIFI);
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
// There are no networks, so there is nothing to select.
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
@@ -366,7 +372,7 @@
@Test
public void testGetCurrentPreferredUpstream() throws Exception {
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.setUpstreamConfig(true /* autoUpstream */, false /* dunRequired */);
mUNM.setTryCell(true);
@@ -438,7 +444,7 @@
@Test
public void testLocalPrefixes() throws Exception {
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
// [0] Test minimum set of local prefixes.
@@ -549,7 +555,7 @@
// Mobile has higher pirority than wifi.
preferredTypes.add(TYPE_MOBILE_HIPRI);
preferredTypes.add(TYPE_WIFI);
- mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(mEntitleMgr);
mUNM.startObserveAllNetworks();
// Setup wifi and make wifi as default network.
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index fda128c..8023aa0 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -102,6 +102,7 @@
import android.net.NetworkInfo.State;
import android.net.NetworkRequest;
import android.net.NetworkUtils;
+import android.net.ProxyInfo;
import android.net.SocketKeepalive;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
@@ -1717,6 +1718,7 @@
* Verify background request can only be requested when acquiring
* {@link android.Manifest.permission.NETWORK_SETTINGS}.
*/
+ @AppModeFull(reason = "Instant apps cannot create test networks")
@Test
public void testRequestBackgroundNetwork() {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
@@ -1912,4 +1914,12 @@
assertNull(NetworkInformationShimImpl.newInstance()
.getCapabilityCarrierName(ConstantsShim.NET_CAPABILITY_NOT_VCN_MANAGED));
}
+
+ @Test
+ public void testSetGlobalProxy() {
+ assumeTrue(TestUtils.shouldTestSApis());
+ // Behavior is verified in gts. Verify exception thrown w/o permission.
+ assertThrows(SecurityException.class, () -> mCm.setGlobalProxy(
+ ProxyInfo.buildDirectProxy("example.com" /* host */, 8080 /* port */)));
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 5cf7140..3214531 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -596,8 +596,7 @@
assertNotNull(vpnNc)
assertEquals(VpnManager.TYPE_VPN_SERVICE,
(vpnNc.transportInfo as VpnTransportInfo).type)
- // TODO: b/183938194 please fix the issue and enable following check.
- // assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId)
+ assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId)
val testAndVpn = intArrayOf(TRANSPORT_TEST, TRANSPORT_VPN)
assertTrue(hasAllTransports(vpnNc, testAndVpn))
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index fa52e9b..52ce83a 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -16,8 +16,8 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-android_test {
- name: "CtsTetheringTest",
+java_defaults {
+ name: "CtsTetheringTestDefaults",
defaults: ["cts_defaults"],
libs: [
@@ -30,7 +30,6 @@
static_libs: [
"TetheringCommonTests",
- "TetheringIntegrationTestsLib",
"compatibility-device-util-axt",
"cts-net-utils",
"net-tests-utils",
@@ -47,14 +46,53 @@
// Change to system current when TetheringManager move to bootclass path.
platform_apis: true,
+}
+
+// Tethering CTS tests that target the latest released SDK. These tests can be installed on release
+// devices which has equal or lowner sdk version than target sdk and are useful for qualifying
+// mainline modules on release devices.
+android_test {
+ name: "CtsTetheringTestLatestSdk",
+ defaults: ["CtsTetheringTestDefaults"],
+
+ min_sdk_version: "30",
+ target_sdk_version: "30",
+
+ static_libs: [
+ "TetheringIntegrationTestsLatestSdkLib",
+ ],
+
+ test_suites: [
+ "general-tests",
+ "mts-tethering",
+ ],
+
+ test_config_template: "AndroidTestTemplate.xml",
+
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+}
+
+// Tethering CTS tests for development and release. These tests always target the platform SDK
+// version, and are subject to all the restrictions appropriate to that version. Before SDK
+// finalization, these tests have a min_sdk_version of 10000, and cannot be installed on release
+// devices.
+android_test {
+ name: "CtsTetheringTest",
+ defaults: ["CtsTetheringTestDefaults"],
+
+ static_libs: [
+ "TetheringIntegrationTestsLib",
+ ],
// Tag this module as a cts test artifact
test_suites: [
"cts",
"general-tests",
- "mts-tethering",
],
+ test_config_template: "AndroidTestTemplate.xml",
+
// Include both the 32 and 64 bit versions
compile_multilib: "both",
}
diff --git a/tests/cts/tethering/AndroidTest.xml b/tests/cts/tethering/AndroidTestTemplate.xml
similarity index 89%
rename from tests/cts/tethering/AndroidTest.xml
rename to tests/cts/tethering/AndroidTestTemplate.xml
index e752e3a..491b004 100644
--- a/tests/cts/tethering/AndroidTest.xml
+++ b/tests/cts/tethering/AndroidTestTemplate.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 The Android Open Source Project
+<!-- 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.
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Config for CTS Tethering test cases">
+<configuration description="Config for {MODULE}">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
@@ -23,7 +23,7 @@
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsTetheringTest.apk" />
+ <option name="test-file-name" value="{MODULE}.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.tethering.cts" />