Merge "Add Low Power Standby test to NetworkManagementServiceTest"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index ecbaf61..ae96e8c 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -99,7 +99,6 @@
],
min_sdk_version: "30",
header_libs: [
- "bpf_syscall_wrappers",
"bpf_connectivity_headers",
],
srcs: [
@@ -112,7 +111,6 @@
static_libs: [
"libnet_utils_device_common_bpfjni",
"libnetjniutils",
- "libtcutils",
],
// We cannot use plain "libc++" here to link libc++ dynamically because it results in:
diff --git a/Tethering/apex/canned_fs_config b/Tethering/apex/canned_fs_config
index 06e9617..5a03347 100644
--- a/Tethering/apex/canned_fs_config
+++ b/Tethering/apex/canned_fs_config
@@ -1,2 +1,2 @@
-/bin/for-system 0 1000 0550
+/bin/for-system 0 1000 0750
/bin/for-system/clatd 1029 1029 06755
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 a33af61..26040a2 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
@@ -27,10 +27,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.networkstack.tethering.Tether4Key;
-import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
import java.util.function.BiConsumer;
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 7189933..e3b1539 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
@@ -30,11 +30,11 @@
import androidx.annotation.Nullable;
import com.android.net.module.util.BpfMap;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.networkstack.tethering.BpfUtils;
-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;
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 08ab9ca..d663968 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
@@ -22,10 +22,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator.Dependencies;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
-import com.android.networkstack.tethering.Tether4Key;
-import com.android.networkstack.tethering.Tether4Value;
import com.android.networkstack.tethering.TetherStatsValue;
import java.util.function.BiConsumer;
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index c82a993..9ca3f14 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -26,13 +26,18 @@
// Using for test only
"//cts/tests/netlegacy22.api",
"//external/sl4a:__subpackages__",
+ "//frameworks/base/core/tests/bandwidthtests",
+ "//frameworks/base/core/tests/benchmarks",
+ "//frameworks/base/core/tests/utillib",
"//frameworks/base/packages/Connectivity/tests:__subpackages__",
+ "//frameworks/base/tests/vcn",
"//frameworks/libs/net/common/testutils",
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
"//packages/modules/Wifi/service/tests/wifitests",
],
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 8c8a2fd..40956f7 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -65,6 +65,8 @@
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.Struct;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.netlink.ConntrackMessage;
import com.android.net.module.util.netlink.NetlinkConstants;
import com.android.net.module.util.netlink.NetlinkSocket;
diff --git a/Tethering/src/com/android/networkstack/tethering/Tether4Key.java b/Tethering/src/com/android/networkstack/tethering/Tether4Key.java
deleted file mode 100644
index a01ea34..0000000
--- a/Tethering/src/com/android/networkstack/tethering/Tether4Key.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2020 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 android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
-import java.util.Objects;
-
-/** Key type for downstream & upstream IPv4 forwarding maps. */
-public class Tether4Key extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long iif;
-
- @Field(order = 1, type = Type.EUI48)
- public final MacAddress dstMac;
-
- @Field(order = 2, type = Type.U8, padding = 1)
- public final short l4proto;
-
- @Field(order = 3, type = Type.ByteArray, arraysize = 4)
- public final byte[] src4;
-
- @Field(order = 4, type = Type.ByteArray, arraysize = 4)
- public final byte[] dst4;
-
- @Field(order = 5, type = Type.UBE16)
- public final int srcPort;
-
- @Field(order = 6, type = Type.UBE16)
- public final int dstPort;
-
- public Tether4Key(final long iif, @NonNull final MacAddress dstMac, final short l4proto,
- final byte[] src4, final byte[] dst4, final int srcPort,
- final int dstPort) {
- Objects.requireNonNull(dstMac);
-
- this.iif = iif;
- this.dstMac = dstMac;
- this.l4proto = l4proto;
- this.src4 = src4;
- this.dst4 = dst4;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- }
-
- @Override
- public String toString() {
- try {
- return String.format(
- "iif: %d, dstMac: %s, l4proto: %d, src4: %s, dst4: %s, "
- + "srcPort: %d, dstPort: %d",
- iif, dstMac, l4proto,
- Inet4Address.getByAddress(src4), Inet4Address.getByAddress(dst4),
- Short.toUnsignedInt((short) srcPort), Short.toUnsignedInt((short) dstPort));
- } catch (UnknownHostException | IllegalArgumentException e) {
- return String.format("Invalid IP address", e);
- }
- }
-}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tether4Value.java b/Tethering/src/com/android/networkstack/tethering/Tether4Value.java
deleted file mode 100644
index 03a226c..0000000
--- a/Tethering/src/com/android/networkstack/tethering/Tether4Value.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2020 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 android.net.MacAddress;
-
-import androidx.annotation.NonNull;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Objects;
-
-/** Value type for downstream & upstream IPv4 forwarding maps. */
-public class Tether4Value extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long oif;
-
- // The ethhdr struct which is defined in uapi/linux/if_ether.h
- @Field(order = 1, type = Type.EUI48)
- public final MacAddress ethDstMac;
- @Field(order = 2, type = Type.EUI48)
- public final MacAddress ethSrcMac;
- @Field(order = 3, type = Type.UBE16)
- public final int ethProto; // Packet type ID field.
-
- @Field(order = 4, type = Type.U16)
- public final int pmtu;
-
- @Field(order = 5, type = Type.ByteArray, arraysize = 16)
- public final byte[] src46;
-
- @Field(order = 6, type = Type.ByteArray, arraysize = 16)
- public final byte[] dst46;
-
- @Field(order = 7, type = Type.UBE16)
- public final int srcPort;
-
- @Field(order = 8, type = Type.UBE16)
- public final int dstPort;
-
- // TODO: consider using U64.
- @Field(order = 9, type = Type.U63)
- public final long lastUsed;
-
- public Tether4Value(final long oif, @NonNull final MacAddress ethDstMac,
- @NonNull final MacAddress ethSrcMac, final int ethProto, final int pmtu,
- final byte[] src46, final byte[] dst46, final int srcPort,
- final int dstPort, final long lastUsed) {
- Objects.requireNonNull(ethDstMac);
- Objects.requireNonNull(ethSrcMac);
-
- this.oif = oif;
- this.ethDstMac = ethDstMac;
- this.ethSrcMac = ethSrcMac;
- this.ethProto = ethProto;
- this.pmtu = pmtu;
- this.src46 = src46;
- this.dst46 = dst46;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- this.lastUsed = lastUsed;
- }
-
- @Override
- public String toString() {
- try {
- return String.format(
- "oif: %d, ethDstMac: %s, ethSrcMac: %s, ethProto: %d, pmtu: %d, "
- + "src46: %s, dst46: %s, srcPort: %d, dstPort: %d, "
- + "lastUsed: %d",
- oif, ethDstMac, ethSrcMac, ethProto, pmtu,
- InetAddress.getByAddress(src46), InetAddress.getByAddress(dst46),
- Short.toUnsignedInt((short) srcPort), Short.toUnsignedInt((short) dstPort),
- lastUsed);
- } catch (UnknownHostException | IllegalArgumentException e) {
- return String.format("Invalid IP address", e);
- }
- }
-}
diff --git a/Tethering/tests/jarjar-rules.txt b/Tethering/tests/jarjar-rules.txt
index 23d3f56..a7c7488 100644
--- a/Tethering/tests/jarjar-rules.txt
+++ b/Tethering/tests/jarjar-rules.txt
@@ -13,6 +13,9 @@
# Classes from net-utils-framework-common
rule com.android.net.module.util.** com.android.networkstack.tethering.util.@1
+# Classes from net-tests-utils
+rule com.android.testutils.TestBpfMap* com.android.networkstack.tethering.testutils.TestBpfMap@1
+
# TODO: either stop using frameworks-base-testutils or remove the unit test classes it contains.
# TestableLooper from "testables" can be used instead of TestLooper from frameworks-base-testutils.
zap android.os.test.TestLooperTest*
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 267c376..a3c46c2 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -101,11 +101,11 @@
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.NetworkStackConstants;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.networkstack.tethering.BpfCoordinator;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.networkstack.tethering.PrivateAddressCoordinator;
-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;
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 c5969d2..6c7a66d 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -89,7 +89,6 @@
import android.os.Build;
import android.os.Handler;
import android.os.test.TestLooper;
-import android.system.ErrnoException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -100,7 +99,8 @@
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkStackConstants;
-import com.android.net.module.util.Struct;
+import com.android.net.module.util.bpf.Tether4Key;
+import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.netlink.ConntrackMessage;
import com.android.net.module.util.netlink.NetlinkConstants;
import com.android.net.module.util.netlink.NetlinkSocket;
@@ -110,6 +110,7 @@
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.TestBpfMap;
import com.android.testutils.TestableNetworkStatsProviderCbBinder;
import org.junit.Before;
@@ -128,10 +129,7 @@
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.function.BiConsumer;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -157,60 +155,6 @@
UPSTREAM_IFACE, UPSTREAM_IFINDEX, null /* macAddr, rawip */,
NetworkStackConstants.ETHER_MTU);
- // The test fake BPF map class is needed because the test has no privilege to access the BPF
- // map. All member functions which eventually call JNI to access the real native BPF map need
- // to be overridden.
- // TODO: consider moving to an individual file.
- private class TestBpfMap<K extends Struct, V extends Struct> extends BpfMap<K, V> {
- private final HashMap<K, V> mMap = new HashMap<K, V>();
-
- TestBpfMap(final Class<K> key, final Class<V> value) {
- super(key, value);
- }
-
- @Override
- public void forEach(BiConsumer<K, V> action) throws ErrnoException {
- // TODO: consider using mocked #getFirstKey and #getNextKey to iterate. It helps to
- // implement the entry deletion in the iteration if required.
- for (Map.Entry<K, V> entry : mMap.entrySet()) {
- action.accept(entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- public void updateEntry(K key, V value) throws ErrnoException {
- mMap.put(key, value);
- }
-
- @Override
- public void insertEntry(K key, V value) throws ErrnoException,
- IllegalArgumentException {
- // The entry is created if and only if it doesn't exist. See BpfMap#insertEntry.
- if (mMap.get(key) != null) {
- throw new IllegalArgumentException(key + " already exist");
- }
- mMap.put(key, value);
- }
-
- @Override
- public boolean deleteEntry(Struct key) throws ErrnoException {
- return mMap.remove(key) != null;
- }
-
- @Override
- public V getValue(@NonNull K key) throws ErrnoException {
- // Return value for a given key. Otherwise, return null without an error ENOENT.
- // BpfMap#getValue treats that the entry is not found as no error.
- return mMap.get(key);
- }
-
- @Override
- public void clear() throws ErrnoException {
- // TODO: consider using mocked #getFirstKey and #deleteEntry to implement.
- mMap.clear();
- }
- };
-
@Mock private NetworkStatsManager mStatsManager;
@Mock private INetd mNetd;
@Mock private IpServer mIpServer;
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index c1a74e7..8d05757 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -297,12 +297,12 @@
return match;
}
-DEFINE_BPF_PROG("cgroupskb/ingress/stats", AID_ROOT, AID_ROOT, bpf_cgroup_ingress)
+DEFINE_BPF_PROG("cgroupskb/ingress/stats", AID_ROOT, AID_SYSTEM, bpf_cgroup_ingress)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, BPF_INGRESS);
}
-DEFINE_BPF_PROG("cgroupskb/egress/stats", AID_ROOT, AID_ROOT, bpf_cgroup_egress)
+DEFINE_BPF_PROG("cgroupskb/egress/stats", AID_ROOT, AID_SYSTEM, bpf_cgroup_egress)
(struct __sk_buff* skb) {
return bpf_traffic_account(skb, BPF_EGRESS);
}
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index b5aedeb..f464322 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -29,22 +29,17 @@
// SDK library for connectivity bootclasspath classes that were part of the non-updatable API before
// T, and were moved to the module in T. Other bootclasspath classes in connectivity should go to
// framework-connectivity.
-java_sdk_library {
- name: "framework-connectivity-tiramisu",
+java_defaults {
+ name: "framework-connectivity-tiramisu-defaults",
sdk_version: "module_current",
min_sdk_version: "Tiramisu",
defaults: [
"framework-module-defaults",
- "enable-framework-connectivity-t-targets",
],
srcs: [
":framework-connectivity-tiramisu-updatable-sources",
":framework-nearby-java-sources",
],
- // Do not add static_libs to this library: put them in framework-connectivity instead.
- // The jarjar rules are only so that references to jarjared utils in
- // framework-connectivity-pre-jarjar match at runtime.
- jarjar_rules: ":connectivity-jarjar-rules",
stub_only_libs: [
// Use prebuilt framework-connectivity stubs to avoid circular dependencies
"sdk_module-lib_current_framework-connectivity",
@@ -67,6 +62,43 @@
// non-jarjard names of widely-used packages such as com.android.net.module.util.
"framework-connectivity-pre-jarjar",
],
+ aidl: {
+ generate_get_transaction_name: true,
+ include_dirs: [
+ // For connectivity-framework classes such as Network.aidl,
+ // and connectivity-framework-t classes such as
+ // NetworkStateSnapshot.aidl
+ "packages/modules/Connectivity/framework/aidl-export",
+ ],
+ },
+ apex_available: [
+ "com.android.tethering",
+ ],
+}
+
+java_library {
+ name: "framework-connectivity-tiramisu-pre-jarjar",
+ defaults: ["framework-connectivity-tiramisu-defaults"],
+ libs: [
+ "framework-bluetooth",
+ "framework-connectivity-pre-jarjar",
+ ],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
+}
+
+// SDK library for connectivity bootclasspath classes that were part of the non-updatable API before
+// T, and were moved to the module in T. Other bootclasspath classes in connectivity should go to
+// framework-connectivity.
+java_sdk_library {
+ name: "framework-connectivity-tiramisu",
+ defaults: [
+ "framework-connectivity-tiramisu-defaults",
+ "enable-framework-connectivity-t-targets",
+ ],
+ // Do not add static_libs to this library: put them in framework-connectivity instead.
+ // The jarjar rules are only so that references to jarjared utils in
+ // framework-connectivity-pre-jarjar match at runtime.
+ jarjar_rules: ":connectivity-jarjar-rules",
permitted_packages: [
"android.net",
"android.net.nsd",
@@ -74,9 +106,6 @@
"com.android.connectivity",
"com.android.nearby",
],
- apex_available: [
- "com.android.tethering",
- ],
impl_library_visibility: [
"//packages/modules/Connectivity/Tethering/apex",
// In preparation for future move
@@ -89,12 +118,17 @@
"//cts/tests/netlegacy22.api",
"//cts/tests/tests/app.usage", // NetworkUsageStatsTest
"//external/sl4a:__subpackages__",
+ "//frameworks/base/core/tests/bandwidthtests",
+ "//frameworks/base/core/tests/benchmarks",
+ "//frameworks/base/core/tests/utillib",
+ "//frameworks/base/tests/vcn",
"//frameworks/libs/net/common/testutils",
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
"//packages/modules/Nearby/tests:__subpackages__",
"//packages/modules/Wifi/service/tests/wifitests",
diff --git a/framework-t/api/OWNERS b/framework-t/api/OWNERS
new file mode 100644
index 0000000..de0f905
--- /dev/null
+++ b/framework-t/api/OWNERS
@@ -0,0 +1 @@
+file:platform/packages/modules/Connectivity:master:/nearby/OWNERS
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index 0443456..7977cc5 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -3,6 +3,8 @@
public final class NsdManager {
method public void discoverServices(String, int, android.net.nsd.NsdManager.DiscoveryListener);
+ method public void discoverServices(@NonNull String, int, @Nullable android.net.Network, @NonNull android.net.nsd.NsdManager.DiscoveryListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void discoverServices(@NonNull String, int, @NonNull android.net.NetworkRequest, @NonNull android.net.nsd.NsdManager.DiscoveryListener);
method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener);
method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener);
@@ -43,12 +45,14 @@
method public int describeContents();
method public java.util.Map<java.lang.String,byte[]> getAttributes();
method public java.net.InetAddress getHost();
+ method @Nullable public android.net.Network getNetwork();
method public int getPort();
method public String getServiceName();
method public String getServiceType();
method public void removeAttribute(String);
method public void setAttribute(String, String);
method public void setHost(java.net.InetAddress);
+ method public void setNetwork(@Nullable android.net.Network);
method public void setPort(int);
method public void setServiceName(String);
method public void setServiceType(String);
diff --git a/framework/Android.bp b/framework/Android.bp
index d3e46fa..da16a8d 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -131,12 +131,17 @@
"//cts/tests/tests/app.usage", // NetworkUsageStatsTest
"//external/sl4a:__subpackages__",
"//frameworks/base/packages/Connectivity/tests:__subpackages__",
+ "//frameworks/base/core/tests/bandwidthtests",
+ "//frameworks/base/core/tests/benchmarks",
+ "//frameworks/base/core/tests/utillib",
+ "//frameworks/base/tests/vcn",
"//frameworks/libs/net/common/testutils",
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/opt/telephony/tests/telephonytests",
"//packages/modules/CaptivePortalLogin/tests",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
"//packages/modules/NetworkStack/tests:__subpackages__",
"//packages/modules/Wifi/service/tests/wifitests",
],
diff --git a/framework/aidl-export/android/net/NetworkAgentConfig.aidl b/framework/aidl-export/android/net/NetworkAgentConfig.aidl
index cb70bdd..02d50b7 100644
--- a/framework/aidl-export/android/net/NetworkAgentConfig.aidl
+++ b/framework/aidl-export/android/net/NetworkAgentConfig.aidl
@@ -16,4 +16,4 @@
package android.net;
-parcelable NetworkAgentConfig;
+@JavaOnlyStableParcelable parcelable NetworkAgentConfig;
diff --git a/framework/aidl-export/android/net/NetworkStateSnapshot.aidl b/framework/aidl-export/android/net/NetworkStateSnapshot.aidl
new file mode 100644
index 0000000..cb602d7
--- /dev/null
+++ b/framework/aidl-export/android/net/NetworkStateSnapshot.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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;
+
+parcelable NetworkStateSnapshot;
diff --git a/framework/api/current.txt b/framework/api/current.txt
index a373b71..547b7e2 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -205,6 +205,21 @@
method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String);
}
+ public final class IpConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.net.ProxyInfo getHttpProxy();
+ method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
+ }
+
+ public static final class IpConfiguration.Builder {
+ ctor public IpConfiguration.Builder();
+ method @NonNull public android.net.IpConfiguration build();
+ method @NonNull public android.net.IpConfiguration.Builder setHttpProxy(@Nullable android.net.ProxyInfo);
+ method @NonNull public android.net.IpConfiguration.Builder setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
+ }
+
public final class IpPrefix implements android.os.Parcelable {
ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
method public boolean contains(@NonNull java.net.InetAddress);
@@ -485,6 +500,25 @@
method public void onStopped();
}
+ public final class StaticIpConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
+ method @Nullable public String getDomains();
+ method @Nullable public java.net.InetAddress getGateway();
+ method @NonNull public android.net.LinkAddress getIpAddress();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
+ }
+
+ public static final class StaticIpConfiguration.Builder {
+ ctor public StaticIpConfiguration.Builder();
+ method @NonNull public android.net.StaticIpConfiguration build();
+ method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
+ method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
+ method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
+ method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@NonNull android.net.LinkAddress);
+ }
+
public interface TransportInfo {
}
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 5961e72..fda1045 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -69,6 +69,7 @@
method @NonNull public static java.time.Duration getDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static int getDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, int);
method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context);
+ method public static long getIngressRateLimitInBytesPerSecond(@NonNull android.content.Context);
method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static boolean getMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
method @NonNull public static java.util.Set<java.lang.Integer> getMobileDataPreferredUids(@NonNull android.content.Context);
@@ -89,6 +90,7 @@
method public static void setDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static void setDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, @IntRange(from=0, to=100) int);
method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo);
+ method public static void setIngressRateLimitInBytesPerSecond(@NonNull android.content.Context, @IntRange(from=0xffffffff, to=java.lang.Integer.MAX_VALUE) long);
method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static void setMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
method public static void setMobileDataPreferredUids(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>);
@@ -124,13 +126,15 @@
public final class NetworkAgentConfig implements android.os.Parcelable {
method @Nullable public String getSubscriberId();
+ method public boolean getVpnRequiresValidation();
method public boolean isBypassableVpn();
}
public static final class NetworkAgentConfig.Builder {
method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean);
- method @NonNull public android.net.NetworkAgentConfig.Builder setExcludeLocalRoutesVpn(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setLocalRoutesExcludedForVpn(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setVpnRequiresValidation(boolean);
}
public final class NetworkCapabilities implements android.os.Parcelable {
diff --git a/framework/api/module-lib-lint-baseline.txt b/framework/api/module-lib-lint-baseline.txt
deleted file mode 100644
index c7b0db5..0000000
--- a/framework/api/module-lib-lint-baseline.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-// Baseline format: 1.0
-NoByteOrShort: android.net.DhcpOption#DhcpOption(byte, byte[]) parameter #0:
- Should avoid odd sized primitives; use `int` instead of `byte` in parameter type in android.net.DhcpOption(byte type, byte[] value)
-NoByteOrShort: android.net.DhcpOption#describeContents():
- Should avoid odd sized primitives; use `int` instead of `byte` in method android.net.DhcpOption.describeContents()
-NoByteOrShort: android.net.DhcpOption#getType():
- Should avoid odd sized primitives; use `int` instead of `byte` in method android.net.DhcpOption.getType()
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index d420958..764cffa 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -133,17 +133,12 @@
public final class IpConfiguration implements android.os.Parcelable {
ctor public IpConfiguration();
ctor public IpConfiguration(@NonNull android.net.IpConfiguration);
- method public int describeContents();
- method @Nullable public android.net.ProxyInfo getHttpProxy();
method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
- method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration();
method public void setHttpProxy(@Nullable android.net.ProxyInfo);
method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment);
method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings);
method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.IpConfiguration> CREATOR;
}
public enum IpConfiguration.IpAssignment {
@@ -484,23 +479,7 @@
ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration);
method public void addDnsServer(@NonNull java.net.InetAddress);
method public void clear();
- method public int describeContents();
- method @NonNull public java.util.List<java.net.InetAddress> getDnsServers();
- method @Nullable public String getDomains();
- method @Nullable public java.net.InetAddress getGateway();
- method @Nullable public android.net.LinkAddress getIpAddress();
method @NonNull public java.util.List<android.net.RouteInfo> getRoutes(@Nullable String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
- }
-
- public static final class StaticIpConfiguration.Builder {
- ctor public StaticIpConfiguration.Builder();
- method @NonNull public android.net.StaticIpConfiguration build();
- method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable<java.net.InetAddress>);
- method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String);
- method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress);
- method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
}
public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index 8fc0065..4e28b29 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -384,6 +384,14 @@
"uids_allowed_on_restricted_networks";
/**
+ * A global rate limit that applies to all networks with NET_CAPABILITY_INTERNET when enabled.
+ *
+ * @hide
+ */
+ public static final String INGRESS_RATE_LIMIT_BYTES_PER_SECOND =
+ "ingress_rate_limit_bytes_per_second";
+
+ /**
* Get mobile data activity timeout from {@link Settings}.
*
* @param context The {@link Context} to query the setting.
@@ -1071,4 +1079,37 @@
Settings.Global.putString(context.getContentResolver(), UIDS_ALLOWED_ON_RESTRICTED_NETWORKS,
uids);
}
+
+ /**
+ * Get the global network bandwidth rate limit.
+ *
+ * The limit is only applicable to networks that provide internet connectivity. If the setting
+ * is unset, it defaults to -1.
+ *
+ * @param context The {@link Context} to query the setting.
+ * @return The rate limit in number of bytes per second or -1 if disabled.
+ */
+ public static long getIngressRateLimitInBytesPerSecond(@NonNull Context context) {
+ return Settings.Global.getLong(context.getContentResolver(),
+ INGRESS_RATE_LIMIT_BYTES_PER_SECOND, -1);
+ }
+
+ /**
+ * Set the global network bandwidth rate limit.
+ *
+ * The limit is only applicable to networks that provide internet connectivity.
+ *
+ * @param context The {@link Context} to set the setting.
+ * @param rateLimitInBytesPerSec The rate limit in number of bytes per second or -1 to disable.
+ */
+ public static void setIngressRateLimitInBytesPerSecond(@NonNull Context context,
+ @IntRange(from = -1, to = Integer.MAX_VALUE) long rateLimitInBytesPerSec) {
+ if (rateLimitInBytesPerSec < -1) {
+ throw new IllegalArgumentException(
+ "Rate limit must be within the range [-1, Integer.MAX_VALUE]");
+ }
+ Settings.Global.putLong(context.getContentResolver(),
+ INGRESS_RATE_LIMIT_BYTES_PER_SECOND,
+ rateLimitInBytesPerSec);
+ }
}
diff --git a/framework/src/android/net/DhcpOption.java b/framework/src/android/net/DhcpOption.java
index a125290..b30470a 100644
--- a/framework/src/android/net/DhcpOption.java
+++ b/framework/src/android/net/DhcpOption.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,12 +36,13 @@
/**
* Constructs a DhcpOption object.
*
- * @param type the type of this option
+ * @param type the type of this option. For more information, see
+ * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml.
* @param value the value of this option. If {@code null}, DHCP packets containing this option
* will include the option type in the Parameter Request List. Otherwise, DHCP
* packets containing this option will include the option in the options section.
*/
- public DhcpOption(byte type, @Nullable byte[] value) {
+ public DhcpOption(@SuppressLint("NoByteOrShort") byte type, @Nullable byte[] value) {
mType = type;
mValue = value;
}
@@ -69,6 +71,7 @@
};
/** Get the type of DHCP option */
+ @SuppressLint("NoByteOrShort")
public byte getType() {
return mType;
}
diff --git a/framework/src/android/net/IpConfiguration.java b/framework/src/android/net/IpConfiguration.java
index d5f8b2e..99835aa 100644
--- a/framework/src/android/net/IpConfiguration.java
+++ b/framework/src/android/net/IpConfiguration.java
@@ -28,16 +28,16 @@
import java.util.Objects;
/**
- * A class representing a configured network.
- * @hide
+ * A class representing the IP configuration of a network.
*/
-@SystemApi
public final class IpConfiguration implements Parcelable {
private static final String TAG = "IpConfiguration";
// This enum has been used by apps through reflection for many releases.
// Therefore they can't just be removed. Duplicating these constants to
// give an alternate SystemApi is a worse option than exposing them.
+ /** @hide */
+ @SystemApi
@SuppressLint("Enum")
public enum IpAssignment {
/* Use statically configured IP settings. Configuration can be accessed
@@ -59,6 +59,8 @@
// This enum has been used by apps through reflection for many releases.
// Therefore they can't just be removed. Duplicating these constants to
// give an alternate SystemApi is a worse option than exposing them.
+ /** @hide */
+ @SystemApi
@SuppressLint("Enum")
public enum ProxySettings {
/* No proxy is to be used. Any existing proxy settings
@@ -94,6 +96,8 @@
null : new ProxyInfo(httpProxy);
}
+ /** @hide */
+ @SystemApi
public IpConfiguration() {
init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null);
}
@@ -107,6 +111,8 @@
init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy);
}
+ /** @hide */
+ @SystemApi
public IpConfiguration(@NonNull IpConfiguration source) {
this();
if (source != null) {
@@ -115,34 +121,58 @@
}
}
+ /** @hide */
+ @SystemApi
public @NonNull IpAssignment getIpAssignment() {
return ipAssignment;
}
+ /** @hide */
+ @SystemApi
public void setIpAssignment(@NonNull IpAssignment ipAssignment) {
this.ipAssignment = ipAssignment;
}
+ /**
+ * Get the current static IP configuration (possibly null). Configured via
+ * {@link Builder#setStaticIpConfiguration(StaticIpConfiguration)}.
+ *
+ * @return Current static IP configuration.
+ */
public @Nullable StaticIpConfiguration getStaticIpConfiguration() {
return staticIpConfiguration;
}
+ /** @hide */
+ @SystemApi
public void setStaticIpConfiguration(@Nullable StaticIpConfiguration staticIpConfiguration) {
this.staticIpConfiguration = staticIpConfiguration;
}
+ /** @hide */
+ @SystemApi
public @NonNull ProxySettings getProxySettings() {
return proxySettings;
}
+ /** @hide */
+ @SystemApi
public void setProxySettings(@NonNull ProxySettings proxySettings) {
this.proxySettings = proxySettings;
}
+ /**
+ * The proxy configuration of this object.
+ *
+ * @return The proxy information of this object configured via
+ * {@link Builder#setHttpProxy(ProxyInfo)}.
+ */
public @Nullable ProxyInfo getHttpProxy() {
return httpProxy;
}
+ /** @hide */
+ @SystemApi
public void setHttpProxy(@Nullable ProxyInfo httpProxy) {
this.httpProxy = httpProxy;
}
@@ -220,4 +250,56 @@
return new IpConfiguration[size];
}
};
+
+ /**
+ * Builder used to construct {@link IpConfiguration} objects.
+ */
+ public static final class Builder {
+ private StaticIpConfiguration mStaticIpConfiguration;
+ private ProxyInfo mProxyInfo;
+
+ /**
+ * Set a static IP configuration.
+ *
+ * @param config Static IP configuration.
+ * @return A {@link Builder} object to allow chaining.
+ */
+ public @NonNull Builder setStaticIpConfiguration(@Nullable StaticIpConfiguration config) {
+ mStaticIpConfiguration = config;
+ return this;
+ }
+
+ /**
+ * Set a proxy configuration.
+ *
+ * @param proxyInfo Proxy configuration.
+ * @return A {@link Builder} object to allow chaining.
+ */
+ public @NonNull Builder setHttpProxy(@Nullable ProxyInfo proxyInfo) {
+ mProxyInfo = proxyInfo;
+ return this;
+ }
+
+ /**
+ * Construct an {@link IpConfiguration}.
+ *
+ * @return A new {@link IpConfiguration} object.
+ */
+ public @NonNull IpConfiguration build() {
+ IpConfiguration config = new IpConfiguration();
+ config.setStaticIpConfiguration(mStaticIpConfiguration);
+ config.setIpAssignment(
+ mStaticIpConfiguration == null ? IpAssignment.DHCP : IpAssignment.STATIC);
+
+ config.setHttpProxy(mProxyInfo);
+ if (mProxyInfo == null) {
+ config.setProxySettings(ProxySettings.NONE);
+ } else {
+ config.setProxySettings(
+ mProxyInfo.getPacFileUrl() == null ? ProxySettings.STATIC
+ : ProxySettings.PAC);
+ }
+ return config;
+ }
+ }
}
diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java
index 040bf31..1991a58 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -34,6 +34,8 @@
*/
@SystemApi
public final class NetworkAgentConfig implements Parcelable {
+ // TODO : make this object immutable. The fields that should stay mutable should likely
+ // migrate to NetworkAgentInfo.
/**
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
@@ -242,10 +244,31 @@
* @return whether local traffic is excluded from the VPN network.
* @hide
*/
- public boolean getExcludeLocalRouteVpn() {
+ public boolean areLocalRoutesExcludedForVpn() {
return excludeLocalRouteVpn;
}
+ /**
+ * Whether network validation should be performed for this VPN network.
+ * {@see #getVpnRequiresValidation}
+ * @hide
+ */
+ private boolean mVpnRequiresValidation = false;
+
+ /**
+ * Whether network validation should be performed for this VPN network.
+ *
+ * If this network isn't a VPN this should always be {@code false}, and will be ignored
+ * if set.
+ * If this network is a VPN, false means this network should always be considered validated;
+ * true means it follows the same validation semantics as general internet networks.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public boolean getVpnRequiresValidation() {
+ return mVpnRequiresValidation;
+ }
+
/** @hide */
public NetworkAgentConfig() {
}
@@ -266,6 +289,7 @@
legacySubTypeName = nac.legacySubTypeName;
mLegacyExtraInfo = nac.mLegacyExtraInfo;
excludeLocalRouteVpn = nac.excludeLocalRouteVpn;
+ mVpnRequiresValidation = nac.mVpnRequiresValidation;
}
}
@@ -409,6 +433,25 @@
}
/**
+ * Sets whether network validation should be performed for this VPN network.
+ *
+ * Only agents registering a VPN network should use this setter. On other network
+ * types it will be ignored.
+ * False means this network should always be considered validated;
+ * true means it follows the same validation semantics as general internet.
+ *
+ * @param vpnRequiresValidation whether this VPN requires validation.
+ * Default is {@code false}.
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = MODULE_LIBRARIES)
+ public Builder setVpnRequiresValidation(boolean vpnRequiresValidation) {
+ mConfig.mVpnRequiresValidation = vpnRequiresValidation;
+ return this;
+ }
+
+ /**
* Sets whether the apps can bypass the VPN connection.
*
* @return this builder, to facilitate chaining.
@@ -429,7 +472,7 @@
*/
@NonNull
@SystemApi(client = MODULE_LIBRARIES)
- public Builder setExcludeLocalRoutesVpn(boolean excludeLocalRoutes) {
+ public Builder setLocalRoutesExcludedForVpn(boolean excludeLocalRoutes) {
mConfig.excludeLocalRouteVpn = excludeLocalRoutes;
return this;
}
@@ -458,14 +501,16 @@
&& Objects.equals(subscriberId, that.subscriberId)
&& Objects.equals(legacyTypeName, that.legacyTypeName)
&& Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo)
- && excludeLocalRouteVpn == that.excludeLocalRouteVpn;
+ && excludeLocalRouteVpn == that.excludeLocalRouteVpn
+ && mVpnRequiresValidation == that.mVpnRequiresValidation;
}
@Override
public int hashCode() {
return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated,
acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId,
- skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn);
+ skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo, excludeLocalRouteVpn,
+ mVpnRequiresValidation);
}
@Override
@@ -483,6 +528,7 @@
+ ", legacyTypeName = '" + legacyTypeName + '\''
+ ", legacyExtraInfo = '" + mLegacyExtraInfo + '\''
+ ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\''
+ + ", vpnRequiresValidation = '" + mVpnRequiresValidation + '\''
+ "}";
}
@@ -506,6 +552,7 @@
out.writeString(legacySubTypeName);
out.writeString(mLegacyExtraInfo);
out.writeInt(excludeLocalRouteVpn ? 1 : 0);
+ out.writeInt(mVpnRequiresValidation ? 1 : 0);
}
public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
@@ -526,6 +573,7 @@
networkAgentConfig.legacySubTypeName = in.readString();
networkAgentConfig.mLegacyExtraInfo = in.readString();
networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0;
+ networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0;
return networkAgentConfig;
}
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index feb9fc1..b6cd760 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -1615,8 +1615,8 @@
* <p>
* Note that when used to register a network callback, this specifies the minimum acceptable
* signal strength. When received as the state of an existing network it specifies the current
- * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no
- * effect when requesting a callback.
+ * value. A value of {@link #SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has
+ * no effect when requesting a callback.
*
* @param signalStrength the bearer-specific signal strength.
* @hide
diff --git a/framework/src/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java
index 7904f7a..194cffd 100644
--- a/framework/src/android/net/StaticIpConfiguration.java
+++ b/framework/src/android/net/StaticIpConfiguration.java
@@ -26,6 +26,7 @@
import com.android.net.module.util.InetAddressUtils;
+import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
@@ -33,24 +34,7 @@
/**
* Class that describes static IP configuration.
- *
- * <p>This class is different from {@link LinkProperties} because it represents
- * configuration intent. The general contract is that if we can represent
- * a configuration here, then we should be able to configure it on a network.
- * The intent is that it closely match the UI we have for configuring networks.
- *
- * <p>In contrast, {@link LinkProperties} represents current state. It is much more
- * expressive. For example, it supports multiple IP addresses, multiple routes,
- * stacked interfaces, and so on. Because LinkProperties is so expressive,
- * using it to represent configuration intent as well as current state causes
- * problems. For example, we could unknowingly save a configuration that we are
- * not in fact capable of applying, or we could save a configuration that the
- * UI cannot display, which has the potential for malicious code to hide
- * hostile or unexpected configuration from the user.
- *
- * @hide
*/
-@SystemApi
public final class StaticIpConfiguration implements Parcelable {
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -69,10 +53,14 @@
@Nullable
public String domains;
+ /** @hide */
+ @SystemApi
public StaticIpConfiguration() {
dnsServers = new ArrayList<>();
}
+ /** @hide */
+ @SystemApi
public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
this();
if (source != null) {
@@ -84,6 +72,8 @@
}
}
+ /** @hide */
+ @SystemApi
public void clear() {
ipAddress = null;
gateway = null;
@@ -94,7 +84,7 @@
/**
* Get the static IP address included in the configuration.
*/
- public @Nullable LinkAddress getIpAddress() {
+ public @NonNull LinkAddress getIpAddress() {
return ipAddress;
}
@@ -130,10 +120,15 @@
private String mDomains;
/**
- * Set the IP address to be included in the configuration; null by default.
+ * Set the IP address to be included in the configuration.
+ *
* @return The {@link Builder} for chaining.
*/
- public @NonNull Builder setIpAddress(@Nullable LinkAddress ipAddress) {
+ public @NonNull Builder setIpAddress(@NonNull LinkAddress ipAddress) {
+ if (ipAddress != null && !(ipAddress.getAddress() instanceof Inet4Address)) {
+ throw new IllegalArgumentException(
+ "Only IPv4 addresses can be used for the IP configuration");
+ }
mIpAddress = ipAddress;
return this;
}
@@ -143,6 +138,10 @@
* @return The {@link Builder} for chaining.
*/
public @NonNull Builder setGateway(@Nullable InetAddress gateway) {
+ if (gateway != null && !(gateway instanceof Inet4Address)) {
+ throw new IllegalArgumentException(
+ "Only IPv4 addresses can be used for the gateway configuration");
+ }
mGateway = gateway;
return this;
}
@@ -153,6 +152,12 @@
*/
public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
Objects.requireNonNull(dnsServers);
+ for (InetAddress inetAddress: dnsServers) {
+ if (!(inetAddress instanceof Inet4Address)) {
+ throw new IllegalArgumentException(
+ "Only IPv4 addresses can be used for the DNS server configuration");
+ }
+ }
mDnsServers = dnsServers;
return this;
}
@@ -171,6 +176,8 @@
/**
* Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}.
* @return The newly created StaticIpConfiguration.
+ * @throws IllegalArgumentException if an invalid configuration is attempted, e.g.
+ * if an IP Address was not configured via {@link #setIpAddress(LinkAddress)}.
*/
public @NonNull StaticIpConfiguration build() {
final StaticIpConfiguration config = new StaticIpConfiguration();
@@ -188,7 +195,9 @@
/**
* Add a DNS server to this configuration.
+ * @hide
*/
+ @SystemApi
public void addDnsServer(@NonNull InetAddress server) {
dnsServers.add(server);
}
@@ -197,7 +206,9 @@
* Returns the network routes specified by this object. Will typically include a
* directly-connected route for the IP address's local subnet and a default route.
* @param iface Interface to include in the routes.
+ * @hide
*/
+ @SystemApi
public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) {
List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
if (ipAddress != null) {
@@ -305,7 +316,7 @@
/** Implement the Parcelable interface */
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelable(ipAddress, flags);
InetAddressUtils.parcelInetAddress(dest, gateway, flags);
dest.writeInt(dnsServers.size());
@@ -316,7 +327,7 @@
}
/** @hide */
- public static StaticIpConfiguration readFromParcel(Parcel in) {
+ public static @NonNull StaticIpConfiguration readFromParcel(Parcel in) {
final StaticIpConfiguration s = new StaticIpConfiguration();
s.ipAddress = in.readParcelable(null);
s.gateway = InetAddressUtils.unparcelInetAddress(in);
diff --git a/nearby/OWNERS b/nearby/OWNERS
new file mode 100644
index 0000000..980c221
--- /dev/null
+++ b/nearby/OWNERS
@@ -0,0 +1,4 @@
+chunzhang@google.com
+weiwa@google.com
+weiwu@google.com
+xlythe@google.com
diff --git a/netd/Android.bp b/netd/Android.bp
index 53c1bd4..b98a859 100644
--- a/netd/Android.bp
+++ b/netd/Android.bp
@@ -31,12 +31,10 @@
"BpfHandler.cpp",
"NetdUpdatable.cpp",
],
- static_libs: [
- "libnetdutils",
- ],
shared_libs: [
"libbase",
"liblog",
+ "libnetdutils",
],
export_include_dirs: ["include"],
header_abi_checker: {
diff --git a/service-t/Android.bp b/service-t/Android.bp
index f33be63..8ba0768 100644
--- a/service-t/Android.bp
+++ b/service-t/Android.bp
@@ -37,7 +37,8 @@
libs: [
"framework-annotations-lib",
"framework-connectivity-pre-jarjar",
- "framework-connectivity-tiramisu.impl",
+ "framework-connectivity-tiramisu-pre-jarjar",
+ "framework-tethering.stubs.module_lib",
"service-connectivity-pre-jarjar",
"unsupportedappusage",
],
@@ -52,7 +53,9 @@
"com.android.tethering",
],
visibility: [
+ "//frameworks/base/tests/vcn",
"//packages/modules/Connectivity/service",
"//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/IPsec/tests/iketests",
],
}
diff --git a/service-t/native/libs/libnetworkstats/Android.bp b/service-t/native/libs/libnetworkstats/Android.bp
index bceeefa..d24b14b 100644
--- a/service-t/native/libs/libnetworkstats/Android.bp
+++ b/service-t/native/libs/libnetworkstats/Android.bp
@@ -61,11 +61,12 @@
"-Wno-unused-parameter",
"-Wthread-safety",
],
- static_libs: ["libgmock"],
+ static_libs: [
+ "libgmock",
+ "libnetworkstats",
+ ],
shared_libs: [
"libbase",
"liblog",
- "libnetworkstats",
- "libutils",
],
}
diff --git a/service/Android.bp b/service/Android.bp
index 6d187ba..33fe3ea 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -33,10 +33,8 @@
srcs: [
"jni/com_android_net_module_util/onload.cpp",
],
- stl: "libc++_static",
static_libs: [
"libnet_utils_device_common_bpfjni",
- "libtcutils",
],
shared_libs: [
"liblog",
@@ -62,21 +60,19 @@
"jni/com_android_server_TestNetworkService.cpp",
"jni/onload.cpp",
],
- stl: "libc++_static",
header_libs: [
"bpf_connectivity_headers",
- "libbase_headers",
],
static_libs: [
- "libbase",
"libclat",
"libip_checksum",
- "libnetdutils",
"libnetjniutils",
"libtraffic_controller",
"netd_aidl_interface-lateststable-ndk",
],
shared_libs: [
+ "libbase",
+ "libnetdutils",
"liblog",
"libnativehelper",
],
diff --git a/service/native/Android.bp b/service/native/Android.bp
index a20c54f..cb26bc3 100644
--- a/service/native/Android.bp
+++ b/service/native/Android.bp
@@ -26,11 +26,8 @@
],
header_libs: [
"bpf_connectivity_headers",
- "bpf_headers",
- "bpf_syscall_wrappers",
],
static_libs: [
- "libnetdutils",
// TrafficController would use the constants of INetd so that add
// netd_aidl_interface-lateststable-ndk.
"netd_aidl_interface-lateststable-ndk",
@@ -39,6 +36,7 @@
// TODO: Find a good way to remove libbase.
"libbase",
"libcutils",
+ "libnetdutils",
"libutils",
"liblog",
],
diff --git a/service/native/libs/libclat/Android.bp b/service/native/libs/libclat/Android.bp
index 5e208d8..17ee996 100644
--- a/service/native/libs/libclat/Android.bp
+++ b/service/native/libs/libclat/Android.bp
@@ -21,8 +21,7 @@
defaults: ["netd_defaults"],
header_libs: [
"bpf_connectivity_headers",
- "bpf_headers",
- "bpf_syscall_wrappers",
+ "libbase_headers",
],
srcs: [
"TcUtils.cpp", // TODO: move to frameworks/libs/net
@@ -31,7 +30,6 @@
],
stl: "libc++_static",
static_libs: [
- "libbase",
"libip_checksum",
"libnetdutils", // for netdutils/UidConstants.h in bpf_shared.h
],
@@ -47,8 +45,6 @@
test_suites: ["device-tests"],
header_libs: [
"bpf_connectivity_headers",
- "bpf_headers",
- "bpf_syscall_wrappers",
],
srcs: [
"TcUtilsTest.cpp",
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 198190a..7bb4529 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -90,6 +90,7 @@
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.system.OsConstants.ETH_P_ALL;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
@@ -191,11 +192,13 @@
import android.net.netd.aidl.NativeUidRangeConfig;
import android.net.networkstack.ModuleNetworkStackClient;
import android.net.networkstack.NetworkStackClientBase;
+import android.net.networkstack.aidl.NetworkMonitorParameters;
import android.net.resolv.aidl.DnsHealthEventParcel;
import android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener;
import android.net.resolv.aidl.Nat64PrefixEventParcel;
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.os.BatteryStatsManager;
import android.os.Binder;
@@ -247,6 +250,7 @@
import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.PermissionUtils;
+import com.android.net.module.util.TcUtils;
import com.android.net.module.util.netlink.InetDiagMessage;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
@@ -273,6 +277,7 @@
import libcore.io.IoUtils;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.Inet4Address;
@@ -708,6 +713,11 @@
private static final int EVENT_SET_TEST_ALLOW_BAD_WIFI_UNTIL = 55;
/**
+ * Used internally when INGRESS_RATE_LIMIT_BYTES_PER_SECOND setting changes.
+ */
+ private static final int EVENT_INGRESS_RATE_LIMIT_CHANGED = 56;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -724,6 +734,18 @@
*/
private static final long MAX_TEST_ALLOW_BAD_WIFI_UNTIL_MS = 5 * 60 * 1000L;
+ /**
+ * The priority of the tc police rate limiter -- smaller value is higher priority.
+ * This value needs to be coordinated with PRIO_CLAT, PRIO_TETHER4, and PRIO_TETHER6.
+ */
+ private static final short TC_PRIO_POLICE = 1;
+
+ /**
+ * The BPF program attached to the tc-police hook to account for to-be-dropped traffic.
+ */
+ private static final String TC_POLICE_BPF_PROG_PATH =
+ "/sys/fs/bpf/prog_netd_schedact_ingress_account";
+
private static String eventName(int what) {
return sMagicDecoderRing.get(what, Integer.toString(what));
}
@@ -814,6 +836,12 @@
final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
new HashMap<>();
+ // Rate limit applicable to all internet capable networks (-1 = disabled). This value is
+ // configured via {@link
+ // ConnectivitySettingsManager#INGRESS_RATE_LIMIT_BYTES_PER_SECOND}
+ // Only the handler thread is allowed to access this field.
+ private long mIngressRateLimit = -1;
+
/**
* Implements support for the legacy "one network per network type" model.
*
@@ -1366,6 +1394,48 @@
public BpfNetMaps getBpfNetMaps(INetd netd) {
return new BpfNetMaps(netd);
}
+
+ /**
+ * Wraps {@link TcUtils#tcFilterAddDevIngressPolice}
+ */
+ public void enableIngressRateLimit(String iface, long rateInBytesPerSecond) {
+ final InterfaceParams params = InterfaceParams.getByName(iface);
+ if (params == null) {
+ // the interface might have disappeared.
+ logw("Failed to get interface params for interface " + iface);
+ return;
+ }
+ try {
+ // converting rateInBytesPerSecond from long to int is safe here because the
+ // setting's range is limited to INT_MAX.
+ // TODO: add long/uint64 support to tcFilterAddDevIngressPolice.
+ TcUtils.tcFilterAddDevIngressPolice(params.index, TC_PRIO_POLICE, (short) ETH_P_ALL,
+ (int) rateInBytesPerSecond, TC_POLICE_BPF_PROG_PATH);
+ } catch (IOException e) {
+ loge("TcUtils.tcFilterAddDevIngressPolice(ifaceIndex=" + params.index
+ + ", PRIO_POLICE, ETH_P_ALL, rateInBytesPerSecond="
+ + rateInBytesPerSecond + ", bpfProgPath=" + TC_POLICE_BPF_PROG_PATH
+ + ") failure: ", e);
+ }
+ }
+
+ /**
+ * Wraps {@link TcUtils#tcFilterDelDev}
+ */
+ public void disableIngressRateLimit(String iface) {
+ final InterfaceParams params = InterfaceParams.getByName(iface);
+ if (params == null) {
+ // the interface might have disappeared.
+ logw("Failed to get interface params for interface " + iface);
+ return;
+ }
+ try {
+ TcUtils.tcFilterDelDev(params.index, true, TC_PRIO_POLICE, (short) ETH_P_ALL);
+ } catch (IOException e) {
+ loge("TcUtils.tcFilterDelDev(ifaceIndex=" + params.index
+ + ", ingress=true, PRIO_POLICE, ETH_P_ALL) failure: ", e);
+ }
+ }
}
public ConnectivityService(Context context) {
@@ -1540,6 +1610,9 @@
} catch (ErrnoException e) {
loge("Unable to create DscpPolicyTracker");
}
+
+ mIngressRateLimit = ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(
+ mContext);
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@@ -1610,6 +1683,11 @@
mHandler.sendEmptyMessage(EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
}
+ @VisibleForTesting
+ void updateIngressRateLimit() {
+ mHandler.sendEmptyMessage(EVENT_INGRESS_RATE_LIMIT_CHANGED);
+ }
+
private void handleAlwaysOnNetworkRequest(NetworkRequest networkRequest, int id) {
final boolean enable = mContext.getResources().getBoolean(id);
handleAlwaysOnNetworkRequest(networkRequest, enable);
@@ -1671,6 +1749,12 @@
mSettingsObserver.observe(
Settings.Secure.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_PREFERRED_UIDS),
EVENT_MOBILE_DATA_PREFERRED_UIDS_CHANGED);
+
+ // Watch for ingress rate limit changes.
+ mSettingsObserver.observe(
+ Settings.Secure.getUriFor(
+ ConnectivitySettingsManager.INGRESS_RATE_LIMIT_BYTES_PER_SECOND),
+ EVENT_INGRESS_RATE_LIMIT_CHANGED);
}
private void registerPrivateDnsSettingsCallbacks() {
@@ -4090,6 +4174,11 @@
// for an unnecessarily long time.
destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
+
+ // clean up tc police filters on interface.
+ if (canNetworkBeRateLimited(nai) && mIngressRateLimit >= 0) {
+ mDeps.disableIngressRateLimit(nai.linkProperties.getInterfaceName());
+ }
}
mNetIdManager.releaseNetId(nai.network.getNetId());
nai.onNetworkDestroyed();
@@ -5157,6 +5246,9 @@
final long timeMs = ((Long) msg.obj).longValue();
mMultinetworkPolicyTracker.setTestAllowBadWifiUntil(timeMs);
break;
+ case EVENT_INGRESS_RATE_LIMIT_CHANGED:
+ handleIngressRateLimitChanged();
+ break;
}
}
}
@@ -7043,7 +7135,7 @@
nai.notifyRegistered();
NetworkInfo networkInfo = nai.networkInfo;
updateNetworkInfo(nai, networkInfo);
- updateUids(nai, null, nai.networkCapabilities);
+ updateVpnUids(nai, null, nai.networkCapabilities);
}
private class NetworkOfferInfo implements IBinder.DeathRecipient {
@@ -7679,7 +7771,8 @@
updateNetworkPermissions(nai, newNc);
final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
- updateUids(nai, prevNc, newNc);
+ updateVpnUids(nai, prevNc, newNc);
+ updateAccessUids(nai, prevNc, newNc);
nai.updateScoreForNetworkAgentUpdate();
if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
@@ -7849,12 +7942,6 @@
}
}
- private void updateUids(@NonNull NetworkAgentInfo nai, @Nullable NetworkCapabilities prevNc,
- @Nullable NetworkCapabilities newNc) {
- updateVpnUids(nai, prevNc, newNc);
- updateAccessUids(nai, prevNc, newNc);
- }
-
private void updateVpnUids(@NonNull NetworkAgentInfo nai, @Nullable NetworkCapabilities prevNc,
@Nullable NetworkCapabilities newNc) {
Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUidRanges();
@@ -7911,7 +7998,7 @@
}
} catch (Exception e) {
// Never crash!
- loge("Exception in updateUids: ", e);
+ loge("Exception in updateVpnUids: ", e);
}
}
@@ -7950,6 +8037,9 @@
intsToUidRangeStableParcels(toRemove),
PREFERENCE_ORDER_IRRELEVANT_BECAUSE_NOT_DEFAULT));
}
+ } catch (ServiceSpecificException e) {
+ // Has the interface disappeared since the network was built ?
+ Log.i(TAG, "Can't set access UIDs for network " + nai.network, e);
} catch (RemoteException e) {
// Netd died. This usually causes a runtime restart anyway.
}
@@ -8855,6 +8945,19 @@
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
+ // If a rate limit has been configured and is applicable to this network (network
+ // provides internet connectivity), apply it.
+ // Note: in case of a system server crash, there is a very small chance that this
+ // leaves some interfaces rate limited (i.e. if the rate limit had been changed just
+ // before the crash and was never applied). One solution would be to delete all
+ // potential tc police filters every time this is called. Since this is an unlikely
+ // scenario in the first place (and worst case, the interface stays rate limited until
+ // the device is rebooted), this seems a little overkill.
+ if (canNetworkBeRateLimited(networkAgent) && mIngressRateLimit >= 0) {
+ mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
+ mIngressRateLimit);
+ }
+
if (!createNativeNetwork(networkAgent)) return;
if (networkAgent.propagateUnderlyingCapabilities()) {
// Initialize the network's capabilities to their starting values according to the
@@ -8864,6 +8967,7 @@
}
networkAgent.created = true;
networkAgent.onNetworkCreated();
+ updateAccessUids(networkAgent, null, networkAgent.networkCapabilities);
}
if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
@@ -8884,10 +8988,12 @@
if (networkAgent.networkAgentConfig.acceptPartialConnectivity) {
networkAgent.networkMonitor().setAcceptPartialConnectivity();
}
- networkAgent.networkMonitor().notifyNetworkConnected(
- new LinkProperties(networkAgent.linkProperties,
- true /* parcelSensitiveFields */),
- networkAgent.networkCapabilities);
+ final NetworkMonitorParameters params = new NetworkMonitorParameters();
+ params.networkAgentConfig = networkAgent.networkAgentConfig;
+ params.networkCapabilities = networkAgent.networkCapabilities;
+ params.linkProperties = new LinkProperties(networkAgent.linkProperties,
+ true /* parcelSensitiveFields */);
+ networkAgent.networkMonitor().notifyNetworkConnected(params);
scheduleUnvalidatedPrompt(networkAgent);
// Whether a particular NetworkRequest listen should cause signal strength thresholds to
@@ -8917,7 +9023,7 @@
} else if (state == NetworkInfo.State.DISCONNECTED) {
networkAgent.disconnect();
if (networkAgent.isVPN()) {
- updateUids(networkAgent, networkAgent.networkCapabilities, null);
+ updateVpnUids(networkAgent, networkAgent.networkCapabilities, null);
}
disconnectAndDestroyNetwork(networkAgent);
if (networkAgent.isVPN()) {
@@ -10512,6 +10618,39 @@
rematchAllNetworksAndRequests();
}
+ private void handleIngressRateLimitChanged() {
+ final long oldIngressRateLimit = mIngressRateLimit;
+ mIngressRateLimit = ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(
+ mContext);
+ for (final NetworkAgentInfo networkAgent : mNetworkAgentInfos) {
+ if (canNetworkBeRateLimited(networkAgent)) {
+ // If rate limit has previously been enabled, remove the old limit first.
+ if (oldIngressRateLimit >= 0) {
+ mDeps.disableIngressRateLimit(networkAgent.linkProperties.getInterfaceName());
+ }
+ if (mIngressRateLimit >= 0) {
+ mDeps.enableIngressRateLimit(networkAgent.linkProperties.getInterfaceName(),
+ mIngressRateLimit);
+ }
+ }
+ }
+ }
+
+ private boolean canNetworkBeRateLimited(@NonNull final NetworkAgentInfo networkAgent) {
+ if (!networkAgent.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) {
+ // rate limits only apply to networks that provide internet connectivity.
+ return false;
+ }
+
+ final String iface = networkAgent.linkProperties.getInterfaceName();
+ if (iface == null) {
+ // This can never happen.
+ logwtf("canNetworkBeRateLimited: LinkProperties#getInterfaceName returns null");
+ return false;
+ }
+ return true;
+ }
+
private void enforceAutomotiveDevice() {
PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE,
"setOemNetworkPreference() is only available on automotive devices.");
diff --git a/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java b/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
index ce955fd..b761762 100644
--- a/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
+++ b/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
@@ -19,6 +19,8 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_NOT_EXPORTED;
+
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -158,7 +160,7 @@
private void registerForCarrierChanges() {
final IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
- mContext.registerReceiver(this, filter, null, mHandler);
+ mContext.registerReceiver(this, filter, null, mHandler, RECEIVER_NOT_EXPORTED /* flags */);
registerCarrierPrivilegesListeners();
}
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index acf04bf..8782684 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -88,6 +88,7 @@
"libstaticjvmtiagent",
// For NetworkStackUtils included in NetworkStackBase
"libnetworkstackutilsjni",
+ "libandroid_net_connectivity_com_android_net_module_util_jni",
"libcom_android_networkstack_tethering_util_jni",
// For framework tests
"libservice-connectivity",
diff --git a/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt b/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
index ebaa787..8d8958d 100644
--- a/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
+++ b/tests/common/java/android/net/ConnectivitySettingsManagerTest.kt
@@ -39,6 +39,7 @@
import android.net.ConnectivitySettingsManager.getDnsResolverSampleRanges
import android.net.ConnectivitySettingsManager.getDnsResolverSampleValidityDuration
import android.net.ConnectivitySettingsManager.getDnsResolverSuccessThresholdPercent
+import android.net.ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond
import android.net.ConnectivitySettingsManager.getMobileDataActivityTimeout
import android.net.ConnectivitySettingsManager.getMobileDataAlwaysOn
import android.net.ConnectivitySettingsManager.getNetworkSwitchNotificationMaximumDailyCount
@@ -51,6 +52,7 @@
import android.net.ConnectivitySettingsManager.setDnsResolverSampleRanges
import android.net.ConnectivitySettingsManager.setDnsResolverSampleValidityDuration
import android.net.ConnectivitySettingsManager.setDnsResolverSuccessThresholdPercent
+import android.net.ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond
import android.net.ConnectivitySettingsManager.setMobileDataActivityTimeout
import android.net.ConnectivitySettingsManager.setMobileDataAlwaysOn
import android.net.ConnectivitySettingsManager.setNetworkSwitchNotificationMaximumDailyCount
@@ -292,4 +294,19 @@
setter = { setWifiAlwaysRequested(context, it) },
testIntValues = intArrayOf(0))
}
+
+ @Test
+ fun testInternetNetworkRateLimitInBytesPerSecond() {
+ val defaultRate = getIngressRateLimitInBytesPerSecond(context)
+ val testRate = 1000L
+ setIngressRateLimitInBytesPerSecond(context, testRate)
+ assertEquals(testRate, getIngressRateLimitInBytesPerSecond(context))
+
+ setIngressRateLimitInBytesPerSecond(context, defaultRate)
+ assertEquals(defaultRate, getIngressRateLimitInBytesPerSecond(context))
+
+ assertFailsWith<IllegalArgumentException>("Expected failure, but setting accepted") {
+ setIngressRateLimitInBytesPerSecond(context, -10)
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/common/java/android/net/NetworkAgentConfigTest.kt b/tests/common/java/android/net/NetworkAgentConfigTest.kt
index b339a27..e5db09f 100644
--- a/tests/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/common/java/android/net/NetworkAgentConfigTest.kt
@@ -20,6 +20,7 @@
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.modules.utils.build.SdkLevel.isAtLeastS
+import com.android.modules.utils.build.SdkLevel.isAtLeastT
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@@ -49,6 +50,10 @@
if (isAtLeastS()) {
setBypassableVpn(true)
}
+ if (isAtLeastT()) {
+ setLocalRoutesExcludedForVpn(true)
+ setVpnRequiresValidation(true)
+ }
}.build()
assertParcelingIsLossless(config)
}
@@ -69,6 +74,10 @@
setProvisioningNotificationEnabled(false)
setBypassableVpn(true)
}
+ if (isAtLeastT()) {
+ setLocalRoutesExcludedForVpn(true)
+ setVpnRequiresValidation(true)
+ }
}.build()
assertTrue(config.isExplicitlySelected())
@@ -77,6 +86,10 @@
assertFalse(config.isPartialConnectivityAcceptable())
assertTrue(config.isUnvalidatedConnectivityAcceptable())
assertEquals("TEST_NETWORK", config.getLegacyTypeName())
+ if (isAtLeastT()) {
+ assertTrue(config.areLocalRoutesExcludedForVpn())
+ assertTrue(config.getVpnRequiresValidation())
+ }
if (isAtLeastS()) {
assertEquals(testExtraInfo, config.getLegacyExtraInfo())
assertFalse(config.isNat64DetectionEnabled())
diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp
index 4c9bccf..01c8cd2 100644
--- a/tests/cts/hostside/app2/Android.bp
+++ b/tests/cts/hostside/app2/Android.bp
@@ -22,7 +22,10 @@
name: "CtsHostsideNetworkTestsApp2",
defaults: ["cts_support_defaults"],
sdk_version: "test_current",
- static_libs: ["CtsHostsideNetworkTestsAidl"],
+ static_libs: [
+ "CtsHostsideNetworkTestsAidl",
+ "NetworkStackApiStableShims",
+ ],
srcs: ["src/**/*.java"],
// Tag this module as a cts test artifact
test_suites: [
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
index 3b5e46f..f2a7b3f 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyService.java
@@ -21,6 +21,7 @@
import static com.android.cts.net.hostside.app2.Common.ACTION_SNOOZE_WARNING;
import static com.android.cts.net.hostside.app2.Common.DYNAMIC_RECEIVER;
import static com.android.cts.net.hostside.app2.Common.TAG;
+import static com.android.networkstack.apishim.ConstantsShim.RECEIVER_EXPORTED;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -40,6 +41,7 @@
import com.android.cts.net.hostside.IMyService;
import com.android.cts.net.hostside.INetworkCallback;
+import com.android.modules.utils.build.SdkLevel;
/**
* Service used to dynamically register a broadcast receiver.
@@ -64,11 +66,14 @@
return;
}
final Context context = getApplicationContext();
+ final int flags = SdkLevel.isAtLeastT() ? RECEIVER_EXPORTED : 0;
mReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
- context.registerReceiver(mReceiver, new IntentFilter(ACTION_RECEIVER_READY));
context.registerReceiver(mReceiver,
- new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED));
- context.registerReceiver(mReceiver, new IntentFilter(ACTION_SNOOZE_WARNING));
+ new IntentFilter(ACTION_RECEIVER_READY), flags);
+ context.registerReceiver(mReceiver,
+ new IntentFilter(ACTION_RESTRICT_BACKGROUND_CHANGED), flags);
+ context.registerReceiver(mReceiver,
+ new IntentFilter(ACTION_SNOOZE_WARNING), flags);
Log.d(TAG, "receiver registered");
}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
index 232114e..68fa38d 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
@@ -278,18 +278,23 @@
assertTrue("Didn't receive broadcast for ACTION_CARRIER_CONFIG_CHANGED for subId=" + subId,
carrierConfigReceiver.waitForCarrierConfigChanged());
- assertTrue("Don't have Carrier Privileges after adding cert for this package",
- mTelephonyManager.createForSubscriptionId(subId).hasCarrierPrivileges());
// Wait for CarrierPrivilegesTracker to receive the ACTION_CARRIER_CONFIG_CHANGED
// broadcast. CPT then needs to update the corresponding DataConnection, which then
// updates ConnectivityService. Unfortunately, this update to the NetworkCapabilities in
// CS does not trigger NetworkCallback#onCapabilitiesChanged as changing the
// administratorUids is not a publicly visible change. In lieu of a better signal to
- // detministically wait for, use Thread#sleep here.
+ // deterministically wait for, use Thread#sleep here.
// TODO(b/157949581): replace this Thread#sleep with a deterministic signal
Thread.sleep(DELAY_FOR_ADMIN_UIDS_MILLIS);
+ // TODO(b/217559768): Receiving carrier config change and immediately checking carrier
+ // privileges is racy, as the CP status is updated after receiving the same signal. Move
+ // the CP check after sleep to temporarily reduce the flakiness. This will soon be fixed
+ // by switching to CarrierPrivilegesListener.
+ assertTrue("Don't have Carrier Privileges after adding cert for this package",
+ mTelephonyManager.createForSubscriptionId(subId).hasCarrierPrivileges());
+
final TestConnectivityDiagnosticsCallback connDiagsCallback =
createAndRegisterConnectivityDiagnosticsCallback(CELLULAR_NETWORK_REQUEST);
diff --git a/tests/cts/net/src/android/net/cts/IpConfigurationTest.java b/tests/cts/net/src/android/net/cts/IpConfigurationTest.java
index 385bf9e..d221694 100644
--- a/tests/cts/net/src/android/net/cts/IpConfigurationTest.java
+++ b/tests/cts/net/src/android/net/cts/IpConfigurationTest.java
@@ -25,12 +25,16 @@
import android.net.LinkAddress;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
+import android.os.Build;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+
import libcore.net.InetAddressUtils;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,6 +54,9 @@
private StaticIpConfiguration mStaticIpConfig;
private ProxyInfo mProxy;
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
@Before
public void setUp() {
dnsServers.add(DNS1);
@@ -99,6 +106,18 @@
assertIpConfigurationEqual(ipConfig, new IpConfiguration(ipConfig));
}
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testBuilder() {
+ final IpConfiguration c = new IpConfiguration.Builder()
+ .setStaticIpConfiguration(mStaticIpConfig)
+ .setHttpProxy(mProxy)
+ .build();
+
+ assertEquals(mStaticIpConfig, c.getStaticIpConfiguration());
+ assertEquals(mProxy, c.getHttpProxy());
+ }
+
private void checkEmpty(IpConfiguration config) {
assertEquals(IpConfiguration.IpAssignment.UNASSIGNED,
config.getIpAssignment().UNASSIGNED);
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 23814c9..9506081 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -15,6 +15,19 @@
*/
package android.net.cts
+import android.Manifest.permission.MANAGE_TEST_NETWORKS
+import android.net.ConnectivityManager
+import android.net.ConnectivityManager.NetworkCallback
+import android.net.LinkProperties
+import android.net.Network
+import android.net.NetworkAgentConfig
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
+import android.net.NetworkCapabilities.TRANSPORT_TEST
+import android.net.NetworkRequest
+import android.net.TestNetworkInterface
+import android.net.TestNetworkManager
+import android.net.TestNetworkSpecifier
import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStarted
import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStopped
import android.net.cts.NsdManagerTest.NsdDiscoveryRecord.DiscoveryEvent.ServiceFound
@@ -32,14 +45,27 @@
import android.net.nsd.NsdManager.RegistrationListener
import android.net.nsd.NsdManager.ResolveListener
import android.net.nsd.NsdServiceInfo
+import android.os.HandlerThread
import android.platform.test.annotations.AppModeFull
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
+import com.android.networkstack.apishim.ConstantsShim
+import com.android.networkstack.apishim.NsdShimImpl
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.SC_V2
+import com.android.testutils.TestableNetworkAgent
+import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.runAsShell
+import com.android.testutils.tryTest
+import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.net.ServerSocket
@@ -57,12 +83,37 @@
private const val TIMEOUT_MS = 2000L
private const val DBG = false
+private val nsdShim = NsdShimImpl.newInstance()
+
@AppModeFull(reason = "Socket cannot bind in instant app mode")
@RunWith(AndroidJUnit4::class)
class NsdManagerTest {
+ // NsdManager is not updatable before S, so tests do not need to be backwards compatible
+ @get:Rule
+ val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
+
private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
private val nsdManager by lazy { context.getSystemService(NsdManager::class.java) }
+
+ private val cm by lazy { context.getSystemService(ConnectivityManager::class.java) }
private val serviceName = "NsdTest%09d".format(Random().nextInt(1_000_000_000))
+ private val handlerThread = HandlerThread(NsdManagerTest::class.java.simpleName)
+
+ private lateinit var testNetwork1: TestTapNetwork
+ private lateinit var testNetwork2: TestTapNetwork
+
+ private class TestTapNetwork(
+ val iface: TestNetworkInterface,
+ val requestCb: NetworkCallback,
+ val agent: TestableNetworkAgent,
+ val network: Network
+ ) {
+ fun close(cm: ConnectivityManager) {
+ cm.unregisterNetworkCallback(requestCb)
+ agent.unregister()
+ iface.fileDescriptor.close()
+ }
+ }
private interface NsdEvent
private open class NsdRecord<T : NsdEvent> private constructor(
@@ -163,9 +214,14 @@
add(ServiceLost(si))
}
- fun waitForServiceDiscovered(serviceName: String): NsdServiceInfo {
+ fun waitForServiceDiscovered(
+ serviceName: String,
+ expectedNetwork: Network? = null
+ ): NsdServiceInfo {
return expectCallbackEventually<ServiceFound> {
- it.serviceInfo.serviceName == serviceName
+ it.serviceInfo.serviceName == serviceName &&
+ (expectedNetwork == null ||
+ expectedNetwork == nsdShim.getNetwork(it.serviceInfo))
}.serviceInfo
}
}
@@ -188,6 +244,58 @@
}
}
+ @Before
+ fun setUp() {
+ handlerThread.start()
+
+ runAsShell(MANAGE_TEST_NETWORKS) {
+ testNetwork1 = createTestNetwork()
+ testNetwork2 = createTestNetwork()
+ }
+ }
+
+ private fun createTestNetwork(): TestTapNetwork {
+ val tnm = context.getSystemService(TestNetworkManager::class.java)
+ val iface = tnm.createTapInterface()
+ val cb = TestableNetworkCallback()
+ val testNetworkSpecifier = TestNetworkSpecifier(iface.interfaceName)
+ cm.requestNetwork(NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .addTransportType(TRANSPORT_TEST)
+ .setNetworkSpecifier(testNetworkSpecifier)
+ .build(), cb)
+ val agent = registerTestNetworkAgent(iface.interfaceName)
+ val network = agent.network ?: fail("Registered agent should have a network")
+ // The network has no INTERNET capability, so will be marked validated immediately
+ cb.expectAvailableThenValidatedCallbacks(network)
+ return TestTapNetwork(iface, cb, agent, network)
+ }
+
+ private fun registerTestNetworkAgent(ifaceName: String): TestableNetworkAgent {
+ val agent = TestableNetworkAgent(context, handlerThread.looper,
+ NetworkCapabilities().apply {
+ removeCapability(NET_CAPABILITY_TRUSTED)
+ addTransportType(TRANSPORT_TEST)
+ setNetworkSpecifier(TestNetworkSpecifier(ifaceName))
+ },
+ LinkProperties().apply {
+ interfaceName = ifaceName
+ },
+ NetworkAgentConfig.Builder().build())
+ agent.register()
+ agent.markConnected()
+ return agent
+ }
+
+ @After
+ fun tearDown() {
+ runAsShell(MANAGE_TEST_NETWORKS) {
+ testNetwork1.close(cm)
+ testNetwork2.close(cm)
+ }
+ handlerThread.quitSafely()
+ }
+
@Test
fun testNsdManager() {
val si = NsdServiceInfo()
@@ -298,6 +406,149 @@
registrationRecord2.expectCallback<ServiceUnregistered>()
}
+ @Test
+ fun testNsdManager_DiscoverOnNetwork() {
+ // This tests requires shims supporting T+ APIs (discovering on specific network)
+ assumeTrue(ConstantsShim.VERSION > SC_V2)
+
+ val si = NsdServiceInfo()
+ si.serviceType = SERVICE_TYPE
+ si.serviceName = this.serviceName
+ si.port = 12345 // Test won't try to connect so port does not matter
+
+ val registrationRecord = NsdRegistrationRecord()
+ val registeredInfo = registerService(registrationRecord, si)
+
+ tryTest {
+ val discoveryRecord = NsdDiscoveryRecord()
+ nsdShim.discoverServices(nsdManager, SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
+ testNetwork1.network, discoveryRecord)
+
+ val foundInfo = discoveryRecord.waitForServiceDiscovered(
+ serviceName, testNetwork1.network)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(foundInfo))
+
+ // Rewind to ensure the service is not found on the other interface
+ discoveryRecord.nextEvents.rewind(0)
+ assertNull(discoveryRecord.nextEvents.poll(timeoutMs = 100L) {
+ it is ServiceFound &&
+ it.serviceInfo.serviceName == registeredInfo.serviceName &&
+ nsdShim.getNetwork(it.serviceInfo) != testNetwork1.network
+ }, "The service should not be found on this network")
+ } cleanup {
+ nsdManager.unregisterService(registrationRecord)
+ }
+ }
+
+ @Test
+ fun testNsdManager_DiscoverWithNetworkRequest() {
+ // This tests requires shims supporting T+ APIs (discovering on network request)
+ assumeTrue(ConstantsShim.VERSION > SC_V2)
+
+ val si = NsdServiceInfo()
+ si.serviceType = SERVICE_TYPE
+ si.serviceName = this.serviceName
+ si.port = 12345 // Test won't try to connect so port does not matter
+
+ val registrationRecord = NsdRegistrationRecord()
+ val registeredInfo1 = registerService(registrationRecord, si)
+ val discoveryRecord = NsdDiscoveryRecord()
+
+ tryTest {
+ val specifier = TestNetworkSpecifier(testNetwork1.iface.interfaceName)
+ nsdShim.discoverServices(nsdManager, SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
+ NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .addTransportType(TRANSPORT_TEST)
+ .setNetworkSpecifier(specifier)
+ .build(),
+ discoveryRecord)
+
+ val discoveryStarted = discoveryRecord.expectCallback<DiscoveryStarted>()
+ assertEquals(SERVICE_TYPE, discoveryStarted.serviceType)
+
+ val serviceDiscovered = discoveryRecord.expectCallback<ServiceFound>()
+ assertEquals(registeredInfo1.serviceName, serviceDiscovered.serviceInfo.serviceName)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(serviceDiscovered.serviceInfo))
+
+ // Unregister, then register the service back: it should be lost and found again
+ nsdManager.unregisterService(registrationRecord)
+ val serviceLost1 = discoveryRecord.expectCallback<ServiceLost>()
+ assertEquals(registeredInfo1.serviceName, serviceLost1.serviceInfo.serviceName)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(serviceLost1.serviceInfo))
+
+ registrationRecord.expectCallback<ServiceUnregistered>()
+ val registeredInfo2 = registerService(registrationRecord, si)
+ val serviceDiscovered2 = discoveryRecord.expectCallback<ServiceFound>()
+ assertEquals(registeredInfo2.serviceName, serviceDiscovered2.serviceInfo.serviceName)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(serviceDiscovered2.serviceInfo))
+
+ // Teardown, then bring back up a network on the test interface: the service should
+ // go away, then come back
+ testNetwork1.agent.unregister()
+ val serviceLost = discoveryRecord.expectCallback<ServiceLost>()
+ assertEquals(registeredInfo2.serviceName, serviceLost.serviceInfo.serviceName)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(serviceLost.serviceInfo))
+
+ val newAgent = runAsShell(MANAGE_TEST_NETWORKS) {
+ registerTestNetworkAgent(testNetwork1.iface.interfaceName)
+ }
+ val newNetwork = newAgent.network ?: fail("Registered agent should have a network")
+ val serviceDiscovered3 = discoveryRecord.expectCallback<ServiceFound>()
+ assertEquals(registeredInfo2.serviceName, serviceDiscovered3.serviceInfo.serviceName)
+ assertEquals(newNetwork, nsdShim.getNetwork(serviceDiscovered3.serviceInfo))
+ } cleanupStep {
+ nsdManager.stopServiceDiscovery(discoveryRecord)
+ discoveryRecord.expectCallback<DiscoveryStopped>()
+ } cleanup {
+ nsdManager.unregisterService(registrationRecord)
+ }
+ }
+
+ @Test
+ fun testNsdManager_ResolveOnNetwork() {
+ // This tests requires shims supporting T+ APIs (NsdServiceInfo.network)
+ assumeTrue(ConstantsShim.VERSION > SC_V2)
+
+ val si = NsdServiceInfo()
+ si.serviceType = SERVICE_TYPE
+ si.serviceName = this.serviceName
+ si.port = 12345 // Test won't try to connect so port does not matter
+
+ val registrationRecord = NsdRegistrationRecord()
+ val registeredInfo = registerService(registrationRecord, si)
+ tryTest {
+ val resolveRecord = NsdResolveRecord()
+
+ val discoveryRecord = NsdDiscoveryRecord()
+ nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryRecord)
+
+ val foundInfo1 = discoveryRecord.waitForServiceDiscovered(
+ serviceName, testNetwork1.network)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(foundInfo1))
+ // Rewind as the service could be found on each interface in any order
+ discoveryRecord.nextEvents.rewind(0)
+ val foundInfo2 = discoveryRecord.waitForServiceDiscovered(
+ serviceName, testNetwork2.network)
+ assertEquals(testNetwork2.network, nsdShim.getNetwork(foundInfo2))
+
+ nsdManager.resolveService(foundInfo1, resolveRecord)
+ val cb = resolveRecord.expectCallback<ServiceResolved>()
+ cb.serviceInfo.let {
+ // Resolved service type has leading dot
+ assertEquals(".$SERVICE_TYPE", it.serviceType)
+ assertEquals(registeredInfo.serviceName, it.serviceName)
+ assertEquals(si.port, it.port)
+ assertEquals(testNetwork1.network, nsdShim.getNetwork(it))
+ }
+ // TODO: check that MDNS packets are sent only on testNetwork1.
+ } cleanupStep {
+ nsdManager.unregisterService(registrationRecord)
+ } cleanup {
+ registrationRecord.expectCallback<ServiceUnregistered>()
+ }
+ }
+
/**
* Register a service and return its registration record.
*/
diff --git a/tests/common/java/android/net/StaticIpConfigurationTest.java b/tests/cts/net/src/android/net/cts/StaticIpConfigurationTest.java
similarity index 81%
rename from tests/common/java/android/net/StaticIpConfigurationTest.java
rename to tests/cts/net/src/android/net/cts/StaticIpConfigurationTest.java
index b5f23bf..9b2756c 100644
--- a/tests/common/java/android/net/StaticIpConfigurationTest.java
+++ b/tests/cts/net/src/android/net/cts/StaticIpConfigurationTest.java
@@ -14,20 +14,30 @@
* limitations under the License.
*/
-package android.net;
+package android.net.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
+import android.os.Build;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,15 +52,20 @@
private static final String ADDRSTR = "192.0.2.2/25";
private static final LinkAddress ADDR = new LinkAddress(ADDRSTR);
- private static final InetAddress GATEWAY = IpAddress("192.0.2.1");
- private static final InetAddress OFFLINKGATEWAY = IpAddress("192.0.2.129");
- private static final InetAddress DNS1 = IpAddress("8.8.8.8");
- private static final InetAddress DNS2 = IpAddress("8.8.4.4");
- private static final InetAddress DNS3 = IpAddress("4.2.2.2");
+ private static final InetAddress GATEWAY = ipAddress("192.0.2.1");
+ private static final InetAddress OFFLINKGATEWAY = ipAddress("192.0.2.129");
+ private static final InetAddress DNS1 = ipAddress("8.8.8.8");
+ private static final InetAddress DNS2 = ipAddress("8.8.4.4");
+ private static final InetAddress DNS3 = ipAddress("4.2.2.2");
+ private static final InetAddress IPV6_ADDRESS = ipAddress("2001:4860:800d::68");
+ private static final LinkAddress IPV6_LINK_ADDRESS = new LinkAddress("2001:db8::1/64");
private static final String IFACE = "eth0";
private static final String FAKE_DOMAINS = "google.com";
- private static InetAddress IpAddress(String addr) {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
+ private static InetAddress ipAddress(String addr) {
return InetAddress.parseNumericAddress(addr);
}
@@ -241,6 +256,29 @@
assertEquals(DNS1, s.getDnsServers().get(0));
}
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+ @Test
+ public void testIllegalBuilders() {
+ assertThrows("Can't set IP Address to IPv6!", IllegalArgumentException.class, () -> {
+ StaticIpConfiguration.Builder b = new StaticIpConfiguration.Builder().setIpAddress(
+ IPV6_LINK_ADDRESS);
+ });
+
+ assertThrows("Can't set gateway to IPv6!", IllegalArgumentException.class, () -> {
+ StaticIpConfiguration.Builder b = new StaticIpConfiguration.Builder().setGateway(
+ IPV6_ADDRESS);
+ });
+
+ assertThrows("Can't set DNS servers using IPv6!", IllegalArgumentException.class, () -> {
+ final ArrayList<InetAddress> dnsServers = new ArrayList<>();
+ dnsServers.add(DNS1);
+ dnsServers.add(IPV6_ADDRESS);
+
+ StaticIpConfiguration.Builder b = new StaticIpConfiguration.Builder().setDnsServers(
+ dnsServers);
+ });
+ }
+
@Test
public void testAddDnsServers() {
final StaticIpConfiguration s = new StaticIpConfiguration((StaticIpConfiguration) null);
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 25b391a..7ae5333 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -107,8 +107,8 @@
visibility: ["//visibility:private"],
}
-android_library {
- name: "FrameworksNetTestsLib",
+java_defaults {
+ name: "FrameworksNetTestsDefaults",
min_sdk_version: "30",
defaults: [
"framework-connectivity-test-defaults",
@@ -117,8 +117,6 @@
"java/**/*.java",
"java/**/*.kt",
],
- exclude_srcs: [":non-connectivity-module-test"],
- jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
"androidx.test.uiautomator",
@@ -144,31 +142,33 @@
"android.test.mock",
"ServiceConnectivityResources",
],
- visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
exclude_kotlinc_generated_files: false,
}
+android_library {
+ name: "FrameworksNetTestsLib",
+ defaults: [
+ "FrameworksNetTestsDefaults",
+ ],
+ exclude_srcs: [":non-connectivity-module-test"],
+ visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
+}
+
android_test {
name: "FrameworksNetTests",
enabled: enable_frameworks_net_tests,
- min_sdk_version: "30",
defaults: [
- "framework-connectivity-test-defaults",
+ "FrameworksNetTestsDefaults",
"FrameworksNetTests-jni-defaults",
],
- // this is in addition to FrameworksNetTestsLib.
- srcs: [":non-connectivity-module-test"],
+ jarjar_rules: ":connectivity-jarjar-rules",
test_suites: ["device-tests"],
static_libs: [
"services.core",
"services.net",
- "FrameworksNetTestsLib",
- ],
- libs: [
- "android.test.mock",
- "android.test.base",
],
jni_libs: [
"libservice-connectivity",
- ]
+ "libandroid_net_connectivity_com_android_net_module_util_jni",
+ ],
}
diff --git a/tests/unit/jarjar-rules.txt b/tests/unit/jarjar-rules.txt
index ca88672..eb3e32a 100644
--- a/tests/unit/jarjar-rules.txt
+++ b/tests/unit/jarjar-rules.txt
@@ -1,2 +1,3 @@
# Module library in frameworks/libs/net
rule com.android.net.module.util.** android.net.frameworktests.util.@1
+rule com.android.testutils.TestBpfMap* android.net.frameworktests.testutils.TestBpfMap@1
diff --git a/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
index a151f03..c3d3bf7 100644
--- a/tests/unit/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
@@ -270,11 +270,11 @@
public void testBuildExcludeLocalRoutesSet() throws Exception {
final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions();
builder.setAuthPsk(PSK_BYTES);
- builder.setExcludeLocalRoutes(true);
+ builder.setLocalRoutesExcluded(true);
final Ikev2VpnProfile profile = builder.build();
assertNotNull(profile);
- assertTrue(profile.getExcludeLocalRoutes());
+ assertTrue(profile.areLocalRoutesExcluded());
builder.setBypassable(false);
try {
diff --git a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
index ca8cf07..e5e7ebc 100644
--- a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
+++ b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.net.Network;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
@@ -123,6 +124,7 @@
fullInfo.setServiceType("_kitten._tcp");
fullInfo.setPort(4242);
fullInfo.setHost(LOCALHOST);
+ fullInfo.setNetwork(new Network(123));
checkParcelable(fullInfo);
NsdServiceInfo noHostInfo = new NsdServiceInfo();
@@ -172,6 +174,7 @@
assertEquals(original.getServiceType(), result.getServiceType());
assertEquals(original.getHost(), result.getHost());
assertTrue(original.getPort() == result.getPort());
+ assertEquals(original.getNetwork(), result.getNetwork());
// Assert equality of attribute map.
Map<String, byte[]> originalMap = original.getAttributes();
diff --git a/tests/unit/java/com/android/internal/net/VpnProfileTest.java b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
index 960a9f1..943a559 100644
--- a/tests/unit/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
@@ -50,6 +50,7 @@
private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23;
private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24;
private static final int ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE = 25;
+ private static final int ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION = 26;
@Test
public void testDefaults() throws Exception {
@@ -78,10 +79,13 @@
assertEquals(1360, p.maxMtu);
assertFalse(p.areAuthParamsInline);
assertFalse(p.isRestrictedToTestNetworks);
+ assertFalse(p.excludeLocalRoutes);
+ assertFalse(p.requiresInternetValidation);
}
private VpnProfile getSampleIkev2Profile(String key) {
- final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */);
+ final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */,
+ false /* excludesLocalRoutes */, true /* requiresPlatformValidation */);
p.name = "foo";
p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
@@ -129,8 +133,8 @@
@Test
public void testParcelUnparcel() {
if (isAtLeastT()) {
- // excludeLocalRoutes is added in T.
- assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 24);
+ // excludeLocalRoutes, requiresPlatformValidation were added in T.
+ assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 25);
} else {
assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23);
}
@@ -174,7 +178,8 @@
getEncodedDecodedIkev2ProfileMissingValues(
ENCODED_INDEX_AUTH_PARAMS_INLINE,
ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS,
- ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()));
}
@@ -194,14 +199,26 @@
public void testEncodeDecodeMissingExcludeLocalRoutes() {
final String tooFewValues =
getEncodedDecodedIkev2ProfileMissingValues(
- ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE /* missingIndices */);
+ ENCODED_INDEX_EXCLUDE_LOCAL_ROUTE,
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
- // Verify decoding without isRestrictedToTestNetworks defaults to false
+ // Verify decoding without excludeLocalRoutes defaults to false
final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
assertFalse(decoded.excludeLocalRoutes);
}
@Test
+ public void testEncodeDecodeMissingRequiresValidation() {
+ final String tooFewValues =
+ getEncodedDecodedIkev2ProfileMissingValues(
+ ENCODED_INDEX_REQUIRE_PLATFORM_VALIDATION /* missingIndices */);
+
+ // Verify decoding without requiresValidation defaults to false
+ final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes());
+ assertFalse(decoded.requiresInternetValidation);
+ }
+
+ @Test
public void testEncodeDecodeLoginsNotSaved() {
final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY);
profile.saveLogin = false;
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 0132525..16b3d5a 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -179,7 +179,6 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
import static java.util.Arrays.asList;
@@ -388,6 +387,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -907,7 +907,7 @@
return null;
};
- doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
+ doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnectedParcel(any());
doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
@@ -1963,6 +1963,25 @@
public BpfNetMaps getBpfNetMaps(INetd netd) {
return mBpfNetMaps;
}
+
+ final ArrayTrackRecord<Pair<String, Long>> mRateLimitHistory = new ArrayTrackRecord<>();
+ final Map<String, Long> mActiveRateLimit = new HashMap<>();
+
+ @Override
+ public void enableIngressRateLimit(final String iface, final long rateInBytesPerSecond) {
+ mRateLimitHistory.add(new Pair<>(iface, rateInBytesPerSecond));
+ // Due to a TC limitation, the rate limit needs to be removed before it can be
+ // updated. Check that this happened.
+ assertEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
+ mActiveRateLimit.put(iface, rateInBytesPerSecond);
+ }
+
+ @Override
+ public void disableIngressRateLimit(final String iface) {
+ mRateLimitHistory.add(new Pair<>(iface, -1L));
+ assertNotEquals(-1L, (long) mActiveRateLimit.getOrDefault(iface, -1L));
+ mActiveRateLimit.put(iface, -1L);
+ }
}
private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {
@@ -5027,6 +5046,13 @@
waitForIdle();
}
+ private void setIngressRateLimit(int rateLimitInBytesPerSec) {
+ ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mServiceContext,
+ rateLimitInBytesPerSec);
+ mService.updateIngressRateLimit();
+ waitForIdle();
+ }
+
private boolean isForegroundNetwork(TestNetworkAgentWrapper network) {
NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
assertNotNull(nc);
@@ -15339,4 +15365,153 @@
ConnectivityManager.TYPE_NONE, null /* hostAddress */, "com.not.package.owner",
null /* callingAttributionTag */));
}
+
+ @Test
+ public void testUpdateRateLimit_EnableDisable() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+ mCellNetworkAgent.connect(false);
+
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadCell =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ // set rate limit to 8MBit/s => 1MB/s
+ final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
+ setIngressRateLimit(rateLimitInBytesPerSec);
+
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+ assertNotNull(readHeadCell.poll(TIMEOUT_MS,
+ it -> it.first == cellLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+
+ // disable rate limiting
+ setIngressRateLimit(-1);
+
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
+ assertNotNull(readHeadCell.poll(TIMEOUT_MS,
+ it -> it.first == cellLp.getInterfaceName() && it.second == -1));
+ }
+
+ @Test
+ public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ // set rate limit to 8MBit/s => 1MB/s
+ final int rateLimitInBytesPerSec = 1 * 1000 * 1000;
+ setIngressRateLimit(rateLimitInBytesPerSec);
+ assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+ mCellNetworkAgent.connect(false);
+ assertNotNull(readHead.poll(TIMEOUT_MS, it -> it.first == cellLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+ }
+
+ @Test
+ public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connectWithoutInternet();
+
+ waitForIdle();
+
+ setIngressRateLimit(1000);
+ setIngressRateLimit(-1);
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+ assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
+ }
+
+ @Test
+ public void testUpdateRateLimit_DisconnectingResetsRateLimit()
+ throws Exception {
+ // Steps:
+ // - connect network
+ // - set rate limit
+ // - disconnect network (interface still exists)
+ // - disable rate limit
+ // - connect network
+ // - ensure network interface is not rate limited
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ int rateLimitInBytesPerSec = 1000;
+ setIngressRateLimit(rateLimitInBytesPerSec);
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == rateLimitInBytesPerSec));
+
+ mWiFiNetworkAgent.disconnect();
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName() && it.second == -1));
+
+ setIngressRateLimit(-1);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
+ }
+
+ @Test
+ public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHeadWifi =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ // update an active ingress rate limit
+ setIngressRateLimit(1000);
+ setIngressRateLimit(2000);
+
+ // verify the following order of execution:
+ // 1. ingress rate limit set to 1000.
+ // 2. ingress rate limit disabled (triggered by updating active rate limit).
+ // 3. ingress rate limit set to 2000.
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == 1000));
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == -1));
+ assertNotNull(readHeadWifi.poll(TIMEOUT_MS,
+ it -> it.first == wifiLp.getInterfaceName()
+ && it.second == 2000));
+ }
}
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 6d1d765..5086943 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -218,14 +218,14 @@
client.discoverServices("a_type", PROTOCOL, listener2);
waitForIdle();
verify(mDaemon, times(1)).maybeStart();
- verifyDaemonCommand("discover 3 a_type");
+ verifyDaemonCommand("discover 3 a_type 0");
// Client resolve request
NsdManager.ResolveListener listener3 = mock(NsdManager.ResolveListener.class);
client.resolveService(request, listener3);
waitForIdle();
verify(mDaemon, times(1)).maybeStart();
- verifyDaemonCommand("resolve 4 a_name a_type local.");
+ verifyDaemonCommand("resolve 4 a_name a_type local. 0");
// Client disconnects, stop the daemon after CLEANUP_DELAY_MS.
deathRecipient.binderDied();
diff --git a/tests/unit/java/com/android/server/connectivity/CarrierPrivilegeAuthenticatorTest.java b/tests/unit/java/com/android/server/connectivity/CarrierPrivilegeAuthenticatorTest.java
index 157507b..553cb83 100644
--- a/tests/unit/java/com/android/server/connectivity/CarrierPrivilegeAuthenticatorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/CarrierPrivilegeAuthenticatorTest.java
@@ -69,6 +69,8 @@
@RunWith(DevSdkIgnoreRunner.class)
@IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
public class CarrierPrivilegeAuthenticatorTest {
+ // TODO : use ConstantsShim.RECEIVER_NOT_EXPORTED when it's available in tests.
+ private static final int RECEIVER_NOT_EXPORTED = 4;
private static final int SUBSCRIPTION_COUNT = 2;
private static final int TEST_SUBSCRIPTION_ID = 1;
@@ -115,7 +117,7 @@
private IntentFilter getIntentFilter() {
final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
+ verify(mContext).registerReceiver(any(), captor.capture(), any(), any(), anyInt());
return captor.getValue();
}
@@ -138,10 +140,11 @@
@Test
public void testConstructor() throws Exception {
verify(mContext).registerReceiver(
- eq(mCarrierPrivilegeAuthenticator),
- any(IntentFilter.class),
- any(),
- any());
+ eq(mCarrierPrivilegeAuthenticator),
+ any(IntentFilter.class),
+ any(),
+ any(),
+ eq(RECEIVER_NOT_EXPORTED));
final IntentFilter filter = getIntentFilter();
assertEquals(1, filter.countActions());
assertTrue(filter.hasAction(ACTION_MULTI_SIM_CONFIG_CHANGED));