Merge "BpfHandler: only allow to tag INET/INET6 socket"
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 8459a2c..dd04d6c 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -38,10 +38,11 @@
apex {
name: "com.android.tethering",
- defaults: ["ConnectivityApexDefaults"],
+ defaults: [
+ "ConnectivityApexDefaults",
+ "r-launched-apex-module",
+ ],
compile_multilib: "both",
- updatable: true,
- min_sdk_version: "30",
bootclasspath_fragments: [
"com.android.tethering-bootclasspath-fragment",
],
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/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index ae5d389..0388758 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -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/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 ab78104..e0bf223 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -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/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));
+ }
}