Merge "Fix testCallback fail caused by lacking of looper"
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/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/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 d51f6fd..6c7a66d 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -99,6 +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.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/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 9eb8100..45cadb2 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -35,7 +35,6 @@
min_sdk_version: "Tiramisu",
defaults: [
"framework-module-defaults",
- "enable-framework-connectivity-t-targets",
],
srcs: [
":framework-connectivity-tiramisu-updatable-sources",
@@ -96,6 +95,7 @@
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
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 2efee58..3d6fb3e 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -84,7 +84,7 @@
field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
}
- public final class IpSecManager {
+ public class IpSecManager {
method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
method public void applyTransportModeTransform(@NonNull java.net.Socket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
diff --git a/framework-t/api/module-lib-current.txt b/framework-t/api/module-lib-current.txt
index b284d4f..2b3ff45 100644
--- a/framework-t/api/module-lib-current.txt
+++ b/framework-t/api/module-lib-current.txt
@@ -10,7 +10,7 @@
method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long);
method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
- method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}, conditional=true) public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long);
method public void setPollForce(boolean);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean);
@@ -31,7 +31,7 @@
method public static void registerServiceWrappers();
}
- public final class IpSecManager {
+ public class IpSecManager {
field public static final int DIRECTION_FWD = 2; // 0x2
}
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index c5cb98c..cc8f6b2 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -2,8 +2,8 @@
package android.app.usage {
public class NetworkStatsManager {
- method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getMobileUidStats();
- method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getWifiUidStats();
+ method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getMobileUidStats();
+ method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getWifiUidStats();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
}
@@ -12,6 +12,47 @@
package android.nearby {
+ public interface BroadcastCallback {
+ method public void onStatus(int);
+ field public static final int STATUS_FAILURE = 1; // 0x1
+ field public static final int STATUS_FAILURE_ALREADY_REGISTERED = 2; // 0x2
+ field public static final int STATUS_FAILURE_MISSING_PERMISSIONS = 4; // 0x4
+ field public static final int STATUS_FAILURE_SIZE_EXCEED_LIMIT = 3; // 0x3
+ field public static final int STATUS_OK = 0; // 0x0
+ }
+
+ public abstract class BroadcastRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.Integer> getMediums();
+ method @IntRange(from=0xffffff81, to=126) public int getTxPower();
+ method public int getType();
+ method public int getVersion();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int BROADCAST_TYPE_NEARBY_PRESENCE = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.BroadcastRequest> CREATOR;
+ field public static final int PRESENCE_VERSION_V0 = 0; // 0x0
+ field public static final int PRESENCE_VERSION_V1 = 1; // 0x1
+ field public static final int UNKNOWN_TX_POWER = -100; // 0xffffff9c
+ }
+
+ public final class CredentialElement implements android.os.Parcelable {
+ ctor public CredentialElement(@NonNull String, @NonNull byte[]);
+ method public int describeContents();
+ method @NonNull public String getKey();
+ method @NonNull public byte[] getValue();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.CredentialElement> CREATOR;
+ }
+
+ public final class DataElement implements android.os.Parcelable {
+ ctor public DataElement(int, @NonNull byte[]);
+ method public int describeContents();
+ method public int getKey();
+ method @NonNull public byte[] getValue();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.DataElement> CREATOR;
+ }
+
public class FastPairAccountKeyDeviceMetadata {
method @Nullable public byte[] getAccountKey();
method @Nullable public android.nearby.FastPairDeviceMetadata getFastPairDeviceMetadata();
@@ -115,6 +156,7 @@
method @Nullable public String getInitialPairingDescription();
method @Nullable public String getIntentUri();
method @Nullable public String getLocale();
+ method @Nullable public String getName();
method @Nullable public String getOpenCompanionAppDescription();
method @Nullable public String getRetroactivePairingDescription();
method @Nullable public String getSubsequentPairingDescription();
@@ -153,6 +195,7 @@
method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setInitialPairingDescription(@Nullable String);
method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setIntentUri(@Nullable String);
method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setLocale(@Nullable String);
+ method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setName(@Nullable String);
method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setOpenCompanionAppDescription(@Nullable String);
method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setRetroactivePairingDescription(@Nullable String);
method @NonNull public android.nearby.FastPairDeviceMetadata.Builder setSubsequentPairingDescription(@Nullable String);
@@ -249,7 +292,8 @@
}
public abstract class NearbyDevice {
- method public int getMedium();
+ method @NonNull public java.util.List<java.lang.Integer> getMediums();
+ method @Nullable public String getName();
method @IntRange(from=0xffffff81, to=126) public int getRssi();
method public static boolean isValidMedium(int);
}
@@ -282,18 +326,143 @@
}
public class NearbyManager {
+ method public void startBroadcast(@NonNull android.nearby.BroadcastRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.BroadcastCallback);
method public void startScan(@NonNull android.nearby.ScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.ScanCallback);
+ method public void stopBroadcast(@NonNull android.nearby.BroadcastCallback);
method public void stopScan(@NonNull android.nearby.ScanCallback);
}
+ public final class PresenceBroadcastRequest extends android.nearby.BroadcastRequest implements android.os.Parcelable {
+ method @NonNull public java.util.List<java.lang.Integer> getActions();
+ method @NonNull public android.nearby.PrivateCredential getCredential();
+ method @NonNull public java.util.List<android.nearby.DataElement> getExtendedProperties();
+ method @NonNull public byte[] getSalt();
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceBroadcastRequest> CREATOR;
+ }
+
+ public static final class PresenceBroadcastRequest.Builder {
+ ctor public PresenceBroadcastRequest.Builder(@NonNull java.util.List<java.lang.Integer>, @NonNull byte[]);
+ method @NonNull public android.nearby.PresenceBroadcastRequest.Builder addAction(@IntRange(from=1, to=255) int);
+ method @NonNull public android.nearby.PresenceBroadcastRequest.Builder addExtendedProperty(@NonNull android.nearby.DataElement);
+ method @NonNull public android.nearby.PresenceBroadcastRequest build();
+ method @NonNull public android.nearby.PresenceBroadcastRequest.Builder setCredential(@NonNull android.nearby.PrivateCredential);
+ method @NonNull public android.nearby.PresenceBroadcastRequest.Builder setTxPower(@IntRange(from=0xffffff81, to=126) int);
+ method @NonNull public android.nearby.PresenceBroadcastRequest.Builder setVersion(int);
+ }
+
+ public abstract class PresenceCredential implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public byte[] getAuthenticityKey();
+ method @NonNull public java.util.List<android.nearby.CredentialElement> getCredentialElements();
+ method public int getIdentityType();
+ method @NonNull public byte[] getSecretId();
+ method public int getType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceCredential> CREATOR;
+ field public static final int CREDENTIAL_TYPE_PRIVATE = 0; // 0x0
+ field public static final int CREDENTIAL_TYPE_PUBLIC = 1; // 0x1
+ field public static final int IDENTITY_TYPE_PRIVATE = 1; // 0x1
+ field public static final int IDENTITY_TYPE_PROVISIONED = 2; // 0x2
+ field public static final int IDENTITY_TYPE_PUBLIC = 4; // 0x4
+ field public static final int IDENTITY_TYPE_TRUSTED = 3; // 0x3
+ field public static final int IDENTITY_TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class PresenceDevice extends android.nearby.NearbyDevice implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getDeviceId();
+ method @Nullable public String getDeviceImageUrl();
+ method public int getDeviceType();
+ method public long getDiscoveryTimestampMillis();
+ method @NonNull public byte[] getEncryptedIdentity();
+ method @NonNull public java.util.List<android.nearby.DataElement> getExtendedProperties();
+ method @NonNull public byte[] getSalt();
+ method @NonNull public byte[] getSecretId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceDevice> CREATOR;
+ }
+
+ public static final class PresenceDevice.Builder {
+ ctor public PresenceDevice.Builder();
+ method @NonNull public android.nearby.PresenceDevice.Builder addExtendedProperty(@NonNull android.nearby.DataElement);
+ method @NonNull public android.nearby.PresenceDevice.Builder addMedium(int);
+ method @NonNull public android.nearby.PresenceDevice build();
+ method @NonNull public android.nearby.PresenceDevice.Builder setDeviceId(@NonNull String);
+ method @NonNull public android.nearby.PresenceDevice.Builder setDeviceImageUrl(@Nullable String);
+ method @NonNull public android.nearby.PresenceDevice.Builder setDeviceType(int);
+ method @NonNull public android.nearby.PresenceDevice.Builder setDiscoveryTimestampMillis(long);
+ method @NonNull public android.nearby.PresenceDevice.Builder setEncryptedIdentity(@NonNull byte[]);
+ method @NonNull public android.nearby.PresenceDevice.Builder setName(@Nullable String);
+ method @NonNull public android.nearby.PresenceDevice.Builder setRssi(int);
+ method @NonNull public android.nearby.PresenceDevice.Builder setSalt(@NonNull byte[]);
+ method @NonNull public android.nearby.PresenceDevice.Builder setSecretId(@NonNull byte[]);
+ }
+
+ public final class PresenceScanFilter extends android.nearby.ScanFilter implements android.os.Parcelable {
+ method @NonNull public java.util.List<android.nearby.PublicCredential> getCredentials();
+ method @NonNull public java.util.List<android.nearby.DataElement> getExtendedProperties();
+ method @NonNull public java.util.List<java.lang.Integer> getPresenceActions();
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceScanFilter> CREATOR;
+ }
+
+ public static final class PresenceScanFilter.Builder {
+ ctor public PresenceScanFilter.Builder();
+ method @NonNull public android.nearby.PresenceScanFilter.Builder addCredential(@NonNull android.nearby.PublicCredential);
+ method @NonNull public android.nearby.PresenceScanFilter.Builder addExtendedProperty(@NonNull android.nearby.DataElement);
+ method @NonNull public android.nearby.PresenceScanFilter.Builder addPresenceAction(@IntRange(from=1, to=255) int);
+ method @NonNull public android.nearby.PresenceScanFilter build();
+ method @NonNull public android.nearby.PresenceScanFilter.Builder setMaxPathLoss(@IntRange(from=0, to=127) int);
+ }
+
+ public final class PrivateCredential extends android.nearby.PresenceCredential implements android.os.Parcelable {
+ method @NonNull public String getDeviceName();
+ method @NonNull public byte[] getMetadataEncryptionKey();
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PrivateCredential> CREATOR;
+ }
+
+ public static final class PrivateCredential.Builder {
+ ctor public PrivateCredential.Builder(@NonNull byte[], @NonNull byte[]);
+ method @NonNull public android.nearby.PrivateCredential.Builder addCredentialElement(@NonNull android.nearby.CredentialElement);
+ method @NonNull public android.nearby.PrivateCredential build();
+ method @NonNull public android.nearby.PrivateCredential.Builder setDeviceName(@NonNull String);
+ method @NonNull public android.nearby.PrivateCredential.Builder setIdentityType(int);
+ method @NonNull public android.nearby.PrivateCredential.Builder setMetadataEncryptionKey(@NonNull byte[]);
+ }
+
+ public final class PublicCredential extends android.nearby.PresenceCredential implements android.os.Parcelable {
+ method @NonNull public byte[] getEncryptedMetadata();
+ method @NonNull public byte[] getEncryptedMetadataKeyTag();
+ method @NonNull public byte[] getPublicKey();
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PublicCredential> CREATOR;
+ }
+
+ public static final class PublicCredential.Builder {
+ ctor public PublicCredential.Builder(@NonNull byte[], @NonNull byte[]);
+ method @NonNull public android.nearby.PublicCredential.Builder addCredentialElement(@NonNull android.nearby.CredentialElement);
+ method @NonNull public android.nearby.PublicCredential build();
+ method @NonNull public android.nearby.PublicCredential.Builder setEncryptedMetadata(@NonNull byte[]);
+ method @NonNull public android.nearby.PublicCredential.Builder setEncryptedMetadataKeyTag(@NonNull byte[]);
+ method @NonNull public android.nearby.PublicCredential.Builder setIdentityType(int);
+ method @NonNull public android.nearby.PublicCredential.Builder setPublicKey(@NonNull byte[]);
+ }
+
public interface ScanCallback {
method public void onDiscovered(@NonNull android.nearby.NearbyDevice);
method public void onLost(@NonNull android.nearby.NearbyDevice);
method public void onUpdated(@NonNull android.nearby.NearbyDevice);
}
+ public abstract class ScanFilter implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0, to=127) public int getMaxPathLoss();
+ method public int getType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.nearby.ScanFilter> CREATOR;
+ }
+
public final class ScanRequest implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public java.util.List<android.nearby.ScanFilter> getScanFilters();
method public int getScanMode();
method public int getScanType();
method @NonNull public android.os.WorkSource getWorkSource();
@@ -315,6 +484,7 @@
public static final class ScanRequest.Builder {
ctor public ScanRequest.Builder();
+ method @NonNull public android.nearby.ScanRequest.Builder addScanFilter(@NonNull android.nearby.ScanFilter);
method @NonNull public android.nearby.ScanRequest build();
method @NonNull public android.nearby.ScanRequest.Builder setEnableBle(boolean);
method @NonNull public android.nearby.ScanRequest.Builder setScanMode(int);
@@ -326,7 +496,7 @@
package android.net {
- public final class IpSecManager {
+ public class IpSecManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
}
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/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/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/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/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index b7a6076..4f9d845 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -423,6 +423,7 @@
*
* @deprecated Use {@link #setNetworkSpecifier(NetworkSpecifier)} instead.
*/
+ @SuppressLint("NewApi") // TODO: b/193460475 remove once fixed
@Deprecated
public Builder setNetworkSpecifier(String networkSpecifier) {
try {
@@ -439,6 +440,15 @@
} else if (mNetworkCapabilities.hasTransport(TRANSPORT_TEST)) {
return setNetworkSpecifier(new TestNetworkSpecifier(networkSpecifier));
} else {
+ // TODO: b/193460475 remove comment once fixed
+ // @SuppressLint("NewApi") is due to EthernetNetworkSpecifier being changed
+ // from @SystemApi to public. EthernetNetworkSpecifier was introduced in Android
+ // 12 as @SystemApi(client = MODULE_LIBRARIES) and made public in Android 13.
+ // b/193460475 means in the above situation the tools will think
+ // EthernetNetworkSpecifier didn't exist in Android 12, causing the NewApi lint
+ // to fail. In this case, this is actually safe because this code was
+ // modularized in Android 12, so it can't run on SDKs before Android 12 and is
+ // therefore guaranteed to always have this class available to it.
return setNetworkSpecifier(new EthernetNetworkSpecifier(networkSpecifier));
}
}
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/service/ServiceConnectivityResources/res/values-lv/strings.xml b/service/ServiceConnectivityResources/res/values-lv/strings.xml
index 9d26c40..ce063a5 100644
--- a/service/ServiceConnectivityResources/res/values-lv/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-lv/strings.xml
@@ -23,7 +23,7 @@
<!-- no translation found for network_available_sign_in_detailed (8439369644697866359) -->
<skip />
<string name="wifi_no_internet" msgid="1326348603404555475">"Tīklā <xliff:g id="NETWORK_SSID">%1$s</xliff:g> nav piekļuves internetam"</string>
- <string name="wifi_no_internet_detailed" msgid="1746921096565304090">"Pieskarieties, lai skatītu iespējas."</string>
+ <string name="wifi_no_internet_detailed" msgid="1746921096565304090">"Pieskarieties, lai skatītu opcijas."</string>
<string name="mobile_no_internet" msgid="4087718456753201450">"Mobilajā tīklā nav piekļuves internetam."</string>
<string name="other_networks_no_internet" msgid="5693932964749676542">"Tīklā nav piekļuves internetam."</string>
<string name="private_dns_broken_detailed" msgid="2677123850463207823">"Nevar piekļūt privātam DNS serverim."</string>
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index d833bc2..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;
}
}
}
@@ -8853,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
@@ -8883,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
@@ -10511,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/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/common/java/android/net/netstats/NetworkStatsCollectionTest.kt b/tests/common/java/android/net/netstats/NetworkStatsCollectionTest.kt
new file mode 100644
index 0000000..ca0e5ed
--- /dev/null
+++ b/tests/common/java/android/net/netstats/NetworkStatsCollectionTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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.netstats
+
+import android.net.NetworkIdentitySet
+import android.net.NetworkStatsCollection
+import android.net.NetworkStatsHistory
+import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.SC_V2
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.test.assertEquals
+import kotlin.test.fail
+
+@ConnectivityModuleTest
+@RunWith(JUnit4::class)
+@SmallTest
+class NetworkStatsCollectionTest {
+ @Rule
+ @JvmField
+ val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
+
+ @Test
+ fun testBuilder() {
+ val ident = NetworkIdentitySet()
+ val key1 = NetworkStatsCollection.Key(ident, /* uid */ 0, /* set */ 0, /* tag */ 0)
+ val key2 = NetworkStatsCollection.Key(ident, /* uid */ 1, /* set */ 0, /* tag */ 0)
+ val bucketDuration = 10L
+ val entry1 = NetworkStatsHistory.Entry(10, 10, 40, 4, 50, 5, 60)
+ val entry2 = NetworkStatsHistory.Entry(30, 10, 3, 41, 7, 1, 0)
+ val history1 = NetworkStatsHistory.Builder(10, 5)
+ .addEntry(entry1)
+ .addEntry(entry2)
+ .build()
+ val history2 = NetworkStatsHistory(10, 5)
+ val actualCollection = NetworkStatsCollection.Builder(bucketDuration)
+ .addEntry(key1, history1)
+ .addEntry(key2, history2)
+ .build()
+
+ // The builder will omit any entry with empty history. Thus, only history1
+ // is expected in the result collection.
+ val actualEntries = actualCollection.entries
+ assertEquals(1, actualEntries.size)
+ val actualHistory = actualEntries[key1] ?: fail("There should be an entry for $key1")
+ assertEquals(history1.entries, actualHistory.entries)
+ }
+}
\ No newline at end of file
diff --git a/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt b/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt
new file mode 100644
index 0000000..c2654c5
--- /dev/null
+++ b/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 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.netstats
+
+import android.net.NetworkStatsHistory
+import android.text.format.DateUtils
+import androidx.test.filters.SmallTest
+import com.android.testutils.ConnectivityModuleTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.SC_V2
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.test.assertEquals
+
+@ConnectivityModuleTest
+@RunWith(JUnit4::class)
+@SmallTest
+class NetworkStatsHistoryTest {
+ @Rule
+ @JvmField
+ val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
+
+ @Test
+ fun testBuilder() {
+ val entry1 = NetworkStatsHistory.Entry(10, 30, 40, 4, 50, 5, 60)
+ val entry2 = NetworkStatsHistory.Entry(30, 15, 3, 41, 7, 1, 0)
+ val entry3 = NetworkStatsHistory.Entry(7, 301, 11, 14, 31, 2, 80)
+ val statsEmpty = NetworkStatsHistory
+ .Builder(DateUtils.HOUR_IN_MILLIS, /* initialCapacity */ 10).build()
+ assertEquals(0, statsEmpty.entries.size)
+ assertEquals(DateUtils.HOUR_IN_MILLIS, statsEmpty.bucketDuration)
+ val statsSingle = NetworkStatsHistory
+ .Builder(DateUtils.HOUR_IN_MILLIS, /* initialCapacity */ 8)
+ .addEntry(entry1)
+ .build()
+ statsSingle.assertEntriesEqual(entry1)
+ assertEquals(DateUtils.HOUR_IN_MILLIS, statsSingle.bucketDuration)
+ val statsMultiple = NetworkStatsHistory
+ .Builder(DateUtils.SECOND_IN_MILLIS, /* initialCapacity */ 0)
+ .addEntry(entry1).addEntry(entry2).addEntry(entry3)
+ .build()
+ assertEquals(DateUtils.SECOND_IN_MILLIS, statsMultiple.bucketDuration)
+ statsMultiple.assertEntriesEqual(entry1, entry2, entry3)
+ }
+
+ fun NetworkStatsHistory.assertEntriesEqual(vararg entries: NetworkStatsHistory.Entry) {
+ assertEquals(entries.size, this.entries.size)
+ entries.forEachIndexed { i, element ->
+ assertEquals(element, this.entries[i])
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/common/java/android/net/netstats/NetworkTemplateTest.kt b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
new file mode 100644
index 0000000..192694b
--- /dev/null
+++ b/tests/common/java/android/net/netstats/NetworkTemplateTest.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2022 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.netstats
+
+import android.net.NetworkStats.DEFAULT_NETWORK_ALL
+import android.net.NetworkStats.METERED_ALL
+import android.net.NetworkStats.METERED_YES
+import android.net.NetworkStats.ROAMING_YES
+import android.net.NetworkStats.ROAMING_ALL
+import android.net.NetworkTemplate
+import android.net.NetworkTemplate.MATCH_BLUETOOTH
+import android.net.NetworkTemplate.MATCH_CARRIER
+import android.net.NetworkTemplate.MATCH_ETHERNET
+import android.net.NetworkTemplate.MATCH_MOBILE
+import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
+import android.net.NetworkTemplate.MATCH_PROXY
+import android.net.NetworkTemplate.MATCH_WIFI
+import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
+import android.net.NetworkTemplate.NETWORK_TYPE_ALL
+import android.net.NetworkTemplate.OEM_MANAGED_ALL
+import android.telephony.TelephonyManager
+import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
+import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT
+import com.android.testutils.ConnectivityModuleTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.SC_V2
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+
+private const val TEST_IMSI1 = "imsi"
+private const val TEST_WIFI_KEY1 = "wifiKey1"
+private const val TEST_WIFI_KEY2 = "wifiKey2"
+
+@RunWith(JUnit4::class)
+@ConnectivityModuleTest
+class NetworkTemplateTest {
+ @Rule
+ @JvmField
+ val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
+
+ @Test
+ fun testBuilderMatchRules() {
+ // Verify unknown match rules cannot construct templates.
+ listOf(Integer.MIN_VALUE, -1, Integer.MAX_VALUE).forEach {
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(it).build()
+ }
+ }
+
+ // Verify hidden match rules cannot construct templates.
+ listOf(MATCH_WIFI_WILDCARD, MATCH_MOBILE_WILDCARD, MATCH_PROXY).forEach {
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(it).build()
+ }
+ }
+
+ // Verify template which matches metered cellular and carrier networks with
+ // the given IMSI. See buildTemplateMobileAll and buildTemplateCarrierMetered.
+ listOf(MATCH_MOBILE, MATCH_CARRIER).forEach { matchRule ->
+ NetworkTemplate.Builder(matchRule).setSubscriberIds(setOf(TEST_IMSI1))
+ .setMeteredness(METERED_YES).build().let {
+ val expectedTemplate = NetworkTemplate(matchRule, TEST_IMSI1,
+ arrayOf(TEST_IMSI1), arrayOf<String>(), METERED_YES,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+ assertEquals(expectedTemplate, it)
+ }
+ }
+
+ // Verify template which matches roaming cellular and carrier networks with
+ // the given IMSI.
+ listOf(MATCH_MOBILE, MATCH_CARRIER).forEach { matchRule ->
+ NetworkTemplate.Builder(matchRule).setSubscriberIds(setOf(TEST_IMSI1))
+ .setRoaming(ROAMING_YES).setMeteredness(METERED_YES).build().let {
+ val expectedTemplate = NetworkTemplate(matchRule, TEST_IMSI1,
+ arrayOf(TEST_IMSI1), arrayOf<String>(), METERED_YES,
+ ROAMING_YES, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+ assertEquals(expectedTemplate, it)
+ }
+ }
+
+ // Verify carrier template cannot be created without IMSI.
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(MATCH_CARRIER).build()
+ }
+
+ // Verify template which matches metered cellular networks,
+ // regardless of IMSI. See buildTemplateMobileWildcard.
+ NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build().let {
+ val expectedTemplate = NetworkTemplate(MATCH_MOBILE_WILDCARD, null /*subscriberId*/,
+ null /*subscriberIds*/, arrayOf<String>(),
+ METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+ assertEquals(expectedTemplate, it)
+ }
+
+ // Verify template which matches metered cellular networks and ratType.
+ // See NetworkTemplate#buildTemplateMobileWithRatType.
+ NetworkTemplate.Builder(MATCH_MOBILE).setSubscriberIds(setOf(TEST_IMSI1))
+ .setMeteredness(METERED_YES).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
+ .build().let {
+ val expectedTemplate = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1,
+ arrayOf(TEST_IMSI1), arrayOf<String>(), METERED_YES,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_UMTS,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+ assertEquals(expectedTemplate, it)
+ }
+
+ // Verify template which matches all wifi networks,
+ // regardless of Wifi Network Key. See buildTemplateWifiWildcard and buildTemplateWifi.
+ NetworkTemplate.Builder(MATCH_WIFI).build().let {
+ val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
+ null /*subscriberIds*/, arrayOf<String>(),
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+ assertEquals(expectedTemplate, it)
+ }
+
+ // Verify template which matches wifi networks with the given Wifi Network Key.
+ // See buildTemplateWifi(wifiNetworkKey).
+ NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build().let {
+ val expectedTemplate = NetworkTemplate(MATCH_WIFI, null /*subscriberId*/,
+ null /*subscriberIds*/, arrayOf(TEST_WIFI_KEY1),
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+ assertEquals(expectedTemplate, it)
+ }
+
+ // Verify template which matches all wifi networks with the
+ // given Wifi Network Key, and IMSI. See buildTemplateWifi(wifiNetworkKey, subscriberId).
+ NetworkTemplate.Builder(MATCH_WIFI).setSubscriberIds(setOf(TEST_IMSI1))
+ .setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build().let {
+ val expectedTemplate = NetworkTemplate(MATCH_WIFI, TEST_IMSI1,
+ arrayOf(TEST_IMSI1), arrayOf(TEST_WIFI_KEY1),
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
+ assertEquals(expectedTemplate, it)
+ }
+
+ // Verify template which matches ethernet and bluetooth networks.
+ // See buildTemplateEthernet and buildTemplateBluetooth.
+ listOf(MATCH_ETHERNET, MATCH_BLUETOOTH).forEach { matchRule ->
+ NetworkTemplate.Builder(matchRule).build().let {
+ val expectedTemplate = NetworkTemplate(matchRule, null /*subscriberId*/,
+ null /*subscriberIds*/, arrayOf<String>(),
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+ assertEquals(expectedTemplate, it)
+ }
+ }
+ }
+
+ @Test
+ fun testBuilderWifiNetworkKeys() {
+ // Verify template builder which generates same template with the given different
+ // sequence keys.
+ NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(
+ setOf(TEST_WIFI_KEY1, TEST_WIFI_KEY2)).build().let {
+ val expectedTemplate = NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(
+ setOf(TEST_WIFI_KEY2, TEST_WIFI_KEY1)).build()
+ assertEquals(expectedTemplate, it)
+ }
+
+ // Verify template which matches non-wifi networks with the given key is invalid.
+ listOf(MATCH_MOBILE, MATCH_CARRIER, MATCH_ETHERNET, MATCH_BLUETOOTH, -1,
+ Integer.MAX_VALUE).forEach { matchRule ->
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(matchRule).setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
+ }
+ }
+
+ // Verify template which matches wifi networks with the given null key is invalid.
+ assertFailsWith<IllegalArgumentException> {
+ NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf(null)).build()
+ }
+
+ // Verify template which matches wifi wildcard with the given empty key set.
+ NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf<String>()).build().let {
+ val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
+ arrayOf<String>() /*subscriberIds*/, arrayOf<String>(),
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+ OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
+ assertEquals(expectedTemplate, it)
+ }
+ }
+}
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/AndroidManifest.xml b/tests/cts/hostside/app2/AndroidManifest.xml
index 6c9b469..ff7240d 100644
--- a/tests/cts/hostside/app2/AndroidManifest.xml
+++ b/tests/cts/hostside/app2/AndroidManifest.xml
@@ -22,6 +22,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!--
This application is used to listen to RESTRICT_BACKGROUND_CHANGED intents and store
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/NetworkStatsManagerTest.java b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
index 1fac108..de4f41b 100644
--- a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
@@ -21,6 +21,9 @@
import static android.app.usage.NetworkStats.Bucket.METERED_ALL;
import static android.app.usage.NetworkStats.Bucket.METERED_NO;
import static android.app.usage.NetworkStats.Bucket.METERED_YES;
+import static android.app.usage.NetworkStats.Bucket.ROAMING_ALL;
+import static android.app.usage.NetworkStats.Bucket.ROAMING_NO;
+import static android.app.usage.NetworkStats.Bucket.ROAMING_YES;
import static android.app.usage.NetworkStats.Bucket.STATE_ALL;
import static android.app.usage.NetworkStats.Bucket.STATE_DEFAULT;
import static android.app.usage.NetworkStats.Bucket.STATE_FOREGROUND;
@@ -92,6 +95,7 @@
private abstract class NetworkInterfaceToTest {
private boolean mMetered;
+ private boolean mRoaming;
private boolean mIsDefault;
abstract int getNetworkType();
@@ -105,6 +109,14 @@
this.mMetered = metered;
}
+ public boolean getRoaming() {
+ return mRoaming;
+ }
+
+ public void setRoaming(boolean roaming) {
+ this.mRoaming = roaming;
+ }
+
public boolean getIsDefault() {
return mIsDefault;
}
@@ -282,6 +294,7 @@
private URL mUrl;
public boolean success;
public boolean metered;
+ public boolean roaming;
public boolean isDefault;
NetworkCallback(long tolerance, URL url) {
@@ -289,6 +302,7 @@
mUrl = url;
success = false;
metered = false;
+ roaming = false;
isDefault = false;
}
@@ -318,6 +332,8 @@
success = true;
metered = !mCm.getNetworkCapabilities(network)
.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ roaming = !mCm.getNetworkCapabilities(network)
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
synchronized (NetworkStatsManagerTest.this) {
NetworkStatsManagerTest.this.notify();
}
@@ -348,6 +364,7 @@
}
if (callback.success) {
mNetworkInterfacesToTest[networkTypeIndex].setMetered(callback.metered);
+ mNetworkInterfacesToTest[networkTypeIndex].setRoaming(callback.roaming);
mNetworkInterfacesToTest[networkTypeIndex].setIsDefault(callback.isDefault);
return true;
}
@@ -392,6 +409,7 @@
assertEquals(bucket.getState(), STATE_ALL);
assertEquals(bucket.getUid(), UID_ALL);
assertEquals(bucket.getMetered(), METERED_ALL);
+ assertEquals(bucket.getRoaming(), ROAMING_ALL);
assertEquals(bucket.getDefaultNetworkStatus(), DEFAULT_NETWORK_ALL);
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
@@ -427,6 +445,7 @@
assertEquals(bucket.getState(), STATE_ALL);
assertEquals(bucket.getUid(), UID_ALL);
assertEquals(bucket.getMetered(), METERED_ALL);
+ assertEquals(bucket.getRoaming(), ROAMING_ALL);
assertEquals(bucket.getDefaultNetworkStatus(), DEFAULT_NETWORK_ALL);
setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, "deny");
try {
@@ -466,15 +485,19 @@
long totalTxBytes = 0;
long totalRxBytes = 0;
boolean hasCorrectMetering = false;
+ boolean hasCorrectRoaming = false;
boolean hasCorrectDefaultStatus = false;
int expectedMetering = mNetworkInterfacesToTest[i].getMetered()
? METERED_YES : METERED_NO;
+ int expectedRoaming = mNetworkInterfacesToTest[i].getRoaming()
+ ? ROAMING_YES : ROAMING_NO;
int expectedDefaultStatus = mNetworkInterfacesToTest[i].getIsDefault()
? DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO;
while (result.hasNextBucket()) {
assertTrue(result.getNextBucket(bucket));
assertTimestamps(bucket);
hasCorrectMetering |= bucket.getMetered() == expectedMetering;
+ hasCorrectRoaming |= bucket.getRoaming() == expectedRoaming;
if (bucket.getUid() == Process.myUid()) {
totalTxPackets += bucket.getTxPackets();
totalRxPackets += bucket.getRxPackets();
@@ -487,6 +510,8 @@
assertFalse(result.getNextBucket(bucket));
assertTrue("Incorrect metering for NetworkType: "
+ mNetworkInterfacesToTest[i].getNetworkType(), hasCorrectMetering);
+ assertTrue("Incorrect roaming for NetworkType: "
+ + mNetworkInterfacesToTest[i].getNetworkType(), hasCorrectRoaming);
assertTrue("Incorrect isDefault for NetworkType: "
+ mNetworkInterfacesToTest[i].getNetworkType(), hasCorrectDefaultStatus);
assertTrue("No Rx bytes usage for uid " + Process.myUid(), totalRxBytes > 0);
@@ -579,6 +604,7 @@
assertTimestamps(bucket);
assertEquals(bucket.getState(), STATE_ALL);
assertEquals(bucket.getMetered(), METERED_ALL);
+ assertEquals(bucket.getRoaming(), ROAMING_ALL);
assertEquals(bucket.getDefaultNetworkStatus(), DEFAULT_NETWORK_ALL);
assertEquals(bucket.getUid(), Process.myUid());
totalTxPackets += bucket.getTxPackets();
@@ -632,6 +658,7 @@
assertTimestamps(bucket);
assertEquals(bucket.getState(), STATE_ALL);
assertEquals(bucket.getMetered(), METERED_ALL);
+ assertEquals(bucket.getRoaming(), ROAMING_ALL);
assertEquals(bucket.getDefaultNetworkStatus(), DEFAULT_NETWORK_ALL);
assertEquals(bucket.getUid(), Process.myUid());
if (bucket.getTag() == NETWORK_TAG) {
@@ -890,6 +917,7 @@
if (expectedTag != null) assertEquals(bucket.getTag(), (int) expectedTag);
if (expectedState != null) assertEquals(bucket.getState(), (int) expectedState);
assertEquals(bucket.getMetered(), METERED_ALL);
+ assertEquals(bucket.getRoaming(), ROAMING_ALL);
assertEquals(bucket.getDefaultNetworkStatus(), DEFAULT_NETWORK_ALL);
if (bucket.getUid() == Process.myUid()) {
totalTxPackets += bucket.getTxPackets();
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/NetworkStatsCollectionTest.java b/tests/unit/java/android/net/NetworkStatsCollectionTest.java
index c27ee93..bc2b532 100644
--- a/tests/unit/java/android/net/NetworkStatsCollectionTest.java
+++ b/tests/unit/java/android/net/NetworkStatsCollectionTest.java
@@ -38,13 +38,11 @@
import static org.junit.Assert.fail;
import android.content.res.Resources;
-import android.net.NetworkStatsCollection.Key;
import android.os.Process;
import android.os.UserHandle;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
-import android.util.ArrayMap;
import android.util.RecurrenceRule;
import androidx.test.InstrumentationRegistry;
@@ -75,7 +73,6 @@
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
* Tests for {@link NetworkStatsCollection}.
@@ -533,52 +530,6 @@
assertThrows(ArithmeticException.class, () -> multiplySafeByRational(30, 3, 0));
}
- @Test
- public void testBuilder() {
- final Map<Key, NetworkStatsHistory> expectedEntries = new ArrayMap<>();
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- final NetworkIdentitySet ident = new NetworkIdentitySet();
- final Key key1 = new Key(ident, 0, 0, 0);
- final Key key2 = new Key(ident, 1, 0, 0);
- final long bucketDuration = 10;
-
- final NetworkStatsHistory.Entry entry1 = new NetworkStatsHistory.Entry(10, 10, 40,
- 4, 50, 5, 60);
- final NetworkStatsHistory.Entry entry2 = new NetworkStatsHistory.Entry(30, 10, 3,
- 41, 7, 1, 0);
-
- NetworkStatsHistory history1 = new NetworkStatsHistory.Builder(10, 5)
- .addEntry(entry1)
- .addEntry(entry2)
- .build();
-
- NetworkStatsHistory history2 = new NetworkStatsHistory(10, 5);
-
- NetworkStatsCollection actualCollection = new NetworkStatsCollection.Builder(bucketDuration)
- .addEntry(key1, history1)
- .addEntry(key2, history2)
- .build();
-
- // The builder will omit any entry with empty history. Thus, history2
- // is not expected in the result collection.
- expectedEntries.put(key1, history1);
-
- final Map<Key, NetworkStatsHistory> actualEntries = actualCollection.getEntries();
-
- assertEquals(expectedEntries.size(), actualEntries.size());
- for (Key expectedKey : expectedEntries.keySet()) {
- final NetworkStatsHistory expectedHistory = expectedEntries.get(expectedKey);
-
- final NetworkStatsHistory actualHistory = actualEntries.get(expectedKey);
- assertNotNull(actualHistory);
-
- assertEquals(expectedHistory.getEntries(), actualHistory.getEntries());
-
- actualEntries.remove(expectedKey);
- }
- assertEquals(0, actualEntries.size());
- }
-
/**
* Copy a {@link Resources#openRawResource(int)} into {@link File} for
* testing purposes.
diff --git a/tests/unit/java/android/net/NetworkStatsHistoryTest.java b/tests/unit/java/android/net/NetworkStatsHistoryTest.java
index c170605..c5f8c00 100644
--- a/tests/unit/java/android/net/NetworkStatsHistoryTest.java
+++ b/tests/unit/java/android/net/NetworkStatsHistoryTest.java
@@ -56,7 +56,6 @@
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
-import java.util.List;
import java.util.Random;
@RunWith(DevSdkIgnoreRunner.class)
@@ -533,40 +532,6 @@
assertEquals(512L + 4096L, stats.getTotalBytes());
}
- @Test
- public void testBuilder() {
- final NetworkStatsHistory.Entry entry1 = new NetworkStatsHistory.Entry(10, 30, 40,
- 4, 50, 5, 60);
- final NetworkStatsHistory.Entry entry2 = new NetworkStatsHistory.Entry(30, 15, 3,
- 41, 7, 1, 0);
- final NetworkStatsHistory.Entry entry3 = new NetworkStatsHistory.Entry(7, 301, 11,
- 14, 31, 2, 80);
-
- final NetworkStatsHistory statsEmpty = new NetworkStatsHistory
- .Builder(HOUR_IN_MILLIS, 10).build();
- assertEquals(0, statsEmpty.getEntries().size());
- assertEquals(HOUR_IN_MILLIS, statsEmpty.getBucketDuration());
-
- NetworkStatsHistory statsSingle = new NetworkStatsHistory
- .Builder(HOUR_IN_MILLIS, 8)
- .addEntry(entry1)
- .build();
- assertEquals(1, statsSingle.getEntries().size());
- assertEquals(HOUR_IN_MILLIS, statsSingle.getBucketDuration());
- assertEquals(entry1, statsSingle.getEntries().get(0));
-
- NetworkStatsHistory statsMultiple = new NetworkStatsHistory
- .Builder(SECOND_IN_MILLIS, 0)
- .addEntry(entry1).addEntry(entry2).addEntry(entry3)
- .build();
- final List<NetworkStatsHistory.Entry> entries = statsMultiple.getEntries();
- assertEquals(3, entries.size());
- assertEquals(SECOND_IN_MILLIS, statsMultiple.getBucketDuration());
- assertEquals(entry1, entries.get(0));
- assertEquals(entry2, entries.get(1));
- assertEquals(entry3, entries.get(2));
- }
-
private static void assertIndexBeforeAfter(
NetworkStatsHistory stats, int before, int after, long time) {
assertEquals("unexpected before", before, stats.getIndexBefore(time));
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index 453612f..abd1825 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -29,12 +29,8 @@
import android.net.NetworkStats.METERED_NO
import android.net.NetworkStats.METERED_YES
import android.net.NetworkStats.ROAMING_ALL
-import android.net.NetworkTemplate.MATCH_BLUETOOTH
-import android.net.NetworkTemplate.MATCH_CARRIER
-import android.net.NetworkTemplate.MATCH_ETHERNET
import android.net.NetworkTemplate.MATCH_MOBILE
import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
-import android.net.NetworkTemplate.MATCH_PROXY
import android.net.NetworkTemplate.MATCH_WIFI
import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
@@ -52,11 +48,9 @@
import android.net.wifi.WifiInfo
import android.os.Build
import android.telephony.TelephonyManager
-import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
import com.android.net.module.util.NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
-import com.android.testutils.SC_V2
import com.android.testutils.assertParcelSane
import org.junit.Before
import org.junit.Test
@@ -65,7 +59,6 @@
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
import kotlin.test.assertNotEquals
import kotlin.test.assertTrue
@@ -555,140 +548,4 @@
it.assertMatches(identMobileImsi3)
}
}
-
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Test
- fun testBuilderMatchRules() {
- // Verify unknown match rules cannot construct templates.
- listOf(Integer.MIN_VALUE, -1, Integer.MAX_VALUE).forEach {
- assertFailsWith<IllegalArgumentException> {
- NetworkTemplate.Builder(it).build()
- }
- }
-
- // Verify hidden match rules cannot construct templates.
- listOf(MATCH_WIFI_WILDCARD, MATCH_MOBILE_WILDCARD, MATCH_PROXY).forEach {
- assertFailsWith<IllegalArgumentException> {
- NetworkTemplate.Builder(it).build()
- }
- }
-
- // Verify template which matches metered cellular and carrier networks with
- // the given IMSI. See buildTemplateMobileAll and buildTemplateCarrierMetered.
- listOf(MATCH_MOBILE, MATCH_CARRIER).forEach { matchRule ->
- NetworkTemplate.Builder(matchRule).setSubscriberIds(setOf(TEST_IMSI1))
- .setMeteredness(METERED_YES).build().let {
- val expectedTemplate = NetworkTemplate(matchRule, TEST_IMSI1,
- arrayOf(TEST_IMSI1), arrayOf<String>(), METERED_YES,
- ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
- assertEquals(expectedTemplate, it)
- }
- }
-
- // Verify carrier template cannot be created without IMSI.
- assertFailsWith<IllegalArgumentException> {
- NetworkTemplate.Builder(MATCH_CARRIER).build()
- }
-
- // Verify template which matches metered cellular networks,
- // regardless of IMSI. See buildTemplateMobileWildcard.
- NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES).build().let {
- val expectedTemplate = NetworkTemplate(MATCH_MOBILE_WILDCARD, null /*subscriberId*/,
- null /*subscriberIds*/, arrayOf<String>(),
- METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
- assertEquals(expectedTemplate, it)
- }
-
- // Verify template which matches metered cellular networks and ratType.
- // See NetworkTemplate#buildTemplateMobileWithRatType.
- NetworkTemplate.Builder(MATCH_MOBILE).setSubscriberIds(setOf(TEST_IMSI1))
- .setMeteredness(METERED_YES).setRatType(TelephonyManager.NETWORK_TYPE_UMTS)
- .build().let {
- val expectedTemplate = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1,
- arrayOf(TEST_IMSI1), arrayOf<String>(), METERED_YES,
- ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_UMTS,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
- assertEquals(expectedTemplate, it)
- }
-
- // Verify template which matches all wifi networks,
- // regardless of Wifi Network Key. See buildTemplateWifiWildcard and buildTemplateWifi.
- NetworkTemplate.Builder(MATCH_WIFI).build().let {
- val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
- null /*subscriberIds*/, arrayOf<String>(),
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
- assertEquals(expectedTemplate, it)
- }
-
- // Verify template which matches wifi networks with the given Wifi Network Key.
- // See buildTemplateWifi(wifiNetworkKey).
- NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build().let {
- val expectedTemplate = NetworkTemplate(MATCH_WIFI, null /*subscriberId*/,
- null /*subscriberIds*/, arrayOf(TEST_WIFI_KEY1),
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
- assertEquals(expectedTemplate, it)
- }
-
- // Verify template which matches all wifi networks with the
- // given Wifi Network Key, and IMSI. See buildTemplateWifi(wifiNetworkKey, subscriberId).
- NetworkTemplate.Builder(MATCH_WIFI).setSubscriberIds(setOf(TEST_IMSI1))
- .setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build().let {
- val expectedTemplate = NetworkTemplate(MATCH_WIFI, TEST_IMSI1,
- arrayOf(TEST_IMSI1), arrayOf(TEST_WIFI_KEY1),
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT)
- assertEquals(expectedTemplate, it)
- }
-
- // Verify template which matches ethernet and bluetooth networks.
- // See buildTemplateEthernet and buildTemplateBluetooth.
- listOf(MATCH_ETHERNET, MATCH_BLUETOOTH).forEach { matchRule ->
- NetworkTemplate.Builder(matchRule).build().let {
- val expectedTemplate = NetworkTemplate(matchRule, null /*subscriberId*/,
- null /*subscriberIds*/, arrayOf<String>(),
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
- assertEquals(expectedTemplate, it)
- }
- }
- }
-
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Test
- fun testBuilderWifiNetworkKeys() {
- // Verify template builder which generates same template with the given different
- // sequence keys.
- NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(
- setOf(TEST_WIFI_KEY1, TEST_WIFI_KEY2)).build().let {
- val expectedTemplate = NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(
- setOf(TEST_WIFI_KEY2, TEST_WIFI_KEY1)).build()
- assertEquals(expectedTemplate, it)
- }
-
- // Verify template which matches non-wifi networks with the given key is invalid.
- listOf(MATCH_MOBILE, MATCH_CARRIER, MATCH_ETHERNET, MATCH_BLUETOOTH, -1,
- Integer.MAX_VALUE).forEach { matchRule ->
- assertFailsWith<IllegalArgumentException> {
- NetworkTemplate.Builder(matchRule).setWifiNetworkKeys(setOf(TEST_WIFI_KEY1)).build()
- }
- }
-
- // Verify template which matches wifi networks with the given null key is invalid.
- assertFailsWith<IllegalArgumentException> {
- NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf(null)).build()
- }
-
- // Verify template which matches wifi wildcard with the given empty key set.
- NetworkTemplate.Builder(MATCH_WIFI).setWifiNetworkKeys(setOf<String>()).build().let {
- val expectedTemplate = NetworkTemplate(MATCH_WIFI_WILDCARD, null /*subscriberId*/,
- arrayOf<String>() /*subscriberIds*/, arrayOf<String>(),
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_ALL)
- assertEquals(expectedTemplate, it)
- }
- }
}
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/NetworkManagementServiceTest.java b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
index 0c58582..a3b0e7c 100644
--- a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,11 @@
package com.android.server;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
import static android.util.DebugUtils.valueToString;
import static org.junit.Assert.assertEquals;
@@ -277,31 +282,38 @@
isRestrictedForDozable.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForDozable.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForDozable.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
+ expected.put(FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
// Powersaver chain
final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>();
isRestrictedForPowerSave.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
+ expected.put(FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
// Standby chain
final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>();
isRestrictedForStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, false);
isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
+ expected.put(FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
// Restricted mode chain
final ArrayMap<Integer, Boolean> isRestrictedForRestrictedMode = new ArrayMap<>();
isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true);
- expected.put(INetd.FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
+ expected.put(FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
+ // Low Power Standby chain
+ final ArrayMap<Integer, Boolean> isRestrictedForLowPowerStandby = new ArrayMap<>();
+ isRestrictedForLowPowerStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
+ isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
+ isRestrictedForLowPowerStandby.put(INetd.FIREWALL_RULE_DENY, true);
+ expected.put(FIREWALL_CHAIN_LOW_POWER_STANDBY, isRestrictedForLowPowerStandby);
final int[] chains = {
- INetd.FIREWALL_CHAIN_STANDBY,
- INetd.FIREWALL_CHAIN_POWERSAVE,
- INetd.FIREWALL_CHAIN_DOZABLE,
- INetd.FIREWALL_CHAIN_RESTRICTED
+ FIREWALL_CHAIN_STANDBY,
+ FIREWALL_CHAIN_POWERSAVE,
+ FIREWALL_CHAIN_DOZABLE,
+ FIREWALL_CHAIN_RESTRICTED,
+ FIREWALL_CHAIN_LOW_POWER_STANDBY
};
final int[] states = {
INetd.FIREWALL_RULE_ALLOW,
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
index 66dcf6d..12b227c 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -36,6 +36,7 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import android.content.Context;
import android.net.DataUsageRequest;
import android.net.NetworkIdentity;
import android.net.NetworkIdentitySet;
@@ -101,6 +102,7 @@
@Mock private IBinder mUsageCallbackBinder;
private TestableUsageCallback mUsageCallback;
+ @Mock private Context mContext;
@Before
public void setUp() throws Exception {
@@ -127,14 +129,14 @@
final DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdTooLowBytes);
- final DataUsageRequest requestByApp = mStatsObservers.register(inputRequest, mUsageCallback,
- UID_RED, NetworkStatsAccess.Level.DEVICE);
+ final DataUsageRequest requestByApp = mStatsObservers.register(mContext, inputRequest,
+ mUsageCallback, UID_RED, NetworkStatsAccess.Level.DEVICE);
assertTrue(requestByApp.requestId > 0);
assertTrue(Objects.equals(sTemplateWifi, requestByApp.template));
- assertEquals(THRESHOLD_BYTES, requestByApp.thresholdInBytes);
+ assertEquals(thresholdTooLowBytes, requestByApp.thresholdInBytes);
// Verify the threshold requested by system uid won't be overridden.
- final DataUsageRequest requestBySystem = mStatsObservers.register(inputRequest,
+ final DataUsageRequest requestBySystem = mStatsObservers.register(mContext, inputRequest,
mUsageCallback, Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(requestBySystem.requestId > 0);
assertTrue(Objects.equals(sTemplateWifi, requestBySystem.template));
@@ -147,7 +149,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, highThresholdBytes);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateWifi, request.template));
@@ -159,13 +161,13 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, THRESHOLD_BYTES);
- DataUsageRequest request1 = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request1 = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request1.requestId > 0);
assertTrue(Objects.equals(sTemplateWifi, request1.template));
assertEquals(THRESHOLD_BYTES, request1.thresholdInBytes);
- DataUsageRequest request2 = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request2 = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request2.requestId > request1.requestId);
assertTrue(Objects.equals(sTemplateWifi, request2.template));
@@ -185,7 +187,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -205,7 +207,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
UID_RED, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -233,7 +235,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -257,7 +259,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -287,7 +289,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -318,7 +320,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
UID_RED, NetworkStatsAccess.Level.DEFAULT);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -351,7 +353,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
UID_BLUE, NetworkStatsAccess.Level.DEFAULT);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -383,7 +385,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
UID_BLUE, NetworkStatsAccess.Level.USER);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));
@@ -416,7 +418,7 @@
DataUsageRequest inputRequest = new DataUsageRequest(
DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
- DataUsageRequest request = mStatsObservers.register(inputRequest, mUsageCallback,
+ DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
UID_RED, NetworkStatsAccess.Level.USER);
assertTrue(request.requestId > 0);
assertTrue(Objects.equals(sTemplateImsi1, request.template));