Merge "Using common apex_defaults for com.android.tethering module."
diff --git a/Tethering/src/android/net/ip/DadProxy.java b/Tethering/src/android/net/ip/DadProxy.java
index e2976b7..36ecfe3 100644
--- a/Tethering/src/android/net/ip/DadProxy.java
+++ b/Tethering/src/android/net/ip/DadProxy.java
@@ -16,11 +16,12 @@
package android.net.ip;
-import android.net.util.InterfaceParams;
import android.os.Handler;
import androidx.annotation.VisibleForTesting;
+import com.android.net.module.util.InterfaceParams;
+
/**
* Basic Duplicate address detection proxy.
*
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index 965c1a1..acd2625 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -46,7 +46,6 @@
import android.net.dhcp.IDhcpServer;
import android.net.ip.IpNeighborMonitor.NeighborEvent;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
-import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -63,6 +62,7 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetdUtils;
import com.android.networkstack.tethering.BpfCoordinator;
import com.android.networkstack.tethering.BpfCoordinator.ClientInfo;
diff --git a/Tethering/src/android/net/ip/NeighborPacketForwarder.java b/Tethering/src/android/net/ip/NeighborPacketForwarder.java
index 27e59a1..723bd63 100644
--- a/Tethering/src/android/net/ip/NeighborPacketForwarder.java
+++ b/Tethering/src/android/net/ip/NeighborPacketForwarder.java
@@ -24,13 +24,13 @@
import static android.system.OsConstants.SOCK_NONBLOCK;
import static android.system.OsConstants.SOCK_RAW;
-import android.net.util.InterfaceParams;
import android.net.util.SocketUtils;
import android.os.Handler;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.PacketReader;
import com.android.networkstack.tethering.util.TetheringUtils;
diff --git a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
index 74f9369..c452e55 100644
--- a/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
+++ b/Tethering/src/android/net/ip/RouterAdvertisementDaemon.java
@@ -37,7 +37,6 @@
import android.net.LinkAddress;
import android.net.MacAddress;
import android.net.TrafficStats;
-import android.net.util.InterfaceParams;
import android.net.util.SocketUtils;
import android.system.ErrnoException;
import android.system.Os;
@@ -45,6 +44,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.structs.Icmpv6Header;
import com.android.net.module.util.structs.LlaOption;
import com.android.net.module.util.structs.MtuOption;
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 6550de2..64365cc 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -44,7 +44,6 @@
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
import android.net.netstats.provider.NetworkStatsProvider;
-import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.SystemClock;
@@ -64,6 +63,7 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.Struct;
import com.android.net.module.util.bpf.Tether4Key;
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfUtils.java b/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
index 77efb51..3d2dfaa 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfUtils.java
@@ -20,10 +20,9 @@
import static com.android.networkstack.tethering.util.TetheringUtils.getTetheringJniLibraryName;
-import android.net.util.InterfaceParams;
-
import androidx.annotation.NonNull;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.TcUtils;
import java.io.IOException;
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 07fce08..bb9b6fb 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -1533,16 +1533,28 @@
return mConfig;
}
- boolean hasTetherableConfiguration() {
- final TetheringConfiguration cfg = mConfig;
- final boolean hasDownstreamConfiguration =
- (cfg.tetherableUsbRegexs.length != 0)
- || (cfg.tetherableWifiRegexs.length != 0)
- || (cfg.tetherableBluetoothRegexs.length != 0);
- final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty()
- || cfg.chooseUpstreamAutomatically;
+ boolean hasAnySupportedDownstream() {
+ if ((mConfig.tetherableUsbRegexs.length != 0)
+ || (mConfig.tetherableWifiRegexs.length != 0)
+ || (mConfig.tetherableBluetoothRegexs.length != 0)) {
+ return true;
+ }
- return hasDownstreamConfiguration && hasUpstreamConfiguration;
+ // Before T, isTetheringSupported would return true if wifi, usb and bluetooth tethering are
+ // disabled (whole tethering settings would be hidden). This means tethering would also not
+ // support wifi p2p, ethernet tethering and mirrorlink. This is wrong but probably there are
+ // some devices in the field rely on this to disable tethering entirely.
+ if (!SdkLevel.isAtLeastT()) return false;
+
+ return (mConfig.tetherableWifiP2pRegexs.length != 0)
+ || (mConfig.tetherableNcmRegexs.length != 0)
+ || isEthernetSupported();
+ }
+
+ // TODO: using EtherentManager new API to check whether ethernet is supported when the API is
+ // ready to use.
+ private boolean isEthernetSupported() {
+ return mContext.getSystemService(Context.ETHERNET_SERVICE) != null;
}
void setUsbTethering(boolean enable, IIntResultListener listener) {
@@ -2463,7 +2475,7 @@
final boolean tetherEnabledInSettings = tetherSupported
&& !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
- return tetherEnabledInSettings && hasTetherableConfiguration()
+ return tetherEnabledInSettings && hasAnySupportedDownstream()
&& !isProvisioningNeededButUnavailable();
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index c1a747e..9224213 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -94,13 +94,6 @@
public abstract IpServer.Dependencies getIpServerDependencies();
/**
- * Indicates whether tethering is supported on the device.
- */
- public boolean isTetheringSupported() {
- return true;
- }
-
- /**
* Get a reference to the EntitlementManager to be used by tethering.
*/
public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
diff --git a/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java b/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
index eb9cf71..ebf09ed 100644
--- a/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
+++ b/Tethering/tests/privileged/src/android/net/ip/DadProxyTest.java
@@ -30,7 +30,6 @@
import android.net.INetd;
import android.net.InetAddresses;
import android.net.MacAddress;
-import android.net.util.InterfaceParams;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -40,6 +39,7 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.net.module.util.InterfaceParams;
import com.android.networkstack.tethering.util.TetheringUtils;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
diff --git a/Tethering/tests/privileged/src/android/net/ip/RouterAdvertisementDaemonTest.java b/Tethering/tests/privileged/src/android/net/ip/RouterAdvertisementDaemonTest.java
index 34f3e0e..328e3fb 100644
--- a/Tethering/tests/privileged/src/android/net/ip/RouterAdvertisementDaemonTest.java
+++ b/Tethering/tests/privileged/src/android/net/ip/RouterAdvertisementDaemonTest.java
@@ -44,7 +44,6 @@
import android.net.MacAddress;
import android.net.RouteInfo;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
-import android.net.util.InterfaceParams;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -54,6 +53,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.Ipv6Utils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.Struct;
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 41bbc4c..6488421 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -86,7 +86,6 @@
import android.net.ip.IpNeighborMonitor.NeighborEvent;
import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
-import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.Handler;
@@ -100,6 +99,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.net.module.util.BpfMap;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value;
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 6c7a66d..c614046 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -84,7 +84,6 @@
import android.net.ip.ConntrackMonitor;
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
-import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.Handler;
@@ -98,6 +97,7 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value;
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 e4dbc7d..0388758 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -152,7 +152,6 @@
import android.net.ip.IpNeighborMonitor;
import android.net.ip.IpServer;
import android.net.ip.RouterAdvertisementDaemon;
-import android.net.util.InterfaceParams;
import android.net.util.NetworkConstants;
import android.net.util.SharedLog;
import android.net.wifi.SoftApConfiguration;
@@ -185,6 +184,7 @@
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.InterfaceParams;
import com.android.networkstack.apishim.common.BluetoothPanShim;
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceCallbackShim;
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceRequestShim;
@@ -297,6 +297,7 @@
private TetheredInterfaceCallbackShim mTetheredInterfaceCallbackShim;
private TestConnectivityManager mCm;
+ private boolean mForceEthernetServiceUnavailable = false;
private class TestContext extends BroadcastInterceptingContext {
TestContext(Context base) {
@@ -331,7 +332,11 @@
if (Context.USER_SERVICE.equals(name)) return mUserManager;
if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
- if (Context.ETHERNET_SERVICE.equals(name)) return mEm;
+ if (Context.ETHERNET_SERVICE.equals(name)) {
+ if (mForceEthernetServiceUnavailable) return null;
+
+ return mEm;
+ }
return super.getSystemService(name);
}
@@ -452,11 +457,6 @@
}
@Override
- public boolean isTetheringSupported() {
- return true;
- }
-
- @Override
public TetheringConfiguration generateTetheringConfiguration(Context ctx, SharedLog log,
int subId) {
mConfig = spy(new FakeTetheringConfiguration(ctx, log, subId));
@@ -680,6 +680,7 @@
.thenReturn(new String[] {TEST_BT_REGEX});
when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
.thenReturn(new String[] {TEST_NCM_REGEX});
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)).thenReturn(true);
when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(
new int[] {TYPE_WIFI, TYPE_MOBILE_DUN});
when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
@@ -2834,6 +2835,55 @@
runDualStackUsbTethering(TEST_RNDIS_IFNAME);
runStopUSBTethering();
}
+
+ @Test
+ public void testTetheringSupported() throws Exception {
+ setTetheringSupported(true /* supported */);
+ updateConfigAndVerifySupported(true /* supported */);
+
+ // Could disable tethering supported by settings.
+ Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED, 0);
+ updateConfigAndVerifySupported(false /* supported */);
+
+ // Could disable tethering supported by user restriction.
+ setTetheringSupported(true /* supported */);
+ when(mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(true);
+ updateConfigAndVerifySupported(false /* supported */);
+
+ // Tethering is supported if it has any supported downstream.
+ setTetheringSupported(true /* supported */);
+ when(mResources.getStringArray(R.array.config_tether_usb_regexs))
+ .thenReturn(new String[0]);
+ updateConfigAndVerifySupported(true /* supported */);
+ when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
+ .thenReturn(new String[0]);
+ updateConfigAndVerifySupported(true /* supported */);
+
+
+ if (isAtLeastT()) {
+ when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
+ .thenReturn(new String[0]);
+ updateConfigAndVerifySupported(true /* supported */);
+ when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
+ .thenReturn(new String[0]);
+ updateConfigAndVerifySupported(true /* supported */);
+ when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
+ .thenReturn(new String[0]);
+ updateConfigAndVerifySupported(true /* supported */);
+ mForceEthernetServiceUnavailable = true;
+ updateConfigAndVerifySupported(false /* supported */);
+ } else {
+ when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
+ .thenReturn(new String[0]);
+ updateConfigAndVerifySupported(false /* supported */);
+ }
+ }
+
+ private void updateConfigAndVerifySupported(boolean supported) {
+ sendConfigurationChanged();
+ assertEquals(supported, mTethering.isTetheringSupported());
+ }
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}
diff --git a/framework/src/android/net/QosFilter.java b/framework/src/android/net/QosFilter.java
index 957c867..5c1c3cc 100644
--- a/framework/src/android/net/QosFilter.java
+++ b/framework/src/android/net/QosFilter.java
@@ -62,23 +62,31 @@
public abstract int validate();
/**
- * Determines whether or not the parameters is a match for the filter.
+ * Determines whether or not the parameters will be matched with source address and port of this
+ * filter.
*
- * @param address the local address
- * @param startPort the start of the port range
- * @param endPort the end of the port range
- * @return whether the parameters match the local address of the filter
+ * @param address the UE side address included in IP packet filter set of a QoS flow assigned
+ * on {@link Network}.
+ * @param startPort the start of UE side port range included in IP packet filter set of a QoS
+ * flow assigned on {@link Network}.
+ * @param endPort the end of UE side port range included in IP packet filter set of a QoS flow
+ * assigned on {@link Network}.
+ * @return whether the parameters match the UE side address and port of the filter
*/
public abstract boolean matchesLocalAddress(@NonNull InetAddress address,
int startPort, int endPort);
/**
- * Determines whether or not the parameters is a match for the filter.
+ * Determines whether or not the parameters will be matched with remote address and port of
+ * this filter.
*
- * @param address the remote address
- * @param startPort the start of the port range
- * @param endPort the end of the port range
- * @return whether the parameters match the remote address of the filter
+ * @param address the remote address included in IP packet filter set of a QoS flow
+ * assigned on {@link Network}.
+ * @param startPort the start of remote port range included in IP packet filter set of a
+ * QoS flow assigned on {@link Network}.
+ * @param endPort the end of the remote range included in IP packet filter set of a QoS
+ * flow assigned on {@link Network}.
+ * @return whether the parameters match the remote address and port of the filter
*/
public abstract boolean matchesRemoteAddress(@NonNull InetAddress address,
int startPort, int endPort);
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 3cd5e13..1e47ea3 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -134,6 +134,34 @@
return -EPERM;
}
+ // Note that tagging the socket to AID_CLAT is only implemented in JNI ClatCoordinator.
+ // The process is not allowed to tag socket to AID_CLAT via tagSocket() which would cause
+ // process data usage accounting to be bypassed. Tagging AID_CLAT is used for avoiding counting
+ // CLAT traffic data usage twice. See packages/modules/Connectivity/service/jni/
+ // com_android_server_connectivity_ClatCoordinator.cpp
+ if (chargeUid == AID_CLAT) {
+ return -EPERM;
+ }
+
+ // The socket destroy listener only monitors on the group {INET_TCP, INET_UDP, INET6_TCP,
+ // INET6_UDP}. Tagging listener unsupported socket causes that the tag can't be removed from
+ // tag map automatically. Eventually, the tag map may run out of space because of dead tag
+ // entries.
+ // See TrafficController::makeSkDestroyListener in
+ // packages/modules/Connectivity/service/native/TrafficController.cpp
+ // TODO: remove this once the socket destroy listener can detect more types of socket destroy.
+ int socketProto;
+ socklen_t intSize = sizeof(socketProto);
+ if (getsockopt(sockFd, SOL_SOCKET, SO_PROTOCOL, &socketProto, &intSize)) {
+ ALOGE("Failed to getsockopt: %s, fd: %d", strerror(errno), sockFd);
+ return -errno;
+ } else {
+ if (socketProto != IPPROTO_UDP && socketProto != IPPROTO_TCP) {
+ ALOGE("Unsupported protocol: %d", socketProto);
+ return -EPROTONOSUPPORT;
+ }
+ }
+
uint64_t sock_cookie = getSocketCookie(sockFd);
if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
UidTagValue newKey = {.uid = (uint32_t)chargeUid, .tag = tag};
diff --git a/netd/BpfHandlerTest.cpp b/netd/BpfHandlerTest.cpp
index db59c7c..66a2f80 100644
--- a/netd/BpfHandlerTest.cpp
+++ b/netd/BpfHandlerTest.cpp
@@ -16,6 +16,7 @@
* BpfHandlerTest.cpp - unit tests for BpfHandler.cpp
*/
+#include <private/android_filesystem_config.h>
#include <sys/socket.h>
#include <gtest/gtest.h>
@@ -187,6 +188,14 @@
expectMapEmpty(mFakeCookieTagMap);
}
+TEST_F(BpfHandlerTest, TestTagSocketWithUnsupportedProtocol) {
+ int rawSocket = socket(AF_INET, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_RAW);
+ EXPECT_LE(0, rawSocket);
+ uint64_t sockCookie = getSocketCookie(rawSocket);
+ EXPECT_NE(NONEXISTENT_COOKIE, sockCookie);
+ EXPECT_EQ(-EPROTONOSUPPORT, mBh.tagSocket(rawSocket, TEST_TAG, TEST_UID, TEST_UID));
+}
+
TEST_F(BpfHandlerTest, TestTagSocketWithoutPermission) {
int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
ASSERT_NE(-1, sock);
@@ -208,6 +217,12 @@
EXPECT_EQ(0, mBh.untagSocket(v6socket));
expectNoTag(sockCookie);
expectMapEmpty(mFakeCookieTagMap);
+
+ // Tag a socket to AID_CLAT other then realUid.
+ int sock = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ ASSERT_NE(-1, sock);
+ ASSERT_EQ(-EPERM, mBh.tagSocket(sock, TEST_TAG, AID_CLAT, realUid));
+ expectMapEmpty(mFakeCookieTagMap);
}
TEST_F(BpfHandlerTest, TestUntagInvalidSocket) {
diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt
index 65ed8a3..06a4cef 100644
--- a/service/jarjar-rules.txt
+++ b/service/jarjar-rules.txt
@@ -92,7 +92,6 @@
rule android.net.util.KeepalivePacketDataUtil* com.android.connectivity.@0
# From connectivity-module-utils
-rule android.net.util.InterfaceParams* com.android.connectivity.@0
rule android.net.util.SharedLog* com.android.connectivity.@0
rule android.net.shared.** com.android.connectivity.@0
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index ee512ec..71ddd11 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -318,30 +318,13 @@
return -1;
}
- // 1. create a throwaway socket to reserve a file descriptor number
- int passedTunFd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (passedTunFd == -1) {
- throwIOException(env, "socket(ipv6/udp) for tun fd failed", errno);
- return -1;
- }
- int passedSockRead = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (passedSockRead == -1) {
- throwIOException(env, "socket(ipv6/udp) for read socket failed", errno);
- return -1;
- }
- int passedSockWrite = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (passedSockWrite == -1) {
- throwIOException(env, "socket(ipv6/udp) for write socket failed", errno);
- return -1;
- }
-
- // these are the FD we'll pass to clatd on the cli, so need it as a string
- char passedTunFdStr[INT32_STRLEN];
- char passedSockReadStr[INT32_STRLEN];
- char passedSockWriteStr[INT32_STRLEN];
- snprintf(passedTunFdStr, sizeof(passedTunFdStr), "%d", passedTunFd);
- snprintf(passedSockReadStr, sizeof(passedSockReadStr), "%d", passedSockRead);
- snprintf(passedSockWriteStr, sizeof(passedSockWriteStr), "%d", passedSockWrite);
+ // 1. these are the FD we'll pass to clatd on the cli, so need it as a string
+ char tunFdStr[INT32_STRLEN];
+ char sockReadStr[INT32_STRLEN];
+ char sockWriteStr[INT32_STRLEN];
+ snprintf(tunFdStr, sizeof(tunFdStr), "%d", tunFd);
+ snprintf(sockReadStr, sizeof(sockReadStr), "%d", readSock);
+ snprintf(sockWriteStr, sizeof(sockWriteStr), "%d", writeSock);
// 2. we're going to use this as argv[0] to clatd to make ps output more useful
std::string progname("clatd-");
@@ -353,9 +336,9 @@
"-p", pfx96Str.c_str(),
"-4", v4Str.c_str(),
"-6", v6Str.c_str(),
- "-t", passedTunFdStr,
- "-r", passedSockReadStr,
- "-w", passedSockWriteStr,
+ "-t", tunFdStr,
+ "-r", sockReadStr,
+ "-w", sockWriteStr,
nullptr};
// clang-format on
@@ -375,7 +358,9 @@
// 4. register dup2() action: this is what 'clears' the CLOEXEC flag
// on the tun fd that we want the child clatd process to inherit
- // (this will happen after the vfork, and before the execve)
+ // (this will happen after the vfork, and before the execve).
+ // Note that even though dup2(2) is a no-op if fd == new_fd but O_CLOEXEC flag will be removed.
+ // See implementation of bionic's posix_spawn_file_actions_adddup2().
posix_spawn_file_actions_t fa;
if (int ret = posix_spawn_file_actions_init(&fa)) {
posix_spawnattr_destroy(&attr);
@@ -383,19 +368,19 @@
return -1;
}
- if (int ret = posix_spawn_file_actions_adddup2(&fa, tunFd, passedTunFd)) {
+ if (int ret = posix_spawn_file_actions_adddup2(&fa, tunFd, tunFd)) {
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
throwIOException(env, "posix_spawn_file_actions_adddup2 for tun fd failed", ret);
return -1;
}
- if (int ret = posix_spawn_file_actions_adddup2(&fa, readSock, passedSockRead)) {
+ if (int ret = posix_spawn_file_actions_adddup2(&fa, readSock, readSock)) {
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
throwIOException(env, "posix_spawn_file_actions_adddup2 for read socket failed", ret);
return -1;
}
- if (int ret = posix_spawn_file_actions_adddup2(&fa, writeSock, passedSockWrite)) {
+ if (int ret = posix_spawn_file_actions_adddup2(&fa, writeSock, writeSock)) {
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
throwIOException(env, "posix_spawn_file_actions_adddup2 for write socket failed", ret);
@@ -414,7 +399,7 @@
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
- // 5. Start BPF if any
+ // 6. Start BPF if any
if (!net::clat::initMaps()) {
net::clat::ClatdTracker tracker = {};
if (!initTracker(ifaceStr.c_str(), pfx96Str.c_str(), v4Str.c_str(), v6Str.c_str(),
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index f2ca18b..c977391 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -69,15 +69,10 @@
* Add naughty app bandwidth rule for specific app
*
* @param uid uid of target app
- * @throws RemoteException when netd has crashed.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void addNaughtyApp(final int uid) throws RemoteException {
- if (USE_NETD) {
- mNetd.bandwidthAddNaughtyApp(uid);
- return;
- }
+ public void addNaughtyApp(final int uid) {
final int err = native_addNaughtyApp(uid);
maybeThrow(err, "Unable to add naughty app");
}
@@ -86,15 +81,10 @@
* Remove naughty app bandwidth rule for specific app
*
* @param uid uid of target app
- * @throws RemoteException when netd has crashed.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void removeNaughtyApp(final int uid) throws RemoteException {
- if (USE_NETD) {
- mNetd.bandwidthRemoveNaughtyApp(uid);
- return;
- }
+ public void removeNaughtyApp(final int uid) {
final int err = native_removeNaughtyApp(uid);
maybeThrow(err, "Unable to remove naughty app");
}
@@ -103,15 +93,10 @@
* Add nice app bandwidth rule for specific app
*
* @param uid uid of target app
- * @throws RemoteException when netd has crashed.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void addNiceApp(final int uid) throws RemoteException {
- if (USE_NETD) {
- mNetd.bandwidthAddNiceApp(uid);
- return;
- }
+ public void addNiceApp(final int uid) {
final int err = native_addNiceApp(uid);
maybeThrow(err, "Unable to add nice app");
}
@@ -120,15 +105,10 @@
* Remove nice app bandwidth rule for specific app
*
* @param uid uid of target app
- * @throws RemoteException when netd has crashed.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void removeNiceApp(final int uid) throws RemoteException {
- if (USE_NETD) {
- mNetd.bandwidthRemoveNiceApp(uid);
- return;
- }
+ public void removeNiceApp(final int uid) {
final int err = native_removeNiceApp(uid);
maybeThrow(err, "Unable to remove nice app");
}
@@ -138,15 +118,10 @@
*
* @param childChain target chain to enable
* @param enable whether to enable or disable child chain.
- * @throws RemoteException when netd has crashed.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void setChildChain(final int childChain, final boolean enable) throws RemoteException {
- if (USE_NETD) {
- mNetd.firewallEnableChildChain(childChain, enable);
- return;
- }
+ public void setChildChain(final int childChain, final boolean enable) {
final int err = native_setChildChain(childChain, enable);
maybeThrow(err, "Unable to set child chain");
}
@@ -163,14 +138,9 @@
* @param isAllowlist Whether this is an allowlist or denylist chain.
* @param uids The list of UIDs to allow/deny.
* @return 0 if the chain was successfully replaced, errno otherwise.
- * @throws RemoteException when netd has crashed.
*/
public int replaceUidChain(final String chainName, final boolean isAllowlist,
- final int[] uids) throws RemoteException {
- if (USE_NETD) {
- mNetd.firewallReplaceUidChain(chainName, isAllowlist, uids);
- return 0;
- }
+ final int[] uids) {
final int err = native_replaceUidChain(chainName, isAllowlist, uids);
if (err != 0) {
Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
@@ -184,16 +154,10 @@
* @param childChain target chain
* @param uid uid to allow/deny
* @param firewallRule either FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
- * @throws RemoteException when netd has crashed.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void setUidRule(final int childChain, final int uid, final int firewallRule)
- throws RemoteException {
- if (USE_NETD) {
- mNetd.firewallSetUidRule(childChain, uid, firewallRule);
- return;
- }
+ public void setUidRule(final int childChain, final int uid, final int firewallRule) {
final int err = native_setUidRule(childChain, uid, firewallRule);
maybeThrow(err, "Unable to set uid rule");
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index eabcd10..e0bf223 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -198,7 +198,6 @@
import android.net.resolv.aidl.Nat64PrefixEventParcel;
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
import android.net.shared.PrivateDnsConfig;
-import android.net.util.InterfaceParams;
import android.net.util.MultinetworkPolicyTracker;
import android.os.BatteryStatsManager;
import android.os.Binder;
@@ -245,6 +244,7 @@
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.net.module.util.LocationPermissionChecker;
@@ -10699,6 +10699,9 @@
}
private boolean canNetworkBeRateLimited(@NonNull final NetworkAgentInfo networkAgent) {
+ // Rate-limiting cannot run correctly before T because the BPF program is not loaded.
+ if (!SdkLevel.isAtLeastT()) return false;
+
final NetworkCapabilities agentCaps = networkAgent.networkCapabilities;
// Only test networks (they cannot hold NET_CAPABILITY_INTERNET) and networks that provide
// internet connectivity can be rate limited.
@@ -11056,7 +11059,7 @@
} else {
mBpfNetMaps.removeNiceApp(uid);
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -11071,7 +11074,7 @@
} else {
mBpfNetMaps.removeNaughtyApp(uid);
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -11083,7 +11086,7 @@
try {
mBpfNetMaps.setUidRule(chain, uid,
allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -11094,7 +11097,7 @@
try {
mBpfNetMaps.setChildChain(chain, enable);
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -11125,7 +11128,7 @@
throw new IllegalArgumentException("replaceFirewallChain with invalid chain: "
+ chain);
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
index 0526a75..78ae7b8 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DumpOnFailureRule.java
@@ -62,6 +62,7 @@
"dumpsys network_management",
"dumpsys usagestats " + TEST_PKG + " " + TEST_APP2_PKG,
"dumpsys usagestats appstandby",
+ "dumpsys connectivity trafficcontroller",
"dumpsys netd trafficcontroller",
}) {
dumpCommandOutput(out, cmd);
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index ac21e77..2959ac9 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -16,8 +16,6 @@
package com.android.server;
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
-import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.PERMISSION_INTERNET;
import static org.junit.Assume.assumeFalse;
@@ -60,20 +58,6 @@
@Test
public void testBpfNetMapsBeforeT() throws Exception {
assumeFalse(SdkLevel.isAtLeastT());
- mBpfNetMaps.addNaughtyApp(TEST_UID);
- verify(mNetd).bandwidthAddNaughtyApp(TEST_UID);
- mBpfNetMaps.removeNaughtyApp(TEST_UID);
- verify(mNetd).bandwidthRemoveNaughtyApp(TEST_UID);
- mBpfNetMaps.addNiceApp(TEST_UID);
- verify(mNetd).bandwidthAddNiceApp(TEST_UID);
- mBpfNetMaps.removeNiceApp(TEST_UID);
- verify(mNetd).bandwidthRemoveNiceApp(TEST_UID);
- mBpfNetMaps.setChildChain(FIREWALL_CHAIN_DOZABLE, true);
- verify(mNetd).firewallEnableChildChain(FIREWALL_CHAIN_DOZABLE, true);
- mBpfNetMaps.replaceUidChain(CHAINNAME, true, TEST_UIDS);
- verify(mNetd).firewallReplaceUidChain(CHAINNAME, true, TEST_UIDS);
- mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW);
- verify(mNetd).firewallSetUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW);
mBpfNetMaps.addUidInterfaceRules(IFNAME, TEST_UIDS);
verify(mNetd).firewallAddUidInterfaceRules(IFNAME, TEST_UIDS);
mBpfNetMaps.removeUidInterfaceRules(TEST_UIDS);
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 777da17..c8dc107 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -137,6 +137,9 @@
import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
import static com.android.testutils.ConcurrentUtils.await;
import static com.android.testutils.ConcurrentUtils.durationOf;
+import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static com.android.testutils.ExceptionUtils.ignoreExceptions;
import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
import static com.android.testutils.MiscAsserts.assertContainsAll;
@@ -358,6 +361,7 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.AdditionalAnswers;
@@ -420,6 +424,9 @@
public class ConnectivityServiceTest {
private static final String TAG = "ConnectivityServiceTest";
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
private static final int TIMEOUT_MS = 2_000;
// Broadcasts can take a long time to be delivered. The test will not wait for that long unless
// there is a failure, so use a long timeout.
@@ -15397,7 +15404,7 @@
null /* callingAttributionTag */));
}
- @Test
+ @Test @IgnoreUpTo(SC_V2)
public void testUpdateRateLimit_EnableDisable() throws Exception {
final LinkProperties wifiLp = new LinkProperties();
wifiLp.setInterfaceName(WIFI_IFNAME);
@@ -15436,7 +15443,7 @@
it -> it.first == cellLp.getInterfaceName() && it.second == -1));
}
- @Test
+ @Test @IgnoreUpTo(SC_V2)
public void testUpdateRateLimit_WhenNewNetworkIsAdded() throws Exception {
final LinkProperties wifiLp = new LinkProperties();
wifiLp.setInterfaceName(WIFI_IFNAME);
@@ -15462,7 +15469,7 @@
&& it.second == rateLimitInBytesPerSec));
}
- @Test
+ @Test @IgnoreUpTo(SC_V2)
public void testUpdateRateLimit_OnlyAffectsInternetCapableNetworks() throws Exception {
final LinkProperties wifiLp = new LinkProperties();
wifiLp.setInterfaceName(WIFI_IFNAME);
@@ -15480,7 +15487,7 @@
assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
}
- @Test
+ @Test @IgnoreUpTo(SC_V2)
public void testUpdateRateLimit_DisconnectingResetsRateLimit()
throws Exception {
// Steps:
@@ -15516,7 +15523,7 @@
assertNull(readHeadWifi.poll(TIMEOUT_MS, it -> it.first == wifiLp.getInterfaceName()));
}
- @Test
+ @Test @IgnoreUpTo(SC_V2)
public void testUpdateRateLimit_UpdateExistingRateLimit() throws Exception {
final LinkProperties wifiLp = new LinkProperties();
wifiLp.setInterfaceName(WIFI_IFNAME);
@@ -15545,4 +15552,21 @@
it -> it.first == wifiLp.getInterfaceName()
&& it.second == 2000));
}
+
+ @Test @IgnoreAfter(SC_V2)
+ public void testUpdateRateLimit_DoesNothingBeforeT() throws Exception {
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ waitForIdle();
+
+ final ArrayTrackRecord<Pair<String, Long>>.ReadHead readHead =
+ mDeps.mRateLimitHistory.newReadHead();
+
+ setIngressRateLimit(1000);
+ waitForIdle();
+
+ assertNull(readHead.poll(TEST_CALLBACK_TIMEOUT_MS, it -> true));
+ }
}