Merge "Obtain the target socket directly to send packets" into main
diff --git a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
index 898b124..4c9460b 100644
--- a/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/30/com/android/networkstack/tethering/apishim/api30/BpfCoordinatorShimImpl.java
@@ -17,6 +17,7 @@
package com.android.networkstack.tethering.apishim.api30;
import android.net.INetd;
+import android.net.IpPrefix;
import android.net.MacAddress;
import android.net.TetherStatsParcel;
import android.os.RemoteException;
@@ -81,14 +82,14 @@
@Override
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
- @NonNull MacAddress inDstMac, @NonNull MacAddress outSrcMac,
- @NonNull MacAddress outDstMac, int mtu) {
+ @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
+ @NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac, int mtu) {
return true;
}
@Override
- public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex,
- int upstreamIfindex, @NonNull MacAddress inDstMac) {
+ public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
+ @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac) {
return true;
}
diff --git a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
index 3cad1c6..119fbc6 100644
--- a/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
+++ b/Tethering/apishim/31/com/android/networkstack/tethering/apishim/api31/BpfCoordinatorShimImpl.java
@@ -18,6 +18,9 @@
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
+import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
+
+import android.net.IpPrefix;
import android.net.MacAddress;
import android.system.ErrnoException;
import android.system.Os;
@@ -48,6 +51,9 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
/**
* Bpf coordinator class for API shims.
@@ -196,13 +202,23 @@
return true;
}
+ @NonNull
+ private TetherUpstream6Key makeUpstream6Key(int downstreamIfindex, @NonNull MacAddress inDstMac,
+ @NonNull IpPrefix sourcePrefix) {
+ byte[] prefixBytes = Arrays.copyOf(sourcePrefix.getRawAddress(), 8);
+ long prefix64 = ByteBuffer.wrap(prefixBytes).order(ByteOrder.BIG_ENDIAN).getLong();
+ return new TetherUpstream6Key(downstreamIfindex, inDstMac, prefix64);
+ }
+
@Override
public boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
- @NonNull MacAddress inDstMac, @NonNull MacAddress outSrcMac,
- @NonNull MacAddress outDstMac, int mtu) {
+ @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
+ @NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac, int mtu) {
if (!isInitialized()) return false;
+ // RFC7421_PREFIX_LENGTH = 64 which is the most commonly used IPv6 subnet prefix length.
+ if (sourcePrefix.getPrefixLength() != RFC7421_PREFIX_LENGTH) return false;
- final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfindex, inDstMac);
+ final TetherUpstream6Key key = makeUpstream6Key(downstreamIfindex, inDstMac, sourcePrefix);
final Tether6Value value = new Tether6Value(upstreamIfindex, outSrcMac,
outDstMac, OsConstants.ETH_P_IPV6, mtu);
try {
@@ -216,10 +232,12 @@
@Override
public boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
- @NonNull MacAddress inDstMac) {
+ @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac) {
if (!isInitialized()) return false;
+ // RFC7421_PREFIX_LENGTH = 64 which is the most commonly used IPv6 subnet prefix length.
+ if (sourcePrefix.getPrefixLength() != RFC7421_PREFIX_LENGTH) return false;
- final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfindex, inDstMac);
+ final TetherUpstream6Key key = makeUpstream6Key(downstreamIfindex, inDstMac, sourcePrefix);
try {
mBpfUpstream6Map.deleteEntry(key);
} catch (ErrnoException e) {
diff --git a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
index 51cecfe..25fa8bc 100644
--- a/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
+++ b/Tethering/apishim/common/com/android/networkstack/tethering/apishim/common/BpfCoordinatorShim.java
@@ -16,6 +16,7 @@
package com.android.networkstack.tethering.apishim.common;
+import android.net.IpPrefix;
import android.net.MacAddress;
import android.util.SparseArray;
@@ -79,25 +80,27 @@
* @param downstreamIfindex the downstream interface index
* @param upstreamIfindex the upstream interface index
+ * @param sourcePrefix the source IPv6 prefix
* @param inDstMac the destination MAC address to use for XDP
* @param outSrcMac the source MAC address to use for packets
* @param outDstMac the destination MAC address to use for packets
* @return true if operation succeeded or was a no-op, false otherwise
*/
public abstract boolean startUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
- @NonNull MacAddress inDstMac, @NonNull MacAddress outSrcMac,
- @NonNull MacAddress outDstMac, int mtu);
+ @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac,
+ @NonNull MacAddress outSrcMac, @NonNull MacAddress outDstMac, int mtu);
/**
* Stops IPv6 forwarding between the specified interfaces.
* @param downstreamIfindex the downstream interface index
* @param upstreamIfindex the upstream interface index
+ * @param sourcePrefix the valid source IPv6 prefix
* @param inDstMac the destination MAC address to use for XDP
* @return true if operation succeeded or was a no-op, false otherwise
*/
- public abstract boolean stopUpstreamIpv6Forwarding(int downstreamIfindex,
- int upstreamIfindex, @NonNull MacAddress inDstMac);
+ public abstract boolean stopUpstreamIpv6Forwarding(int downstreamIfindex, int upstreamIfindex,
+ @NonNull IpPrefix sourcePrefix, @NonNull MacAddress inDstMac);
/**
* Return BPF tethering offload statistics.
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 6affb62..56b5c2e 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -28,11 +28,11 @@
import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
-import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.net.util.NetworkConstants.asByte;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
+import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
import static com.android.networkstack.tethering.UpstreamNetworkState.isVcnInterface;
import static com.android.networkstack.tethering.util.PrefixUtils.asIpPrefix;
import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_IPSERVER;
diff --git a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index 18c2171..50d6c4b 100644
--- a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -16,7 +16,6 @@
package android.net.ip;
-import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.IPPROTO_ICMPV6;
import static android.system.OsConstants.SOCK_RAW;
@@ -30,6 +29,7 @@
import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_AUTONOMOUS;
import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_ON_LINK;
+import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
import static com.android.net.module.util.NetworkStackConstants.TAG_SYSTEM_NEIGHBOR;
import static com.android.networkstack.tethering.util.TetheringUtils.getAllNodesForScopeId;
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 976f5df..f22ccbd 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -37,6 +37,7 @@
import android.app.usage.NetworkStatsManager;
import android.net.INetd;
+import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.NetworkStats;
@@ -119,6 +120,7 @@
private static final int DUMP_TIMEOUT_MS = 10_000;
private static final MacAddress NULL_MAC_ADDRESS = MacAddress.fromString(
"00:00:00:00:00:00");
+ private static final IpPrefix IPV6_ZERO_PREFIX64 = new IpPrefix("::/64");
private static final String TETHER_DOWNSTREAM4_MAP_PATH = makeMapPath(DOWNSTREAM, 4);
private static final String TETHER_UPSTREAM4_MAP_PATH = makeMapPath(UPSTREAM, 4);
private static final String TETHER_DOWNSTREAM6_FS_PATH = makeMapPath(DOWNSTREAM, 6);
@@ -615,8 +617,9 @@
final int upstream = rule.upstreamIfindex;
// TODO: support upstream forwarding on non-point-to-point interfaces.
// TODO: get the MTU from LinkProperties and update the rules when it changes.
- if (!mBpfCoordinatorShim.startUpstreamIpv6Forwarding(downstream, upstream, rule.srcMac,
- NULL_MAC_ADDRESS, NULL_MAC_ADDRESS, NetworkStackConstants.ETHER_MTU)) {
+ if (!mBpfCoordinatorShim.startUpstreamIpv6Forwarding(downstream, upstream,
+ IPV6_ZERO_PREFIX64, rule.srcMac, NULL_MAC_ADDRESS, NULL_MAC_ADDRESS,
+ NetworkStackConstants.ETHER_MTU)) {
mLog.e("Failed to enable upstream IPv6 forwarding from "
+ getIfName(downstream) + " to " + getIfName(upstream));
}
@@ -657,7 +660,7 @@
final int downstream = rule.downstreamIfindex;
final int upstream = rule.upstreamIfindex;
if (!mBpfCoordinatorShim.stopUpstreamIpv6Forwarding(downstream, upstream,
- rule.srcMac)) {
+ IPV6_ZERO_PREFIX64, rule.srcMac)) {
mLog.e("Failed to disable upstream IPv6 forwarding from "
+ getIfName(downstream) + " to " + getIfName(upstream));
}
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index de15c5b..53c80ae 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -283,13 +283,16 @@
private int initWithHandles(NativeHandle h1, NativeHandle h2) {
if (h1 == null || h2 == null) {
+ // Set mIOffload to null has two purposes:
+ // 1. NativeHandles can be closed after initWithHandles() fails
+ // 2. Prevent mIOffload.stopOffload() to be called in stopOffload()
+ mIOffload = null;
mLog.e("Failed to create socket.");
return OFFLOAD_HAL_VERSION_NONE;
}
requestSocketDump(h1);
if (!mIOffload.initOffload(h1, h2, mOffloadHalCallback)) {
- mIOffload.stopOffload();
mLog.e("Failed to initialize offload.");
return OFFLOAD_HAL_VERSION_NONE;
}
@@ -329,9 +332,9 @@
mOffloadHalCallback = offloadCb;
final int version = initWithHandles(h1, h2);
- // Explicitly close FDs for HIDL. AIDL will pass the original FDs to the service,
- // they shouldn't be closed here.
- if (version < OFFLOAD_HAL_VERSION_AIDL) {
+ // Explicitly close FDs for HIDL or when mIOffload is null (cleared in initWithHandles).
+ // AIDL will pass the original FDs to the service, they shouldn't be closed here.
+ if (mIOffload == null || mIOffload.getVersion() < OFFLOAD_HAL_VERSION_AIDL) {
maybeCloseFdInNativeHandles(h1, h2);
}
return version;
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherUpstream6Key.java b/Tethering/src/com/android/networkstack/tethering/TetherUpstream6Key.java
index 5893885..36a1c3c 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetherUpstream6Key.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetherUpstream6Key.java
@@ -29,13 +29,17 @@
@Field(order = 0, type = Type.S32)
public final int iif; // The input interface index.
- @Field(order = 1, type = Type.EUI48, padding = 2)
+ @Field(order = 1, type = Type.EUI48, padding = 6)
public final MacAddress dstMac; // Destination ethernet mac address (zeroed iff rawip ingress).
- public TetherUpstream6Key(int iif, @NonNull final MacAddress dstMac) {
+ @Field(order = 2, type = Type.S64)
+ public final long src64; // The top 64-bits of the source ip.
+
+ public TetherUpstream6Key(int iif, @NonNull final MacAddress dstMac, long src64) {
Objects.requireNonNull(dstMac);
this.iif = iif;
this.dstMac = dstMac;
+ this.src64 = src64;
}
}
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 46e50ef..464778f 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -985,7 +985,7 @@
throws Exception {
if (!mBpfDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
- TEST_IFACE_PARAMS.macAddr);
+ TEST_IFACE_PARAMS.macAddr, 0);
final Tether6Value value = new Tether6Value(upstreamIfindex,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
@@ -996,7 +996,7 @@
throws Exception {
if (!mBpfDeps.isAtLeastS()) return;
final TetherUpstream6Key key = new TetherUpstream6Key(TEST_IFACE_PARAMS.index,
- TEST_IFACE_PARAMS.macAddr);
+ TEST_IFACE_PARAMS.macAddr, 0);
verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 4f32f3c..8bc4c18 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -641,7 +641,7 @@
private void verifyStartUpstreamIpv6Forwarding(@Nullable InOrder inOrder, int downstreamIfIndex,
MacAddress downstreamMac, int upstreamIfindex) throws Exception {
if (!mDeps.isAtLeastS()) return;
- final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac);
+ final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac, 0);
final Tether6Value value = new Tether6Value(upstreamIfindex,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
@@ -652,7 +652,7 @@
MacAddress downstreamMac)
throws Exception {
if (!mDeps.isAtLeastS()) return;
- final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac);
+ final TetherUpstream6Key key = new TetherUpstream6Key(downstreamIfIndex, downstreamMac, 0);
verifyWithOrder(inOrder, mBpfUpstream6Map).deleteEntry(key);
}
@@ -2192,7 +2192,7 @@
mBpfDownstream6Map.insertEntry(rule.makeTetherDownstream6Key(), rule.makeTether6Value());
final TetherUpstream6Key upstream6Key = new TetherUpstream6Key(DOWNSTREAM_IFINDEX,
- DOWNSTREAM_MAC);
+ DOWNSTREAM_MAC, 0);
final Tether6Value upstream6Value = new Tether6Value(UPSTREAM_IFINDEX,
MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS,
ETH_P_IPV6, NetworkStackConstants.ETHER_MTU);
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
index b1f875b..4413d26 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
@@ -20,6 +20,8 @@
import static android.system.OsConstants.AF_UNIX;
import static android.system.OsConstants.SOCK_STREAM;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_DESTROY;
+import static com.android.networkstack.tethering.OffloadHardwareInterface.NF_NETLINK_CONNTRACK_NEW;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_AIDL;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_1;
@@ -34,6 +36,7 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -57,7 +60,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
@@ -75,8 +77,9 @@
private OffloadHardwareInterface mOffloadHw;
private OffloadHalCallback mOffloadHalCallback;
- @Mock private IOffloadHal mIOffload;
- @Mock private NativeHandle mNativeHandle;
+ private IOffloadHal mIOffload;
+ private NativeHandle mNativeHandle1;
+ private NativeHandle mNativeHandle2;
// Random values to test Netlink message.
private static final short TEST_TYPE = 184;
@@ -97,7 +100,9 @@
@Override
public NativeHandle createConntrackSocket(final int groups) {
- return mNativeHandle;
+ return groups == (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY)
+ ? mNativeHandle1
+ : mNativeHandle2;
}
}
@@ -105,45 +110,89 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mOffloadHalCallback = new OffloadHalCallback();
- when(mIOffload.initOffload(any(NativeHandle.class), any(NativeHandle.class),
- any(OffloadHalCallback.class))).thenReturn(true);
+ mIOffload = mock(IOffloadHal.class);
}
- private void startOffloadHardwareInterface(int offloadHalVersion)
+ private void startOffloadHardwareInterface(int offloadHalVersion, boolean isHalInitSuccess)
throws Exception {
+ startOffloadHardwareInterface(offloadHalVersion, isHalInitSuccess, mock(NativeHandle.class),
+ mock(NativeHandle.class));
+ }
+
+ private void startOffloadHardwareInterface(int offloadHalVersion, boolean isHalInitSuccess,
+ NativeHandle handle1, NativeHandle handle2) throws Exception {
final SharedLog log = new SharedLog("test");
final Handler handler = new Handler(mTestLooper.getLooper());
- final int num = offloadHalVersion != OFFLOAD_HAL_VERSION_NONE ? 1 : 0;
+ final boolean hasNullHandle = handle1 == null || handle2 == null;
+ // If offloadHalVersion is OFFLOAD_HAL_VERSION_NONE or it has null NativeHandle arguments,
+ // mIOffload.initOffload() shouldn't be called.
+ final int initNum = (offloadHalVersion != OFFLOAD_HAL_VERSION_NONE && !hasNullHandle)
+ ? 1
+ : 0;
+ // If it is HIDL or has null NativeHandle argument, NativeHandles should be closed.
+ final int handleCloseNum = (hasNullHandle
+ || offloadHalVersion == OFFLOAD_HAL_VERSION_HIDL_1_0
+ || offloadHalVersion == OFFLOAD_HAL_VERSION_HIDL_1_1) ? 1 : 0;
+ mNativeHandle1 = handle1;
+ mNativeHandle2 = handle2;
+ when(mIOffload.initOffload(any(NativeHandle.class), any(NativeHandle.class),
+ any(OffloadHalCallback.class))).thenReturn(isHalInitSuccess);
mOffloadHw = new OffloadHardwareInterface(handler, log,
new MyDependencies(handler, log, offloadHalVersion));
- assertEquals(offloadHalVersion, mOffloadHw.initOffload(mOffloadHalCallback));
- verify(mIOffload, times(num)).initOffload(any(NativeHandle.class), any(NativeHandle.class),
- eq(mOffloadHalCallback));
+ assertEquals(isHalInitSuccess && !hasNullHandle
+ ? offloadHalVersion
+ : OFFLOAD_HAL_VERSION_NONE,
+ mOffloadHw.initOffload(mOffloadHalCallback));
+ verify(mIOffload, times(initNum)).initOffload(any(NativeHandle.class),
+ any(NativeHandle.class), eq(mOffloadHalCallback));
+ if (mNativeHandle1 != null) verify(mNativeHandle1, times(handleCloseNum)).close();
+ if (mNativeHandle2 != null) verify(mNativeHandle2, times(handleCloseNum)).close();
}
@Test
public void testInitFailureWithNoHal() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_NONE);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_NONE, true);
}
@Test
public void testInitSuccessWithAidl() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_AIDL);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_AIDL, true);
}
@Test
public void testInitSuccessWithHidl_1_0() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
}
@Test
public void testInitSuccessWithHidl_1_1() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1, true);
+ }
+
+ @Test
+ public void testInitFailWithAidl() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_AIDL, false);
+ }
+
+ @Test
+ public void testInitFailWithHidl_1_0() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, false);
+ }
+
+ @Test
+ public void testInitFailWithHidl_1_1() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1, false);
+ }
+
+ @Test
+ public void testInitFailDueToNullHandles() throws Exception {
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_AIDL, true, mock(NativeHandle.class),
+ null);
}
@Test
public void testGetForwardedStats() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
ForwardedStats stats = new ForwardedStats(12345, 56780);
when(mIOffload.getForwardedStats(anyString())).thenReturn(stats);
assertEquals(mOffloadHw.getForwardedStats(RMNET0), stats);
@@ -152,7 +201,7 @@
@Test
public void testSetLocalPrefixes() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
final ArrayList<String> localPrefixes = new ArrayList<>();
localPrefixes.add("127.0.0.0/8");
localPrefixes.add("fe80::/64");
@@ -165,7 +214,7 @@
@Test
public void testSetDataLimit() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
final long limit = 12345;
when(mIOffload.setDataLimit(anyString(), anyLong())).thenReturn(true);
assertTrue(mOffloadHw.setDataLimit(RMNET0, limit));
@@ -177,7 +226,7 @@
@Test
public void testSetDataWarningAndLimitFailureWithHidl_1_0() throws Exception {
// Verify V1.0 control HAL would reject the function call with exception.
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
final long warning = 12345;
final long limit = 67890;
assertThrows(UnsupportedOperationException.class,
@@ -187,7 +236,7 @@
@Test
public void testSetDataWarningAndLimit() throws Exception {
// Verify V1.1 control HAL could receive this function call.
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_1, true);
final long warning = 12345;
final long limit = 67890;
when(mIOffload.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(true);
@@ -199,7 +248,7 @@
@Test
public void testSetUpstreamParameters() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
final String v4addr = "192.168.10.1";
final String v4gateway = "192.168.10.255";
final ArrayList<String> v6gws = new ArrayList<>(0);
@@ -220,7 +269,7 @@
@Test
public void testUpdateDownstream() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
final String ifName = "wlan1";
final String prefix = "192.168.43.0/24";
when(mIOffload.addDownstream(anyString(), anyString())).thenReturn(true);
@@ -237,7 +286,7 @@
@Test
public void testSendIpv4NfGenMsg() throws Exception {
- startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0);
+ startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_HIDL_1_0, true);
FileDescriptor writeSocket = new FileDescriptor();
FileDescriptor readSocket = new FileDescriptor();
try {
@@ -246,9 +295,9 @@
fail();
return;
}
- when(mNativeHandle.getFileDescriptor()).thenReturn(writeSocket);
+ when(mNativeHandle1.getFileDescriptor()).thenReturn(writeSocket);
- mOffloadHw.sendIpv4NfGenMsg(mNativeHandle, TEST_TYPE, TEST_FLAGS);
+ mOffloadHw.sendIpv4NfGenMsg(mNativeHandle1, TEST_TYPE, TEST_FLAGS);
ByteBuffer buffer = ByteBuffer.allocate(9823); // Arbitrary value > expectedLen.
buffer.order(ByteOrder.nativeOrder());
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 9c6904d..770507e 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -68,6 +68,7 @@
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
+import static com.android.net.module.util.NetworkStackConstants.RFC7421_PREFIX_LENGTH;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_HIDL_1_0;
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
import static com.android.networkstack.tethering.TestConnectivityManager.BROADCAST_FIRST;
@@ -157,7 +158,6 @@
import android.net.ip.DadProxy;
import android.net.ip.IpServer;
import android.net.ip.RouterAdvertisementDaemon;
-import android.net.util.NetworkConstants;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiManager;
@@ -559,7 +559,7 @@
prop.addDnsServer(InetAddresses.parseNumericAddress("2001:db8::2"));
prop.addLinkAddress(
new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::"),
- NetworkConstants.RFC7421_PREFIX_LENGTH));
+ RFC7421_PREFIX_LENGTH));
prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
InetAddresses.parseNumericAddress("2001:db8::1"),
interfaceName, RTN_UNICAST));
diff --git a/bpf_progs/netd.h b/bpf_progs/netd.h
index be604f9..1326db0 100644
--- a/bpf_progs/netd.h
+++ b/bpf_progs/netd.h
@@ -65,8 +65,6 @@
uint64_t rxPackets;
uint64_t txBytes;
uint64_t txPackets;
- uint64_t tcpRxPackets;
- uint64_t tcpTxPackets;
} Stats;
typedef struct {
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index 8645dd7..c752779 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -194,6 +194,7 @@
TetherUpstream6Key ku = {
.iif = skb->ifindex,
+ .src64 = 0,
};
if (is_ethernet) __builtin_memcpy(downstream ? kd.dstMac : ku.dstMac, eth->h_dest, ETH_ALEN);
diff --git a/bpf_progs/offload.h b/bpf_progs/offload.h
index 9dae6c9..1e28f01 100644
--- a/bpf_progs/offload.h
+++ b/bpf_progs/offload.h
@@ -135,10 +135,10 @@
typedef struct {
uint32_t iif; // The input interface index
uint8_t dstMac[ETH_ALEN]; // destination ethernet mac address (zeroed iff rawip ingress)
- uint8_t zero[2]; // zero pad for 8 byte alignment
- // TODO: extend this to include src ip /64 subnet
+ uint8_t zero[6]; // zero pad for 8 byte alignment
+ uint64_t src64; // Top 64-bits of the src ip
} TetherUpstream6Key;
-STRUCT_SIZE(TetherUpstream6Key, 12);
+STRUCT_SIZE(TetherUpstream6Key, 4 + 6 + 6 + 8); // 24
typedef struct {
uint32_t iif; // The input interface index
diff --git a/framework-t/api/OWNERS b/framework-t/api/OWNERS
index de0f905..af583c3 100644
--- a/framework-t/api/OWNERS
+++ b/framework-t/api/OWNERS
@@ -1 +1,2 @@
file:platform/packages/modules/Connectivity:master:/nearby/OWNERS
+file:platform/packages/modules/Connectivity:master:/remoteauth/OWNERS
diff --git a/service-t/jni/com_android_server_net_NetworkStatsService.cpp b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
index 8d8dc32..ae553f0 100644
--- a/service-t/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/service-t/jni/com_android_server_net_NetworkStatsService.cpp
@@ -47,8 +47,8 @@
RX_PACKETS = 1,
TX_BYTES = 2,
TX_PACKETS = 3,
- TCP_RX_PACKETS = 4,
- TCP_TX_PACKETS = 5
+ TCP_RX_PACKETS = 4, // not supported, always returns UNKNOWN (-1)
+ TCP_TX_PACKETS = 5, // not supported, always returns UNKNOWN (-1)
};
static uint64_t getStatsType(Stats* stats, StatsType type) {
@@ -62,9 +62,7 @@
case TX_PACKETS:
return stats->txPackets;
case TCP_RX_PACKETS:
- return stats->tcpRxPackets;
case TCP_TX_PACKETS:
- return stats->tcpTxPackets;
default:
return UNKNOWN;
}
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
index 2e6e3e5..317c3f9 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
@@ -46,8 +46,6 @@
stats->rxPackets = 0;
stats->txBytes = 0;
stats->txPackets = 0;
- stats->tcpRxPackets = -1;
- stats->tcpTxPackets = -1;
}
int bpfGetUidStatsInternal(uid_t uid, Stats* stats,
diff --git a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
index bcedbef..4594f71 100644
--- a/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
+++ b/service-t/src/com/android/metrics/NetworkNsdReportedMetrics.java
@@ -66,7 +66,8 @@
event.getFoundServiceCount(),
event.getFoundCallbackCount(),
event.getLostCallbackCount(),
- event.getRepliedRequestsCount());
+ event.getRepliedRequestsCount(),
+ event.getSentQueryCount());
}
}
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index 53782ac..f7edbe4 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -1920,11 +1920,14 @@
@Override
public INsdServiceConnector connect(INsdManagerCallback cb, boolean useJavaBackend) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
+ final int uid = mDeps.getCallingUid();
+ if (cb == null) {
+ throw new IllegalArgumentException("Unknown client callback from uid=" + uid);
+ }
if (DBG) Log.d(TAG, "New client connect. useJavaBackend=" + useJavaBackend);
final INsdServiceConnector connector = new NsdServiceConnector();
mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(NsdManager.REGISTER_CLIENT,
- new ConnectorArgs((NsdServiceConnector) connector, cb, useJavaBackend,
- mDeps.getCallingUid())));
+ new ConnectorArgs((NsdServiceConnector) connector, cb, useJavaBackend, uid)));
return connector;
}
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 3f4113a..c46eada 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -63,6 +63,7 @@
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
@@ -3248,7 +3249,8 @@
* Default external settings that read from
* {@link android.provider.Settings.Global}.
*/
- private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
+ @VisibleForTesting(visibility = PRIVATE)
+ static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
DefaultNetworkStatsSettings() {}
@Override
diff --git a/service/src/com/android/metrics/stats.proto b/service/src/com/android/metrics/stats.proto
index 006d20a..99afb90 100644
--- a/service/src/com/android/metrics/stats.proto
+++ b/service/src/com/android/metrics/stats.proto
@@ -61,6 +61,9 @@
// Record query service count before unregistered service
optional int32 replied_requests_count = 11;
+
+ // Record sent query count before stopped discovery
+ optional int32 sent_query_count = 12;
}
/**
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index 7aff6a4..f08ffc3 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -1143,7 +1143,7 @@
}
}
- @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
private static native void native_init(boolean startSkDestroyListener);
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index bc703a9..a29f47f 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -2985,19 +2985,17 @@
}
private void handleFrozenUids(int[] uids, int[] frozenStates) {
- final ArraySet<Range<Integer>> ranges = new ArraySet<>();
+ final ArraySet<Integer> ownerUids = new ArraySet<>();
for (int i = 0; i < uids.length; i++) {
if (frozenStates[i] == UID_FROZEN_STATE_FROZEN) {
- Integer uidAsInteger = Integer.valueOf(uids[i]);
- ranges.add(new Range(uidAsInteger, uidAsInteger));
+ ownerUids.add(uids[i]);
}
}
- if (!ranges.isEmpty()) {
- final Set<Integer> exemptUids = new ArraySet<>();
+ if (!ownerUids.isEmpty()) {
try {
- mDeps.destroyLiveTcpSockets(ranges, exemptUids);
+ mDeps.destroyLiveTcpSocketsByOwnerUids(ownerUids);
} catch (Exception e) {
loge("Exception in socket destroy: " + e);
}
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index c15f042..beaa174 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -1011,9 +1011,8 @@
* @param ranges The updated UID ranges under VPN Lockdown. This function does not treat the VPN
* app's UID in any special way. The caller is responsible for excluding the VPN
* app UID from the passed-in ranges.
- * Ranges can have duplications and/or contain the range that is already subject
- * to lockdown. However, ranges can not have overlaps with other ranges including
- * ranges that are currently subject to lockdown.
+ * Ranges can have duplications, overlaps, and/or contain the range that is
+ * already subject to lockdown.
*/
public synchronized void updateVpnLockdownUidRanges(boolean add, UidRange[] ranges) {
final Set<UidRange> affectedUidRanges = new HashSet<>();
@@ -1045,8 +1044,10 @@
// exclude privileged apps from the prohibit routing rules used to implement outgoing packet
// filtering, privileged apps can still bypass outgoing packet filtering because the
// prohibit rules observe the protected from VPN bit.
+ // If removing a UID, we ensure it is not present anywhere in the set first.
for (final int uid: affectedUids) {
- if (!hasRestrictedNetworksPermission(uid)) {
+ if (!hasRestrictedNetworksPermission(uid)
+ && (add || !UidRange.containsUid(mVpnLockdownUidRanges.getSet(), uid))) {
updateLockdownUidRule(uid, add);
}
}
diff --git a/tests/cts/net/native/dns/Android.bp b/tests/cts/net/native/dns/Android.bp
index 2469710..da4fe28 100644
--- a/tests/cts/net/native/dns/Android.bp
+++ b/tests/cts/net/native/dns/Android.bp
@@ -30,6 +30,7 @@
],
// To be compatible with R devices, the min_sdk_version must be 30.
min_sdk_version: "30",
+ host_required: ["net-tests-utils-host-common"],
}
cc_test {
diff --git a/tests/cts/net/native/dns/AndroidTest.xml b/tests/cts/net/native/dns/AndroidTest.xml
index 6d03c23..d49696b 100644
--- a/tests/cts/net/native/dns/AndroidTest.xml
+++ b/tests/cts/net/native/dns/AndroidTest.xml
@@ -24,6 +24,8 @@
<option name="push" value="CtsNativeNetDnsTestCases->/data/local/tmp/CtsNativeNetDnsTestCases" />
<option name="append-bitness" value="true" />
</target_preparer>
+ <target_preparer class="com.android.testutils.ConnectivityTestTargetPreparer">
+ </target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="CtsNativeNetDnsTestCases" />
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index e978664..bce08df 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -2744,7 +2744,6 @@
*/
@AppModeFull(reason = "Instant apps cannot create test networks")
@Test
- @SkipMainlinePresubmit(reason = "Out of SLO flakiness")
public void testSetOemNetworkPreferenceForTestOnlyPref() throws Exception {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
@@ -2757,17 +2756,19 @@
final TestableNetworkCallback systemDefaultCallback = new TestableNetworkCallback();
final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
+ final Network testNetwork = tnt.getNetwork();
testAndCleanup(() -> {
setOemNetworkPreferenceForMyPackage(
OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY);
registerTestOemNetworkPreferenceCallbacks(defaultCallback, systemDefaultCallback);
- waitForAvailable(defaultCallback, tnt.getNetwork());
+ waitForAvailable(defaultCallback, testNetwork);
systemDefaultCallback.eventuallyExpect(CallbackEntry.AVAILABLE,
NETWORK_CALLBACK_TIMEOUT_MS, cb -> wifiNetwork.equals(cb.getNetwork()));
}, /* cleanup */ () -> {
runWithShellPermissionIdentity(tnt::teardown);
- defaultCallback.expect(CallbackEntry.LOST, tnt, NETWORK_CALLBACK_TIMEOUT_MS);
+ defaultCallback.eventuallyExpect(CallbackEntry.LOST, NETWORK_CALLBACK_TIMEOUT_MS,
+ cb -> testNetwork.equals(cb.getNetwork()));
// This network preference should only ever use the test network therefore available
// should not trigger when the test network goes down (e.g. switch to cellular).
@@ -3205,7 +3206,6 @@
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
- @SkipPresubmit(reason = "Out of SLO flakiness")
public void testMobileDataPreferredUids() throws Exception {
assumeTrue(TestUtils.shouldTestSApis());
final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 7731ac9..e4ee8de 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -910,12 +910,16 @@
val record = NsdRegistrationRecord()
nsdManager.registerService(si, NsdManager.PROTOCOL_DNS_SD, record)
val addOrUpdateEvent = offloadEngine
- .expectCallback<TestNsdOffloadEngine.OffloadEvent.AddOrUpdateEvent>()
+ .expectCallbackEventually<TestNsdOffloadEngine.OffloadEvent.AddOrUpdateEvent> {
+ it.info.key.serviceName == serviceName
+ }
checkOffloadServiceInfo(addOrUpdateEvent.info)
nsdManager.unregisterService(record)
val unregisterEvent = offloadEngine
- .expectCallback<TestNsdOffloadEngine.OffloadEvent.RemoveEvent>()
+ .expectCallbackEventually<TestNsdOffloadEngine.OffloadEvent.RemoveEvent> {
+ it.info.key.serviceName == serviceName
+ }
checkOffloadServiceInfo(unregisterEvent.info)
runAsShell(NETWORK_SETTINGS) {
diff --git a/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java b/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java
index 0eb5644..1b22f42 100644
--- a/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java
+++ b/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java
@@ -95,14 +95,17 @@
testIface.getFileDescriptor().close();
}
- if (tunNetworkCallback != null) {
- sCm.unregisterNetworkCallback(tunNetworkCallback);
- }
final Network testNetwork = tunNetworkCallback.currentNetwork;
if (testNetwork != null) {
tnm.teardownTestNetwork(testNetwork);
}
+ // Ensure test network being torn down.
+ tunNetworkCallback.waitForLost();
+
+ if (tunNetworkCallback != null) {
+ sCm.unregisterNetworkCallback(tunNetworkCallback);
+ }
}
}
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index c294e7b..442d69f 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -33,6 +33,8 @@
using android::modules::sdklevel::IsAtLeastR;
using android::modules::sdklevel::IsAtLeastS;
using android::modules::sdklevel::IsAtLeastT;
+using android::modules::sdklevel::IsAtLeastU;
+using android::modules::sdklevel::IsAtLeastV;
#define PLATFORM "/sys/fs/bpf/"
#define TETHERING "/sys/fs/bpf/tethering/"
@@ -147,10 +149,14 @@
// so we should only test for the removal of stuff that was mainline'd,
// and for the presence of mainline stuff.
+ // Note: Q is no longer supported by mainline
+ ASSERT_TRUE(IsAtLeastR());
+
// R can potentially run on pre-4.9 kernel non-eBPF capable devices.
DO_EXPECT(IsAtLeastR() && !IsAtLeastS() && isAtLeastKernelVersion(4, 9, 0), PLATFORM_ONLY_IN_R);
// S requires Linux Kernel 4.9+ and thus requires eBPF support.
+ if (IsAtLeastS()) ASSERT_TRUE(isAtLeastKernelVersion(4, 9, 0));
DO_EXPECT(IsAtLeastS(), MAINLINE_FOR_S_PLUS);
DO_EXPECT(IsAtLeastS() && isAtLeastKernelVersion(5, 10, 0), MAINLINE_FOR_S_5_10_PLUS);
@@ -163,6 +169,10 @@
DO_EXPECT(IsAtLeastT() && isAtLeastKernelVersion(5, 15, 0), MAINLINE_FOR_T_5_15_PLUS);
// U requires Linux Kernel 4.14+, but nothing (as yet) added or removed in U.
+ if (IsAtLeastU()) ASSERT_TRUE(isAtLeastKernelVersion(4, 14, 0));
+
+ // V requires Linux Kernel 4.19+, but nothing (as yet) added or removed in V.
+ if (IsAtLeastV()) ASSERT_TRUE(isAtLeastKernelVersion(4, 19, 0));
for (const auto& file : mustExist) {
EXPECT_EQ(0, access(file.c_str(), R_OK)) << file << " does not exist";
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 5d957b7..3688d83 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -18547,12 +18547,7 @@
waitForIdle();
- final Set<Integer> exemptUids = new ArraySet();
- final UidRange frozenUidRange = new UidRange(TEST_FROZEN_UID, TEST_FROZEN_UID);
- final Set<UidRange> ranges = Collections.singleton(frozenUidRange);
-
- verify(mDestroySocketsWrapper).destroyLiveTcpSockets(eq(UidRange.toIntRanges(ranges)),
- eq(exemptUids));
+ verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(Set.of(TEST_FROZEN_UID));
}
@Test
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 55384b3..f778075 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -1585,6 +1585,20 @@
lockOrder.verify(mMulticastLock).release();
}
+ @Test
+ public void testNullINsdManagerCallback() {
+ final NsdService service = new NsdService(mContext, mHandler, CLEANUP_DELAY_MS, mDeps) {
+ @Override
+ public INsdServiceConnector connect(INsdManagerCallback baseCb,
+ boolean runNewMdnsBackend) {
+ // Pass null INsdManagerCallback
+ return super.connect(null /* cb */, runNewMdnsBackend);
+ }
+ };
+
+ assertThrows(IllegalArgumentException.class, () -> new NsdManager(mContext, service));
+ }
+
private void waitForIdle() {
HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS);
}
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index cf02e3a..8dcfffa 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -55,6 +55,7 @@
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.intThat;
+import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
@@ -126,12 +127,14 @@
private static final int MOCK_APPID1 = 10001;
private static final int MOCK_APPID2 = 10086;
private static final int MOCK_APPID3 = 10110;
+ private static final int MOCK_APPID4 = 10111;
private static final int SYSTEM_APPID1 = 1100;
private static final int SYSTEM_APPID2 = 1108;
private static final int VPN_APPID = 10002;
private static final int MOCK_UID11 = MOCK_USER1.getUid(MOCK_APPID1);
private static final int MOCK_UID12 = MOCK_USER1.getUid(MOCK_APPID2);
private static final int MOCK_UID13 = MOCK_USER1.getUid(MOCK_APPID3);
+ private static final int MOCK_UID14 = MOCK_USER1.getUid(MOCK_APPID4);
private static final int SYSTEM_APP_UID11 = MOCK_USER1.getUid(SYSTEM_APPID1);
private static final int VPN_UID = MOCK_USER1.getUid(VPN_APPID);
private static final int MOCK_UID21 = MOCK_USER2.getUid(MOCK_APPID1);
@@ -965,6 +968,66 @@
}
@Test
+ public void testLockdownUidFilteringWithLockdownEnableDisableWithMultiAddAndOverlap() {
+ doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS),
+ buildPackageInfo(MOCK_PACKAGE1, MOCK_UID13),
+ buildPackageInfo(MOCK_PACKAGE2, MOCK_UID14),
+ buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
+ .when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
+ startMonitoring();
+ // MOCK_UID13 is subject to the VPN.
+ final UidRange range1 = new UidRange(MOCK_UID13, MOCK_UID13);
+ final UidRange[] lockdownRange1 = {range1};
+
+ // Add Lockdown uid range at 1st time, expect a rule to be set up
+ mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange1);
+ verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(true) /* add */);
+ verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID13, true /* add */);
+
+ reset(mBpfNetMaps);
+
+ // MOCK_UID13 and MOCK_UID14 are sequential and subject to the VPN in a separate range.
+ final UidRange range2 = new UidRange(MOCK_UID13, MOCK_UID14);
+ final UidRange[] lockdownRange2 = {range2};
+
+ // Add overlapping multiple-UID range. Rule may be set again, which is functionally
+ // a no-op, so it is fine.
+ mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange2);
+ verify(mBpfNetMaps, atLeast(1)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
+ verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID14, true /* add */);
+
+ reset(mBpfNetMaps);
+
+ // Remove the multiple-UID range. UID from first rule should not be removed.
+ mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, lockdownRange2);
+ verify(mBpfNetMaps, times(1)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
+ verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID14, false /* add */);
+
+ reset(mBpfNetMaps);
+
+ // Add the multiple-UID range back again to be able to test removing the first range, too.
+ mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange2);
+ verify(mBpfNetMaps, atLeast(1)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
+ verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID14, true /* add */);
+
+ reset(mBpfNetMaps);
+
+ // Remove the single-UID range. The rule for MOCK_UID11 should not change because it is
+ // still covered by the second, multiple-UID range rule.
+ mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, lockdownRange1);
+ verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(), anyBoolean());
+
+ reset(mBpfNetMaps);
+
+ // Remove the multiple-UID range. Expect both UID rules to be torn down.
+ mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, lockdownRange2);
+ verify(mBpfNetMaps, times(2)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
+ verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID13, false /* add */);
+ verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID14, false /* add */);
+ }
+
+ @Test
public void testLockdownUidFilteringWithLockdownEnableDisableWithDuplicates() {
doReturn(List.of(
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index ad178c0..385f831 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -182,7 +182,6 @@
import com.android.server.VpnTestBase;
import com.android.server.vcn.util.PersistableBundleUtils;
import com.android.testutils.DevSdkIgnoreRule;
-import com.android.testutils.SkipPresubmit;
import org.junit.Before;
import org.junit.Rule;
@@ -1712,7 +1711,6 @@
errorCode);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testStartPlatformVpnFailedWithRecoverableError() throws Exception {
final IkeProtocolException exception = mock(IkeProtocolException.class);
@@ -1722,7 +1720,6 @@
VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, errorCode);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testStartPlatformVpnFailedWithUnknownHostException() throws Exception {
final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
@@ -1734,7 +1731,6 @@
errorCode);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testStartPlatformVpnFailedWithIkeTimeoutException() throws Exception {
final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
@@ -1756,7 +1752,6 @@
VpnManager.ERROR_CODE_NETWORK_LOST);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testStartPlatformVpnFailedWithIOException() throws Exception {
final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
@@ -2389,7 +2384,6 @@
true /* areLongLivedTcpConnectionsExpensive */);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testPreferredIpProtocolFromCarrierConfig_v4UDP() throws Exception {
doTestReadCarrierConfig(createTestCellNc(),
@@ -2402,7 +2396,6 @@
false /* areLongLivedTcpConnectionsExpensive */);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testPreferredIpProtocolFromCarrierConfig_v6ESP() throws Exception {
doTestReadCarrierConfig(createTestCellNc(),
@@ -2415,7 +2408,6 @@
false /* areLongLivedTcpConnectionsExpensive */);
}
- @SkipPresubmit(reason = "Out of SLO flakiness")
@Test
public void testPreferredIpProtocolFromCarrierConfig_v6UDP() throws Exception {
doTestReadCarrierConfig(createTestCellNc(),
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 6292d45..9453617 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -79,7 +79,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -240,7 +239,9 @@
private @Mock INetd mNetd;
private @Mock TetheringManager mTetheringManager;
private @Mock NetworkStatsFactory mStatsFactory;
- private @Mock NetworkStatsSettings mSettings;
+ @NonNull
+ private final TestNetworkStatsSettings mSettings =
+ new TestNetworkStatsSettings(HOUR_IN_MILLIS, WEEK_IN_MILLIS);
private @Mock IBinder mUsageCallbackBinder;
private TestableUsageCallback mUsageCallback;
private @Mock AlarmManager mAlarmManager;
@@ -533,7 +534,6 @@
mStatsDir = null;
mNetd = null;
- mSettings = null;
mSession.close();
mService = null;
@@ -1765,7 +1765,7 @@
}
private void setCombineSubtypeEnabled(boolean enable) {
- doReturn(enable).when(mSettings).getCombineSubtypeEnabled();
+ mSettings.setCombineSubtypeEnabled(enable);
mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
.getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED)));
waitForIdle();
@@ -2289,21 +2289,80 @@
mockSettings(HOUR_IN_MILLIS, WEEK_IN_MILLIS);
}
- private void mockSettings(long bucketDuration, long deleteAge) throws Exception {
- doReturn(HOUR_IN_MILLIS).when(mSettings).getPollInterval();
- doReturn(0L).when(mSettings).getPollDelay();
- doReturn(true).when(mSettings).getSampleEnabled();
- doReturn(false).when(mSettings).getCombineSubtypeEnabled();
+ private void mockSettings(long bucketDuration, long deleteAge) {
+ mSettings.setConfig(new Config(bucketDuration, deleteAge, deleteAge));
+ }
- final Config config = new Config(bucketDuration, deleteAge, deleteAge);
- doReturn(config).when(mSettings).getXtConfig();
- doReturn(config).when(mSettings).getUidConfig();
- doReturn(config).when(mSettings).getUidTagConfig();
+ // Note that this object will be accessed from test main thread and service handler thread.
+ // Thus, it has to be thread safe in order to prevent from flakiness.
+ private static class TestNetworkStatsSettings
+ extends NetworkStatsService.DefaultNetworkStatsSettings {
- doReturn(MB_IN_BYTES).when(mSettings).getGlobalAlertBytes(anyLong());
- doReturn(MB_IN_BYTES).when(mSettings).getXtPersistBytes(anyLong());
- doReturn(MB_IN_BYTES).when(mSettings).getUidPersistBytes(anyLong());
- doReturn(MB_IN_BYTES).when(mSettings).getUidTagPersistBytes(anyLong());
+ @NonNull
+ private volatile Config mConfig;
+ private final AtomicBoolean mCombineSubtypeEnabled = new AtomicBoolean();
+
+ TestNetworkStatsSettings(long bucketDuration, long deleteAge) {
+ mConfig = new Config(bucketDuration, deleteAge, deleteAge);
+ }
+
+ void setConfig(@NonNull Config config) {
+ mConfig = config;
+ }
+
+ @Override
+ public long getPollDelay() {
+ return 0L;
+ }
+
+ @Override
+ public long getGlobalAlertBytes(long def) {
+ return MB_IN_BYTES;
+ }
+
+ @Override
+ public Config getXtConfig() {
+ return mConfig;
+ }
+
+ @Override
+ public Config getUidConfig() {
+ return mConfig;
+ }
+
+ @Override
+ public Config getUidTagConfig() {
+ return mConfig;
+ }
+
+ @Override
+ public long getXtPersistBytes(long def) {
+ return MB_IN_BYTES;
+ }
+
+ @Override
+ public long getUidPersistBytes(long def) {
+ return MB_IN_BYTES;
+ }
+
+ @Override
+ public long getUidTagPersistBytes(long def) {
+ return MB_IN_BYTES;
+ }
+
+ @Override
+ public boolean getCombineSubtypeEnabled() {
+ return mCombineSubtypeEnabled.get();
+ }
+
+ public void setCombineSubtypeEnabled(boolean enable) {
+ mCombineSubtypeEnabled.set(enable);
+ }
+
+ @Override
+ public boolean getAugmentEnabled() {
+ return false;
+ }
}
private void assertStatsFilesExist(boolean exist) {