Merge "Migrate buildTemplate* to use NetworkTemplate.Builder"
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 299a88e..a7028b7 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -85,7 +85,7 @@
bpfs: [
"block.o",
"clatd.o",
- "dscp_policy.o",
+ "dscpPolicy.o",
"netd.o",
"offload.o",
"offload@btf.o",
@@ -122,6 +122,12 @@
certificate: "com.android.tethering",
}
+filegroup {
+ name: "connectivity-hiddenapi-files",
+ srcs: ["hiddenapi/*.txt"],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
+}
+
// Encapsulate the contributions made by the com.android.tethering to the bootclasspath.
bootclasspath_fragment {
name: "com.android.tethering-bootclasspath-fragment",
@@ -203,7 +209,7 @@
bpfs: [
"block.o",
"clatd.o",
- "dscp_policy.o",
+ "dscpPolicy.o",
"netd.o",
"offload@inprocess.o",
"test@inprocess.o",
diff --git a/Tethering/src/android/net/ip/NeighborPacketForwarder.java b/Tethering/src/android/net/ip/NeighborPacketForwarder.java
index 723bd63..8384562 100644
--- a/Tethering/src/android/net/ip/NeighborPacketForwarder.java
+++ b/Tethering/src/android/net/ip/NeighborPacketForwarder.java
@@ -23,6 +23,7 @@
import static android.system.OsConstants.SOCK_DGRAM;
import static android.system.OsConstants.SOCK_NONBLOCK;
import static android.system.OsConstants.SOCK_RAW;
+import static android.system.OsConstants.ENODEV;
import android.net.util.SocketUtils;
import android.os.Handler;
@@ -131,7 +132,13 @@
ETH_P_IPV6, mListenIfaceParams.index);
Os.bind(mFd, bindAddress);
} catch (ErrnoException | SocketException e) {
- Log.wtf(mTag, "Failed to create socket", e);
+ // An ENODEV(No such device) will rise if tethering stopped before this function, this
+ // may happen when enable/disable tethering quickly.
+ if (e instanceof ErrnoException && ((ErrnoException) e).errno == ENODEV) {
+ Log.w(mTag, "Failed to create socket because tethered interface is gone", e);
+ } else {
+ Log.wtf(mTag, "Failed to create socket", e);
+ }
closeSocketQuietly(mFd);
return null;
}
diff --git a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
index 4525568..85ee466 100644
--- a/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
+++ b/Tethering/tests/mts/src/android/tethering/mts/TetheringModuleTest.java
@@ -15,27 +15,23 @@
*/
package android.tethering.mts;
-import static android.Manifest.permission.ACCESS_WIFI_STATE;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
-import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.READ_DEVICE_CONFIG;
-import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.Manifest.permission.WRITE_SETTINGS;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import android.app.UiAutomation;
import android.content.Context;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.TetheringInterface;
-import android.net.TetheringManager;
import android.net.cts.util.CtsTetheringUtils;
import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
import android.provider.DeviceConfig;
@@ -46,7 +42,6 @@
import com.android.testutils.TestNetworkTracker;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -60,26 +55,14 @@
@RunWith(AndroidJUnit4.class)
public class TetheringModuleTest {
private Context mContext;
- private TetheringManager mTm;
private CtsTetheringUtils mCtsTetheringUtils;
- private UiAutomation mUiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
-
@Before
public void setUp() throws Exception {
- mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS,
- WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED, ACCESS_WIFI_STATE);
mContext = InstrumentationRegistry.getContext();
- mTm = mContext.getSystemService(TetheringManager.class);
mCtsTetheringUtils = new CtsTetheringUtils(mContext);
}
- @After
- public void tearDown() throws Exception {
- mUiAutomation.dropShellPermissionIdentity();
- }
-
@Test
public void testSwitchBasePrefixRangeWhenConflict() throws Exception {
addressConflictTest(true);
@@ -130,10 +113,8 @@
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
} finally {
- if (tnt != null) {
- tnt.teardown();
- }
- mTm.stopAllTethering();
+ teardown(tnt);
+ mCtsTetheringUtils.stopAllTethering();
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
}
}
@@ -169,11 +150,19 @@
}
private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception {
- return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/);
+ return runAsShell(MANAGE_TEST_NETWORKS, WRITE_SETTINGS,
+ () -> initTestNetwork(mContext, address, 10_000L /* test timeout ms*/));
}
+ private void teardown(TestNetworkTracker tracker) throws Exception {
+ if (tracker == null) return;
+
+ runAsShell(MANAGE_TEST_NETWORKS, () -> tracker.teardown());
+ }
+
public static boolean isFeatureEnabled(final String name, final boolean defaultValue) {
- return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue);
+ return runAsShell(READ_DEVICE_CONFIG,
+ () -> DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue));
}
}
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 6ab5281..c2e28f4 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -72,8 +72,8 @@
}
bpf {
- name: "dscp_policy.o",
- srcs: ["dscp_policy.c"],
+ name: "dscpPolicy.o",
+ srcs: ["dscpPolicy.c"],
btf: true,
cflags: [
"-Wall",
diff --git a/bpf_progs/dscp_policy.c b/bpf_progs/dscpPolicy.c
similarity index 74%
rename from bpf_progs/dscp_policy.c
rename to bpf_progs/dscpPolicy.c
index 92ea0e2..25abd2b 100644
--- a/bpf_progs/dscp_policy.c
+++ b/bpf_progs/dscpPolicy.c
@@ -31,7 +31,7 @@
#define BPFLOADER_MIN_VER BPFLOADER_T_BETA3_VERSION
#include "bpf_helpers.h"
-#include "dscp_policy.h"
+#include "dscpPolicy.h"
#define ECN_MASK 3
#define IP4_OFFSET(field, header) (header + offsetof(struct iphdr, field))
@@ -64,10 +64,10 @@
int zero = 0;
int hdr_size = 0;
- uint64_t* selectedMap = bpf_switch_comp_map_lookup_elem(&zero);
+ uint64_t* selected_map = bpf_switch_comp_map_lookup_elem(&zero);
// use this with HASH map so map lookup only happens once policies have been added?
- if (!selectedMap) {
+ if (!selected_map) {
return;
}
@@ -78,8 +78,8 @@
uint16_t sport = 0;
uint16_t dport = 0;
uint8_t protocol = 0; // TODO: Use are reserved value? Or int (-1) and cast to uint below?
- struct in6_addr srcIp = {};
- struct in6_addr dstIp = {};
+ struct in6_addr src_ip = {};
+ struct in6_addr dst_ip = {};
uint8_t tos = 0; // Only used for IPv4
uint8_t priority = 0; // Only used for IPv6
uint8_t flow_lbl = 0; // Only used for IPv6
@@ -96,12 +96,12 @@
if (iph->ihl != 5) return;
// V4 mapped address in in6_addr sets 10/11 position to 0xff.
- srcIp.s6_addr32[2] = htonl(0x0000ffff);
- dstIp.s6_addr32[2] = htonl(0x0000ffff);
+ src_ip.s6_addr32[2] = htonl(0x0000ffff);
+ dst_ip.s6_addr32[2] = htonl(0x0000ffff);
// Copy IPv4 address into in6_addr for easy comparison below.
- srcIp.s6_addr32[3] = iph->saddr;
- dstIp.s6_addr32[3] = iph->daddr;
+ src_ip.s6_addr32[3] = iph->saddr;
+ dst_ip.s6_addr32[3] = iph->daddr;
protocol = iph->protocol;
tos = iph->tos;
} else {
@@ -112,8 +112,8 @@
if (ip6h->version != 6) return;
- srcIp = ip6h->saddr;
- dstIp = ip6h->daddr;
+ src_ip = ip6h->saddr;
+ dst_ip = ip6h->daddr;
protocol = ip6h->nexthdr;
priority = ip6h->priority;
flow_lbl = ip6h->flow_lbl[0];
@@ -139,33 +139,33 @@
return;
}
- RuleEntry* existingRule;
+ RuleEntry* existing_rule;
if (ipv4) {
- if (*selectedMap == MAP_A) {
- existingRule = bpf_ipv4_socket_to_policies_map_A_lookup_elem(&cookie);
+ if (*selected_map == MAP_A) {
+ existing_rule = bpf_ipv4_socket_to_policies_map_A_lookup_elem(&cookie);
} else {
- existingRule = bpf_ipv4_socket_to_policies_map_B_lookup_elem(&cookie);
+ existing_rule = bpf_ipv4_socket_to_policies_map_B_lookup_elem(&cookie);
}
} else {
- if (*selectedMap == MAP_A) {
- existingRule = bpf_ipv6_socket_to_policies_map_A_lookup_elem(&cookie);
+ if (*selected_map == MAP_A) {
+ existing_rule = bpf_ipv6_socket_to_policies_map_A_lookup_elem(&cookie);
} else {
- existingRule = bpf_ipv6_socket_to_policies_map_B_lookup_elem(&cookie);
+ existing_rule = bpf_ipv6_socket_to_policies_map_B_lookup_elem(&cookie);
}
}
- if (existingRule && v6_equal(srcIp, existingRule->srcIp) &&
- v6_equal(dstIp, existingRule->dstIp) && skb->ifindex == existingRule->ifindex &&
- ntohs(sport) == htons(existingRule->srcPort) &&
- ntohs(dport) == htons(existingRule->dstPort) && protocol == existingRule->proto) {
+ if (existing_rule && v6_equal(src_ip, existing_rule->src_ip) &&
+ v6_equal(dst_ip, existing_rule->dst_ip) && skb->ifindex == existing_rule->ifindex &&
+ ntohs(sport) == htons(existing_rule->src_port) &&
+ ntohs(dport) == htons(existing_rule->dst_port) && protocol == existing_rule->proto) {
if (ipv4) {
- uint8_t newTos = UPDATE_TOS(existingRule->dscpVal, tos);
+ uint8_t newTos = UPDATE_TOS(existing_rule->dscp_val, tos);
bpf_l3_csum_replace(skb, IP4_OFFSET(check, l2_header_size), htons(tos), htons(newTos),
sizeof(uint16_t));
bpf_skb_store_bytes(skb, IP4_OFFSET(tos, l2_header_size), &newTos, sizeof(newTos), 0);
} else {
- uint8_t new_priority = UPDATE_PRIORITY(existingRule->dscpVal);
- uint8_t new_flow_label = UPDATE_FLOW_LABEL(existingRule->dscpVal, flow_lbl);
+ uint8_t new_priority = UPDATE_PRIORITY(existing_rule->dscp_val);
+ uint8_t new_flow_label = UPDATE_FLOW_LABEL(existing_rule->dscp_val, flow_lbl);
bpf_skb_store_bytes(skb, 0 + l2_header_size, &new_priority, sizeof(uint8_t), 0);
bpf_skb_store_bytes(skb, 1 + l2_header_size, &new_flow_label, sizeof(uint8_t), 0);
}
@@ -173,12 +173,12 @@
}
// Linear scan ipv4_dscp_policies_map since no stored params match skb.
- int bestScore = -1;
- uint32_t bestMatch = 0;
+ int best_score = -1;
+ uint32_t best_match = 0;
for (register uint64_t i = 0; i < MAX_POLICIES; i++) {
int score = 0;
- uint8_t tempMask = 0;
+ uint8_t temp_mask = 0;
// Using a uint64 in for loop prevents infinite loop during BPF load,
// but the key is uint32, so convert back.
uint32_t key = i;
@@ -190,40 +190,40 @@
policy = bpf_ipv6_dscp_policies_map_lookup_elem(&key);
}
- // If the policy lookup failed, presentFields is 0, or iface index does not match
+ // If the policy lookup failed, present_fields is 0, or iface index does not match
// index on skb buff, then we can continue to next policy.
- if (!policy || policy->presentFields == 0 || policy->ifindex != skb->ifindex) continue;
+ if (!policy || policy->present_fields == 0 || policy->ifindex != skb->ifindex) continue;
- if ((policy->presentFields & SRC_IP_MASK_FLAG) == SRC_IP_MASK_FLAG &&
- v6_equal(srcIp, policy->srcIp)) {
+ if ((policy->present_fields & SRC_IP_MASK_FLAG) == SRC_IP_MASK_FLAG &&
+ v6_equal(src_ip, policy->src_ip)) {
score++;
- tempMask |= SRC_IP_MASK_FLAG;
+ temp_mask |= SRC_IP_MASK_FLAG;
}
- if ((policy->presentFields & DST_IP_MASK_FLAG) == DST_IP_MASK_FLAG &&
- v6_equal(dstIp, policy->dstIp)) {
+ if ((policy->present_fields & DST_IP_MASK_FLAG) == DST_IP_MASK_FLAG &&
+ v6_equal(dst_ip, policy->dst_ip)) {
score++;
- tempMask |= DST_IP_MASK_FLAG;
+ temp_mask |= DST_IP_MASK_FLAG;
}
- if ((policy->presentFields & SRC_PORT_MASK_FLAG) == SRC_PORT_MASK_FLAG &&
- ntohs(sport) == htons(policy->srcPort)) {
+ if ((policy->present_fields & SRC_PORT_MASK_FLAG) == SRC_PORT_MASK_FLAG &&
+ ntohs(sport) == htons(policy->src_port)) {
score++;
- tempMask |= SRC_PORT_MASK_FLAG;
+ temp_mask |= SRC_PORT_MASK_FLAG;
}
- if ((policy->presentFields & DST_PORT_MASK_FLAG) == DST_PORT_MASK_FLAG &&
- ntohs(dport) >= htons(policy->dstPortStart) &&
- ntohs(dport) <= htons(policy->dstPortEnd)) {
+ if ((policy->present_fields & DST_PORT_MASK_FLAG) == DST_PORT_MASK_FLAG &&
+ ntohs(dport) >= htons(policy->dst_port_start) &&
+ ntohs(dport) <= htons(policy->dst_port_end)) {
score++;
- tempMask |= DST_PORT_MASK_FLAG;
+ temp_mask |= DST_PORT_MASK_FLAG;
}
- if ((policy->presentFields & PROTO_MASK_FLAG) == PROTO_MASK_FLAG &&
+ if ((policy->present_fields & PROTO_MASK_FLAG) == PROTO_MASK_FLAG &&
protocol == policy->proto) {
score++;
- tempMask |= PROTO_MASK_FLAG;
+ temp_mask |= PROTO_MASK_FLAG;
}
- if (score > bestScore && tempMask == policy->presentFields) {
- bestMatch = i;
- bestScore = score;
+ if (score > best_score && temp_mask == policy->present_fields) {
+ best_match = i;
+ best_score = score;
}
}
@@ -231,16 +231,16 @@
uint8_t new_dscp = 0;
uint8_t new_priority = 0;
uint8_t new_flow_lbl = 0;
- if (bestScore > 0) {
+ if (best_score > 0) {
DscpPolicy* policy;
if (ipv4) {
- policy = bpf_ipv4_dscp_policies_map_lookup_elem(&bestMatch);
+ policy = bpf_ipv4_dscp_policies_map_lookup_elem(&best_match);
} else {
- policy = bpf_ipv6_dscp_policies_map_lookup_elem(&bestMatch);
+ policy = bpf_ipv6_dscp_policies_map_lookup_elem(&best_match);
}
if (policy) {
- new_dscp = policy->dscpVal;
+ new_dscp = policy->dscp_val;
if (ipv4) {
new_tos = UPDATE_TOS(new_dscp, tos);
} else {
@@ -252,24 +252,24 @@
return;
RuleEntry value = {
- .srcIp = srcIp,
- .dstIp = dstIp,
+ .src_ip = src_ip,
+ .dst_ip = dst_ip,
.ifindex = skb->ifindex,
- .srcPort = sport,
- .dstPort = dport,
+ .src_port = sport,
+ .dst_port = dport,
.proto = protocol,
- .dscpVal = new_dscp,
+ .dscp_val = new_dscp,
};
// Update map with new policy.
if (ipv4) {
- if (*selectedMap == MAP_A) {
+ if (*selected_map == MAP_A) {
bpf_ipv4_socket_to_policies_map_A_update_elem(&cookie, &value, BPF_ANY);
} else {
bpf_ipv4_socket_to_policies_map_B_update_elem(&cookie, &value, BPF_ANY);
}
} else {
- if (*selectedMap == MAP_A) {
+ if (*selected_map == MAP_A) {
bpf_ipv6_socket_to_policies_map_A_update_elem(&cookie, &value, BPF_ANY);
} else {
bpf_ipv6_socket_to_policies_map_B_update_elem(&cookie, &value, BPF_ANY);
diff --git a/bpf_progs/dscp_policy.h b/bpf_progs/dscpPolicy.h
similarity index 87%
rename from bpf_progs/dscp_policy.h
rename to bpf_progs/dscpPolicy.h
index 1637f7a..455a121 100644
--- a/bpf_progs/dscp_policy.h
+++ b/bpf_progs/dscpPolicy.h
@@ -44,27 +44,27 @@
(void*)BPF_FUNC_skb_ecn_set_ce;
typedef struct {
- struct in6_addr srcIp;
- struct in6_addr dstIp;
+ struct in6_addr src_ip;
+ struct in6_addr dst_ip;
uint32_t ifindex;
- __be16 srcPort;
- __be16 dstPortStart;
- __be16 dstPortEnd;
+ __be16 src_port;
+ __be16 dst_port_start;
+ __be16 dst_port_end;
uint8_t proto;
- uint8_t dscpVal;
- uint8_t presentFields;
+ uint8_t dscp_val;
+ uint8_t present_fields;
uint8_t pad[3];
} DscpPolicy;
STRUCT_SIZE(DscpPolicy, 2 * 16 + 4 + 3 * 2 + 3 * 1 + 3); // 48
typedef struct {
- struct in6_addr srcIp;
- struct in6_addr dstIp;
+ struct in6_addr src_ip;
+ struct in6_addr dst_ip;
__u32 ifindex;
- __be16 srcPort;
- __be16 dstPort;
+ __be16 src_port;
+ __be16 dst_port;
__u8 proto;
- __u8 dscpVal;
+ __u8 dscp_val;
__u8 pad[2];
} RuleEntry;
STRUCT_SIZE(RuleEntry, 2 * 16 + 1 * 4 + 2 * 2 + 2 * 1 + 2); // 44
\ No newline at end of file
diff --git a/framework-t/Android.bp b/framework-t/Android.bp
index 1e508a0..80477f1 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -103,7 +103,7 @@
// Do not add static_libs to this library: put them in framework-connectivity instead.
// The jarjar rules are only so that references to jarjared utils in
// framework-connectivity-pre-jarjar match at runtime.
- jarjar_rules: ":connectivity-jarjar-rules",
+ jarjar_rules: ":framework-connectivity-jarjar-rules",
permitted_packages: [
"android.app.usage",
"android.net",
@@ -116,6 +116,7 @@
"//packages/modules/Connectivity/Tethering/apex",
// In preparation for future move
"//packages/modules/Connectivity/apex",
+ "//packages/modules/Connectivity/service", // For R8 only
"//packages/modules/Connectivity/service-t",
"//packages/modules/Nearby/service",
"//frameworks/base",
diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp
index b30ee80..391a562 100644
--- a/framework-t/Sources.bp
+++ b/framework-t/Sources.bp
@@ -14,125 +14,13 @@
// limitations under the License.
//
-// NetworkStats related libraries.
-
-filegroup {
- name: "framework-connectivity-netstats-internal-sources",
- srcs: [
- "src/android/app/usage/*.java",
- "src/android/net/DataUsageRequest.*",
- "src/android/net/INetworkStatsService.aidl",
- "src/android/net/INetworkStatsSession.aidl",
- "src/android/net/NetworkIdentity.java",
- "src/android/net/NetworkIdentitySet.java",
- "src/android/net/NetworkStateSnapshot.*",
- "src/android/net/NetworkStats.*",
- "src/android/net/NetworkStatsAccess.*",
- "src/android/net/NetworkStatsCollection.*",
- "src/android/net/NetworkStatsHistory.*",
- "src/android/net/NetworkTemplate.*",
- "src/android/net/TrafficStats.java",
- "src/android/net/UnderlyingNetworkInfo.*",
- "src/android/net/netstats/**/*.*",
- ],
- path: "src",
- visibility: [
- "//visibility:private",
- ],
-}
-
-filegroup {
- name: "framework-connectivity-netstats-sources",
- srcs: [
- ":framework-connectivity-netstats-internal-sources",
- ],
- visibility: [
- "//visibility:private",
- ],
-}
-
-// Nsd related libraries.
-
-filegroup {
- name: "framework-connectivity-nsd-internal-sources",
- srcs: [
- "src/android/net/nsd/*.aidl",
- "src/android/net/nsd/*.java",
- ],
- path: "src",
- visibility: [
- "//visibility:private",
- ],
-}
-
-filegroup {
- name: "framework-connectivity-nsd-sources",
- srcs: [
- ":framework-connectivity-nsd-internal-sources",
- ],
- visibility: [
- "//visibility:private",
- ],
-}
-
-// IpSec related libraries.
-
-filegroup {
- name: "framework-connectivity-ipsec-sources",
- srcs: [
- "src/android/net/IIpSecService.aidl",
- "src/android/net/IpSec*.*",
- ],
- path: "src",
- visibility: [
- "//visibility:private",
- ],
-}
-
-// Ethernet related libraries.
-
-filegroup {
- name: "framework-connectivity-ethernet-sources",
- srcs: [
- "src/android/net/EthernetManager.java",
- "src/android/net/EthernetNetworkManagementException.java",
- "src/android/net/EthernetNetworkManagementException.aidl",
- "src/android/net/EthernetNetworkSpecifier.java",
- "src/android/net/EthernetNetworkUpdateRequest.java",
- "src/android/net/EthernetNetworkUpdateRequest.aidl",
- "src/android/net/IEthernetManager.aidl",
- "src/android/net/IEthernetServiceListener.aidl",
- "src/android/net/INetworkInterfaceOutcomeReceiver.aidl",
- "src/android/net/ITetheredInterfaceCallback.aidl",
- ],
- path: "src",
- visibility: [
- "//visibility:private",
- ],
-}
-
-// Connectivity-T common libraries.
-
-filegroup {
- name: "framework-connectivity-tiramisu-internal-sources",
- srcs: [
- "src/android/net/ConnectivityFrameworkInitializerTiramisu.java",
- ],
- path: "src",
- visibility: [
- "//visibility:private",
- ],
-}
-
filegroup {
name: "framework-connectivity-tiramisu-updatable-sources",
srcs: [
- ":framework-connectivity-ethernet-sources",
- ":framework-connectivity-ipsec-sources",
- ":framework-connectivity-netstats-sources",
- ":framework-connectivity-nsd-sources",
- ":framework-connectivity-tiramisu-internal-sources",
+ "src/**/*.java",
+ "src/**/*.aidl",
],
+ path: "src",
visibility: [
"//frameworks/base",
"//packages/modules/Connectivity:__subpackages__",
diff --git a/framework-t/src/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java
index 74fe4bd..26841de 100644
--- a/framework-t/src/android/app/usage/NetworkStats.java
+++ b/framework-t/src/android/app/usage/NetworkStats.java
@@ -1,17 +1,17 @@
/**
* Copyright (C) 2015 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
+ * 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
+ * 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.
+ * 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.app.usage;
@@ -36,11 +36,11 @@
import java.util.ArrayList;
/**
- * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
- * are returned as results to various queries in {@link NetworkStatsManager}.
+ * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats}
+ * objects are returned as results to various queries in {@link NetworkStatsManager}.
*/
public final class NetworkStats implements AutoCloseable {
- private final static String TAG = "NetworkStats";
+ private static final String TAG = "NetworkStats";
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -616,7 +616,7 @@
/**
* Steps to next uid in enumeration and collects history for that.
*/
- private void stepHistory(){
+ private void stepHistory() {
if (hasNextUid()) {
stepUid();
mHistory = null;
@@ -692,8 +692,8 @@
bucketOut.mMetered = Bucket.METERED_ALL;
bucketOut.mRoaming = Bucket.ROAMING_ALL;
bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
- bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
- mRecycledHistoryEntry.bucketDuration;
+ bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart
+ + mRecycledHistoryEntry.bucketDuration;
bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
index 0bb98f8..a655a9b 100644
--- a/framework-t/src/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -1041,7 +1041,7 @@
*/
public long getTotalPackets() {
long total = 0;
- for (int i = size-1; i >= 0; i--) {
+ for (int i = size - 1; i >= 0; i--) {
total += rxPackets[i] + txPackets[i];
}
return total;
diff --git a/framework/Android.bp b/framework/Android.bp
index 6350e14..fcce7a5 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -112,6 +112,7 @@
// because the tethering stubs depend on the connectivity stubs (e.g.,
// TetheringRequest depends on LinkAddress).
"framework-tethering.stubs.module_lib",
+ "framework-wifi.stubs.module_lib",
],
visibility: ["//packages/modules/Connectivity:__subpackages__"]
}
@@ -120,7 +121,7 @@
name: "framework-connectivity",
defaults: ["framework-connectivity-defaults"],
installable: true,
- jarjar_rules: ":connectivity-jarjar-rules",
+ jarjar_rules: ":framework-connectivity-jarjar-rules",
permitted_packages: ["android.net"],
impl_library_visibility: [
"//packages/modules/Connectivity/Tethering/apex",
@@ -211,3 +212,33 @@
"com.android.tethering",
],
}
+
+java_genrule {
+ name: "framework-connectivity-jarjar-rules",
+ tool_files: [
+ ":connectivity-hiddenapi-files",
+ ":framework-connectivity-pre-jarjar{.jar}",
+ ":framework-connectivity-t-pre-jarjar{.jar}",
+ ":framework-connectivity.stubs.module_lib{.jar}",
+ ":framework-connectivity-t.stubs.module_lib{.jar}",
+ "jarjar-excludes.txt",
+ ],
+ tools: [
+ "jarjar-rules-generator",
+ ],
+ out: ["framework_connectivity_jarjar_rules.txt"],
+ cmd: "$(location jarjar-rules-generator) " +
+ "--jars $(location :framework-connectivity-pre-jarjar{.jar}) " +
+ "$(location :framework-connectivity-t-pre-jarjar{.jar}) " +
+ "--prefix android.net.connectivity " +
+ "--apistubs $(location :framework-connectivity.stubs.module_lib{.jar}) " +
+ "$(location :framework-connectivity-t.stubs.module_lib{.jar}) " +
+ "--unsupportedapi $(locations :connectivity-hiddenapi-files) " +
+ "--excludes $(location jarjar-excludes.txt) " +
+ "--output $(out)",
+ visibility: [
+ "//packages/modules/Connectivity/framework:__subpackages__",
+ "//packages/modules/Connectivity/framework-t:__subpackages__",
+ "//packages/modules/Connectivity/service",
+ ],
+}
diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp
index 7478b3e..857ece5 100644
--- a/framework/jni/android_net_NetworkUtils.cpp
+++ b/framework/jni/android_net_NetworkUtils.cpp
@@ -232,7 +232,8 @@
return NULL;
}
- jclass class_TcpRepairWindow = env->FindClass("android/net/TcpRepairWindow");
+ jclass class_TcpRepairWindow = env->FindClass(
+ "android/net/connectivity/android/net/TcpRepairWindow");
jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "<init>", "(IIIIII)V");
return env->NewObject(class_TcpRepairWindow, ctor, trw.snd_wl1, trw.snd_wnd, trw.max_window,
@@ -253,7 +254,7 @@
{ "bindSocketToNetworkHandle", "(Ljava/io/FileDescriptor;J)I", (void*) android_net_utils_bindSocketToNetworkHandle },
{ "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter },
{ "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter },
- { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow },
+ { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/connectivity/android/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow },
{ "resNetworkSend", "(J[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
{ "resNetworkQuery", "(JLjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
diff --git a/framework/src/android/net/DnsResolverServiceManager.java b/framework/src/android/net/DnsResolverServiceManager.java
index 79009e8..e64d2ae 100644
--- a/framework/src/android/net/DnsResolverServiceManager.java
+++ b/framework/src/android/net/DnsResolverServiceManager.java
@@ -29,7 +29,7 @@
private final IBinder mResolver;
- DnsResolverServiceManager(IBinder resolver) {
+ public DnsResolverServiceManager(IBinder resolver) {
mResolver = resolver;
}
diff --git a/framework/src/android/net/ITestNetworkManager.aidl b/framework/src/android/net/ITestNetworkManager.aidl
index d18b931..9432acb 100644
--- a/framework/src/android/net/ITestNetworkManager.aidl
+++ b/framework/src/android/net/ITestNetworkManager.aidl
@@ -30,7 +30,8 @@
interface ITestNetworkManager
{
TestNetworkInterface createInterface(boolean isTun, boolean hasCarrier, boolean bringUp,
- in LinkAddress[] addrs, in @nullable String iface);
+ boolean disableIpv6ProvisioningDelay, in LinkAddress[] addrs,
+ in @nullable String iface);
void setCarrierEnabled(in TestNetworkInterface iface, boolean enabled);
diff --git a/framework/src/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java
index a15d165..56cc923 100644
--- a/framework/src/android/net/NattSocketKeepalive.java
+++ b/framework/src/android/net/NattSocketKeepalive.java
@@ -33,7 +33,7 @@
@NonNull private final InetAddress mDestination;
private final int mResourceId;
- NattSocketKeepalive(@NonNull IConnectivityManager service,
+ public NattSocketKeepalive(@NonNull IConnectivityManager service,
@NonNull Network network,
@NonNull ParcelFileDescriptor pfd,
int resourceId,
@@ -48,7 +48,7 @@
}
@Override
- void startImpl(int intervalSec) {
+ protected void startImpl(int intervalSec) {
mExecutor.execute(() -> {
try {
mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId,
@@ -62,7 +62,7 @@
}
@Override
- void stopImpl() {
+ protected void stopImpl() {
mExecutor.execute(() -> {
try {
if (mSlot != null) {
diff --git a/framework/src/android/net/QosCallbackConnection.java b/framework/src/android/net/QosCallbackConnection.java
index de0fc24..cfceddd 100644
--- a/framework/src/android/net/QosCallbackConnection.java
+++ b/framework/src/android/net/QosCallbackConnection.java
@@ -35,7 +35,7 @@
*
* @hide
*/
-class QosCallbackConnection extends android.net.IQosCallback.Stub {
+public class QosCallbackConnection extends android.net.IQosCallback.Stub {
@NonNull private final ConnectivityManager mConnectivityManager;
@Nullable private volatile QosCallback mCallback;
@@ -56,7 +56,7 @@
* {@link Executor} must run callback sequentially, otherwise the order of
* callbacks cannot be guaranteed.
*/
- QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager,
+ public QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager,
@NonNull final QosCallback callback,
@NonNull final Executor executor) {
mConnectivityManager = Objects.requireNonNull(connectivityManager,
@@ -142,7 +142,7 @@
* There are no synchronization guarantees on exactly when the callback will stop receiving
* messages.
*/
- void stopReceivingMessages() {
+ public void stopReceivingMessages() {
mCallback = null;
}
}
diff --git a/framework/src/android/net/QosCallbackException.java b/framework/src/android/net/QosCallbackException.java
index 72430d2..7de3dd1 100644
--- a/framework/src/android/net/QosCallbackException.java
+++ b/framework/src/android/net/QosCallbackException.java
@@ -88,7 +88,7 @@
* {@hide}
*/
@NonNull
- static QosCallbackException createException(@ExceptionType final int type) {
+ public static QosCallbackException createException(@ExceptionType final int type) {
switch (type) {
case EX_TYPE_FILTER_NETWORK_RELEASED:
return new QosCallbackException(new NetworkReleasedException());
diff --git a/framework/src/android/net/QosFilter.java b/framework/src/android/net/QosFilter.java
index b432644..01dc4bb 100644
--- a/framework/src/android/net/QosFilter.java
+++ b/framework/src/android/net/QosFilter.java
@@ -33,13 +33,15 @@
@SystemApi
public abstract class QosFilter {
- /**
- * The constructor is kept hidden from outside this package to ensure that all derived types
- * are known and properly handled when being passed to and from {@link NetworkAgent}.
- *
- * @hide
- */
- QosFilter() {
+ /** @hide */
+ protected QosFilter() {
+ // Ensure that all derived types are known, and known to be properly handled when being
+ // passed to and from NetworkAgent.
+ // For now the only known derived type is QosSocketFilter.
+ if (!(this instanceof QosSocketFilter)) {
+ throw new UnsupportedOperationException(
+ "Unsupported QosFilter type: " + this.getClass().getName());
+ }
}
/**
diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java
index 49ac22b..da9b356 100644
--- a/framework/src/android/net/QosSocketInfo.java
+++ b/framework/src/android/net/QosSocketInfo.java
@@ -73,9 +73,10 @@
* The parcel file descriptor wrapped around the socket's file descriptor.
*
* @return the parcel file descriptor of the socket
+ * @hide
*/
@NonNull
- ParcelFileDescriptor getParcelFileDescriptor() {
+ public ParcelFileDescriptor getParcelFileDescriptor() {
return mParcelFileDescriptor;
}
diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java
index f6cae72..57cf5e3 100644
--- a/framework/src/android/net/SocketKeepalive.java
+++ b/framework/src/android/net/SocketKeepalive.java
@@ -52,7 +52,8 @@
* request. If it does, it MUST support at least 3 concurrent keepalive slots.
*/
public abstract class SocketKeepalive implements AutoCloseable {
- static final String TAG = "SocketKeepalive";
+ /** @hide */
+ protected static final String TAG = "SocketKeepalive";
/**
* Success. It indicates there is no error.
@@ -215,15 +216,22 @@
}
}
- @NonNull final IConnectivityManager mService;
- @NonNull final Network mNetwork;
- @NonNull final ParcelFileDescriptor mPfd;
- @NonNull final Executor mExecutor;
- @NonNull final ISocketKeepaliveCallback mCallback;
+ /** @hide */
+ @NonNull protected final IConnectivityManager mService;
+ /** @hide */
+ @NonNull protected final Network mNetwork;
+ /** @hide */
+ @NonNull protected final ParcelFileDescriptor mPfd;
+ /** @hide */
+ @NonNull protected final Executor mExecutor;
+ /** @hide */
+ @NonNull protected final ISocketKeepaliveCallback mCallback;
// TODO: remove slot since mCallback could be used to identify which keepalive to stop.
- @Nullable Integer mSlot;
+ /** @hide */
+ @Nullable protected Integer mSlot;
- SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
+ /** @hide */
+ public SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
@NonNull ParcelFileDescriptor pfd,
@NonNull Executor executor, @NonNull Callback callback) {
mService = service;
@@ -303,7 +311,8 @@
startImpl(intervalSec);
}
- abstract void startImpl(int intervalSec);
+ /** @hide */
+ protected abstract void startImpl(int intervalSec);
/**
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
@@ -313,7 +322,8 @@
stopImpl();
}
- abstract void stopImpl();
+ /** @hide */
+ protected abstract void stopImpl();
/**
* Deactivate this {@link SocketKeepalive} and free allocated resources. The instance won't be
diff --git a/framework/src/android/net/TcpSocketKeepalive.java b/framework/src/android/net/TcpSocketKeepalive.java
index d89814d..7131784 100644
--- a/framework/src/android/net/TcpSocketKeepalive.java
+++ b/framework/src/android/net/TcpSocketKeepalive.java
@@ -24,9 +24,9 @@
import java.util.concurrent.Executor;
/** @hide */
-final class TcpSocketKeepalive extends SocketKeepalive {
+public final class TcpSocketKeepalive extends SocketKeepalive {
- TcpSocketKeepalive(@NonNull IConnectivityManager service,
+ public TcpSocketKeepalive(@NonNull IConnectivityManager service,
@NonNull Network network,
@NonNull ParcelFileDescriptor pfd,
@NonNull Executor executor,
@@ -50,7 +50,7 @@
* acknowledgement.
*/
@Override
- void startImpl(int intervalSec) {
+ protected void startImpl(int intervalSec) {
mExecutor.execute(() -> {
try {
mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback);
@@ -62,7 +62,7 @@
}
@Override
- void stopImpl() {
+ protected void stopImpl() {
mExecutor.execute(() -> {
try {
if (mSlot != null) {
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index 788834a..b64299f 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -59,6 +59,8 @@
private static final boolean TUN = true;
private static final boolean BRING_UP = true;
private static final boolean CARRIER_UP = true;
+ // sets disableIpv6ProvisioningDelay to false.
+ private static final boolean USE_IPV6_PROV_DELAY = false;
private static final LinkAddress[] NO_ADDRS = new LinkAddress[0];
/** @hide */
@@ -167,8 +169,8 @@
public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) {
try {
final LinkAddress[] arr = new LinkAddress[linkAddrs.size()];
- return mService.createInterface(TUN, CARRIER_UP, BRING_UP, linkAddrs.toArray(arr),
- null /* iface */);
+ return mService.createInterface(TUN, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
+ linkAddrs.toArray(arr), null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -186,7 +188,8 @@
@NonNull
public TestNetworkInterface createTapInterface() {
try {
- return mService.createInterface(TAP, CARRIER_UP, BRING_UP, NO_ADDRS, null /* iface */);
+ return mService.createInterface(TAP, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
+ NO_ADDRS, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -204,7 +207,8 @@
@NonNull
public TestNetworkInterface createTapInterface(@NonNull LinkAddress[] linkAddrs) {
try {
- return mService.createInterface(TAP, CARRIER_UP, BRING_UP, linkAddrs, null /* iface */);
+ return mService.createInterface(TAP, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
+ linkAddrs, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -223,7 +227,8 @@
@NonNull
public TestNetworkInterface createTapInterface(boolean bringUp) {
try {
- return mService.createInterface(TAP, CARRIER_UP, bringUp, NO_ADDRS, null /* iface */);
+ return mService.createInterface(TAP, CARRIER_UP, bringUp, USE_IPV6_PROV_DELAY,
+ NO_ADDRS, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -245,7 +250,8 @@
@NonNull
public TestNetworkInterface createTapInterface(boolean bringUp, @NonNull String iface) {
try {
- return mService.createInterface(TAP, CARRIER_UP, bringUp, NO_ADDRS, iface);
+ return mService.createInterface(TAP, CARRIER_UP, bringUp, USE_IPV6_PROV_DELAY,
+ NO_ADDRS, iface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -264,7 +270,49 @@
@NonNull
public TestNetworkInterface createTapInterface(boolean carrierUp, boolean bringUp) {
try {
- return mService.createInterface(TAP, carrierUp, bringUp, NO_ADDRS, null /* iface */);
+ return mService.createInterface(TAP, carrierUp, bringUp, USE_IPV6_PROV_DELAY, NO_ADDRS,
+ null /* iface */);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Create a tap interface for testing purposes.
+ *
+ * @param carrierUp whether the created interface has a carrier or not.
+ * @param bringUp whether to bring up the interface before returning it.
+ * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
+ @NonNull
+ public TestNetworkInterface createTapInterface(boolean carrierUp, boolean bringUp,
+ boolean disableIpv6ProvisioningDelay) {
+ try {
+ return mService.createInterface(TAP, carrierUp, bringUp, disableIpv6ProvisioningDelay,
+ NO_ADDRS, null /* iface */);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Create a tap interface for testing purposes.
+ *
+ * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay.
+ * @param linkAddrs an array of LinkAddresses to assign to the TAP interface
+ * @return A TestNetworkInterface representing the underlying TAP interface. Close the contained
+ * ParcelFileDescriptor to tear down the TAP interface.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
+ @NonNull
+ public TestNetworkInterface createTapInterface(boolean disableIpv6ProvisioningDelay,
+ @NonNull LinkAddress[] linkAddrs) {
+ try {
+ return mService.createInterface(TAP, CARRIER_UP, BRING_UP, disableIpv6ProvisioningDelay,
+ linkAddrs, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/nearby/OWNERS b/nearby/OWNERS
index 980c221..844ef06 100644
--- a/nearby/OWNERS
+++ b/nearby/OWNERS
@@ -1,4 +1,6 @@
+chenw@google.com
chunzhang@google.com
weiwa@google.com
weiwu@google.com
+xinhe@google.com
xlythe@google.com
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index 604afc3..e5bddf6 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -649,13 +649,12 @@
if (!up) { // was up, goes down
// retract network offer and stop IpClient.
unregisterNetworkOfferAndStop();
- // If only setting the interface down, send a callback to signal completion.
- EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null);
} else { // was down, goes up
// register network offer
registerNetworkOffer();
}
+ EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null);
return true;
}
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 91b3989..8032303 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -2810,7 +2810,7 @@
throw new IllegalStateException("invalid tethering stats " + e);
}
}
- } catch (IllegalStateException e) {
+ } catch (IllegalStateException | ServiceSpecificException e) {
Log.wtf(TAG, "problem reading network stats", e);
}
return stats;
diff --git a/service/Android.bp b/service/Android.bp
index 7a4fb33..7dcc888 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -225,12 +225,27 @@
// This library combines system server jars that have access to different bootclasspath jars.
// Lower SDK service jars must not depend on higher SDK jars as that would let them
// transitively depend on the wrong bootclasspath jars. Sources also cannot be added here as
- // they would transitively depend on bootclasspath jars that may not be available.
+ // they would depend on bootclasspath jars that may not be available.
static_libs: [
"service-connectivity-pre-jarjar",
"service-connectivity-tiramisu-pre-jarjar",
"service-nearby-pre-jarjar",
],
+ // The below libraries are not actually needed to build since no source is compiled
+ // (only combining prebuilt static_libs), but they are necessary so that R8 has the right
+ // references to optimize the code. Without these, there will be missing class warnings and
+ // code may be wrongly optimized.
+ // R8 runs after jarjar, so the framework-X libraries need to be the post-jarjar artifacts
+ // (.impl), if they are not just stubs, so that the name of jarjared classes match.
+ libs: [
+ "androidx.annotation_annotation",
+ "framework-annotations-lib",
+ "framework-connectivity.impl",
+ "framework-connectivity-t.impl",
+ "framework-tethering.stubs.module_lib",
+ "framework-wifi.stubs.module_lib",
+ "libprotobuf-java-nano",
+ ],
jarjar_rules: ":connectivity-jarjar-rules",
apex_available: [
"com.android.tethering",
@@ -261,9 +276,15 @@
installable: true,
}
-filegroup {
+genrule {
name: "connectivity-jarjar-rules",
- srcs: ["jarjar-rules.txt"],
+ defaults: ["jarjar-rules-combine-defaults"],
+ srcs: [
+ ":framework-connectivity-jarjar-rules",
+ ":service-connectivity-jarjar-gen",
+ ":service-nearby-jarjar-gen",
+ ],
+ out: ["connectivity-jarjar-rules.txt"],
visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
@@ -274,3 +295,41 @@
srcs: ["src/com/android/server/BpfNetMaps.java"],
visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
+
+java_genrule {
+ name: "service-connectivity-jarjar-gen",
+ tool_files: [
+ ":service-connectivity-pre-jarjar{.jar}",
+ ":service-connectivity-tiramisu-pre-jarjar{.jar}",
+ "jarjar-excludes.txt",
+ ],
+ tools: [
+ "jarjar-rules-generator",
+ ],
+ out: ["service_connectivity_jarjar_rules.txt"],
+ cmd: "$(location jarjar-rules-generator) " +
+ "--jars $(location :service-connectivity-pre-jarjar{.jar}) " +
+ "$(location :service-connectivity-tiramisu-pre-jarjar{.jar}) " +
+ "--prefix android.net.connectivity " +
+ "--excludes $(location jarjar-excludes.txt) " +
+ "--output $(out)",
+ visibility: ["//visibility:private"],
+}
+
+java_genrule {
+ name: "service-nearby-jarjar-gen",
+ tool_files: [
+ ":service-nearby-pre-jarjar{.jar}",
+ "jarjar-excludes.txt",
+ ],
+ tools: [
+ "jarjar-rules-generator",
+ ],
+ out: ["service_nearby_jarjar_rules.txt"],
+ cmd: "$(location jarjar-rules-generator) " +
+ "--jars $(location :service-nearby-pre-jarjar{.jar}) " +
+ "--prefix com.android.server.nearby " +
+ "--excludes $(location jarjar-excludes.txt) " +
+ "--output $(out)",
+ visibility: ["//visibility:private"],
+}
diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt
deleted file mode 100644
index 1ad75e3..0000000
--- a/service/jarjar-rules.txt
+++ /dev/null
@@ -1,123 +0,0 @@
-# Classes in framework-connectivity are restricted to the android.net package.
-# This cannot be changed because it is harcoded in ART in S.
-# Any missing jarjar rule for framework-connectivity would be caught by the
-# build as an unexpected class outside of the android.net package.
-rule com.android.net.module.util.** android.net.connectivity.@0
-rule com.android.modules.utils.** android.net.connectivity.@0
-rule android.net.NetworkFactory* android.net.connectivity.@0
-
-# From modules-utils-preconditions
-rule com.android.internal.util.Preconditions* android.net.connectivity.@0
-
-# From framework-connectivity-shared-srcs
-rule android.util.LocalLog* android.net.connectivity.@0
-rule android.util.IndentingPrintWriter* android.net.connectivity.@0
-rule com.android.internal.util.IndentingPrintWriter* android.net.connectivity.@0
-rule com.android.internal.util.MessageUtils* android.net.connectivity.@0
-rule com.android.internal.util.WakeupMessage* android.net.connectivity.@0
-rule com.android.internal.util.FileRotator* android.net.connectivity.@0
-rule com.android.internal.util.ProcFileReader* android.net.connectivity.@0
-
-# From framework-connectivity-protos
-rule com.google.protobuf.** android.net.connectivity.@0
-rule android.service.** android.net.connectivity.@0
-
-rule android.sysprop.** com.android.connectivity.@0
-
-rule com.android.internal.messages.** com.android.connectivity.@0
-
-# From dnsresolver_aidl_interface (newer AIDLs should go to android.net.resolv.aidl)
-rule android.net.resolv.aidl.** com.android.connectivity.@0
-rule android.net.IDnsResolver* com.android.connectivity.@0
-rule android.net.ResolverHostsParcel* com.android.connectivity.@0
-rule android.net.ResolverOptionsParcel* com.android.connectivity.@0
-rule android.net.ResolverParamsParcel* com.android.connectivity.@0
-rule android.net.ResolverParamsParcel* com.android.connectivity.@0
-# Also includes netd event listener AIDL, but this is handled by netd-client rules
-
-# From netd-client (newer AIDLs should go to android.net.netd.aidl)
-rule android.net.netd.aidl.** com.android.connectivity.@0
-# Avoid including android.net.INetdEventCallback, used in tests but not part of the module
-rule android.net.INetd com.android.connectivity.@0
-rule android.net.INetd$* com.android.connectivity.@0
-rule android.net.INetdUnsolicitedEventListener* com.android.connectivity.@0
-rule android.net.InterfaceConfigurationParcel* com.android.connectivity.@0
-rule android.net.MarkMaskParcel* com.android.connectivity.@0
-rule android.net.NativeNetworkConfig* com.android.connectivity.@0
-rule android.net.NativeNetworkType* com.android.connectivity.@0
-rule android.net.NativeVpnType* com.android.connectivity.@0
-rule android.net.RouteInfoParcel* com.android.connectivity.@0
-rule android.net.TetherConfigParcel* com.android.connectivity.@0
-rule android.net.TetherOffloadRuleParcel* com.android.connectivity.@0
-rule android.net.TetherStatsParcel* com.android.connectivity.@0
-rule android.net.UidRangeParcel* com.android.connectivity.@0
-rule android.net.metrics.INetdEventListener* com.android.connectivity.@0
-
-# From netlink-client
-rule android.net.netlink.** com.android.connectivity.@0
-
-# From networkstack-client (newer AIDLs should go to android.net.[networkstack|ipmemorystore].aidl)
-rule android.net.networkstack.aidl.** com.android.connectivity.@0
-rule android.net.ipmemorystore.aidl.** com.android.connectivity.@0
-rule android.net.ipmemorystore.aidl.** com.android.connectivity.@0
-rule android.net.DataStallReportParcelable* com.android.connectivity.@0
-rule android.net.DhcpResultsParcelable* com.android.connectivity.@0
-rule android.net.IIpMemoryStore* com.android.connectivity.@0
-rule android.net.INetworkMonitor* com.android.connectivity.@0
-rule android.net.INetworkStackConnector* com.android.connectivity.@0
-rule android.net.INetworkStackStatusCallback* com.android.connectivity.@0
-rule android.net.InformationElementParcelable* com.android.connectivity.@0
-rule android.net.InitialConfigurationParcelable* com.android.connectivity.@0
-rule android.net.IpMemoryStore* com.android.connectivity.@0
-rule android.net.Layer2InformationParcelable* com.android.connectivity.@0
-rule android.net.Layer2PacketParcelable* com.android.connectivity.@0
-rule android.net.NattKeepalivePacketDataParcelable* com.android.connectivity.@0
-rule android.net.NetworkMonitorManager* com.android.connectivity.@0
-rule android.net.NetworkTestResultParcelable* com.android.connectivity.@0
-rule android.net.PrivateDnsConfigParcel* com.android.connectivity.@0
-rule android.net.ProvisioningConfigurationParcelable* com.android.connectivity.@0
-rule android.net.ScanResultInfoParcelable* com.android.connectivity.@0
-rule android.net.TcpKeepalivePacketDataParcelable* com.android.connectivity.@0
-rule android.net.dhcp.DhcpLeaseParcelable* com.android.connectivity.@0
-rule android.net.dhcp.DhcpServingParamsParcel* com.android.connectivity.@0
-rule android.net.dhcp.IDhcpEventCallbacks* com.android.connectivity.@0
-rule android.net.dhcp.IDhcpServer* com.android.connectivity.@0
-rule android.net.ip.IIpClient* com.android.connectivity.@0
-rule android.net.ip.IpClientCallbacks* com.android.connectivity.@0
-rule android.net.ip.IpClientManager* com.android.connectivity.@0
-rule android.net.ip.IpClientUtil* com.android.connectivity.@0
-rule android.net.ipmemorystore.** com.android.connectivity.@0
-rule android.net.networkstack.** com.android.connectivity.@0
-rule android.net.shared.** com.android.connectivity.@0
-rule android.net.util.KeepalivePacketDataUtil* com.android.connectivity.@0
-
-# From connectivity-module-utils
-rule android.net.shared.** com.android.connectivity.@0
-
-# From services-connectivity-shared-srcs
-rule android.net.util.NetworkConstants* com.android.connectivity.@0
-
-# From modules-utils-statemachine
-rule com.android.internal.util.IState* com.android.connectivity.@0
-rule com.android.internal.util.State* com.android.connectivity.@0
-
-# From the API shims
-rule com.android.networkstack.apishim.** com.android.connectivity.@0
-
-# From filegroup framework-connectivity-protos
-rule android.service.*Proto com.android.connectivity.@0
-
-# From mdns-aidl-interface
-rule android.net.mdns.aidl.** android.net.connectivity.@0
-
-# From nearby-service, including proto
-rule service.proto.** com.android.server.nearby.@0
-rule androidx.annotation.Keep* com.android.server.nearby.@0
-rule androidx.collection.** com.android.server.nearby.@0
-rule androidx.core.** com.android.server.nearby.@0
-rule androidx.versionedparcelable.** com.android.server.nearby.@0
-rule com.google.common.** com.android.server.nearby.@0
-rule android.support.v4.** com.android.server.nearby.@0
-
-# Remaining are connectivity sources in com.android.server and com.android.server.connectivity:
-# TODO: move to a subpackage of com.android.connectivity (such as com.android.connectivity.server)
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
index 9c7a761..a1d0310 100644
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ b/service/jni/com_android_server_TestNetworkService.cpp
@@ -76,27 +76,47 @@
setTunTapCarrierEnabledImpl(env, iface, tun.get(), hasCarrier);
}
- // Activate interface using an unconnected datagram socket.
- base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
- ifr.ifr_flags = IFF_UP;
// Mark TAP interfaces as supporting multicast
- if (!isTun) ifr.ifr_flags |= IFF_MULTICAST;
+ if (!isTun) {
+ base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+ ifr.ifr_flags = IFF_MULTICAST;
- if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
- throwException(env, errno, "activating", ifr.ifr_name);
- return -1;
+ if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+ throwException(env, errno, "set IFF_MULTICAST", ifr.ifr_name);
+ return -1;
+ }
}
return tun.release();
}
+static void bringUpInterfaceImpl(JNIEnv* env, const char* iface) {
+ // Activate interface using an unconnected datagram socket.
+ base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+
+ ifreq ifr{};
+ strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
+ if (ioctl(inet6CtrlSock.get(), SIOCGIFFLAGS, &ifr)) {
+ throwException(env, errno, "read flags", iface);
+ return;
+ }
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+ throwException(env, errno, "set IFF_UP", iface);
+ return;
+ }
+}
+
//------------------------------------------------------------------------------
+
+
static void setTunTapCarrierEnabled(JNIEnv* env, jclass /* clazz */, jstring
jIface, jint tunFd, jboolean enabled) {
ScopedUtfChars iface(env, jIface);
if (!iface.c_str()) {
jniThrowNullPointerException(env, "iface");
+ return;
}
setTunTapCarrierEnabledImpl(env, iface.c_str(), tunFd, enabled);
}
@@ -112,11 +132,21 @@
return createTunTapImpl(env, isTun, hasCarrier, iface.c_str());
}
+static void bringUpInterface(JNIEnv* env, jclass /* clazz */, jstring jIface) {
+ ScopedUtfChars iface(env, jIface);
+ if (!iface.c_str()) {
+ jniThrowNullPointerException(env, "iface");
+ return;
+ }
+ bringUpInterfaceImpl(env, iface.c_str());
+}
+
//------------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
{"nativeSetTunTapCarrierEnabled", "(Ljava/lang/String;IZ)V", (void*)setTunTapCarrierEnabled},
{"nativeCreateTunTap", "(ZZLjava/lang/String;)I", (void*)createTunTap},
+ {"nativeBringUpInterface", "(Ljava/lang/String;)V", (void*)bringUpInterface},
};
int register_com_android_server_TestNetworkService(JNIEnv* env) {
diff --git a/service/proguard.flags b/service/proguard.flags
index cffa490..f546e82 100644
--- a/service/proguard.flags
+++ b/service/proguard.flags
@@ -2,8 +2,6 @@
# TODO: instead of keeping everything, consider listing only "entry points"
# (service loader, JNI registered methods, etc) and letting the optimizer do its job
-keep class android.net.** { *; }
--keep class com.android.connectivity.** { *; }
--keep class com.android.net.** { *; }
-keep class !com.android.server.nearby.**,com.android.server.** { *; }
# Prevent proguard from stripping out any nearby-service and fast-pair-lite-protos fields.
@@ -13,5 +11,5 @@
# the schema, keep all the fields.
# This replicates the base proguard rule used by the build by default
# (proguard_basic_keeps.flags), but needs to be specified here because the
-# com.google.protobuf package is jarjared to the below package.
--keepclassmembers class * extends android.net.connectivity.com.google.protobuf.MessageLite { <fields>; }
+# com.google.protobuf package is jarjared to use a package prefix.
+-keepclassmembers class * extends **.com.google.protobuf.MessageLite { <fields>; }
diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java
index 1209579..15d9f13 100644
--- a/service/src/com/android/server/TestNetworkService.java
+++ b/service/src/com/android/server/TestNetworkService.java
@@ -47,7 +47,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.NetworkStackConstants;
import java.io.IOException;
@@ -83,6 +82,8 @@
private static native void nativeSetTunTapCarrierEnabled(@NonNull String iface, int tunFd,
boolean enabled);
+ private static native void nativeBringUpInterface(String iface);
+
@VisibleForTesting
protected TestNetworkService(@NonNull Context context) {
mHandlerThread = new HandlerThread("TestNetworkServiceThread");
@@ -120,7 +121,7 @@
*/
@Override
public TestNetworkInterface createInterface(boolean isTun, boolean hasCarrier, boolean bringUp,
- LinkAddress[] linkAddrs, @Nullable String iface) {
+ boolean disableIpv6ProvisioningDelay, LinkAddress[] linkAddrs, @Nullable String iface) {
enforceTestNetworkPermissions(mContext);
Objects.requireNonNull(linkAddrs, "missing linkAddrs");
@@ -137,6 +138,14 @@
try {
ParcelFileDescriptor tunIntf = ParcelFileDescriptor.adoptFd(
nativeCreateTunTap(isTun, hasCarrier, interfaceName));
+
+ // Disable DAD and remove router_solicitation_delay before assigning link addresses.
+ if (disableIpv6ProvisioningDelay) {
+ mNetd.setProcSysNet(
+ INetd.IPV6, INetd.CONF, interfaceName, "router_solicitation_delay", "0");
+ mNetd.setProcSysNet(INetd.IPV6, INetd.CONF, interfaceName, "dad_transmits", "0");
+ }
+
for (LinkAddress addr : linkAddrs) {
mNetd.interfaceAddAddress(
interfaceName,
@@ -145,7 +154,7 @@
}
if (bringUp) {
- NetdUtils.setInterfaceUp(mNetd, interfaceName);
+ nativeBringUpInterface(interfaceName);
}
return new TestNetworkInterface(tunIntf, interfaceName);
diff --git a/service/src/com/android/server/connectivity/DscpPolicyTracker.java b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
index 7829d1a..8cb3213 100644
--- a/service/src/com/android/server/connectivity/DscpPolicyTracker.java
+++ b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
@@ -52,12 +52,12 @@
private static final String TAG = DscpPolicyTracker.class.getSimpleName();
private static final String PROG_PATH =
- "/sys/fs/bpf/net_shared/prog_dscp_policy_schedcls_set_dscp";
+ "/sys/fs/bpf/net_shared/prog_dscpPolicy_schedcls_set_dscp_ether";
// Name is "map + *.o + map_name + map". Can probably shorten this
private static final String IPV4_POLICY_MAP_PATH = makeMapPath(
- "dscp_policy_ipv4_dscp_policies");
+ "dscpPolicy_ipv4_dscp_policies");
private static final String IPV6_POLICY_MAP_PATH = makeMapPath(
- "dscp_policy_ipv6_dscp_policies");
+ "dscpPolicy_ipv6_dscp_policies");
private static final int MAX_POLICIES = 16;
private static String makeMapPath(String which) {
@@ -212,8 +212,17 @@
return DSCP_POLICY_STATUS_SUCCESS;
}
+ private boolean isEthernet(String iface) {
+ try {
+ return TcUtils.isEthernet(iface);
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to check ether type", e);
+ }
+ return false;
+ }
+
/**
- * Add the provided DSCP policy to the bpf map. Attach bpf program dscp_policy to iface
+ * Add the provided DSCP policy to the bpf map. Attach bpf program dscpPolicy to iface
* if not already attached. Response will be sent back to nai with status.
*
* DSCP_POLICY_STATUS_SUCCESS - if policy was added successfully
@@ -221,13 +230,17 @@
* DSCP_POLICY_STATUS_REQUEST_DECLINED - Interface index was invalid
*/
public void addDscpPolicy(NetworkAgentInfo nai, DscpPolicy policy) {
- if (!mAttachedIfaces.contains(nai.linkProperties.getInterfaceName())) {
- if (!attachProgram(nai.linkProperties.getInterfaceName())) {
- Log.e(TAG, "Unable to attach program");
- sendStatus(nai, policy.getPolicyId(),
- DSCP_POLICY_STATUS_INSUFFICIENT_PROCESSING_RESOURCES);
- return;
- }
+ String iface = nai.linkProperties.getInterfaceName();
+ if (!isEthernet(iface)) {
+ Log.e(TAG, "DSCP policies are not supported on raw IP interfaces.");
+ sendStatus(nai, policy.getPolicyId(), DSCP_POLICY_STATUS_REQUEST_DECLINED);
+ return;
+ }
+ if (!mAttachedIfaces.contains(iface) && !attachProgram(iface)) {
+ Log.e(TAG, "Unable to attach program");
+ sendStatus(nai, policy.getPolicyId(),
+ DSCP_POLICY_STATUS_INSUFFICIENT_PROCESSING_RESOURCES);
+ return;
}
final int ifIndex = getIfaceIndex(nai);
@@ -314,10 +327,8 @@
private boolean attachProgram(@NonNull String iface) {
try {
NetworkInterface netIface = NetworkInterface.getByName(iface);
- boolean isEth = TcUtils.isEthernet(iface);
- String path = PROG_PATH + (isEth ? "_ether" : "_raw_ip");
TcUtils.tcFilterAddDevBpf(netIface.getIndex(), false, PRIO_DSCP, (short) ETH_P_ALL,
- path);
+ PROG_PATH);
} catch (IOException e) {
Log.e(TAG, "Unable to attach to TC on " + iface + ": " + e);
return false;
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index 58731e0..5c9cc63 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -21,9 +21,22 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+// The target SDK version of the "latest released SDK" CTS tests.
+// This should be updated soon after a new SDK level is finalized.
+// It is different from the target SDK version of production code (e.g., the Tethering,
+// NetworkStack, and CaptivePortalLogin APKs):
+// - The target SDK of production code influences the behaviour of the production code.
+// - The target SDK of the CTS tests validates the behaviour seen by apps that call production APIs.
+// - The behaviour seen by apps that target previous SDKs is tested by previous CTS versions
+// (currently, CTS 10, 11, and 12).
+java_defaults {
+ name: "ConnectivityTestsLatestSdkDefaults",
+ target_sdk_version: "33",
+}
+
java_library {
name: "FrameworksNetCommonTests",
- defaults: ["framework-connectivity-test-defaults"],
+ defaults: ["framework-connectivity-internal-test-defaults"],
srcs: [
"java/**/*.java",
"java/**/*.kt",
@@ -49,6 +62,7 @@
// jarjar stops at the first matching rule, so order of concatenation affects the output.
genrule {
name: "ConnectivityCoverageJarJarRules",
+ defaults: ["jarjar-rules-combine-defaults"],
srcs: [
"tethering-jni-jarjar-rules.txt",
":connectivity-jarjar-rules",
@@ -56,8 +70,6 @@
":NetworkStackJarJarRules",
],
out: ["jarjar-rules-connectivity-coverage.txt"],
- // Concat files with a line break in the middle
- cmd: "for src in $(in); do cat $${src}; echo; done > $(out)",
visibility: ["//visibility:private"],
}
@@ -81,10 +93,10 @@
name: "ConnectivityCoverageTests",
// Tethering started on SDK 30
min_sdk_version: "30",
- target_sdk_version: "31",
test_suites: ["general-tests", "mts-tethering"],
defaults: [
- "framework-connectivity-test-defaults",
+ "ConnectivityTestsLatestSdkDefaults",
+ "framework-connectivity-internal-test-defaults",
"FrameworksNetTests-jni-defaults",
"libnetworkstackutilsjni_deps",
],
diff --git a/tests/common/java/android/net/LinkPropertiesTest.java b/tests/common/java/android/net/LinkPropertiesTest.java
index 9506fc9..5ee375f 100644
--- a/tests/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/common/java/android/net/LinkPropertiesTest.java
@@ -36,10 +36,10 @@
import android.system.OsConstants;
import android.util.ArraySet;
-import androidx.core.os.BuildCompat;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.testutils.ConnectivityModuleTest;
import com.android.testutils.DevSdkIgnoreRule;
@@ -114,11 +114,6 @@
return InetAddresses.parseNumericAddress(addrString);
}
- private static boolean isAtLeastR() {
- // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R)
- return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR();
- }
-
private void checkEmpty(final LinkProperties lp) {
assertEquals(0, lp.getAllInterfaceNames().size());
assertEquals(0, lp.getAllAddresses().size());
@@ -139,7 +134,7 @@
assertFalse(lp.isIpv6Provisioned());
assertFalse(lp.isPrivateDnsActive());
- if (isAtLeastR()) {
+ if (SdkLevel.isAtLeastR()) {
assertNull(lp.getDhcpServerAddress());
assertFalse(lp.isWakeOnLanSupported());
assertNull(lp.getCaptivePortalApiUrl());
@@ -166,7 +161,7 @@
lp.setMtu(MTU);
lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
- if (isAtLeastR()) {
+ if (SdkLevel.isAtLeastR()) {
lp.setDhcpServerAddress(DHCPSERVER);
lp.setWakeOnLanSupported(true);
lp.setCaptivePortalApiUrl(CAPPORT_API_URL);
@@ -210,7 +205,7 @@
assertTrue(source.isIdenticalTcpBufferSizes(target));
assertTrue(target.isIdenticalTcpBufferSizes(source));
- if (isAtLeastR()) {
+ if (SdkLevel.isAtLeastR()) {
assertTrue(source.isIdenticalDhcpServerAddress(target));
assertTrue(source.isIdenticalDhcpServerAddress(source));
@@ -1295,56 +1290,73 @@
assertEquals(2, lp.getRoutes().size());
}
- @Test @IgnoreUpTo(Build.VERSION_CODES.R)
- @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
- @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
- public void testExcludedRoutesEnabled() {
+ private void assertExcludeRoutesVisible() {
final LinkProperties lp = new LinkProperties();
assertEquals(0, lp.getRoutes().size());
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV4, 0), RTN_UNREACHABLE));
+ lp.addRoute(new RouteInfo(new IpPrefix(ADDRV4, 31), RTN_UNREACHABLE));
assertEquals(1, lp.getRoutes().size());
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 0), RTN_THROW));
+ lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 127), RTN_THROW));
assertEquals(2, lp.getRoutes().size());
lp.addRoute(new RouteInfo(GATEWAY1));
assertEquals(3, lp.getRoutes().size());
+
+ lp.addRoute(new RouteInfo(new IpPrefix(DNS6, 127), RTN_UNICAST));
+ assertEquals(4, lp.getRoutes().size());
}
- @Test @IgnoreUpTo(Build.VERSION_CODES.R) @IgnoreAfter(Build.VERSION_CODES.S_V2)
- @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
- @DisableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
- public void testExcludedRoutesDisabled_S() {
+ private void assertExcludeRoutesNotVisible() {
final LinkProperties lp = new LinkProperties();
assertEquals(0, lp.getRoutes().size());
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV4, 0), RTN_UNREACHABLE));
+ lp.addRoute(new RouteInfo(new IpPrefix(ADDRV4, 31), RTN_UNREACHABLE));
+ assertEquals(0, lp.getRoutes().size());
+
+ lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 127), RTN_THROW));
+ assertEquals(0, lp.getRoutes().size());
+
+ lp.addRoute(new RouteInfo(GATEWAY1));
assertEquals(1, lp.getRoutes().size());
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 5), RTN_THROW));
- // RTN_THROW routes are visible on S when added by the caller (but they are not added by
- // the system). This is uncommon usage but was tested by CTSv12.
+ lp.addRoute(new RouteInfo(new IpPrefix(DNS6, 127), RTN_UNICAST));
assertEquals(2, lp.getRoutes().size());
-
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 2), RTN_UNICAST));
- assertEquals(3, lp.getRoutes().size());
}
- @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ private void checkExcludeRoutesNotVisibleAfterS() {
+ if (!SdkLevel.isAtLeastT()) {
+ // RTN_THROW routes are visible on R and S when added by the caller (but they are not
+ // added by the system except for legacy VPN).
+ // This is uncommon usage but was tested by CTSr12.
+ assertExcludeRoutesVisible();
+ } else {
+ assertExcludeRoutesNotVisible();
+ }
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ @CtsNetTestCasesMaxTargetSdk31(reason = "Testing behaviour for target SDK 31")
+ public void testExcludedRoutesNotVisibleOnTargetSdk31() {
+ checkExcludeRoutesNotVisibleAfterS();
+ }
+
+ @Test
+ public void testExcludedRoutesVisibleOnTargetSdk33AndAbove() {
+ assertExcludeRoutesVisible();
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ @CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
+ @EnableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
+ public void testExcludedRoutesEnabledByCompatChange() {
+ assertExcludeRoutesVisible();
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
@CtsNetTestCasesMaxTargetSdk31(reason = "Compat change cannot be overridden when targeting T+")
@DisableCompatChanges({LinkProperties.EXCLUDED_ROUTES})
- public void testExcludedRoutesDisabled() {
- final LinkProperties lp = new LinkProperties();
- assertEquals(0, lp.getRoutes().size());
-
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV4, 0), RTN_UNREACHABLE));
- assertEquals(0, lp.getRoutes().size());
-
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 5), RTN_THROW));
- assertEquals(0, lp.getRoutes().size());
-
- lp.addRoute(new RouteInfo(new IpPrefix(ADDRV6, 2), RTN_UNICAST));
- assertEquals(1, lp.getRoutes().size());
+ public void testExcludedRoutesDisabledByCompatChange() {
+ checkExcludeRoutesNotVisibleAfterS();
}
}
diff --git a/tests/common/java/android/net/NetworkProviderTest.kt b/tests/common/java/android/net/NetworkProviderTest.kt
index 3ceacf8..c0e7f61 100644
--- a/tests/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/common/java/android/net/NetworkProviderTest.kt
@@ -30,6 +30,7 @@
import android.os.Looper
import android.util.Log
import androidx.test.InstrumentationRegistry
+import com.android.modules.utils.build.SdkLevel.isAtLeastS
import com.android.net.module.util.ArrayTrackRecord
import com.android.testutils.CompatUtil
import com.android.testutils.ConnectivityModuleTest
@@ -38,7 +39,6 @@
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkOfferCallback
-import com.android.testutils.isDevSdkInRange
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -376,7 +376,7 @@
doReturn(mCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE)
val provider = createNetworkProvider(mockContext)
// ConnectivityManager not required at creation time after R
- if (!isDevSdkInRange(0, Build.VERSION_CODES.R)) {
+ if (isAtLeastS()) {
verifyNoMoreInteractions(mockContext)
}
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index ac84e57..47ea53e 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -26,7 +26,6 @@
"tradefed",
],
static_libs: [
- "CompatChangeGatingTestBase",
"modules-utils-build-testing",
],
// Tag this module as a cts test artifact
@@ -38,8 +37,6 @@
data: [
":CtsHostsideNetworkTestsApp",
":CtsHostsideNetworkTestsApp2",
- ":CtsHostsideNetworkTestsApp3",
- ":CtsHostsideNetworkTestsApp3PreT",
":CtsHostsideNetworkTestsAppNext",
],
per_testcase_directory: true,
diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl
index 68176ad..6986e7e 100644
--- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl
+++ b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl
@@ -20,6 +20,7 @@
interface IRemoteSocketFactory {
ParcelFileDescriptor openSocketFd(String host, int port, int timeoutMs);
+ ParcelFileDescriptor openDatagramSocketFd();
String getPackageName();
int getUid();
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java
index 80f99b6..01fbd66 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java
@@ -83,9 +83,19 @@
public FileDescriptor openSocketFd(String host, int port, int timeoutMs)
throws RemoteException, ErrnoException, IOException {
// Dup the filedescriptor so ParcelFileDescriptor's finalizer doesn't garbage collect it
- // and cause our fd to become invalid. http://b/35927643 .
- ParcelFileDescriptor pfd = mService.openSocketFd(host, port, timeoutMs);
- FileDescriptor fd = Os.dup(pfd.getFileDescriptor());
+ // and cause fd to become invalid. http://b/35927643.
+ final ParcelFileDescriptor pfd = mService.openSocketFd(host, port, timeoutMs);
+ final FileDescriptor fd = Os.dup(pfd.getFileDescriptor());
+ pfd.close();
+ return fd;
+ }
+
+ public FileDescriptor openDatagramSocketFd()
+ throws RemoteException, ErrnoException, IOException {
+ // Dup the filedescriptor so ParcelFileDescriptor's finalizer doesn't garbage collect it
+ // and cause fd to become invalid. http://b/35927643.
+ final ParcelFileDescriptor pfd = mService.openDatagramSocketFd();
+ final FileDescriptor fd = Os.dup(pfd.getFileDescriptor());
pfd.close();
return fd;
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index dd8b523..5f032be 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -16,6 +16,7 @@
package com.android.cts.net.hostside;
+import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.content.pm.PackageManager.FEATURE_WIFI;
@@ -35,6 +36,8 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
+import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
@@ -59,12 +62,15 @@
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Proxy;
import android.net.ProxyInfo;
+import android.net.TestNetworkInterface;
+import android.net.TestNetworkManager;
import android.net.TransportInfo;
import android.net.Uri;
import android.net.VpnManager;
@@ -72,6 +78,7 @@
import android.net.VpnTransportInfo;
import android.net.cts.util.CtsNetUtils;
import android.net.wifi.WifiManager;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
@@ -90,11 +97,13 @@
import android.test.MoreAsserts;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Range;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.PacketBuilder;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.RecorderCallback;
@@ -113,12 +122,14 @@
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
+import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -164,6 +175,12 @@
private static final String PRIVATE_DNS_SPECIFIER_SETTING = "private_dns_specifier";
private static final int NETWORK_CALLBACK_TIMEOUT_MS = 30_000;
+ private static final LinkAddress TEST_IP4_DST_ADDR = new LinkAddress("198.51.100.1/24");
+ private static final LinkAddress TEST_IP4_SRC_ADDR = new LinkAddress("198.51.100.2/24");
+ private static final LinkAddress TEST_IP6_DST_ADDR = new LinkAddress("2001:db8:1:3::1/64");
+ private static final LinkAddress TEST_IP6_SRC_ADDR = new LinkAddress("2001:db8:1:3::2/64");
+ private static final short TEST_SRC_PORT = 5555;
+
public static String TAG = "VpnTest";
public static int TIMEOUT_MS = 3 * 1000;
public static int SOCKET_TIMEOUT_MS = 100;
@@ -1572,4 +1589,180 @@
return future.get(timeout, unit);
}
}
+
+ private static final boolean EXPECT_PASS = false;
+ private static final boolean EXPECT_BLOCK = true;
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testBlockIncomingPackets() throws Exception {
+ assumeTrue(supportedHardware());
+ final Network network = mCM.getActiveNetwork();
+ assertNotNull("Requires a working Internet connection", network);
+
+ final int remoteUid = mRemoteSocketFactoryClient.getUid();
+ final List<Range<Integer>> lockdownRange = List.of(new Range<>(remoteUid, remoteUid));
+ final DetailedBlockedStatusCallback remoteUidCallback = new DetailedBlockedStatusCallback();
+
+ // Create a TUN interface
+ final FileDescriptor tunFd = runWithShellPermissionIdentity(() -> {
+ final TestNetworkManager tnm = getInstrumentation().getContext().getSystemService(
+ TestNetworkManager.class);
+ final TestNetworkInterface iface = tnm.createTunInterface(List.of(
+ TEST_IP4_DST_ADDR, TEST_IP6_DST_ADDR));
+ return iface.getFileDescriptor().getFileDescriptor();
+ }, MANAGE_TEST_NETWORKS);
+
+ // Create a remote UDP socket
+ final FileDescriptor remoteUdpFd = mRemoteSocketFactoryClient.openDatagramSocketFd();
+
+ testAndCleanup(() -> {
+ runWithShellPermissionIdentity(() -> {
+ mCM.registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback,
+ new Handler(Looper.getMainLooper()));
+ }, NETWORK_SETTINGS);
+ remoteUidCallback.expectAvailableCallbacks(network);
+
+ // The remote UDP socket can receive packets coming from the TUN interface
+ checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_PASS);
+
+ // Lockdown uid that has the remote UDP socket
+ runWithShellPermissionIdentity(() -> {
+ mCM.setRequireVpnForUids(true /* requireVpn */, lockdownRange);
+ }, NETWORK_SETTINGS);
+
+ // setRequireVpnForUids setup a lockdown rule asynchronously. So it needs to wait for
+ // BlockedStatusCallback to be fired before checking the blocking status of incoming
+ // packets.
+ remoteUidCallback.expectBlockedStatusCallback(network, BLOCKED_REASON_LOCKDOWN_VPN);
+
+ if (SdkLevel.isAtLeastT()) {
+ // On T and above, lockdown rule drop packets not coming from lo regardless of the
+ // VPN connectivity.
+ checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_BLOCK);
+ }
+
+ // Start the VPN that has default routes. This VPN should have interface filtering rule
+ // for incoming packet and drop packets not coming from lo nor the VPN interface.
+ final String allowedApps =
+ mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
+ startVpn(new String[]{"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[]{"0.0.0.0/0", "::/0"}, allowedApps, "" /* disallowedApplications */,
+ null /* proxyInfo */, null /* underlyingNetworks */,
+ false /* isAlwaysMetered */);
+
+ checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_BLOCK);
+ }, /* cleanup */ () -> {
+ mCM.unregisterNetworkCallback(remoteUidCallback);
+ }, /* cleanup */ () -> {
+ Os.close(tunFd);
+ }, /* cleanup */ () -> {
+ Os.close(remoteUdpFd);
+ }, /* cleanup */ () -> {
+ runWithShellPermissionIdentity(() -> {
+ mCM.setRequireVpnForUids(false /* requireVpn */, lockdownRange);
+ }, NETWORK_SETTINGS);
+ });
+ }
+
+ private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr,
+ final short dstPort, final short srcPort, final byte[] payload) throws IOException {
+
+ final ByteBuffer buffer = PacketBuilder.allocate(false /* hasEther */,
+ OsConstants.IPPROTO_IP, OsConstants.IPPROTO_UDP, payload.length);
+ final PacketBuilder packetBuilder = new PacketBuilder(buffer);
+
+ packetBuilder.writeIpv4Header(
+ (byte) 0 /* TOS */,
+ (short) 27149 /* ID */,
+ (short) 0x4000 /* flags=DF, offset=0 */,
+ (byte) 64 /* TTL */,
+ (byte) OsConstants.IPPROTO_UDP,
+ srcAddr,
+ dstAddr);
+ packetBuilder.writeUdpHeader(srcPort, dstPort);
+ buffer.put(payload);
+
+ return packetBuilder.finalizePacket();
+ }
+
+ private ByteBuffer buildIpv6UdpPacket(final Inet6Address dstAddr, final Inet6Address srcAddr,
+ final short dstPort, final short srcPort, final byte[] payload) throws IOException {
+
+ final ByteBuffer buffer = PacketBuilder.allocate(false /* hasEther */,
+ OsConstants.IPPROTO_IPV6, OsConstants.IPPROTO_UDP, payload.length);
+ final PacketBuilder packetBuilder = new PacketBuilder(buffer);
+
+ packetBuilder.writeIpv6Header(
+ 0x60000000 /* version=6, traffic class=0, flow label=0 */,
+ (byte) OsConstants.IPPROTO_UDP,
+ (short) 64 /* hop limit */,
+ srcAddr,
+ dstAddr);
+ packetBuilder.writeUdpHeader(srcPort, dstPort);
+ buffer.put(payload);
+
+ return packetBuilder.finalizePacket();
+ }
+
+ private void checkBlockUdp(
+ final FileDescriptor srcTunFd,
+ final FileDescriptor dstUdpFd,
+ final boolean ipv6,
+ final boolean expectBlock) throws Exception {
+ final Random random = new Random();
+ final byte[] sendData = new byte[100];
+ random.nextBytes(sendData);
+ final short dstPort = (short) ((InetSocketAddress) Os.getsockname(dstUdpFd)).getPort();
+
+ ByteBuffer buf;
+ if (ipv6) {
+ buf = buildIpv6UdpPacket(
+ (Inet6Address) TEST_IP6_DST_ADDR.getAddress(),
+ (Inet6Address) TEST_IP6_SRC_ADDR.getAddress(),
+ dstPort, TEST_SRC_PORT, sendData);
+ } else {
+ buf = buildIpv4UdpPacket(
+ (Inet4Address) TEST_IP4_DST_ADDR.getAddress(),
+ (Inet4Address) TEST_IP4_SRC_ADDR.getAddress(),
+ dstPort, TEST_SRC_PORT, sendData);
+ }
+
+ Os.write(srcTunFd, buf);
+
+ final StructPollfd pollfd = new StructPollfd();
+ pollfd.events = (short) POLLIN;
+ pollfd.fd = dstUdpFd;
+ final int ret = Os.poll(new StructPollfd[]{pollfd}, SOCKET_TIMEOUT_MS);
+
+ if (expectBlock) {
+ assertEquals("Expect not to receive a packet but received a packet", 0, ret);
+ } else {
+ assertEquals("Expect to receive a packet but did not receive a packet", 1, ret);
+ final byte[] recvData = new byte[sendData.length];
+ final int readSize = Os.read(dstUdpFd, recvData, 0 /* byteOffset */, recvData.length);
+ assertEquals(recvData.length, readSize);
+ MoreAsserts.assertEquals(sendData, recvData);
+ }
+ }
+
+ private void checkBlockIncomingPacket(
+ final FileDescriptor srcTunFd,
+ final FileDescriptor dstUdpFd,
+ final boolean expectBlock) throws Exception {
+ checkBlockUdp(srcTunFd, dstUdpFd, false /* ipv6 */, expectBlock);
+ checkBlockUdp(srcTunFd, dstUdpFd, true /* ipv6 */, expectBlock);
+ }
+
+ private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
+ public void expectAvailableCallbacks(Network network) {
+ super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
+ BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
+ }
+ public void expectBlockedStatusCallback(Network network, int blockedStatus) {
+ super.expectBlockedStatusCallback(blockedStatus, network, NETWORK_CALLBACK_TIMEOUT_MS);
+ }
+ public void onBlockedStatusChanged(Network network, int blockedReasons) {
+ getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
+ }
+ }
}
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java
index b1b7d77..fb6d16f 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java
@@ -17,16 +17,17 @@
package com.android.cts.net.hostside.app2;
import android.app.Service;
-import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.util.Log;
import com.android.cts.net.hostside.IRemoteSocketFactory;
+import java.io.UncheckedIOException;
+import java.net.DatagramSocket;
import java.net.Socket;
+import java.net.SocketException;
public class RemoteSocketFactoryService extends Service {
@@ -54,6 +55,16 @@
public int getUid() {
return Process.myUid();
}
+
+ @Override
+ public ParcelFileDescriptor openDatagramSocketFd() {
+ try {
+ final DatagramSocket s = new DatagramSocket();
+ return ParcelFileDescriptor.fromDatagramSocket(s);
+ } catch (SocketException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
};
@Override
diff --git a/tests/cts/hostside/app3/Android.bp b/tests/cts/hostside/app3/Android.bp
deleted file mode 100644
index 141cf03..0000000
--- a/tests/cts/hostside/app3/Android.bp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_defaults {
- name: "CtsHostsideNetworkTestsApp3Defaults",
- srcs: ["src/**/*.java"],
- libs: [
- "junit",
- ],
- static_libs: [
- "ctstestrunner-axt",
- "truth-prebuilt",
- ],
-
- // Tag this module as a cts test artifact
- test_suites: [
- "cts",
- "general-tests",
- ],
-}
-
-android_test_helper_app {
- name: "CtsHostsideNetworkTestsApp3",
- defaults: [
- "cts_support_defaults",
- "CtsHostsideNetworkTestsApp3Defaults",
- ],
-}
-
-android_test_helper_app {
- name: "CtsHostsideNetworkTestsApp3PreT",
- target_sdk_version: "31",
- defaults: [
- "cts_support_defaults",
- "CtsHostsideNetworkTestsApp3Defaults",
- ],
-}
diff --git a/tests/cts/hostside/app3/AndroidManifest.xml b/tests/cts/hostside/app3/AndroidManifest.xml
deleted file mode 100644
index eabcacb..0000000
--- a/tests/cts/hostside/app3/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.net.hostside.app3">
-
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.cts.net.hostside.app3" />
-
-</manifest>
diff --git a/tests/cts/hostside/app3/src/com/android/cts/net/hostside/app3/ExcludedRoutesGatingTest.java b/tests/cts/hostside/app3/src/com/android/cts/net/hostside/app3/ExcludedRoutesGatingTest.java
deleted file mode 100644
index a1a8209..0000000
--- a/tests/cts/hostside/app3/src/com/android/cts/net/hostside/app3/ExcludedRoutesGatingTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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 com.android.cts.net.hostside.app3;
-
-import static org.junit.Assert.assertEquals;
-
-import android.Manifest;
-import android.net.IpPrefix;
-import android.net.LinkProperties;
-import android.net.RouteInfo;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests to verify {@link LinkProperties#getRoutes} behavior, depending on
- * {@LinkProperties#EXCLUDED_ROUTES} change state.
- */
-@RunWith(AndroidJUnit4.class)
-public class ExcludedRoutesGatingTest {
- @Before
- public void setUp() {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .adoptShellPermissionIdentity(Manifest.permission.LOG_COMPAT_CHANGE,
- Manifest.permission.READ_COMPAT_CHANGE_CONFIG);
- }
-
- @After
- public void tearDown() {
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .dropShellPermissionIdentity();
- }
-
- @Test
- public void testExcludedRoutesChangeEnabled() {
- final LinkProperties lp = makeLinkPropertiesWithExcludedRoutes();
-
- // Excluded routes change is enabled: non-RTN_UNICAST routes are visible.
- assertEquals(2, lp.getRoutes().size());
- assertEquals(2, lp.getAllRoutes().size());
- }
-
- @Test
- public void testExcludedRoutesChangeDisabled() {
- final LinkProperties lp = makeLinkPropertiesWithExcludedRoutes();
-
- // Excluded routes change is disabled: non-RTN_UNICAST routes are filtered out.
- assertEquals(0, lp.getRoutes().size());
- assertEquals(0, lp.getAllRoutes().size());
- }
-
- private LinkProperties makeLinkPropertiesWithExcludedRoutes() {
- final LinkProperties lp = new LinkProperties();
-
- lp.addRoute(new RouteInfo(new IpPrefix("10.0.0.0/8"), null, null, RouteInfo.RTN_THROW));
- lp.addRoute(new RouteInfo(new IpPrefix("2001:db8::/64"), null, null,
- RouteInfo.RTN_UNREACHABLE));
-
- return lp;
- }
-}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideLinkPropertiesGatingTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideLinkPropertiesGatingTests.java
deleted file mode 100644
index 9a1fa42..0000000
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideLinkPropertiesGatingTests.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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 com.android.cts.net;
-
-import android.compat.cts.CompatChangeGatingTestCase;
-
-import java.util.Set;
-
-/**
- * Tests for the {@link android.net.LinkProperties#EXCLUDED_ROUTES} compatibility change.
- *
- * TODO: see if we can delete this cumbersome host test by moving the coverage to CtsNetTestCases
- * and CtsNetTestCasesMaxTargetSdk31.
- */
-public class HostsideLinkPropertiesGatingTests extends CompatChangeGatingTestCase {
- private static final String TEST_APK = "CtsHostsideNetworkTestsApp3.apk";
- private static final String TEST_APK_PRE_T = "CtsHostsideNetworkTestsApp3PreT.apk";
- private static final String TEST_PKG = "com.android.cts.net.hostside.app3";
- private static final String TEST_CLASS = ".ExcludedRoutesGatingTest";
-
- private static final long EXCLUDED_ROUTES_CHANGE_ID = 186082280;
-
- protected void tearDown() throws Exception {
- uninstallPackage(TEST_PKG, true);
- }
-
- public void testExcludedRoutesChangeEnabled() throws Exception {
- installPackage(TEST_APK, true);
- runDeviceCompatTest("testExcludedRoutesChangeEnabled");
- }
-
- public void testExcludedRoutesChangeDisabledPreT() throws Exception {
- installPackage(TEST_APK_PRE_T, true);
- runDeviceCompatTest("testExcludedRoutesChangeDisabled");
- }
-
- public void testExcludedRoutesChangeDisabledByOverrideOnDebugBuild() throws Exception {
- // Must install APK even when skipping test, because tearDown expects uninstall to succeed.
- installPackage(TEST_APK, true);
-
- // This test uses an app with a target SDK where the compat change is on by default.
- // Because user builds do not allow overriding compat changes, only run this test on debug
- // builds. This seems better than deleting this test and not running it anywhere because we
- // could in the future run this test on userdebug builds in presubmit.
- //
- // We cannot use assumeXyz here because CompatChangeGatingTestCase ultimately inherits from
- // junit.framework.TestCase, which does not understand assumption failures.
- if ("user".equals(getDevice().getProperty("ro.build.type"))) return;
-
- runDeviceCompatTestWithChangeDisabled("testExcludedRoutesChangeDisabled");
- }
-
- public void testExcludedRoutesChangeEnabledByOverridePreT() throws Exception {
- installPackage(TEST_APK_PRE_T, true);
- runDeviceCompatTestWithChangeEnabled("testExcludedRoutesChangeEnabled");
- }
-
- private void runDeviceCompatTest(String methodName) throws Exception {
- runDeviceCompatTest(TEST_PKG, TEST_CLASS, methodName, Set.of(), Set.of());
- }
-
- private void runDeviceCompatTestWithChangeEnabled(String methodName) throws Exception {
- runDeviceCompatTest(TEST_PKG, TEST_CLASS, methodName, Set.of(EXCLUDED_ROUTES_CHANGE_ID),
- Set.of());
- }
-
- private void runDeviceCompatTestWithChangeDisabled(String methodName) throws Exception {
- runDeviceCompatTest(TEST_PKG, TEST_CLASS, methodName, Set.of(),
- Set.of(EXCLUDED_ROUTES_CHANGE_ID));
- }
-}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
index 3821f87..4d90a4a 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -116,4 +116,8 @@
public void testInterleavedRoutes() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testInterleavedRoutes");
}
+
+ public void testBlockIncomingPackets() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBlockIncomingPackets");
+ }
}
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index a6ed762..62f37bb 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -72,9 +72,9 @@
android_test {
name: "CtsNetTestCases",
defaults: ["CtsNetTestCasesDefaults", "ConnectivityNextEnableDefaults"],
- // TODO: CTS should not depend on the entirety of the networkstack code.
static_libs: [
- "NetworkStackApiCurrentLib",
+ "DhcpPacketLib",
+ "NetworkStackApiCurrentShims",
],
test_suites: [
"cts",
@@ -86,7 +86,8 @@
name: "CtsNetTestCasesApiStableDefaults",
// TODO: CTS should not depend on the entirety of the networkstack code.
static_libs: [
- "NetworkStackApiStableLib",
+ "DhcpPacketLib",
+ "NetworkStackApiStableShims",
],
jni_uses_sdk_apis: true,
min_sdk_version: "29",
@@ -98,10 +99,10 @@
android_test {
name: "CtsNetTestCasesLatestSdk",
defaults: [
+ "ConnectivityTestsLatestSdkDefaults",
"CtsNetTestCasesDefaults",
"CtsNetTestCasesApiStableDefaults",
],
- target_sdk_version: "33",
test_suites: [
"general-tests",
"mts-dnsresolver",
diff --git a/tests/cts/net/native/src/BpfCompatTest.cpp b/tests/cts/net/native/src/BpfCompatTest.cpp
index e52533b..5c02b0d 100644
--- a/tests/cts/net/native/src/BpfCompatTest.cpp
+++ b/tests/cts/net/native/src/BpfCompatTest.cpp
@@ -31,7 +31,10 @@
std::ifstream elfFile(elfPath, std::ios::in | std::ios::binary);
ASSERT_TRUE(elfFile.is_open());
- if (android::modules::sdklevel::IsAtLeastT()) {
+ if (android::modules::sdklevel::IsAtLeastU()) {
+ EXPECT_EQ(120, readSectionUint("size_of_bpf_map_def", elfFile, 0));
+ EXPECT_EQ(92, readSectionUint("size_of_bpf_prog_def", elfFile, 0));
+ } else if (android::modules::sdklevel::IsAtLeastT()) {
EXPECT_EQ(116, readSectionUint("size_of_bpf_map_def", elfFile, 0));
EXPECT_EQ(92, readSectionUint("size_of_bpf_prog_def", elfFile, 0));
} else {
@@ -47,8 +50,13 @@
}
TEST(BpfTest, bpfStructSizeTest) {
- doBpfStructSizeTest("/system/etc/bpf/gpu_mem.o");
- doBpfStructSizeTest("/system/etc/bpf/time_in_state.o");
+ if (android::modules::sdklevel::IsAtLeastU()) {
+ doBpfStructSizeTest("/system/etc/bpf/gpuMem.o");
+ doBpfStructSizeTest("/system/etc/bpf/timeInState.o");
+ } else {
+ doBpfStructSizeTest("/system/etc/bpf/gpu_mem.o");
+ doBpfStructSizeTest("/system/etc/bpf/time_in_state.o");
+ }
}
int main(int argc, char **argv) {
diff --git a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
index 1b77d5f..aad8804 100644
--- a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
+++ b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
@@ -37,9 +37,8 @@
import android.net.cts.NetworkValidationTestUtil.setHttpsUrlDeviceConfig
import android.net.cts.NetworkValidationTestUtil.setUrlExpirationDeviceConfig
import android.net.cts.util.CtsNetUtils
-import android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL
-import android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL
-import android.os.Build
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
@@ -47,11 +46,11 @@
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.AndroidJUnit4
+import com.android.modules.utils.build.SdkLevel.isAtLeastR
import com.android.testutils.RecorderCallback
import com.android.testutils.TestHttpServer
import com.android.testutils.TestHttpServer.Request
import com.android.testutils.TestableNetworkCallback
-import com.android.testutils.isDevSdkInRange
import com.android.testutils.runAsShell
import fi.iki.elonen.NanoHTTPD.Response.Status
import junit.framework.AssertionFailedError
@@ -196,8 +195,8 @@
assertNotEquals(network, cm.activeNetwork, wifiDefaultMessage)
val startPortalAppPermission =
- if (isDevSdkInRange(0, Build.VERSION_CODES.Q)) CONNECTIVITY_INTERNAL
- else NETWORK_SETTINGS
+ if (isAtLeastR()) NETWORK_SETTINGS
+ else CONNECTIVITY_INTERNAL
runAsShell(startPortalAppPermission) { cm.startCaptivePortalApp(network) }
// Expect the portal content to be fetched at some point after detecting the portal.
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 766d62f..64238b3 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -37,9 +37,14 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.EXTRA_NETWORK;
import static android.net.ConnectivityManager.EXTRA_NETWORK_REQUEST;
+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_OEM_DENY_1;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
+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.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
@@ -75,8 +80,6 @@
import static android.net.cts.util.CtsNetUtils.TEST_HOST;
import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
-import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL;
-import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.os.Process.INVALID_UID;
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
@@ -88,6 +91,8 @@
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
+import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL;
+import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.Cleanup.testAndCleanup;
@@ -186,7 +191,6 @@
import com.android.testutils.CompatUtil;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
-import com.android.testutils.DevSdkIgnoreRuleKt;
import com.android.testutils.DeviceInfoUtils;
import com.android.testutils.DumpTestUtils;
import com.android.testutils.RecorderCallback.CallbackEntry;
@@ -331,11 +335,10 @@
mCtsNetUtils = new CtsNetUtils(mContext);
mTm = mContext.getSystemService(TelephonyManager.class);
- if (DevSdkIgnoreRuleKt.isDevSdkInRange(null /* minExclusive */,
- Build.VERSION_CODES.R /* maxInclusive */)) {
- addLegacySupportedNetworkTypes();
- } else {
+ if (isAtLeastS()) {
addSupportedNetworkTypes();
+ } else {
+ addLegacySupportedNetworkTypes();
}
mUiAutomation = mInstrumentation.getUiAutomation();
@@ -2092,25 +2095,15 @@
try {
// Verify we cannot set Airplane Mode without correct permission:
- try {
- setAndVerifyAirplaneMode(true);
- fail("SecurityException should have been thrown when setAirplaneMode was called"
- + "without holding permission NETWORK_AIRPLANE_MODE.");
- } catch (SecurityException expected) {}
+ assertThrows(SecurityException.class, () -> setAndVerifyAirplaneMode(true));
// disable airplane mode again to reach a known state
runShellCommand("cmd connectivity airplane-mode disable");
- // adopt shell permission which holds NETWORK_AIRPLANE_MODE
- mUiAutomation.adoptShellPermissionIdentity();
+ // Verify we can enable Airplane Mode with correct permission.
+ // TODO: test that NETWORK_AIRPLANE_MODE works as well, once the shell has it.
+ runAsShell(NETWORK_SETTINGS, () -> setAndVerifyAirplaneMode(true));
- // Verify we can enable Airplane Mode with correct permission:
- try {
- setAndVerifyAirplaneMode(true);
- } catch (SecurityException e) {
- fail("SecurityException should not have been thrown when setAirplaneMode(true) was"
- + "called whilst holding the NETWORK_AIRPLANE_MODE permission.");
- }
// Verify that the enabling airplane mode takes effect as expected to prevent flakiness
// caused by fast airplane mode switches. Ensure network lost before turning off
// airplane mode.
@@ -2118,12 +2111,8 @@
if (supportTelephony) waitForLost(telephonyCb);
// Verify we can disable Airplane Mode with correct permission:
- try {
- setAndVerifyAirplaneMode(false);
- } catch (SecurityException e) {
- fail("SecurityException should not have been thrown when setAirplaneMode(false) was"
- + "called whilst holding the NETWORK_AIRPLANE_MODE permission.");
- }
+ runAsShell(NETWORK_SETTINGS, () -> setAndVerifyAirplaneMode(false));
+
// Verify that turning airplane mode off takes effect as expected.
// connectToCell only registers a request, it cannot / does not need to be called twice
mCtsNetUtils.ensureWifiConnected();
@@ -2133,7 +2122,6 @@
// Restore the previous state of airplane mode and permissions:
runShellCommand("cmd connectivity airplane-mode "
+ (isAirplaneModeEnabled ? "enable" : "disable"));
- mUiAutomation.dropShellPermissionIdentity();
}
}
@@ -2500,13 +2488,11 @@
final CtsTetheringUtils tetherUtils = new CtsTetheringUtils(mContext);
try {
tetherEventCallback = tetherUtils.registerTetheringEventCallback();
- // Adopt for NETWORK_SETTINGS permission.
- mUiAutomation.adoptShellPermissionIdentity();
// start tethering
tetherEventCallback.assumeWifiTetheringSupported(mContext);
tetherUtils.startWifiTethering(tetherEventCallback);
// Update setting to verify the behavior.
- mCm.setAirplaneMode(true);
+ setAirplaneMode(true);
ConnectivitySettingsManager.setPrivateDnsMode(mContext,
ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF);
ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext,
@@ -2514,7 +2500,7 @@
assertEquals(AIRPLANE_MODE_ON, Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON));
// Verify factoryReset
- mCm.factoryReset();
+ runAsShell(NETWORK_SETTINGS, () -> mCm.factoryReset());
verifySettings(AIRPLANE_MODE_OFF,
ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC,
ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_PROMPT);
@@ -2522,17 +2508,20 @@
tetherEventCallback.expectNoTetheringActive();
} finally {
// Restore settings.
- mCm.setAirplaneMode(false);
+ setAirplaneMode(false);
ConnectivitySettingsManager.setNetworkAvoidBadWifi(mContext, curAvoidBadWifi);
ConnectivitySettingsManager.setPrivateDnsMode(mContext, curPrivateDnsMode);
if (tetherEventCallback != null) {
tetherUtils.unregisterTetheringEventCallback(tetherEventCallback);
}
tetherUtils.stopAllTethering();
- mUiAutomation.dropShellPermissionIdentity();
}
}
+ private void setAirplaneMode(boolean enable) {
+ runAsShell(NETWORK_SETTINGS, () -> mCm.setAirplaneMode(enable));
+ }
+
/**
* Verify that {@link ConnectivityManager#setProfileNetworkPreference} cannot be called
* without required NETWORK_STACK permissions.
@@ -3313,84 +3302,76 @@
private static final boolean EXPECT_PASS = false;
private static final boolean EXPECT_BLOCK = true;
+ private static final boolean ALLOWLIST = true;
+ private static final boolean DENYLIST = false;
- private void doTestFirewallBlockingDenyRule(final int chain) {
+ private void doTestFirewallBlocking(final int chain, final boolean isAllowList) {
+ final int myUid = Process.myUid();
+ final int ruleToAddMatch = isAllowList ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY;
+ final int ruleToRemoveMatch = isAllowList ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW;
+
runWithShellPermissionIdentity(() -> {
- try (DatagramSocket srcSock = new DatagramSocket();
- DatagramSocket dstSock = new DatagramSocket()) {
+ // Firewall chain status will be restored after the test.
+ final boolean wasChainEnabled = mCm.getFirewallChainEnabled(chain);
+ final DatagramSocket srcSock = new DatagramSocket();
+ final DatagramSocket dstSock = new DatagramSocket();
+ testAndCleanup(() -> {
+ if (wasChainEnabled) {
+ mCm.setFirewallChainEnabled(chain, false /* enable */);
+ }
dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
- // No global config, No uid config
+ // Chain disabled, UID not on chain.
checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- // Has global config, No uid config
+ // Chain enabled, UID not on chain.
mCm.setFirewallChainEnabled(chain, true /* enable */);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ assertTrue(mCm.getFirewallChainEnabled(chain));
+ checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS);
- // Has global config, Has uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_BLOCK);
+ // Chain enabled, UID on chain.
+ mCm.setUidFirewallRule(chain, myUid, ruleToAddMatch);
+ checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_PASS : EXPECT_BLOCK);
- // No global config, Has uid config
+ // Chain disabled, UID on chain.
mCm.setFirewallChainEnabled(chain, false /* enable */);
+ assertFalse(mCm.getFirewallChainEnabled(chain));
checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- // No global config, No uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
+ // Chain disabled, UID not on chain.
+ mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- } finally {
- mCm.setFirewallChainEnabled(chain, false /* enable */);
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
- }
- }, NETWORK_SETTINGS);
- }
-
- private void doTestFirewallBlockingAllowRule(final int chain) {
- runWithShellPermissionIdentity(() -> {
- try (DatagramSocket srcSock = new DatagramSocket();
- DatagramSocket dstSock = new DatagramSocket()) {
- dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
-
- // No global config, No uid config
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
-
- // Has global config, No uid config
- mCm.setFirewallChainEnabled(chain, true /* enable */);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_BLOCK);
-
- // Has global config, Has uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
-
- // No global config, Has uid config
- mCm.setFirewallChainEnabled(chain, false /* enable */);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
-
- // No global config, No uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- } finally {
- mCm.setFirewallChainEnabled(chain, false /* enable */);
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
- }
+ }, /* cleanup */ () -> {
+ srcSock.close();
+ dstSock.close();
+ }, /* cleanup */ () -> {
+ // Restore the global chain status
+ mCm.setFirewallChainEnabled(chain, wasChainEnabled);
+ }, /* cleanup */ () -> {
+ try {
+ mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
+ } catch (IllegalStateException ignored) {
+ // Removing match causes an exception when the rule entry for the uid does
+ // not exist. But this is fine and can be ignored.
+ }
+ });
}, NETWORK_SETTINGS);
}
@Test @IgnoreUpTo(SC_V2)
@AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testFirewallBlocking() {
- // Following tests affect the actual state of networking on the device after the test.
- // This might cause unexpected behaviour of the device. So, we skip them for now.
- // We will enable following tests after adding the logic of firewall state restoring.
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_DOZABLE);
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_POWERSAVE);
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_RESTRICTED);
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_LOW_POWER_STANDBY);
+ // ALLOWLIST means the firewall denies all by default, uids must be explicitly allowed
+ doTestFirewallBlocking(FIREWALL_CHAIN_DOZABLE, ALLOWLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_POWERSAVE, ALLOWLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_RESTRICTED, ALLOWLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_LOW_POWER_STANDBY, ALLOWLIST);
- // doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_STANDBY);
- doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_1);
- doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_2);
- doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_3);
+ // DENYLIST means the firewall allows all by default, uids must be explicitly denyed
+ doTestFirewallBlocking(FIREWALL_CHAIN_STANDBY, DENYLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_1, DENYLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_2, DENYLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_3, DENYLIST);
}
private void assumeTestSApis() {
diff --git a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
index 621b743..b68d3bf 100644
--- a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
+++ b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
@@ -27,6 +27,8 @@
import android.net.IpPrefix
import android.net.LinkAddress
import android.net.LinkProperties
+import android.net.Network
+import android.net.MacAddress
import android.net.NetworkAgent
import android.net.NetworkAgent.DSCP_POLICY_STATUS_DELETED
import android.net.NetworkAgent.DSCP_POLICY_STATUS_SUCCESS
@@ -45,10 +47,13 @@
import android.net.TestNetworkManager
import android.net.RouteInfo
import android.os.HandlerThread
+import android.os.SystemClock
import android.platform.test.annotations.AppModeFull
+import android.system.ErrnoException
import android.system.Os
import android.system.OsConstants.AF_INET
import android.system.OsConstants.AF_INET6
+import android.system.OsConstants.ENETUNREACH
import android.system.OsConstants.IPPROTO_UDP
import android.system.OsConstants.SOCK_DGRAM
import android.system.OsConstants.SOCK_NONBLOCK
@@ -56,9 +61,15 @@
import android.util.Range
import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
+import com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4
+import com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6
+import com.android.net.module.util.Struct
+import com.android.net.module.util.structs.EthernetHeader
+import com.android.testutils.ArpResponder
import com.android.testutils.CompatUtil
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.assertParcelingIsLossless
+import com.android.testutils.RouterAdvertisementResponder
import com.android.testutils.runAsShell
import com.android.testutils.SC_V2
import com.android.testutils.TapPacketReader
@@ -74,7 +85,7 @@
import org.junit.runner.RunWith
import java.net.Inet4Address
import java.net.Inet6Address
-import java.net.InetAddress
+import java.net.InetSocketAddress
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.util.regex.Pattern
@@ -103,10 +114,12 @@
private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1")
private val TEST_TARGET_IPV4_ADDR =
- InetAddresses.parseNumericAddress("8.8.8.8") as Inet4Address
- private val LOCAL_IPV6_ADDRESS = InetAddresses.parseNumericAddress("2001:db8::1")
+ InetAddresses.parseNumericAddress("203.0.113.1") as Inet4Address
private val TEST_TARGET_IPV6_ADDR =
- InetAddresses.parseNumericAddress("2001:4860:4860::8888") as Inet6Address
+ InetAddresses.parseNumericAddress("2001:4860:4860::8888") as Inet6Address
+ private val TEST_ROUTER_IPV6_ADDR =
+ InetAddresses.parseNumericAddress("fe80::1234") as Inet6Address
+ private val TEST_TARGET_MAC_ADDR = MacAddress.fromString("12:34:56:78:9a:bc")
private val realContext = InstrumentationRegistry.getContext()
private val cm = realContext.getSystemService(ConnectivityManager::class.java)
@@ -116,9 +129,12 @@
private val handlerThread = HandlerThread(DscpPolicyTest::class.java.simpleName)
+ private lateinit var srcAddressV6: Inet6Address
private lateinit var iface: TestNetworkInterface
private lateinit var tunNetworkCallback: TestNetworkCallback
private lateinit var reader: TapPacketReader
+ private lateinit var arpResponder: ArpResponder
+ private lateinit var raResponder: RouterAdvertisementResponder
private fun getKernelVersion(): IntArray {
// Example:
@@ -129,6 +145,7 @@
return intArrayOf(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)))
}
+ // TODO: replace with DeviceInfoUtils#isKernelVersionAtLeast
private fun kernelIsAtLeast(major: Int, minor: Int): Boolean {
val version = getKernelVersion()
return (version.get(0) > major || (version.get(0) == major && version.get(1) >= minor))
@@ -142,9 +159,10 @@
runAsShell(MANAGE_TEST_NETWORKS) {
val tnm = realContext.getSystemService(TestNetworkManager::class.java)
- iface = tnm.createTunInterface(arrayOf(
- LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN),
- LinkAddress(LOCAL_IPV6_ADDRESS, IP6_PREFIX_LEN)))
+ // Only statically configure the IPv4 address; for IPv6, use the SLAAC generated
+ // address.
+ iface = tnm.createTapInterface(true /* disableIpv6ProvisioningDelay */,
+ arrayOf(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN)))
assertNotNull(iface)
}
@@ -154,21 +172,30 @@
iface.fileDescriptor.fileDescriptor,
MAX_PACKET_LENGTH)
reader.startAsyncForTest()
+
+ arpResponder = ArpResponder(reader, mapOf(TEST_TARGET_IPV4_ADDR to TEST_TARGET_MAC_ADDR))
+ arpResponder.start()
+ raResponder = RouterAdvertisementResponder(reader)
+ raResponder.addRouterEntry(TEST_TARGET_MAC_ADDR, TEST_ROUTER_IPV6_ADDR)
+ raResponder.start()
}
@After
fun tearDown() {
if (!kernelIsAtLeast(5, 15)) {
- return;
+ return
}
+ raResponder.stop()
+ arpResponder.stop()
+
agentsToCleanUp.forEach { it.unregister() }
callbacksToCleanUp.forEach { cm.unregisterNetworkCallback(it) }
// reader.stop() cleans up tun fd
reader.handler.post { reader.stop() }
- if (iface.fileDescriptor.fileDescriptor != null)
- Os.close(iface.fileDescriptor.fileDescriptor)
+ // quitSafely processes all events in the queue, except delayed messages.
handlerThread.quitSafely()
+ handlerThread.join()
}
private fun requestNetwork(request: NetworkRequest, callback: TestableNetworkCallback) {
@@ -189,6 +216,39 @@
.build()
}
+ private fun waitForGlobalIpv6Address(network: Network): Inet6Address {
+ // Wait for global IPv6 address to be available
+ val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
+ network.bindSocket(sock)
+
+ var inet6Addr: Inet6Address? = null
+ val timeout = SystemClock.elapsedRealtime() + PACKET_TIMEOUT_MS
+ while (timeout > SystemClock.elapsedRealtime()) {
+ try {
+ // Pick any arbitrary port
+ Os.connect(sock, TEST_TARGET_IPV6_ADDR, 12345)
+ val sockAddr = Os.getsockname(sock) as InetSocketAddress
+
+ // TODO: make RouterAdvertisementResponder.SLAAC_PREFIX public and use it here,
+ // or make it configurable and configure it here.
+ if (IpPrefix("2001:db8::/64").contains(sockAddr.address)) {
+ inet6Addr = sockAddr.address as Inet6Address
+ break
+ }
+ } catch (e: ErrnoException) {
+ // ignore ENETUNREACH -- there may not be an address available yet.
+ if (e.errno != ENETUNREACH) {
+ Os.close(sock)
+ throw e
+ }
+ }
+ SystemClock.sleep(10 /* ms */)
+ }
+ Os.close(sock)
+ assertNotNull(inet6Addr)
+ return inet6Addr!!
+ }
+
private fun createConnectedNetworkAgent(
context: Context = realContext,
specifier: String? = iface.getInterfaceName()
@@ -211,9 +271,8 @@
}
val lp = LinkProperties().apply {
addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN))
- addLinkAddress(LinkAddress(LOCAL_IPV6_ADDRESS, IP6_PREFIX_LEN))
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
- addRoute(RouteInfo(InetAddress.getByName("fe80::1234")))
+ addRoute(RouteInfo(IpPrefix("::/0"), TEST_ROUTER_IPV6_ADDR))
setInterfaceName(specifier)
}
val config = NetworkAgentConfig.Builder().build()
@@ -226,7 +285,9 @@
agent.expectCallback<OnNetworkCreated>()
agent.expectSignalStrengths(intArrayOf())
agent.expectValidationBypassedStatus()
+
val network = agent.network ?: fail("Expected a non-null network")
+ srcAddressV6 = waitForGlobalIpv6Address(network)
return agent to callback
}
@@ -237,7 +298,7 @@
fun sendPacket(
agent: TestableNetworkAgent,
sendV6: Boolean,
- dstPort: Int = 0,
+ dstPort: Int = 0
) {
val testString = "test string"
val testPacket = ByteBuffer.wrap(testString.toByteArray(Charsets.UTF_8))
@@ -249,11 +310,11 @@
val originalPacket = testPacket.readAsArray()
Os.sendto(socket, originalPacket, 0 /* bytesOffset */, originalPacket.size, 0 /* flags */,
- if(sendV6) TEST_TARGET_IPV6_ADDR else TEST_TARGET_IPV4_ADDR, dstPort)
+ if (sendV6) TEST_TARGET_IPV6_ADDR else TEST_TARGET_IPV4_ADDR, dstPort)
Os.close(socket)
}
- fun parseV4PacketDscp(buffer : ByteBuffer) : Int {
+ fun parseV4PacketDscp(buffer: ByteBuffer): Int {
val ip_ver = buffer.get()
val tos = buffer.get()
val length = buffer.getShort()
@@ -265,7 +326,7 @@
return tos.toInt().shr(2)
}
- fun parseV6PacketDscp(buffer : ByteBuffer) : Int {
+ fun parseV6PacketDscp(buffer: ByteBuffer): Int {
val ip_ver = buffer.get()
val tc = buffer.get()
val fl = buffer.getShort()
@@ -279,9 +340,9 @@
}
fun parsePacketIp(
- buffer : ByteBuffer,
- sendV6 : Boolean,
- ) : Boolean {
+ buffer: ByteBuffer,
+ sendV6: Boolean
+ ): Boolean {
val ipAddr = if (sendV6) ByteArray(16) else ByteArray(4)
buffer.get(ipAddr)
val srcIp = if (sendV6) Inet6Address.getByAddress(ipAddr)
@@ -292,20 +353,20 @@
Log.e(TAG, "IP Src:" + srcIp + " dst: " + dstIp)
- if ((sendV6 && srcIp == LOCAL_IPV6_ADDRESS && dstIp == TEST_TARGET_IPV6_ADDR) ||
+ if ((sendV6 && srcIp == srcAddressV6 && dstIp == TEST_TARGET_IPV6_ADDR) ||
(!sendV6 && srcIp == LOCAL_IPV4_ADDRESS && dstIp == TEST_TARGET_IPV4_ADDR)) {
- Log.e(TAG, "IP return true");
+ Log.e(TAG, "IP return true")
return true
}
- Log.e(TAG, "IP return false");
+ Log.e(TAG, "IP return false")
return false
}
fun parsePacketPort(
- buffer : ByteBuffer,
- srcPort : Int,
- dstPort : Int
- ) : Boolean {
+ buffer: ByteBuffer,
+ srcPort: Int,
+ dstPort: Int
+ ): Boolean {
if (srcPort == 0 && dstPort == 0) return true
val packetSrcPort = buffer.getShort().toInt()
@@ -315,26 +376,33 @@
if ((srcPort == 0 || (srcPort != 0 && srcPort == packetSrcPort)) &&
(dstPort == 0 || (dstPort != 0 && dstPort == packetDstPort))) {
- Log.e(TAG, "Port return true");
+ Log.e(TAG, "Port return true")
return true
}
- Log.e(TAG, "Port return false");
+ Log.e(TAG, "Port return false")
return false
}
fun validatePacket(
- agent : TestableNetworkAgent,
- sendV6 : Boolean = false,
- dscpValue : Int = 0,
- dstPort : Int = 0,
+ agent: TestableNetworkAgent,
+ sendV6: Boolean = false,
+ dscpValue: Int = 0,
+ dstPort: Int = 0
) {
- var packetFound = false;
+ var packetFound = false
sendPacket(agent, sendV6, dstPort)
// TODO: grab source port from socket in sendPacket
Log.e(TAG, "find DSCP value:" + dscpValue)
- generateSequence { reader.poll(PACKET_TIMEOUT_MS) }.forEach { packet ->
+ val packets = generateSequence { reader.poll(PACKET_TIMEOUT_MS) }
+ for (packet in packets) {
val buffer = ByteBuffer.wrap(packet, 0, packet.size).order(ByteOrder.BIG_ENDIAN)
+ // TODO: consider using Struct.parse for all packet parsing.
+ val etherHdr = Struct.parse(EthernetHeader::class.java, buffer)
+ val expectedType = if (sendV6) ETHER_TYPE_IPV6 else ETHER_TYPE_IPV4
+ if (etherHdr.etherType != expectedType) {
+ continue
+ }
val dscp = if (sendV6) parseV6PacketDscp(buffer) else parseV4PacketDscp(buffer)
Log.e(TAG, "DSCP value:" + dscp)
@@ -420,7 +488,7 @@
val policy2 = DscpPolicy.Builder(1, 4)
.setDestinationPortRange(Range(5555, 5555))
.setDestinationAddress(TEST_TARGET_IPV6_ADDR)
- .setSourceAddress(LOCAL_IPV6_ADDRESS)
+ .setSourceAddress(srcAddressV6)
.setProtocol(IPPROTO_UDP).build()
agent.sendAddDscpPolicy(policy2)
agent.expectCallback<OnDscpPolicyStatusUpdated>().let {
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index 1748612..89b107e 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -21,6 +21,8 @@
import android.content.Context
import android.net.ConnectivityManager
import android.net.EthernetManager
+import android.net.EthernetManager.ETHERNET_STATE_DISABLED
+import android.net.EthernetManager.ETHERNET_STATE_ENABLED
import android.net.EthernetManager.InterfaceStateListener
import android.net.EthernetManager.ROLE_CLIENT
import android.net.EthernetManager.ROLE_NONE
@@ -35,15 +37,19 @@
import android.net.EthernetNetworkUpdateRequest
import android.net.InetAddresses
import android.net.IpConfiguration
+import android.net.LinkAddress
import android.net.MacAddress
import android.net.Network
import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkRequest
+import android.net.StaticIpConfiguration
import android.net.TestNetworkInterface
import android.net.TestNetworkManager
+import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.EthernetStateChanged
import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
import android.os.Build
import android.os.Handler
@@ -54,16 +60,17 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
-import com.android.testutils.anyNetwork
import com.android.testutils.ConnectivityModuleTest
-import com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast
import com.android.testutils.RecorderCallback.CallbackEntry.Available
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
import com.android.testutils.RouterAdvertisementResponder
import com.android.testutils.TapPacketReader
import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.anyNetwork
import com.android.testutils.runAsShell
import com.android.testutils.waitForIdle
import org.junit.After
@@ -74,8 +81,9 @@
import java.net.Inet6Address
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException
-import java.util.concurrent.TimeoutException
import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
+import java.util.function.IntConsumer
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
@@ -84,17 +92,25 @@
import kotlin.test.assertTrue
import kotlin.test.fail
+private const val TAG = "EthernetManagerTest"
// TODO: try to lower this timeout in the future. Currently, ethernet tests are still flaky because
// the interface is not ready fast enough (mostly due to the up / up / down / up issue).
private const val TIMEOUT_MS = 2000L
-private const val NO_CALLBACK_TIMEOUT_MS = 200L
+// Timeout used to confirm no callbacks matching given criteria are received. Must be long enough to
+// process all callbacks including ip provisioning when using the updateConfiguration API.
+private const val NO_CALLBACK_TIMEOUT_MS = 500L
+
private val DEFAULT_IP_CONFIGURATION = IpConfiguration(IpConfiguration.IpAssignment.DHCP,
- IpConfiguration.ProxySettings.NONE, null, null)
+ IpConfiguration.ProxySettings.NONE, null, null)
private val ETH_REQUEST: NetworkRequest = NetworkRequest.Builder()
- .addTransportType(TRANSPORT_TEST)
- .addTransportType(TRANSPORT_ETHERNET)
- .removeCapability(NET_CAPABILITY_TRUSTED)
- .build()
+ .addTransportType(TRANSPORT_TEST)
+ .addTransportType(TRANSPORT_ETHERNET)
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .build()
+private val STATIC_IP_CONFIGURATION = IpConfiguration.Builder()
+ .setStaticIpConfiguration(StaticIpConfiguration.Builder()
+ .setIpAddress(LinkAddress("192.0.2.1/30")).build())
+ .build()
@AppModeFull(reason = "Instant apps can't access EthernetManager")
// EthernetManager is not updatable before T, so tests do not need to be backwards compatible.
@@ -161,7 +177,7 @@
private open class EthernetStateListener private constructor(
private val history: ArrayTrackRecord<CallbackEntry>
- ) : InterfaceStateListener,
+ ) : InterfaceStateListener, IntConsumer,
TrackRecord<EthernetStateListener.CallbackEntry> by history {
constructor() : this(ArrayTrackRecord())
@@ -174,6 +190,8 @@
val role: Int,
val configuration: IpConfiguration?
) : CallbackEntry()
+
+ data class EthernetStateChanged(val state: Int) : CallbackEntry()
}
override fun onInterfaceStateChanged(
@@ -185,6 +203,10 @@
add(InterfaceStateChanged(iface, state, role, cfg))
}
+ override fun accept(state: Int) {
+ add(EthernetStateChanged(state))
+ }
+
fun <T : CallbackEntry> expectCallback(expected: T): T {
val event = pollForNextCallback()
assertEquals(expected, event)
@@ -195,6 +217,10 @@
expectCallback(createChangeEvent(iface.name, state, role))
}
+ fun expectCallback(state: Int) {
+ expectCallback(EthernetStateChanged(state))
+ }
+
fun createChangeEvent(iface: String, state: Int, role: Int) =
InterfaceStateChanged(iface, state, role,
if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null)
@@ -209,6 +235,10 @@
assertNotNull(eventuallyExpect(createChangeEvent(iface.name, state, role)))
}
+ fun eventuallyExpect(state: Int) {
+ assertNotNull(eventuallyExpect(EthernetStateChanged(state)))
+ }
+
fun assertNoCallback() {
val cb = events.poll(NO_CALLBACK_TIMEOUT_MS)
assertNull(cb, "Expected no callback but got $cb")
@@ -280,11 +310,17 @@
@After
fun tearDown() {
- setIncludeTestInterfaces(false)
+ // Reenable ethernet, so ABSENT callbacks are received.
+ setEthernetEnabled(true)
+
for (iface in createdIfaces) {
iface.destroy()
ifaceListener.eventuallyExpect(iface, STATE_ABSENT, ROLE_NONE)
}
+
+ // After test interfaces are removed, disable tracking.
+ setIncludeTestInterfaces(false)
+
for (listener in addedListeners) {
em.removeInterfaceStateListener(listener)
}
@@ -391,6 +427,19 @@
}
}
+ private fun setEthernetEnabled(enabled: Boolean) {
+ runAsShell(NETWORK_SETTINGS) { em.setEthernetEnabled(enabled) }
+
+ val listener = EthernetStateListener()
+ em.addEthernetStateListener(handler::post, listener)
+ try {
+ listener.eventuallyExpect(
+ if (enabled) ETHERNET_STATE_ENABLED else ETHERNET_STATE_DISABLED)
+ } finally {
+ em.removeEthernetStateListener(listener)
+ }
+ }
+
// NetworkRequest.Builder does not create a copy of the passed NetworkRequest, so in order to
// keep ETH_REQUEST as it is, a defensive copy is created here.
private fun NetworkRequest.createCopyWithEthernetSpecifier(ifaceName: String) =
@@ -399,7 +448,10 @@
// It can take multiple seconds for the network to become available.
private fun TestableNetworkCallback.expectAvailable() =
- expectCallback<Available>(anyNetwork(), 5000 /* ms timeout */).network
+ expectCallback<Available>(anyNetwork(), 5000 /* ms timeout */).network
+
+ private fun TestableNetworkCallback.expectLost(n: Network = anyNetwork()) =
+ expectCallback<Lost>(n, 5000 /* ms timeout */)
// b/233534110: eventuallyExpect<Lost>() does not advance ReadHead, use
// eventuallyExpect(Lost::class) instead.
@@ -407,7 +459,9 @@
eventuallyExpect(Lost::class, TIMEOUT_MS) { n?.equals(it.network) ?: true }
private fun TestableNetworkCallback.assertNeverLost(n: Network? = null) =
- assertNoCallbackThat() { it is Lost && (n?.equals(it.network) ?: true) }
+ assertNoCallbackThat(NO_CALLBACK_TIMEOUT_MS) {
+ it is Lost && (n?.equals(it.network) ?: true)
+ }
private fun TestableNetworkCallback.assertNeverAvailable(n: Network? = null) =
assertNoCallbackThat() { it is Available && (n?.equals(it.network) ?: true) }
@@ -417,6 +471,18 @@
it.networkSpecifier == EthernetNetworkSpecifier(name)
}
+ private fun TestableNetworkCallback.expectCapabilitiesWithCapability(cap: Int) =
+ expectCapabilitiesThat(anyNetwork(), TIMEOUT_MS) {
+ it.hasCapability(cap)
+ }
+
+ private fun TestableNetworkCallback.expectLinkPropertiesWithLinkAddress(addr: LinkAddress) =
+ expectLinkPropertiesThat(anyNetwork(), TIMEOUT_MS) {
+ // LinkAddress.equals isn't possible as the system changes the LinkAddress.flags value.
+ // any() must be used since the interface may also have a link-local address.
+ it.linkAddresses.any { x -> x.isSameAddressAs(addr) }
+ }
+
@Test
fun testCallbacks() {
// If an interface exists when the callback is registered, it is reported on registration.
@@ -681,4 +747,80 @@
releaseTetheredInterface()
listener.assertNoCallback()
}
+
+ @Test
+ fun testEnableDisableInterface_withActiveRequest() {
+ val iface = createInterface()
+ val cb = requestNetwork(ETH_REQUEST)
+ cb.expectAvailable()
+ cb.assertNeverLost()
+
+ disableInterface(iface).expectResult(iface.name)
+ cb.eventuallyExpectLost()
+
+ enableInterface(iface).expectResult(iface.name)
+ cb.expectAvailable()
+ }
+
+ @Test
+ fun testUpdateConfiguration_forBothIpConfigAndCapabilities() {
+ val iface = createInterface()
+ val cb = requestNetwork(ETH_REQUEST.createCopyWithEthernetSpecifier(iface.name))
+ val network = cb.expectAvailable()
+ cb.assertNeverLost()
+
+ val testCapability = NET_CAPABILITY_TEMPORARILY_NOT_METERED
+ val nc = NetworkCapabilities
+ .Builder(ETH_REQUEST.networkCapabilities)
+ .addCapability(testCapability)
+ .build()
+ updateConfiguration(iface, STATIC_IP_CONFIGURATION, nc)
+
+ // UpdateConfiguration() currently does a restarts on the ethernet interface therefore lost
+ // will be expected first before available, as part of the restart.
+ cb.expectLost(network)
+ cb.expectAvailable()
+ cb.expectCapabilitiesWithCapability(testCapability)
+ cb.expectLinkPropertiesWithLinkAddress(
+ STATIC_IP_CONFIGURATION.staticIpConfiguration.ipAddress!!)
+ }
+
+ @Test
+ fun testUpdateConfiguration_forOnlyIpConfig() {
+ val iface: EthernetTestInterface = createInterface()
+ val cb = requestNetwork(ETH_REQUEST.createCopyWithEthernetSpecifier(iface.name))
+ val network = cb.expectAvailable()
+ cb.assertNeverLost()
+
+ updateConfiguration(iface, STATIC_IP_CONFIGURATION)
+
+ // UpdateConfiguration() currently does a restarts on the ethernet interface therefore lost
+ // will be expected first before available, as part of the restart.
+ cb.expectLost(network)
+ cb.expectAvailable()
+ cb.expectCallback<CapabilitiesChanged>()
+ cb.expectLinkPropertiesWithLinkAddress(
+ STATIC_IP_CONFIGURATION.staticIpConfiguration.ipAddress!!)
+ }
+
+ @Test
+ fun testUpdateConfiguration_forOnlyCapabilities() {
+ val iface: EthernetTestInterface = createInterface()
+ val cb = requestNetwork(ETH_REQUEST.createCopyWithEthernetSpecifier(iface.name))
+ val network = cb.expectAvailable()
+ cb.assertNeverLost()
+
+ val testCapability = NET_CAPABILITY_TEMPORARILY_NOT_METERED
+ val nc = NetworkCapabilities
+ .Builder(ETH_REQUEST.networkCapabilities)
+ .addCapability(testCapability)
+ .build()
+ updateConfiguration(iface, capabilities = nc)
+
+ // UpdateConfiguration() currently does a restarts on the ethernet interface therefore lost
+ // will be expected first before available, as part of the restart.
+ cb.expectLost(network)
+ cb.expectAvailable()
+ cb.expectCapabilitiesWithCapability(testCapability)
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt b/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt
index 462c8a3..375bfb8 100644
--- a/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt
@@ -17,9 +17,9 @@
package android.net.cts
import android.Manifest.permission.WRITE_DEVICE_CONFIG
-import android.net.util.NetworkStackUtils
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
+import com.android.net.module.util.NetworkStackConstants
import com.android.testutils.runAsShell
/**
@@ -35,41 +35,41 @@
@JvmStatic fun clearValidationTestUrlsDeviceConfig() {
runAsShell(WRITE_DEVICE_CONFIG) {
DeviceConfig.setProperty(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, null, false)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL, null, false)
DeviceConfig.setProperty(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, null, false)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL, null, false)
DeviceConfig.setProperty(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_URL_EXPIRATION_TIME, null, false)
+ NetworkStackConstants.TEST_URL_EXPIRATION_TIME, null, false)
}
}
/**
* Set the test validation HTTPS URL.
*
- * @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL
+ * @see NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
*/
@JvmStatic
fun setHttpsUrlDeviceConfig(rule: DeviceConfigRule, url: String?) =
rule.setConfig(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, url)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL, url)
/**
* Set the test validation HTTP URL.
*
- * @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL
+ * @see NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
*/
@JvmStatic
fun setHttpUrlDeviceConfig(rule: DeviceConfigRule, url: String?) =
rule.setConfig(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, url)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL, url)
/**
* Set the test validation URL expiration.
*
- * @see NetworkStackUtils.TEST_URL_EXPIRATION_TIME
+ * @see NetworkStackConstants.TEST_URL_EXPIRATION_TIME
*/
@JvmStatic
fun setUrlExpirationDeviceConfig(rule: DeviceConfigRule, timestamp: Long?) =
rule.setConfig(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_URL_EXPIRATION_TIME, timestamp?.toString())
+ NetworkStackConstants.TEST_URL_EXPIRATION_TIME, timestamp?.toString())
}
diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java
index 8c5372d..d5e9c9e 100644
--- a/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsTetheringUtils.java
@@ -16,12 +16,18 @@
package android.net.cts.util;
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.ACCESS_WIFI_STATE;
+import static android.Manifest.permission.NETWORK_SETTINGS;
+import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -396,9 +402,14 @@
}
}
+ private static boolean isWifiEnabled(final WifiManager wm) {
+ return runAsShell(ACCESS_WIFI_STATE, () -> wm.isWifiEnabled());
+
+ }
+
private static void waitForWifiEnabled(final Context ctx) throws Exception {
WifiManager wm = ctx.getSystemService(WifiManager.class);
- if (wm.isWifiEnabled()) return;
+ if (isWifiEnabled(wm)) return;
final ConditionVariable mWaiting = new ConditionVariable();
final BroadcastReceiver receiver = new BroadcastReceiver() {
@@ -406,7 +417,7 @@
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
- if (wm.isWifiEnabled()) mWaiting.open();
+ if (isWifiEnabled(wm)) mWaiting.open();
}
}
};
@@ -414,7 +425,7 @@
ctx.registerReceiver(receiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
assertTrue("Wifi did not become enabled after " + DEFAULT_TIMEOUT_MS + "ms",
- wm.isWifiEnabled());
+ isWifiEnabled(wm));
}
} finally {
ctx.unregisterReceiver(receiver);
@@ -425,14 +436,16 @@
final TestTetheringEventCallback tetherEventCallback =
new TestTetheringEventCallback();
- mTm.registerTetheringEventCallback(c -> c.run() /* executor */, tetherEventCallback);
- tetherEventCallback.expectCallbackStarted();
+ runAsShell(ACCESS_NETWORK_STATE, NETWORK_SETTINGS, () -> {
+ mTm.registerTetheringEventCallback(c -> c.run() /* executor */, tetherEventCallback);
+ tetherEventCallback.expectCallbackStarted();
+ });
return tetherEventCallback;
}
public void unregisterTetheringEventCallback(final TestTetheringEventCallback callback) {
- mTm.unregisterTetheringEventCallback(callback);
+ runAsShell(ACCESS_NETWORK_STATE, () -> mTm.unregisterTetheringEventCallback(callback));
}
private static List<String> getWifiTetherableInterfaceRegexps(
@@ -446,11 +459,11 @@
if (!pm.hasSystemFeature(PackageManager.FEATURE_WIFI)) return false;
final WifiManager wm = ctx.getSystemService(WifiManager.class);
// Wifi feature flags only work when wifi is on.
- final boolean previousWifiEnabledState = wm.isWifiEnabled();
+ final boolean previousWifiEnabledState = isWifiEnabled(wm);
try {
if (!previousWifiEnabledState) SystemUtil.runShellCommand("svc wifi enable");
waitForWifiEnabled(ctx);
- return wm.isPortableHotspotSupported();
+ return runAsShell(ACCESS_WIFI_STATE, () -> wm.isPortableHotspotSupported());
} finally {
if (!previousWifiEnabledState) SystemUtil.runShellCommand("svc wifi disable");
}
@@ -463,17 +476,20 @@
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
.setShouldShowEntitlementUi(false).build();
- mTm.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
- startTetheringCallback.verifyTetheringStarted();
- final TetheringInterface iface =
- callback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI);
+ return runAsShell(TETHER_PRIVILEGED, () -> {
+ mTm.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
+ startTetheringCallback.verifyTetheringStarted();
- callback.expectOneOfOffloadStatusChanged(
- TETHER_HARDWARE_OFFLOAD_STARTED,
- TETHER_HARDWARE_OFFLOAD_FAILED);
+ final TetheringInterface iface =
+ callback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI);
- return iface;
+ callback.expectOneOfOffloadStatusChanged(
+ TETHER_HARDWARE_OFFLOAD_STARTED,
+ TETHER_HARDWARE_OFFLOAD_FAILED);
+
+ return iface;
+ });
}
private static class StopSoftApCallback implements SoftApCallback {
@@ -501,23 +517,33 @@
public void expectSoftApDisabled() {
final StopSoftApCallback callback = new StopSoftApCallback();
try {
- mWm.registerSoftApCallback(c -> c.run(), callback);
+ runAsShell(NETWORK_SETTINGS, () -> mWm.registerSoftApCallback(c -> c.run(), callback));
// registerSoftApCallback will immediately call the callback with the current state, so
// this callback will fire even if softAp is already disabled.
callback.waitForSoftApStopped();
} finally {
- mWm.unregisterSoftApCallback(callback);
+ runAsShell(NETWORK_SETTINGS, () -> mWm.unregisterSoftApCallback(callback));
}
}
public void stopWifiTethering(final TestTetheringEventCallback callback) {
- mTm.stopTethering(TETHERING_WIFI);
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ mTm.stopTethering(TETHERING_WIFI);
+ callback.expectNoTetheringActive();
+ callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
+ });
expectSoftApDisabled();
- callback.expectNoTetheringActive();
- callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
}
public void stopAllTethering() {
- mTm.stopAllTethering();
+ final TestTetheringEventCallback callback = registerTetheringEventCallback();
+ try {
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ mTm.stopAllTethering();
+ callback.expectNoTetheringActive();
+ });
+ } finally {
+ unregisterTetheringEventCallback(callback);
+ }
}
}
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index 6096a8b..42949a4 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -53,10 +53,12 @@
// mainline modules on release devices.
android_test {
name: "CtsTetheringTestLatestSdk",
- defaults: ["CtsTetheringTestDefaults"],
+ defaults: [
+ "ConnectivityTestsLatestSdkDefaults",
+ "CtsTetheringTestDefaults",
+ ],
min_sdk_version: "30",
- target_sdk_version: "33",
static_libs: [
"TetheringIntegrationTestsLatestSdkLib",
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index bd1b74a..274596f 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -15,6 +15,8 @@
*/
package android.tethering.test;
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -28,6 +30,8 @@
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.cts.util.CtsTetheringUtils.isAnyIfaceMatch;
+import static com.android.testutils.TestPermissionUtil.runAsShell;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -37,7 +41,6 @@
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import android.app.UiAutomation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -97,21 +100,8 @@
private static final int DEFAULT_TIMEOUT_MS = 60_000;
- private void adoptShellPermissionIdentity() {
- final UiAutomation uiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
- uiAutomation.adoptShellPermissionIdentity();
- }
-
- private void dropShellPermissionIdentity() {
- final UiAutomation uiAutomation =
- InstrumentationRegistry.getInstrumentation().getUiAutomation();
- uiAutomation.dropShellPermissionIdentity();
- }
-
@Before
public void setUp() throws Exception {
- adoptShellPermissionIdentity();
mContext = InstrumentationRegistry.getContext();
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mTM = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE);
@@ -128,9 +118,8 @@
@After
public void tearDown() throws Exception {
- mTM.stopAllTethering();
+ mCtsTetheringUtils.stopAllTethering();
mContext.unregisterReceiver(mTetherChangeReceiver);
- dropShellPermissionIdentity();
}
private class TetherChangeReceiver extends BroadcastReceiver {
@@ -208,22 +197,19 @@
mCtsTetheringUtils.registerTetheringEventCallback();
try {
tetherEventCallback.assumeWifiTetheringSupported(mContext);
+ tetherEventCallback.expectNoTetheringActive();
+
+ final String[] wifiRegexs = mTM.getTetherableWifiRegexs();
+ mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
+
+ mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs);
+
+ mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
+ mTetherChangeReceiver.expectTethering(false /* active */, wifiRegexs);
} finally {
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
}
- final String[] wifiRegexs = mTM.getTetherableWifiRegexs();
- final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
- final TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI)
- .setShouldShowEntitlementUi(false).build();
- mTM.startTethering(request, c -> c.run() /* executor */, startTetheringCallback);
- startTetheringCallback.verifyTetheringStarted();
-
- mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs);
-
- mTM.stopTethering(TETHERING_WIFI);
- mCtsTetheringUtils.expectSoftApDisabled();
- mTetherChangeReceiver.expectTethering(false /* active */, wifiRegexs);
}
@Test
@@ -267,7 +253,7 @@
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
try {
- final int ret = mTM.tether(wifiTetheringIface);
+ final int ret = runAsShell(TETHER_PRIVILEGED, () -> mTM.tether(wifiTetheringIface));
// There is no guarantee that the wifi interface will be available after disabling
// the hotspot, so don't fail the test if the call to tether() fails.
if (ret == TETHER_ERROR_NO_ERROR) {
@@ -277,7 +263,7 @@
new TetheringInterface(TETHERING_WIFI, wifiTetheringIface));
}
} finally {
- mTM.untether(wifiTetheringIface);
+ runAsShell(TETHER_PRIVILEGED, () -> mTM.untether(wifiTetheringIface));
}
} finally {
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
@@ -320,7 +306,7 @@
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
- mTM.stopAllTethering();
+ mCtsTetheringUtils.stopAllTethering();
tetherEventCallback.expectNoTetheringActive();
} finally {
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
@@ -329,7 +315,6 @@
@Test
public void testEnableTetheringPermission() throws Exception {
- dropShellPermissionIdentity();
final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
c -> c.run() /* executor */, startTetheringCallback);
@@ -352,15 +337,21 @@
private void assertEntitlementResult(final Consumer<EntitlementResultListener> functor,
final int expect) throws Exception {
- final EntitlementResultListener listener = new EntitlementResultListener();
- functor.accept(listener);
+ runAsShell(TETHER_PRIVILEGED, () -> {
+ final EntitlementResultListener listener = new EntitlementResultListener();
+ functor.accept(listener);
- assertEquals(expect, listener.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(expect, listener.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ });
+ }
+
+ private boolean isTetheringSupported() {
+ return runAsShell(TETHER_PRIVILEGED, () -> mTM.isTetheringSupported());
}
@Test
public void testRequestLatestEntitlementResult() throws Exception {
- assumeTrue(mTM.isTetheringSupported());
+ assumeTrue(isTetheringSupported());
assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY));
// Verify that requestLatestTetheringEntitlementResult() can get entitlement
// result(TETHER_ERROR_ENTITLEMENT_UNKNOWN due to invalid downstream type) via listener.
@@ -407,7 +398,13 @@
final CarrierConfigManager configManager = (CarrierConfigManager) mContext
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
final int subId = SubscriptionManager.getDefaultSubscriptionId();
- configManager.overrideConfig(subId, bundle);
+ runAsShell(MODIFY_PHONE_STATE, () -> configManager.overrideConfig(subId, bundle));
+ }
+
+ private boolean isTetheringApnRequired() {
+ final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ return runAsShell(MODIFY_PHONE_STATE, () -> tm.isTetheringApnRequired());
+
}
@Test
@@ -447,10 +444,8 @@
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
- final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
- Context.TELEPHONY_SERVICE);
- final boolean dunRequired = telephonyManager.isTetheringApnRequired();
- final int expectedCap = dunRequired ? NET_CAPABILITY_DUN : NET_CAPABILITY_INTERNET;
+ final int expectedCap = isTetheringApnRequired()
+ ? NET_CAPABILITY_DUN : NET_CAPABILITY_INTERNET;
final Network network = tetherEventCallback.getCurrentValidUpstream();
final NetworkCapabilities netCap = mCm.getNetworkCapabilities(network);
assertTrue(netCap.hasTransport(TRANSPORT_CELLULAR));
diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp
index b3684ac..e3d80a0 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -21,7 +21,7 @@
android_test {
name: "FrameworksNetIntegrationTests",
- defaults: ["framework-connectivity-test-defaults"],
+ defaults: ["framework-connectivity-internal-test-defaults"],
platform_apis: true,
certificate: "platform",
srcs: [
@@ -71,8 +71,12 @@
"net-tests-utils",
],
libs: [
- "service-connectivity-for-tests",
+ "service-connectivity-pre-jarjar",
"services.core",
"services.net",
],
+ visibility: [
+ "//packages/modules/Connectivity/tests/integration",
+ "//packages/modules/Connectivity/tests/unit",
+ ],
}
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index 2613363..67b4f42 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -87,13 +87,13 @@
SHARED "map_block_blocked_ports_map",
SHARED "map_clatd_clat_egress4_map",
SHARED "map_clatd_clat_ingress6_map",
- SHARED "map_dscp_policy_ipv4_dscp_policies_map",
- SHARED "map_dscp_policy_ipv4_socket_to_policies_map_A",
- SHARED "map_dscp_policy_ipv4_socket_to_policies_map_B",
- SHARED "map_dscp_policy_ipv6_dscp_policies_map",
- SHARED "map_dscp_policy_ipv6_socket_to_policies_map_A",
- SHARED "map_dscp_policy_ipv6_socket_to_policies_map_B",
- SHARED "map_dscp_policy_switch_comp_map",
+ SHARED "map_dscpPolicy_ipv4_dscp_policies_map",
+ SHARED "map_dscpPolicy_ipv4_socket_to_policies_map_A",
+ SHARED "map_dscpPolicy_ipv4_socket_to_policies_map_B",
+ SHARED "map_dscpPolicy_ipv6_dscp_policies_map",
+ SHARED "map_dscpPolicy_ipv6_socket_to_policies_map_A",
+ SHARED "map_dscpPolicy_ipv6_socket_to_policies_map_B",
+ SHARED "map_dscpPolicy_switch_comp_map",
NETD "map_netd_app_uid_stats_map",
NETD "map_netd_configuration_map",
NETD "map_netd_cookie_tag_map",
@@ -126,8 +126,8 @@
// Provided by *current* mainline module for T+ devices with 5.15+ kernels
static const set<string> MAINLINE_FOR_T_5_15_PLUS = {
- SHARED "prog_dscp_policy_schedcls_set_dscp_ether",
- SHARED "prog_dscp_policy_schedcls_set_dscp_raw_ip",
+ SHARED "prog_dscpPolicy_schedcls_set_dscp_ether",
+ SHARED "prog_dscpPolicy_schedcls_set_dscp_raw_ip",
};
void addAll(set<string>* a, const set<string>& b) {
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 58d002a..07884cf 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.net.nsd.NsdManager.FAILURE_INTERNAL_ERROR;
+
import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -44,11 +46,15 @@
import android.net.mdns.aidl.DiscoveryInfo;
import android.net.mdns.aidl.GetAddressInfo;
import android.net.mdns.aidl.IMDnsEventListener;
+import android.net.mdns.aidl.RegistrationInfo;
import android.net.mdns.aidl.ResolutionInfo;
import android.net.nsd.INsdManagerCallback;
import android.net.nsd.INsdServiceConnector;
import android.net.nsd.MDnsManager;
import android.net.nsd.NsdManager;
+import android.net.nsd.NsdManager.DiscoveryListener;
+import android.net.nsd.NsdManager.RegistrationListener;
+import android.net.nsd.NsdManager.ResolveListener;
import android.net.nsd.NsdServiceInfo;
import android.os.Binder;
import android.os.Build;
@@ -226,7 +232,7 @@
request.setPort(PORT);
// Client registration request
- NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
+ final RegistrationListener listener1 = mock(RegistrationListener.class);
client.registerService(request, PROTOCOL, listener1);
waitForIdle();
verify(mMockMDnsM).registerEventListener(any());
@@ -235,13 +241,13 @@
eq(2), eq(SERVICE_NAME), eq(SERVICE_TYPE), eq(PORT), any(), eq(IFACE_IDX_ANY));
// Client discovery request
- NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class);
+ final DiscoveryListener listener2 = mock(DiscoveryListener.class);
client.discoverServices(SERVICE_TYPE, PROTOCOL, listener2);
waitForIdle();
verify(mMockMDnsM).discover(3 /* id */, SERVICE_TYPE, IFACE_IDX_ANY);
// Client resolve request
- NsdManager.ResolveListener listener3 = mock(NsdManager.ResolveListener.class);
+ final ResolveListener listener3 = mock(ResolveListener.class);
client.resolveService(request, listener3);
waitForIdle();
verify(mMockMDnsM).resolve(
@@ -263,7 +269,7 @@
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
request.setPort(PORT);
- NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
+ final RegistrationListener listener1 = mock(RegistrationListener.class);
client.registerService(request, PROTOCOL, listener1);
waitForIdle();
verify(mMockMDnsM).registerEventListener(any());
@@ -285,17 +291,22 @@
verify(mMockMDnsM, never()).stopDaemon();
}
+ private IMDnsEventListener getEventListener() {
+ final ArgumentCaptor<IMDnsEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(IMDnsEventListener.class);
+ verify(mMockMDnsM).registerEventListener(listenerCaptor.capture());
+ return listenerCaptor.getValue();
+ }
+
@Test
public void testDiscoverOnTetheringDownstream() throws Exception {
final NsdManager client = connectClient(mService);
final int interfaceIdx = 123;
- final NsdManager.DiscoveryListener discListener = mock(NsdManager.DiscoveryListener.class);
+ final DiscoveryListener discListener = mock(DiscoveryListener.class);
client.discoverServices(SERVICE_TYPE, PROTOCOL, discListener);
waitForIdle();
- final ArgumentCaptor<IMDnsEventListener> listenerCaptor =
- ArgumentCaptor.forClass(IMDnsEventListener.class);
- verify(mMockMDnsM).registerEventListener(listenerCaptor.capture());
+ final IMDnsEventListener eventListener = getEventListener();
final ArgumentCaptor<Integer> discIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMockMDnsM).discover(discIdCaptor.capture(), eq(SERVICE_TYPE),
eq(0) /* interfaceIdx */);
@@ -311,7 +322,6 @@
DOMAIN_NAME,
interfaceIdx,
INetd.LOCAL_NET_ID); // LOCAL_NET_ID (99) used on tethering downstreams
- final IMDnsEventListener eventListener = listenerCaptor.getValue();
eventListener.onServiceDiscoveryStatus(discoveryInfo);
waitForIdle();
@@ -326,7 +336,7 @@
assertEquals(interfaceIdx, foundInfo.getInterfaceIndex());
// After discovering the service, verify resolving it
- final NsdManager.ResolveListener resolveListener = mock(NsdManager.ResolveListener.class);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
client.resolveService(foundInfo, resolveListener);
waitForIdle();
@@ -378,6 +388,154 @@
assertEquals(interfaceIdx, resolvedService.getInterfaceIndex());
}
+ @Test
+ public void testServiceRegistrationSuccessfulAndFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ request.setPort(PORT);
+ final RegistrationListener regListener = mock(RegistrationListener.class);
+ client.registerService(request, PROTOCOL, regListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> regIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).registerService(regIdCaptor.capture(),
+ eq(SERVICE_NAME), eq(SERVICE_TYPE), eq(PORT), any(), eq(IFACE_IDX_ANY));
+
+ // Register service successfully.
+ final RegistrationInfo registrationInfo = new RegistrationInfo(
+ regIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_REGISTERED,
+ SERVICE_NAME,
+ SERVICE_TYPE,
+ PORT,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ eventListener.onServiceRegistrationStatus(registrationInfo);
+
+ final ArgumentCaptor<NsdServiceInfo> registeredInfoCaptor =
+ ArgumentCaptor.forClass(NsdServiceInfo.class);
+ verify(regListener, timeout(TIMEOUT_MS))
+ .onServiceRegistered(registeredInfoCaptor.capture());
+ final NsdServiceInfo registeredInfo = registeredInfoCaptor.getValue();
+ assertEquals(SERVICE_NAME, registeredInfo.getServiceName());
+
+ // Fail to register service.
+ final RegistrationInfo registrationFailedInfo = new RegistrationInfo(
+ regIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_REGISTRATION_FAILED,
+ null /* serviceName */,
+ null /* registrationType */,
+ 0 /* port */,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ eventListener.onServiceRegistrationStatus(registrationFailedInfo);
+ verify(regListener, timeout(TIMEOUT_MS))
+ .onRegistrationFailed(any(), eq(FAILURE_INTERNAL_ERROR));
+ }
+
+ @Test
+ public void testServiceDiscoveryFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final DiscoveryListener discListener = mock(DiscoveryListener.class);
+ client.discoverServices(SERVICE_TYPE, PROTOCOL, discListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> discIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).discover(discIdCaptor.capture(), eq(SERVICE_TYPE), eq(IFACE_IDX_ANY));
+ verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+
+ // Fail to discover service.
+ final DiscoveryInfo discoveryFailedInfo = new DiscoveryInfo(
+ discIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_DISCOVERY_FAILED,
+ null /* serviceName */,
+ null /* registrationType */,
+ null /* domainName */,
+ IFACE_IDX_ANY,
+ 0 /* netId */);
+ eventListener.onServiceDiscoveryStatus(discoveryFailedInfo);
+ verify(discListener, timeout(TIMEOUT_MS))
+ .onStartDiscoveryFailed(SERVICE_TYPE, FAILURE_INTERNAL_ERROR);
+ }
+
+ @Test
+ public void testServiceResolutionFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
+ client.resolveService(request, resolveListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+ eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+ // Fail to resolve service.
+ final ResolutionInfo resolutionFailedInfo = new ResolutionInfo(
+ resolvIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_RESOLUTION_FAILED,
+ null /* serviceName */,
+ null /* serviceType */,
+ null /* domain */,
+ null /* serviceFullName */,
+ null /* domainName */,
+ 0 /* port */,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ eventListener.onServiceResolutionStatus(resolutionFailedInfo);
+ verify(resolveListener, timeout(TIMEOUT_MS))
+ .onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR));
+ }
+
+ @Test
+ public void testGettingAddressFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
+ client.resolveService(request, resolveListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+ eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+ // Resolve service successfully.
+ final ResolutionInfo resolutionInfo = new ResolutionInfo(
+ resolvIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_RESOLVED,
+ null /* serviceName */,
+ null /* serviceType */,
+ null /* domain */,
+ SERVICE_FULL_NAME,
+ DOMAIN_NAME,
+ PORT,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ doReturn(true).when(mMockMDnsM).getServiceAddress(anyInt(), any(), anyInt());
+ eventListener.onServiceResolutionStatus(resolutionInfo);
+ waitForIdle();
+
+ final ArgumentCaptor<Integer> getAddrIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).getServiceAddress(getAddrIdCaptor.capture(), eq(DOMAIN_NAME),
+ eq(IFACE_IDX_ANY));
+
+ // Fail to get service address.
+ final GetAddressInfo gettingAddrFailedInfo = new GetAddressInfo(
+ getAddrIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_GET_ADDR_FAILED,
+ null /* hostname */,
+ null /* address */,
+ IFACE_IDX_ANY,
+ 0 /* netId */);
+ eventListener.onGettingServiceAddressStatus(gettingAddrFailedInfo);
+ verify(resolveListener, timeout(TIMEOUT_MS))
+ .onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR));
+ }
+
private void waitForIdle() {
HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS);
}
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 5c1992d..6f25d1b 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -969,6 +969,31 @@
AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, AppOpsManager.OPSTR_ACTIVATE_VPN);
}
+ private void setAppOpsPermission() {
+ doAnswer(invocation -> {
+ when(mAppOps.noteOpNoThrow(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN,
+ Process.myUid(), TEST_VPN_PKG,
+ null /* attributionTag */, null /* message */))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+ return null;
+ }).when(mAppOps).setMode(
+ eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN),
+ eq(Process.myUid()),
+ eq(TEST_VPN_PKG),
+ eq(AppOpsManager.MODE_ALLOWED));
+ }
+
+ @Test
+ public void testProvisionVpnProfileNotPreconsented_withControlVpnPermission() throws Exception {
+ setAppOpsPermission();
+ doReturn(PERMISSION_GRANTED).when(mContext).checkCallingOrSelfPermission(CONTROL_VPN);
+ final Vpn vpn = createVpnAndSetupUidChecks();
+
+ // ACTIVATE_PLATFORM_VPN will be granted if VPN app has CONTROL_VPN permission.
+ checkProvisionVpnProfile(vpn, true /* expectedResult */,
+ AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ }
+
@Test
public void testProvisionVpnProfileVpnServicePreconsented() throws Exception {
final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN);
@@ -1589,6 +1614,30 @@
assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state);
}
+ @Test
+ public void testVpnManagerEventWillNotBeSentToSettingsVpn() throws Exception {
+ startLegacyVpn(createVpn(PRIMARY_USER.id), mVpnProfile);
+ triggerOnAvailableAndGetCallback();
+
+ verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
+
+ final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
+ final IkeTimeoutException ikeTimeoutException =
+ new IkeTimeoutException("IkeTimeoutException");
+ when(exception.getCause()).thenReturn(ikeTimeoutException);
+
+ final ArgumentCaptor<IkeSessionCallback> captor =
+ ArgumentCaptor.forClass(IkeSessionCallback.class);
+ verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
+ .createIkeSession(any(), any(), any(), any(), captor.capture(), any());
+ final IkeSessionCallback ikeCb = captor.getValue();
+ ikeCb.onClosedWithException(exception);
+
+ final Context userContext =
+ mContext.createContextAsUser(UserHandle.of(PRIMARY_USER.id), 0 /* flags */);
+ verify(userContext, never()).startService(any());
+ }
+
private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) {
assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null));
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
index 8a18ee7..503d920 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
@@ -313,21 +313,28 @@
assertTrue(ret);
verify(mIpClient).shutdown();
- assertEquals(listener.expectOnResult(), TEST_IFACE);
+ assertEquals(TEST_IFACE, listener.expectOnResult());
}
@Test
public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception {
initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
- final TestNetworkManagementListener listener = new TestNetworkManagementListener();
+ final TestNetworkManagementListener listenerDown = new TestNetworkManagementListener();
+ final TestNetworkManagementListener listenerUp = new TestNetworkManagementListener();
- final boolean ret =
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener);
+ final boolean retDown =
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listenerDown);
- assertTrue(ret);
+ assertTrue(retDown);
verifyStop();
- assertEquals(listener.expectOnResult(), TEST_IFACE);
+ assertEquals(TEST_IFACE, listenerDown.expectOnResult());
+
+ final boolean retUp =
+ mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */, listenerUp);
+
+ assertTrue(retUp);
+ assertEquals(TEST_IFACE, listenerUp.expectOnResult());
}
@Test
@@ -344,7 +351,7 @@
verify(mDeps, never()).makeIpClient(any(), any(), any());
verify(mDeps, never())
.makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any());
- assertEquals(listener.expectOnResult(), TEST_IFACE);
+ assertEquals(TEST_IFACE, listener.expectOnResult());
}
@Test
@@ -609,7 +616,7 @@
mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
triggerOnProvisioningSuccess();
- assertEquals(listener.expectOnResult(), TEST_IFACE);
+ assertEquals(TEST_IFACE, listener.expectOnResult());
}
@Test
@@ -655,6 +662,7 @@
});
assertEquals(successfulListener.expectOnResult(), TEST_IFACE);
+ assertEquals(TEST_IFACE, successfulListener.expectOnResult());
}
private void verifyNetworkManagementCallIsAbortedWhenInterrupted(
@@ -683,7 +691,7 @@
mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener);
triggerOnProvisioningSuccess();
- assertEquals(listener.expectOnResult(), TEST_IFACE);
+ assertEquals(TEST_IFACE, listener.expectOnResult());
verify(mDeps).makeEthernetNetworkAgent(any(), any(),
eq(capabilities), any(), any(), any(), any());
verifyRestart(ipConfiguration);