Merge "Fix ConnectivityManagerTest#testFactoryReset flaky"
diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index b3f0cf2..cd914d3 100644
--- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -1273,8 +1273,10 @@
@Override
public int hashCode() {
- return Objects.hash(mTetherableBluetoothRegexs, mTetherableUsbRegexs,
- mTetherableWifiRegexs);
+ return Objects.hash(
+ Arrays.hashCode(mTetherableBluetoothRegexs),
+ Arrays.hashCode(mTetherableUsbRegexs),
+ Arrays.hashCode(mTetherableWifiRegexs));
}
@Override
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index ac0bbd4..05a2884 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -64,7 +64,7 @@
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.SharedLog;
import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.S32;
import com.android.net.module.util.bpf.Tether4Key;
import com.android.net.module.util.bpf.Tether4Value;
import com.android.net.module.util.bpf.TetherStatsKey;
@@ -575,7 +575,7 @@
if (!mBpfCoordinatorShim.startUpstreamIpv6Forwarding(downstream, upstream, rule.srcMac,
NULL_MAC_ADDRESS, NULL_MAC_ADDRESS, NetworkStackConstants.ETHER_MTU)) {
mLog.e("Failed to enable upstream IPv6 forwarding from "
- + mInterfaceNames.get(downstream) + " to " + mInterfaceNames.get(upstream));
+ + getIfName(downstream) + " to " + getIfName(upstream));
}
}
@@ -616,7 +616,7 @@
if (!mBpfCoordinatorShim.stopUpstreamIpv6Forwarding(downstream, upstream,
rule.srcMac)) {
mLog.e("Failed to disable upstream IPv6 forwarding from "
- + mInterfaceNames.get(downstream) + " to " + mInterfaceNames.get(upstream));
+ + getIfName(downstream) + " to " + getIfName(upstream));
}
}
@@ -960,8 +960,12 @@
}
// TODO: make mInterfaceNames accessible to the shim and move this code to there.
- private String getIfName(long ifindex) {
- return mInterfaceNames.get((int) ifindex, Long.toString(ifindex));
+ // This function should only be used for logging/dump purposes.
+ private String getIfName(int ifindex) {
+ // TODO: return something more useful on lookup failure
+ // likely use the 'iface_index_name_map' bpf map and/or if_nametoindex
+ // perhaps should even check that all 3 match if available.
+ return mInterfaceNames.get(ifindex, Integer.toString(ifindex));
}
/**
@@ -1038,8 +1042,8 @@
for (int i = 0; i < mStats.size(); i++) {
final int upstreamIfindex = mStats.keyAt(i);
final ForwardedStats stats = mStats.get(upstreamIfindex);
- pw.println(String.format("%d(%s) - %s", upstreamIfindex, mInterfaceNames.get(
- upstreamIfindex), stats.toString()));
+ pw.println(String.format("%d(%s) - %s", upstreamIfindex, getIfName(upstreamIfindex),
+ stats.toString()));
}
}
private void dumpBpfStats(@NonNull IndentingPrintWriter pw) {
@@ -1082,8 +1086,9 @@
for (Ipv6ForwardingRule rule : rules.values()) {
final int upstreamIfindex = rule.upstreamIfindex;
pw.println(String.format("%d(%s) %d(%s) %s [%s] [%s]", upstreamIfindex,
- mInterfaceNames.get(upstreamIfindex), rule.downstreamIfindex,
- downstreamIface, rule.address.getHostAddress(), rule.srcMac, rule.dstMac));
+ getIfName(upstreamIfindex), rule.downstreamIfindex,
+ getIfName(rule.downstreamIfindex), rule.address.getHostAddress(),
+ rule.srcMac, rule.dstMac));
}
pw.decreaseIndent();
}
@@ -1278,18 +1283,18 @@
pw.println("No counter support");
return;
}
- try (BpfMap<U32, U32> map = new BpfMap<>(TETHER_ERROR_MAP_PATH, BpfMap.BPF_F_RDONLY,
- U32.class, U32.class)) {
+ try (BpfMap<S32, S32> map = new BpfMap<>(TETHER_ERROR_MAP_PATH, BpfMap.BPF_F_RDONLY,
+ S32.class, S32.class)) {
map.forEach((k, v) -> {
String counterName;
try {
- counterName = sBpfCounterNames[(int) k.val];
+ counterName = sBpfCounterNames[k.val];
} catch (IndexOutOfBoundsException e) {
// Should never happen because this code gets the counter name from the same
// include file as the BPF program that increments the counter.
Log.wtf(TAG, "Unknown tethering counter type " + k.val);
- counterName = Long.toString(k.val);
+ counterName = Integer.toString(k.val);
}
if (v.val > 0) pw.println(String.format("%s: %d", counterName, v.val));
});
@@ -1817,8 +1822,7 @@
// TODO: Perhaps stop the coordinator.
boolean success = updateDataLimit(upstreamIfindex);
if (!success) {
- final String iface = mInterfaceNames.get(upstreamIfindex);
- mLog.e("Setting data limit for " + iface + " failed.");
+ mLog.e("Setting data limit for " + getIfName(upstreamIfindex) + " failed.");
}
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java b/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
index 4283c1b..997080c 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetherDevKey.java
@@ -22,10 +22,10 @@
/** The key of BpfMap which is used for mapping interface index. */
public class TetherDevKey extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long ifIndex; // interface index
+ @Field(order = 0, type = Type.S32)
+ public final int ifIndex; // interface index
- public TetherDevKey(final long ifIndex) {
+ public TetherDevKey(final int ifIndex) {
this.ifIndex = ifIndex;
}
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java b/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
index 1cd99b5..b6e0c73 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetherDevValue.java
@@ -22,10 +22,10 @@
/** The key of BpfMap which is used for mapping interface index. */
public class TetherDevValue extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long ifIndex; // interface index
+ @Field(order = 0, type = Type.S32)
+ public final int ifIndex; // interface index
- public TetherDevValue(final long ifIndex) {
+ public TetherDevValue(final int ifIndex) {
this.ifIndex = ifIndex;
}
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherDownstream6Key.java b/Tethering/src/com/android/networkstack/tethering/TetherDownstream6Key.java
index a08ad4a..e34b3f1 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetherDownstream6Key.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetherDownstream6Key.java
@@ -32,8 +32,8 @@
/** The key of BpfMap which is used for bpf offload. */
public class TetherDownstream6Key extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long iif; // The input interface index.
+ @Field(order = 0, type = Type.S32)
+ public final int iif; // The input interface index.
@Field(order = 1, type = Type.EUI48, padding = 2)
public final MacAddress dstMac; // Destination ethernet mac address (zeroed iff rawip ingress).
@@ -41,7 +41,7 @@
@Field(order = 2, type = Type.ByteArray, arraysize = 16)
public final byte[] neigh6; // The destination IPv6 address.
- public TetherDownstream6Key(final long iif, @NonNull final MacAddress dstMac,
+ public TetherDownstream6Key(final int iif, @NonNull final MacAddress dstMac,
final byte[] neigh6) {
Objects.requireNonNull(dstMac);
diff --git a/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java b/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java
index bc9bb47..a7e8ccf 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetherLimitKey.java
@@ -22,10 +22,10 @@
/** The key of BpfMap which is used for tethering per-interface limit. */
public class TetherLimitKey extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long ifindex; // upstream interface index
+ @Field(order = 0, type = Type.S32)
+ public final int ifindex; // upstream interface index
- public TetherLimitKey(final long ifindex) {
+ public TetherLimitKey(final int ifindex) {
this.ifindex = ifindex;
}
@@ -43,7 +43,7 @@
@Override
public int hashCode() {
- return Long.hashCode(ifindex);
+ return Integer.hashCode(ifindex);
}
@Override
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 5191bb7..0d1b22e 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -97,6 +97,7 @@
import android.net.TetheringInterface;
import android.net.TetheringManager.TetheringRequest;
import android.net.TetheringRequestParcel;
+import android.net.Uri;
import android.net.ip.IpServer;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiManager;
@@ -343,9 +344,8 @@
mEntitlementMgr.reevaluateSimCardProvisioning(mConfig);
});
- mSettingsObserver = new SettingsObserver(mHandler);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(TETHER_FORCE_USB_FUNCTIONS), false, mSettingsObserver);
+ mSettingsObserver = new SettingsObserver(mContext, mHandler);
+ mSettingsObserver.startObserve();
mStateReceiver = new StateReceiver();
@@ -397,18 +397,42 @@
}
private class SettingsObserver extends ContentObserver {
- SettingsObserver(Handler handler) {
+ private final Uri mForceUsbFunctions;
+ private final Uri mTetherSupported;
+ private final Context mContext;
+
+ SettingsObserver(Context ctx, Handler handler) {
super(handler);
+ mContext = ctx;
+ mForceUsbFunctions = Settings.Global.getUriFor(TETHER_FORCE_USB_FUNCTIONS);
+ mTetherSupported = Settings.Global.getUriFor(Settings.Global.TETHER_SUPPORTED);
+ }
+
+ public void startObserve() {
+ mContext.getContentResolver().registerContentObserver(mForceUsbFunctions, false, this);
+ mContext.getContentResolver().registerContentObserver(mTetherSupported, false, this);
}
@Override
public void onChange(boolean selfChange) {
- mLog.i("OBSERVED Settings change");
- final boolean isUsingNcm = mConfig.isUsingNcm();
- updateConfiguration();
- if (isUsingNcm != mConfig.isUsingNcm()) {
- stopTetheringInternal(TETHERING_USB);
- stopTetheringInternal(TETHERING_NCM);
+ Log.wtf(TAG, "Should never be reached.");
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mForceUsbFunctions.equals(uri)) {
+ mLog.i("OBSERVED TETHER_FORCE_USB_FUNCTIONS settings change");
+ final boolean isUsingNcm = mConfig.isUsingNcm();
+ updateConfiguration();
+ if (isUsingNcm != mConfig.isUsingNcm()) {
+ stopTetheringInternal(TETHERING_USB);
+ stopTetheringInternal(TETHERING_NCM);
+ }
+ } else if (mTetherSupported.equals(uri)) {
+ mLog.i("OBSERVED TETHER_SUPPORTED settings change");
+ updateSupportedDownstreams(mConfig);
+ } else {
+ mLog.e("Unexpected settings change: " + uri);
}
}
}
@@ -1322,7 +1346,9 @@
}
private void handleUserRestrictionAction() {
- mTetheringRestriction.onUserRestrictionsChanged();
+ if (mTetheringRestriction.onUserRestrictionsChanged()) {
+ updateSupportedDownstreams(mConfig);
+ }
}
private void handleDataSaverChanged() {
@@ -1350,6 +1376,8 @@
return getTetheredIfaces().length > 0;
}
+ // TODO: Refine TetheringTest then remove UserRestrictionActionListener class and handle
+ // onUserRestrictionsChanged inside Tethering#handleUserRestrictionAction directly.
@VisibleForTesting
protected static class UserRestrictionActionListener {
private final UserManager mUserMgr;
@@ -1365,7 +1393,8 @@
mDisallowTethering = false;
}
- public void onUserRestrictionsChanged() {
+ // return whether tethering disallowed is changed.
+ public boolean onUserRestrictionsChanged() {
// getUserRestrictions gets restriction for this process' user, which is the primary
// user. This is fine because DISALLOW_CONFIG_TETHERING can only be set on the primary
// user. See UserManager.DISALLOW_CONFIG_TETHERING.
@@ -1376,15 +1405,13 @@
mDisallowTethering = newlyDisallowed;
final boolean tetheringDisallowedChanged = (newlyDisallowed != prevDisallowed);
- if (!tetheringDisallowedChanged) {
- return;
- }
+ if (!tetheringDisallowedChanged) return false;
if (!newlyDisallowed) {
// Clear the restricted notification when user is allowed to have tethering
// function.
mNotificationUpdater.tetheringRestrictionLifted();
- return;
+ return true;
}
if (mTethering.isTetheringActive()) {
@@ -1395,6 +1422,8 @@
// Untether from all downstreams since tethering is disallowed.
mTethering.untetherAll();
}
+
+ return true;
// TODO(b/148139325): send tetheringSupported on restriction change
}
}
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
index 536ab2d..0e8b044 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
@@ -98,7 +98,7 @@
assertTrue(mTestMap.isEmpty());
}
- private TetherDownstream6Key createTetherDownstream6Key(long iif, String mac,
+ private TetherDownstream6Key createTetherDownstream6Key(int iif, String mac,
String address) throws Exception {
final MacAddress dstMac = MacAddress.fromString(mac);
final InetAddress ipv6Address = InetAddress.getByName(address);
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 63bb731..b100f58 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -222,7 +222,7 @@
private static class TestUpstream4Key {
public static class Builder {
- private long mIif = DOWNSTREAM_IFINDEX;
+ private int mIif = DOWNSTREAM_IFINDEX;
private MacAddress mDstMac = DOWNSTREAM_MAC;
private short mL4proto = (short) IPPROTO_TCP;
private byte[] mSrc4 = PRIVATE_ADDR.getAddress();
@@ -246,7 +246,7 @@
private static class TestDownstream4Key {
public static class Builder {
- private long mIif = UPSTREAM_IFINDEX;
+ private int mIif = UPSTREAM_IFINDEX;
private MacAddress mDstMac = MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */;
private short mL4proto = (short) IPPROTO_TCP;
private byte[] mSrc4 = REMOTE_ADDR.getAddress();
@@ -270,7 +270,7 @@
private static class TestUpstream4Value {
public static class Builder {
- private long mOif = UPSTREAM_IFINDEX;
+ private int mOif = UPSTREAM_IFINDEX;
private MacAddress mEthDstMac = MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */;
private MacAddress mEthSrcMac = MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */;
private int mEthProto = ETH_P_IP;
@@ -290,7 +290,7 @@
private static class TestDownstream4Value {
public static class Builder {
- private long mOif = DOWNSTREAM_IFINDEX;
+ private int mOif = DOWNSTREAM_IFINDEX;
private MacAddress mEthDstMac = MAC_A /* client mac */;
private MacAddress mEthSrcMac = DOWNSTREAM_MAC;
private int mEthProto = ETH_P_IP;
@@ -941,11 +941,11 @@
@Test
public void testRuleMakeTetherDownstream6Key() throws Exception {
- final Integer mobileIfIndex = 100;
+ final int mobileIfIndex = 100;
final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
final TetherDownstream6Key key = rule.makeTetherDownstream6Key();
- assertEquals(key.iif, (long) mobileIfIndex);
+ assertEquals(key.iif, mobileIfIndex);
assertEquals(key.dstMac, MacAddress.ALL_ZEROS_ADDRESS); // rawip upstream
assertTrue(Arrays.equals(key.neigh6, NEIGH_A.getAddress()));
// iif (4) + dstMac(6) + padding(2) + neigh6 (16) = 28.
@@ -954,7 +954,7 @@
@Test
public void testRuleMakeTether6Value() throws Exception {
- final Integer mobileIfIndex = 100;
+ final int mobileIfIndex = 100;
final Ipv6ForwardingRule rule = buildTestForwardingRule(mobileIfIndex, NEIGH_A, MAC_A);
final Tether6Value value = rule.makeTether6Value();
@@ -974,7 +974,7 @@
final BpfCoordinator coordinator = makeBpfCoordinator();
final String mobileIface = "rmnet_data0";
- final Integer mobileIfIndex = 100;
+ final int mobileIfIndex = 100;
coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
// [1] Default limit.
@@ -1018,7 +1018,7 @@
final BpfCoordinator coordinator = makeBpfCoordinator();
final String mobileIface = "rmnet_data0";
- final Integer mobileIfIndex = 100;
+ final int mobileIfIndex = 100;
coordinator.addUpstreamNameToLookupTable(mobileIfIndex, mobileIface);
// Applying a data limit to the current upstream does not take any immediate action.
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 66ad167..a36d67f 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -2899,9 +2899,13 @@
}
private void forceUsbTetheringUse(final int function) {
- Settings.Global.putInt(mContentResolver, TETHER_FORCE_USB_FUNCTIONS, function);
+ setSetting(TETHER_FORCE_USB_FUNCTIONS, function);
+ }
+
+ private void setSetting(final String key, final int value) {
+ Settings.Global.putInt(mContentResolver, key, value);
final ContentObserver observer = mTethering.getSettingsObserverForTest();
- observer.onChange(false /* selfChange */);
+ observer.onChange(false /* selfChange */, Settings.Global.getUriFor(key));
mLooper.dispatchAll();
}
@@ -2957,74 +2961,86 @@
TETHERING_WIFI_P2P, TETHERING_BLUETOOTH, TETHERING_ETHERNET });
}
+ private void setUserRestricted(boolean restricted) {
+ final Bundle restrictions = new Bundle();
+ restrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, restricted);
+ when(mUserManager.getUserRestrictions()).thenReturn(restrictions);
+ when(mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(restricted);
+
+ final Intent intent = new Intent(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
+ mServiceContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ mLooper.dispatchAll();
+ }
+
@Test
public void testTetheringSupported() throws Exception {
final ArraySet<Integer> expectedTypes = getAllSupportedTetheringTypes();
// Check tethering is supported after initialization.
- setTetheringSupported(true /* supported */);
TestTetheringEventCallback callback = new TestTetheringEventCallback();
mTethering.registerTetheringEventCallback(callback);
mLooper.dispatchAll();
- updateConfigAndVerifySupported(callback, expectedTypes);
+ verifySupported(callback, expectedTypes);
- // Could disable tethering supported by settings.
- Settings.Global.putInt(mContentResolver, Settings.Global.TETHER_SUPPORTED, 0);
- updateConfigAndVerifySupported(callback, new ArraySet<>());
+ // Could change tethering supported by settings.
+ setSetting(Settings.Global.TETHER_SUPPORTED, 0);
+ verifySupported(callback, new ArraySet<>());
+ setSetting(Settings.Global.TETHER_SUPPORTED, 1);
+ verifySupported(callback, expectedTypes);
- // Could disable tethering supported by user restriction.
- setTetheringSupported(true /* supported */);
- updateConfigAndVerifySupported(callback, expectedTypes);
- when(mUserManager.hasUserRestriction(
- UserManager.DISALLOW_CONFIG_TETHERING)).thenReturn(true);
- updateConfigAndVerifySupported(callback, new ArraySet<>());
+ // Could change tethering supported by user restriction.
+ setUserRestricted(true /* restricted */);
+ verifySupported(callback, new ArraySet<>());
+ setUserRestricted(false /* restricted */);
+ verifySupported(callback, expectedTypes);
- // Tethering is supported if it has any supported downstream.
- setTetheringSupported(true /* supported */);
- updateConfigAndVerifySupported(callback, expectedTypes);
// Usb tethering is not supported:
expectedTypes.remove(TETHERING_USB);
when(mResources.getStringArray(R.array.config_tether_usb_regexs))
.thenReturn(new String[0]);
- updateConfigAndVerifySupported(callback, expectedTypes);
+ sendConfigurationChanged();
+ verifySupported(callback, expectedTypes);
// Wifi tethering is not supported:
expectedTypes.remove(TETHERING_WIFI);
when(mResources.getStringArray(R.array.config_tether_wifi_regexs))
.thenReturn(new String[0]);
- updateConfigAndVerifySupported(callback, expectedTypes);
+ sendConfigurationChanged();
+ verifySupported(callback, expectedTypes);
// Bluetooth tethering is not supported:
expectedTypes.remove(TETHERING_BLUETOOTH);
when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]);
if (isAtLeastT()) {
- updateConfigAndVerifySupported(callback, expectedTypes);
+ sendConfigurationChanged();
+ verifySupported(callback, expectedTypes);
// P2p tethering is not supported:
expectedTypes.remove(TETHERING_WIFI_P2P);
when(mResources.getStringArray(R.array.config_tether_wifi_p2p_regexs))
.thenReturn(new String[0]);
- updateConfigAndVerifySupported(callback, expectedTypes);
+ sendConfigurationChanged();
+ verifySupported(callback, expectedTypes);
// Ncm tethering is not supported:
expectedTypes.remove(TETHERING_NCM);
when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
.thenReturn(new String[0]);
- updateConfigAndVerifySupported(callback, expectedTypes);
+ sendConfigurationChanged();
+ verifySupported(callback, expectedTypes);
// Ethernet tethering (last supported type) is not supported:
expectedTypes.remove(TETHERING_ETHERNET);
mForceEthernetServiceUnavailable = true;
- updateConfigAndVerifySupported(callback, new ArraySet<>());
-
+ sendConfigurationChanged();
+ verifySupported(callback, new ArraySet<>());
} else {
// If wifi, usb and bluetooth are all not supported, all the types are not supported.
- expectedTypes.clear();
- updateConfigAndVerifySupported(callback, expectedTypes);
+ sendConfigurationChanged();
+ verifySupported(callback, new ArraySet<>());
}
}
- private void updateConfigAndVerifySupported(final TestTetheringEventCallback callback,
+ private void verifySupported(final TestTetheringEventCallback callback,
final ArraySet<Integer> expectedTypes) {
- sendConfigurationChanged();
-
assertEquals(expectedTypes.size() > 0, mTethering.isTetheringSupported());
callback.expectSupportedTetheringTypes(expectedTypes);
}
diff --git a/bpf_progs/dscpPolicy.c b/bpf_progs/dscpPolicy.c
index 3e4456f..72f63c6 100644
--- a/bpf_progs/dscpPolicy.c
+++ b/bpf_progs/dscpPolicy.c
@@ -62,8 +62,8 @@
uint8_t protocol = 0; // TODO: Use are reserved value? Or int (-1) and cast to uint below?
struct in6_addr src_ip = {};
struct in6_addr dst_ip = {};
- uint8_t tos = 0; // Only used for IPv4
- uint32_t old_first_u32 = 0; // Only used for IPv6
+ uint8_t tos = 0; // Only used for IPv4
+ __be32 old_first_be32 = 0; // Only used for IPv6
if (ipv4) {
const struct iphdr* const iph = (void*)(eth + 1);
hdr_size = l2_header_size + sizeof(struct iphdr);
@@ -96,7 +96,7 @@
src_ip = ip6h->saddr;
dst_ip = ip6h->daddr;
protocol = ip6h->nexthdr;
- old_first_u32 = *(uint32_t*)ip6h;
+ old_first_be32 = *(__be32*)ip6h;
}
switch (protocol) {
@@ -135,9 +135,9 @@
sizeof(uint16_t));
bpf_skb_store_bytes(skb, IP4_OFFSET(tos, l2_header_size), &newTos, sizeof(newTos), 0);
} else {
- uint32_t new_first_u32 =
- htonl(ntohl(old_first_u32) & 0xF03FFFFF | (existing_rule->dscp_val << 22));
- bpf_skb_store_bytes(skb, l2_header_size, &new_first_u32, sizeof(uint32_t),
+ __be32 new_first_be32 =
+ htonl(ntohl(old_first_be32) & 0xF03FFFFF | (existing_rule->dscp_val << 22));
+ bpf_skb_store_bytes(skb, l2_header_size, &new_first_be32, sizeof(__be32),
BPF_F_RECOMPUTE_CSUM);
}
return;
@@ -214,8 +214,8 @@
bpf_l3_csum_replace(skb, IP4_OFFSET(check, l2_header_size), htons(tos), htons(new_tos), 2);
bpf_skb_store_bytes(skb, IP4_OFFSET(tos, l2_header_size), &new_tos, sizeof(new_tos), 0);
} else {
- uint32_t new_first_u32 = htonl(ntohl(old_first_u32) & 0xF03FFFFF | (new_dscp << 22));
- bpf_skb_store_bytes(skb, l2_header_size, &new_first_u32, sizeof(uint32_t),
+ __be32 new_first_be32 = htonl(ntohl(old_first_be32) & 0xF03FFFFF | (new_dscp << 22));
+ bpf_skb_store_bytes(skb, l2_header_size, &new_first_be32, sizeof(__be32),
BPF_F_RECOMPUTE_CSUM);
}
return;
diff --git a/common/src/com/android/net/module/util/bpf/Tether4Key.java b/common/src/com/android/net/module/util/bpf/Tether4Key.java
index 638576f..8273e6a 100644
--- a/common/src/com/android/net/module/util/bpf/Tether4Key.java
+++ b/common/src/com/android/net/module/util/bpf/Tether4Key.java
@@ -30,8 +30,8 @@
/** Key type for downstream & upstream IPv4 forwarding maps. */
public class Tether4Key extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long iif;
+ @Field(order = 0, type = Type.S32)
+ public final int iif;
@Field(order = 1, type = Type.EUI48)
public final MacAddress dstMac;
@@ -51,7 +51,7 @@
@Field(order = 6, type = Type.UBE16)
public final int dstPort;
- public Tether4Key(final long iif, @NonNull final MacAddress dstMac, final short l4proto,
+ public Tether4Key(final int iif, @NonNull final MacAddress dstMac, final short l4proto,
final byte[] src4, final byte[] dst4, final int srcPort,
final int dstPort) {
Objects.requireNonNull(dstMac);
diff --git a/common/src/com/android/net/module/util/bpf/Tether4Value.java b/common/src/com/android/net/module/util/bpf/Tether4Value.java
index de98766..74fdda2 100644
--- a/common/src/com/android/net/module/util/bpf/Tether4Value.java
+++ b/common/src/com/android/net/module/util/bpf/Tether4Value.java
@@ -30,8 +30,8 @@
/** Value type for downstream & upstream IPv4 forwarding maps. */
public class Tether4Value extends Struct {
- @Field(order = 0, type = Type.U32)
- public final long oif;
+ @Field(order = 0, type = Type.S32)
+ public final int oif;
// The ethhdr struct which is defined in uapi/linux/if_ether.h
@Field(order = 1, type = Type.EUI48)
@@ -60,7 +60,7 @@
@Field(order = 9, type = Type.U63)
public final long lastUsed;
- public Tether4Value(final long oif, @NonNull final MacAddress ethDstMac,
+ public Tether4Value(final int oif, @NonNull final MacAddress ethDstMac,
@NonNull final MacAddress ethSrcMac, final int ethProto, final int pmtu,
final byte[] src46, final byte[] dst46, final int srcPort,
final int dstPort, final long lastUsed) {
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 11ba235..71fa8e4 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -191,6 +191,10 @@
mTc.dump(fd, verbose);
}
+static jint native_synchronizeKernelRCU(JNIEnv* env, jobject self) {
+ return -bpf::synchronizeKernelRCU();
+}
+
/*
* JNI registration.
*/
@@ -225,6 +229,8 @@
(void*)native_setPermissionForUids},
{"native_dump", "(Ljava/io/FileDescriptor;Z)V",
(void*)native_dump},
+ {"native_synchronizeKernelRCU", "()I",
+ (void*)native_synchronizeKernelRCU},
};
// clang-format on
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
index a1d0310..bd74d54 100644
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ b/service/jni/com_android_server_TestNetworkService.cpp
@@ -59,7 +59,8 @@
}
}
-static int createTunTapImpl(JNIEnv* env, bool isTun, bool hasCarrier, const char* iface) {
+static int createTunTapImpl(JNIEnv* env, bool isTun, bool hasCarrier, bool setIffMulticast,
+ const char* iface) {
base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
ifreq ifr{};
@@ -76,8 +77,8 @@
setTunTapCarrierEnabledImpl(env, iface, tun.get(), hasCarrier);
}
- // Mark TAP interfaces as supporting multicast
- if (!isTun) {
+ // Mark some TAP interfaces as supporting multicast
+ if (setIffMulticast && !isTun) {
base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
ifr.ifr_flags = IFF_MULTICAST;
@@ -122,14 +123,14 @@
}
static jint createTunTap(JNIEnv* env, jclass /* clazz */, jboolean isTun,
- jboolean hasCarrier, jstring jIface) {
+ jboolean hasCarrier, jboolean setIffMulticast, jstring jIface) {
ScopedUtfChars iface(env, jIface);
if (!iface.c_str()) {
jniThrowNullPointerException(env, "iface");
return -1;
}
- return createTunTapImpl(env, isTun, hasCarrier, iface.c_str());
+ return createTunTapImpl(env, isTun, hasCarrier, setIffMulticast, iface.c_str());
}
static void bringUpInterface(JNIEnv* env, jclass /* clazz */, jstring jIface) {
@@ -145,7 +146,7 @@
static const JNINativeMethod gMethods[] = {
{"nativeSetTunTapCarrierEnabled", "(Ljava/lang/String;IZ)V", (void*)setTunTapCarrierEnabled},
- {"nativeCreateTunTap", "(ZZLjava/lang/String;)I", (void*)createTunTap},
+ {"nativeCreateTunTap", "(ZZZLjava/lang/String;)I", (void*)createTunTap},
{"nativeBringUpInterface", "(Ljava/lang/String;)V", (void*)bringUpInterface},
};
diff --git a/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
index 3db1b22..f366363 100644
--- a/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
+++ b/service/mdns/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java
@@ -38,7 +38,7 @@
* and the list of the subtypes in the query as a {@link Pair}. If a query is failed to build, or if
* it can not be enqueued, then call to {@link #call()} returns {@code null}.
*/
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<String>>> {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java b/service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java
index ed28700..0b2066a 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsConstants.java
@@ -27,7 +27,7 @@
import java.nio.charset.StandardCharsets;
/** mDNS-related constants. */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting
public final class MdnsConstants {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java b/service/mdns/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java
index e35743c..bd47414 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java
@@ -27,7 +27,7 @@
import java.util.Objects;
/** An mDNS "AAAA" or "A" record, which holds an IPv6 or IPv4 address. */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting
public class MdnsInetAddressRecord extends MdnsRecord {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsPointerRecord.java b/service/mdns/com/android/server/connectivity/mdns/MdnsPointerRecord.java
index 2b36a3c..0166815 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsPointerRecord.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsPointerRecord.java
@@ -22,7 +22,7 @@
import java.util.Arrays;
/** An mDNS "PTR" record, which holds a name (the "pointer"). */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting
public class MdnsPointerRecord extends MdnsRecord {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java b/service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java
index 4bfdb2c..24fb09e 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsRecord.java
@@ -30,7 +30,7 @@
* Abstract base class for mDNS records. Stores the header fields and provides methods for reading
* the record from and writing it to a packet.
*/
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public abstract class MdnsRecord {
public static final int TYPE_A = 0x0001;
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponse.java b/service/mdns/com/android/server/connectivity/mdns/MdnsResponse.java
index 1305e07..9f3894f 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsResponse.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsResponse.java
@@ -25,7 +25,7 @@
import java.util.List;
/** An mDNS response. */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsResponse {
private final List<MdnsRecord> records;
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java b/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
index 72c3156..3e5fc42 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsResponseDecoder.java
@@ -30,7 +30,7 @@
import java.util.List;
/** A class that decodes mDNS responses from UDP packets. */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsResponseDecoder {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceRecord.java b/service/mdns/com/android/server/connectivity/mdns/MdnsServiceRecord.java
index 51de3b2..7f54d96 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceRecord.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsServiceRecord.java
@@ -24,7 +24,7 @@
import java.util.Objects;
/** An mDNS "SRV" record, which contains service information. */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting
public class MdnsServiceRecord extends MdnsRecord {
@@ -143,7 +143,7 @@
return super.equals(other)
&& (servicePriority == otherRecord.servicePriority)
&& (serviceWeight == otherRecord.serviceWeight)
- && Objects.equals(serviceHost, otherRecord.serviceHost)
+ && Arrays.equals(serviceHost, otherRecord.serviceHost)
&& (servicePort == otherRecord.servicePort);
}
-}
\ No newline at end of file
+}
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java b/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index c3a86e3..e335de9 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -39,7 +39,7 @@
* Instance of this class sends and receives mDNS packets of a given service type and invoke
* registered {@link MdnsServiceBrowserListener} instances.
*/
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsServiceTypeClient {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java b/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
index 241a52a..34db7f0 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsSocket.java
@@ -32,7 +32,7 @@
*
* @see MulticastSocket for javadoc of each public method.
*/
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsSocket {
private static final InetSocketAddress MULTICAST_IPV4_ADDRESS =
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
index e689d6c..010f761 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsSocketClient.java
@@ -46,7 +46,7 @@
*
* <p>See https://tools.ietf.org/html/rfc6763 (namely sections 4 and 5).
*/
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsSocketClient {
diff --git a/service/mdns/com/android/server/connectivity/mdns/MdnsTextRecord.java b/service/mdns/com/android/server/connectivity/mdns/MdnsTextRecord.java
index a5b5595..a364560 100644
--- a/service/mdns/com/android/server/connectivity/mdns/MdnsTextRecord.java
+++ b/service/mdns/com/android/server/connectivity/mdns/MdnsTextRecord.java
@@ -25,7 +25,7 @@
import java.util.Objects;
/** An mDNS "TXT" record, which contains a list of text strings. */
-// TODO(b/177655645): Resolve nullness suppression.
+// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting
public class MdnsTextRecord extends MdnsRecord {
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index 594223c..7387483 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -26,6 +26,8 @@
import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
+import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_UNINSTALLED;
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.ENODEV;
import static android.system.OsConstants.ENOENT;
@@ -45,6 +47,7 @@
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.DeviceConfigUtils;
import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.U8;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -81,10 +84,17 @@
// BpfNetMaps acquires this lock while sequence of read, modify, and write.
private static final Object sUidRulesConfigBpfMapLock = new Object();
+ // Lock for sConfigurationMap entry for CURRENT_STATS_MAP_CONFIGURATION_KEY.
+ // BpfNetMaps acquires this lock while sequence of read, modify, and write.
+ // BpfNetMaps is an only writer of this entry.
+ private static final Object sCurrentStatsMapConfigLock = new Object();
+
private static final String CONFIGURATION_MAP_PATH =
"/sys/fs/bpf/netd_shared/map_netd_configuration_map";
private static final String UID_OWNER_MAP_PATH =
"/sys/fs/bpf/netd_shared/map_netd_uid_owner_map";
+ private static final String UID_PERMISSION_MAP_PATH =
+ "/sys/fs/bpf/netd_shared/map_netd_uid_permission_map";
private static final U32 UID_RULES_CONFIGURATION_KEY = new U32(0);
private static final U32 CURRENT_STATS_MAP_CONFIGURATION_KEY = new U32(1);
private static final long UID_RULES_DEFAULT_CONFIGURATION = 0;
@@ -94,6 +104,7 @@
private static BpfMap<U32, U32> sConfigurationMap = null;
// BpfMap for UID_OWNER_MAP_PATH. This map is not accessed by others.
private static BpfMap<U32, UidOwnerValue> sUidOwnerMap = null;
+ private static BpfMap<U32, U8> sUidPermissionMap = null;
// LINT.IfChange(match_type)
@VisibleForTesting public static final long NO_MATCH = 0;
@@ -135,6 +146,14 @@
sUidOwnerMap = uidOwnerMap;
}
+ /**
+ * Set uidPermissionMap for test.
+ */
+ @VisibleForTesting
+ public static void setUidPermissionMapForTest(BpfMap<U32, U8> uidPermissionMap) {
+ sUidPermissionMap = uidPermissionMap;
+ }
+
private static BpfMap<U32, U32> getConfigurationMap() {
try {
return new BpfMap<>(
@@ -153,6 +172,15 @@
}
}
+ private static BpfMap<U32, U8> getUidPermissionMap() {
+ try {
+ return new BpfMap<>(
+ UID_PERMISSION_MAP_PATH, BpfMap.BPF_F_RDWR, U32.class, U8.class);
+ } catch (ErrnoException e) {
+ throw new IllegalStateException("Cannot open uid permission map", e);
+ }
+ }
+
private static void initBpfMaps() {
if (sConfigurationMap == null) {
sConfigurationMap = getConfigurationMap();
@@ -178,6 +206,10 @@
} catch (ErrnoException e) {
throw new IllegalStateException("Failed to initialize uid owner map", e);
}
+
+ if (sUidPermissionMap == null) {
+ sUidPermissionMap = getUidPermissionMap();
+ }
}
/**
@@ -209,6 +241,13 @@
public int getIfIndex(final String ifName) {
return Os.if_nametoindex(ifName);
}
+
+ /**
+ * Call synchronize_rcu()
+ */
+ public int synchronizeKernelRCU() {
+ return native_synchronizeKernelRCU();
+ }
}
/** Constructor used after T that doesn't need to use netd anymore. */
@@ -696,12 +735,40 @@
/**
* Request netd to change the current active network stats map.
*
+ * @throws UnsupportedOperationException if called on pre-T devices.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
public void swapActiveStatsMap() {
- final int err = native_swapActiveStatsMap();
- maybeThrow(err, "Unable to swap active stats map");
+ throwIfPreT("swapActiveStatsMap is not available on pre-T devices");
+
+ if (sEnableJavaBpfMap) {
+ try {
+ synchronized (sCurrentStatsMapConfigLock) {
+ final long config = sConfigurationMap.getValue(
+ CURRENT_STATS_MAP_CONFIGURATION_KEY).val;
+ final long newConfig = (config == STATS_SELECT_MAP_A)
+ ? STATS_SELECT_MAP_B : STATS_SELECT_MAP_A;
+ sConfigurationMap.updateEntry(CURRENT_STATS_MAP_CONFIGURATION_KEY,
+ new U32(newConfig));
+ }
+ } catch (ErrnoException e) {
+ throw new ServiceSpecificException(e.errno, "Failed to swap active stats map");
+ }
+
+ // After changing the config, it's needed to make sure all the current running eBPF
+ // programs are finished and all the CPUs are aware of this config change before the old
+ // map is modified. So special hack is needed here to wait for the kernel to do a
+ // synchronize_rcu(). Once the kernel called synchronize_rcu(), the updated config will
+ // be available to all cores and the next eBPF programs triggered inside the kernel will
+ // use the new map configuration. So once this function returns it is safe to modify the
+ // old stats map without concerning about race between the kernel and userspace.
+ final int err = mDeps.synchronizeKernelRCU();
+ maybeThrow(err, "synchronizeKernelRCU failed");
+ } else {
+ final int err = native_swapActiveStatsMap();
+ maybeThrow(err, "Unable to swap active stats map");
+ }
}
/**
@@ -719,7 +786,31 @@
mNetd.trafficSetNetPermForUids(permissions, uids);
return;
}
- native_setPermissionForUids(permissions, uids);
+
+ if (sEnableJavaBpfMap) {
+ // Remove the entry if package is uninstalled or uid has only INTERNET permission.
+ if (permissions == PERMISSION_UNINSTALLED || permissions == PERMISSION_INTERNET) {
+ for (final int uid : uids) {
+ try {
+ sUidPermissionMap.deleteEntry(new U32(uid));
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Failed to remove uid " + uid + " from permission map: " + e);
+ }
+ }
+ return;
+ }
+
+ for (final int uid : uids) {
+ try {
+ sUidPermissionMap.updateEntry(new U32(uid), new U8((short) permissions));
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Failed to set permission "
+ + permissions + " to uid " + uid + ": " + e);
+ }
+ }
+ } else {
+ native_setPermissionForUids(permissions, uids);
+ }
}
/**
@@ -753,4 +844,5 @@
private native int native_swapActiveStatsMap();
private native void native_setPermissionForUids(int permissions, int[] uids);
private native void native_dump(FileDescriptor fd, boolean verbose);
+ private static native int native_synchronizeKernelRCU();
}
diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java
index 15d9f13..5549fbe 100644
--- a/service/src/com/android/server/TestNetworkService.java
+++ b/service/src/com/android/server/TestNetworkService.java
@@ -77,7 +77,7 @@
// Native method stubs
private static native int nativeCreateTunTap(boolean isTun, boolean hasCarrier,
- @NonNull String iface);
+ boolean setIffMulticast, @NonNull String iface);
private static native void nativeSetTunTapCarrierEnabled(@NonNull String iface, int tunFd,
boolean enabled);
@@ -136,8 +136,14 @@
final long token = Binder.clearCallingIdentity();
try {
+ // Note: if the interface is brought up by ethernet, setting IFF_MULTICAST
+ // races NetUtils#setInterfaceUp(). This flag is not necessary for ethernet
+ // tests, so let's not set it when bringUp is false. See also b/242343156.
+ // In the future, we could use RTM_SETLINK with ifi_change set to set the
+ // flags atomically.
+ final boolean setIffMulticast = bringUp;
ParcelFileDescriptor tunIntf = ParcelFileDescriptor.adoptFd(
- nativeCreateTunTap(isTun, hasCarrier, interfaceName));
+ nativeCreateTunTap(isTun, hasCarrier, setIffMulticast, interfaceName));
// Disable DAD and remove router_solicitation_delay before assigning link addresses.
if (disableIpv6ProvisioningDelay) {
diff --git a/tests/cts/net/src/android/net/cts/DeviceConfigRule.kt b/tests/cts/net/src/android/net/cts/DeviceConfigRule.kt
index 3a739f2..9599d4e 100644
--- a/tests/cts/net/src/android/net/cts/DeviceConfigRule.kt
+++ b/tests/cts/net/src/android/net/cts/DeviceConfigRule.kt
@@ -21,7 +21,7 @@
import android.provider.DeviceConfig
import android.util.Log
import com.android.modules.utils.build.SdkLevel
-import com.android.testutils.ExceptionUtils.ThrowingRunnable
+import com.android.testutils.FunctionalUtils.ThrowingRunnable
import com.android.testutils.runAsShell
import com.android.testutils.tryTest
import org.junit.rules.TestRule
diff --git a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
index 1f76773..8940075 100644
--- a/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
+++ b/tests/cts/net/src/android/net/cts/DscpPolicyTest.kt
@@ -163,8 +163,7 @@
// Only statically configure the IPv4 address; for IPv6, use the SLAAC generated
// address.
- iface = tnm.createTapInterface(true /* disableIpv6ProvisioningDelay */,
- arrayOf(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN)))
+ iface = tnm.createTapInterface(arrayOf(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN)))
assertNotNull(iface)
}
@@ -224,7 +223,7 @@
val onLinkPrefix = raResponder.prefix
val startTime = SystemClock.elapsedRealtime()
while (SystemClock.elapsedRealtime() - startTime < PACKET_TIMEOUT_MS) {
- SystemClock.sleep(1 /* ms */)
+ SystemClock.sleep(50 /* ms */)
val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
try {
network.bindSocket(sock)
@@ -273,7 +272,6 @@
val lp = LinkProperties().apply {
addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, IP4_PREFIX_LEN))
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
- addRoute(RouteInfo(IpPrefix("::/0"), TEST_ROUTER_IPV6_ADDR))
setInterfaceName(specifier)
}
val config = NetworkAgentConfig.Builder().build()
@@ -318,6 +316,7 @@
fun parseV4PacketDscp(buffer: ByteBuffer): Int {
// Validate checksum before parsing packet.
val calCheck = IpUtils.ipChecksum(buffer, Struct.getSize(EthernetHeader::class.java))
+ assertEquals(0, calCheck, "Invalid IPv4 header checksum")
val ip_ver = buffer.get()
val tos = buffer.get()
@@ -328,7 +327,11 @@
val ipType = buffer.get()
val checksum = buffer.getShort()
- assertEquals(0, calCheck, "Invalid IPv4 header checksum")
+ if (ipType.toInt() == 2 /* IPPROTO_IGMP */ && ip_ver.toInt() == 0x46) {
+ // Need to ignore 'igmp v3 report' with 'router alert' option
+ } else {
+ assertEquals(0x45, ip_ver.toInt(), "Invalid IPv4 version or IPv4 options present")
+ }
return tos.toInt().shr(2)
}
@@ -339,6 +342,9 @@
val length = buffer.getShort()
val proto = buffer.get()
val hop = buffer.get()
+
+ assertEquals(6, ip_ver.toInt().shr(4), "Invalid IPv6 version")
+
// DSCP is bottom 4 bits of ip_ver and top 2 of tc.
val ip_ver_bottom = ip_ver.toInt().and(0xf)
val tc_dscp = tc.toInt().shr(6)
diff --git a/tests/cts/net/src/android/net/cts/TunUtils.java b/tests/cts/net/src/android/net/cts/TunUtils.java
index d8e39b4..0377160 100644
--- a/tests/cts/net/src/android/net/cts/TunUtils.java
+++ b/tests/cts/net/src/android/net/cts/TunUtils.java
@@ -27,12 +27,13 @@
import android.os.ParcelFileDescriptor;
+import com.android.net.module.util.CollectionUtils;
+
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
@@ -170,7 +171,7 @@
*/
private static boolean isEspFailIfSpecifiedPlaintextFound(
byte[] pkt, int spi, boolean encap, byte[] plaintext) {
- if (Collections.indexOfSubList(Arrays.asList(pkt), Arrays.asList(plaintext)) != -1) {
+ if (CollectionUtils.indexOfSubArray(pkt, plaintext) != -1) {
fail("Banned plaintext packet found");
}
diff --git a/tests/integration/AndroidManifest.xml b/tests/integration/AndroidManifest.xml
index 2e13689..50f02d3 100644
--- a/tests/integration/AndroidManifest.xml
+++ b/tests/integration/AndroidManifest.xml
@@ -60,7 +60,7 @@
<action android:name=".INetworkStackInstrumentation"/>
</intent-filter>
</service>
- <service android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService"
+ <service android:name="com.android.networkstack.ipmemorystore.RegularMaintenanceJobService"
android:process="com.android.server.net.integrationtests.testnetworkstack"
android:permission="android.permission.BIND_JOB_SERVICE"/>
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index e3dbb14..8a4932b 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -38,7 +38,7 @@
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
-import com.android.testutils.ExceptionUtils;
+import com.android.testutils.FunctionalUtils.ThrowingConsumer;
import org.junit.Before;
import org.junit.Rule;
@@ -396,7 +396,7 @@
}
}
- int getRequestKey(ExceptionUtils.ThrowingConsumer<ArgumentCaptor<Integer>> verifier)
+ int getRequestKey(ThrowingConsumer<ArgumentCaptor<Integer>> verifier)
throws Exception {
final ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
verifier.accept(captor);
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index 2d09bf2..be286ec 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -27,6 +27,10 @@
import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_NONE;
+import static android.net.INetd.PERMISSION_UNINSTALLED;
+import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
+import static android.system.OsConstants.EPERM;
import static com.android.server.BpfNetMaps.DOZABLE_MATCH;
import static com.android.server.BpfNetMaps.HAPPY_BOX_MATCH;
@@ -56,6 +60,7 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BpfMap;
import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.U8;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -88,6 +93,7 @@
private static final int NULL_IIF = 0;
private static final String CHAINNAME = "fw_dozable";
private static final U32 UID_RULES_CONFIGURATION_KEY = new U32(0);
+ private static final U32 CURRENT_STATS_MAP_CONFIGURATION_KEY = new U32(1);
private static final List<Integer> FIREWALL_CHAINS = List.of(
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_STANDBY,
@@ -99,6 +105,9 @@
FIREWALL_CHAIN_OEM_DENY_3
);
+ private static final long STATS_SELECT_MAP_A = 0;
+ private static final long STATS_SELECT_MAP_B = 1;
+
private BpfNetMaps mBpfNetMaps;
@Mock INetd mNetd;
@@ -107,14 +116,17 @@
private final BpfMap<U32, U32> mConfigurationMap = new TestBpfMap<>(U32.class, U32.class);
private final BpfMap<U32, UidOwnerValue> mUidOwnerMap =
new TestBpfMap<>(U32.class, UidOwnerValue.class);
+ private final BpfMap<U32, U8> mUidPermissionMap = new TestBpfMap<>(U32.class, U8.class);
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doReturn(TEST_IF_INDEX).when(mDeps).getIfIndex(TEST_IF_NAME);
+ doReturn(0).when(mDeps).synchronizeKernelRCU();
BpfNetMaps.setEnableJavaBpfMapForTest(true /* enable */);
BpfNetMaps.setConfigurationMapForTest(mConfigurationMap);
BpfNetMaps.setUidOwnerMapForTest(mUidOwnerMap);
+ BpfNetMaps.setUidPermissionMapForTest(mUidPermissionMap);
mBpfNetMaps = new BpfNetMaps(mContext, mNetd, mDeps);
}
@@ -728,4 +740,141 @@
() -> mBpfNetMaps.replaceUidChain(FIREWALL_CHAIN_DOZABLE, TEST_UIDS));
}
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsGrantInternetPermission() throws Exception {
+ mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS);
+
+ assertTrue(mUidPermissionMap.isEmpty());
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsGrantUpdateStatsPermission() throws Exception {
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, TEST_UIDS);
+
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ assertEquals(PERMISSION_UPDATE_DEVICE_STATS, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(PERMISSION_UPDATE_DEVICE_STATS, mUidPermissionMap.getValue(new U32(uid1)).val);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsGrantMultiplePermissions() throws Exception {
+ final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS;
+ mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS);
+
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid1)).val);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsRevokeInternetPermission() throws Exception {
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS);
+ mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, new int[]{uid0});
+
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertNull(mUidPermissionMap.getValue(new U32(uid1)));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsRevokeUpdateDeviceStatsPermission() throws Exception {
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, TEST_UIDS);
+ mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, new int[]{uid0});
+
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(PERMISSION_UPDATE_DEVICE_STATS, mUidPermissionMap.getValue(new U32(uid1)).val);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsRevokeMultiplePermissions() throws Exception {
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS;
+ mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS);
+ mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, new int[]{uid0});
+
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid1)).val);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsPermissionUninstalled() throws Exception {
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS;
+ mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS);
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED, new int[]{uid0});
+
+ assertNull(mUidPermissionMap.getValue(new U32(uid0)));
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid1)).val);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSetNetPermForUidsDuplicatedRequestSilentlyIgnored() throws Exception {
+ final int uid0 = TEST_UIDS[0];
+ final int uid1 = TEST_UIDS[1];
+ final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS;
+
+ mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS);
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid1)).val);
+
+ mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS);
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(permission, mUidPermissionMap.getValue(new U32(uid1)).val);
+
+ mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, TEST_UIDS);
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid1)).val);
+
+ mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, TEST_UIDS);
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid0)).val);
+ assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new U32(uid1)).val);
+
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED, TEST_UIDS);
+ assertNull(mUidPermissionMap.getValue(new U32(uid0)));
+ assertNull(mUidPermissionMap.getValue(new U32(uid1)));
+
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED, TEST_UIDS);
+ assertNull(mUidPermissionMap.getValue(new U32(uid0)));
+ assertNull(mUidPermissionMap.getValue(new U32(uid1)));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSwapActiveStatsMap() throws Exception {
+ mConfigurationMap.updateEntry(
+ CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_A));
+
+ mBpfNetMaps.swapActiveStatsMap();
+ assertEquals(STATS_SELECT_MAP_B,
+ mConfigurationMap.getValue(CURRENT_STATS_MAP_CONFIGURATION_KEY).val);
+
+ mBpfNetMaps.swapActiveStatsMap();
+ assertEquals(STATS_SELECT_MAP_A,
+ mConfigurationMap.getValue(CURRENT_STATS_MAP_CONFIGURATION_KEY).val);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testSwapActiveStatsMapSynchronizeKernelRCUFail() throws Exception {
+ doReturn(EPERM).when(mDeps).synchronizeKernelRCU();
+ mConfigurationMap.updateEntry(
+ CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_A));
+
+ assertThrows(ServiceSpecificException.class, () -> mBpfNetMaps.swapActiveStatsMap());
+ }
}
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 4b832dd..8bf0ca5 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -159,7 +159,7 @@
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.FunctionalUtils.ignoreExceptions;
import static com.android.testutils.HandlerUtils.waitForIdleSerialExecutor;
import static com.android.testutils.MiscAsserts.assertContainsAll;
import static com.android.testutils.MiscAsserts.assertContainsExactly;
@@ -378,7 +378,9 @@
import com.android.server.net.NetworkPinner;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
-import com.android.testutils.ExceptionUtils;
+import com.android.testutils.FunctionalUtils.Function3;
+import com.android.testutils.FunctionalUtils.ThrowingConsumer;
+import com.android.testutils.FunctionalUtils.ThrowingRunnable;
import com.android.testutils.HandlerUtils;
import com.android.testutils.RecorderCallback.CallbackEntry;
import com.android.testutils.TestableNetworkCallback;
@@ -744,7 +746,7 @@
}
private int checkMockedPermission(String permission, int pid, int uid,
- Supplier<Integer> ifAbsent) {
+ Function3<String, Integer, Integer, Integer> ifAbsent /* perm, uid, pid -> int */) {
final Integer granted = mMockedPermissions.get(permission + "," + pid + "," + uid);
if (null != granted) {
return granted;
@@ -753,27 +755,27 @@
if (null != allGranted) {
return allGranted;
}
- return ifAbsent.get();
+ return ifAbsent.apply(permission, pid, uid);
}
@Override
public int checkPermission(String permission, int pid, int uid) {
return checkMockedPermission(permission, pid, uid,
- () -> super.checkPermission(permission, pid, uid));
+ (perm, p, u) -> super.checkPermission(perm, p, u));
}
@Override
public int checkCallingOrSelfPermission(String permission) {
return checkMockedPermission(permission, Process.myPid(), Process.myUid(),
- () -> super.checkCallingOrSelfPermission(permission));
+ (perm, p, u) -> super.checkCallingOrSelfPermission(perm));
}
@Override
public void enforceCallingOrSelfPermission(String permission, String message) {
final Integer granted = checkMockedPermission(permission,
Process.myPid(), Process.myUid(),
- () -> {
- super.enforceCallingOrSelfPermission(permission, message);
+ (perm, p, u) -> {
+ super.enforceCallingOrSelfPermission(perm, message);
// enforce will crash if the permission is not granted
return PERMISSION_GRANTED;
});
@@ -786,7 +788,7 @@
/**
* Mock checks for the specified permission, and have them behave as per {@code granted}.
*
- * This will apply across the board no matter what the checked UID and PID are.
+ * This will apply to all calls no matter what the checked UID and PID are.
*
* <p>Passing null reverts to default behavior, which does a real permission check on the
* test package.
@@ -1718,11 +1720,7 @@
});
}
- private interface ExceptionalRunnable {
- void run() throws Exception;
- }
-
- private void withPermission(String permission, ExceptionalRunnable r) throws Exception {
+ private void withPermission(String permission, ThrowingRunnable r) throws Exception {
try {
mServiceContext.setPermission(permission, PERMISSION_GRANTED);
r.run();
@@ -1731,7 +1729,7 @@
}
}
- private void withPermission(String permission, int pid, int uid, ExceptionalRunnable r)
+ private void withPermission(String permission, int pid, int uid, ThrowingRunnable r)
throws Exception {
try {
mServiceContext.setPermission(permission, pid, uid, PERMISSION_GRANTED);
@@ -6200,7 +6198,7 @@
}
// Helper method to prepare the executor and run test
- private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
+ private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor)
throws Exception {
final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
final Executor executorInline = (Runnable r) -> r.run();
@@ -15752,7 +15750,7 @@
final UserHandle testHandle = setupEnterpriseNetwork();
final TestOnCompleteListener listener = new TestOnCompleteListener();
// Leave one request available so the profile preference can be set.
- testRequestCountLimits(1 /* countToLeaveAvailable */, () -> {
+ withRequestCountersAcquired(1 /* countToLeaveAvailable */, () -> {
withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
Process.myPid(), Process.myUid(), () -> {
// Set initially to test the limit prior to having existing requests.
@@ -15801,7 +15799,7 @@
@OemNetworkPreferences.OemNetworkPreference final int networkPref =
OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
// Leave one request available so the OEM preference can be set.
- testRequestCountLimits(1 /* countToLeaveAvailable */, () ->
+ withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, () -> {
// Set initially to test the limit prior to having existing requests.
final TestOemListenerCallback listener = new TestOemListenerCallback();
@@ -15816,8 +15814,8 @@
}));
}
- private void testRequestCountLimits(final int countToLeaveAvailable,
- @NonNull final ExceptionalRunnable r) throws Exception {
+ private void withRequestCountersAcquired(final int countToLeaveAvailable,
+ @NonNull final ThrowingRunnable r) throws Exception {
final ArraySet<TestNetworkCallback> callbacks = new ArraySet<>();
try {
final int requestCount = mService.mSystemNetworkRequestCounter
@@ -16084,7 +16082,7 @@
ConnectivitySettingsManager.setMobileDataPreferredUids(mServiceContext,
Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
// Leave one request available so MDO preference set up above can be set.
- testRequestCountLimits(1 /* countToLeaveAvailable */, () ->
+ withRequestCountersAcquired(1 /* countToLeaveAvailable */, () ->
withPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
Process.myPid(), Process.myUid(), () -> {
// Set initially to test the limit prior to having existing requests.
diff --git a/tests/unit/java/com/android/server/NetIdManagerTest.kt b/tests/unit/java/com/android/server/NetIdManagerTest.kt
index 811134e..f2b14a1 100644
--- a/tests/unit/java/com/android/server/NetIdManagerTest.kt
+++ b/tests/unit/java/com/android/server/NetIdManagerTest.kt
@@ -21,7 +21,7 @@
import com.android.server.NetIdManager.MIN_NET_ID
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
-import com.android.testutils.ExceptionUtils.ThrowingRunnable
+import com.android.testutils.FunctionalUtils.ThrowingRunnable
import com.android.testutils.assertThrows
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 041e4ea..f159859 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -92,6 +92,7 @@
import android.net.LinkProperties;
import android.net.LocalSocket;
import android.net.Network;
+import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo;
@@ -264,6 +265,7 @@
final Ikev2VpnProfile.Builder builder =
new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY);
builder.setAuthPsk(TEST_VPN_PSK);
+ builder.setBypassable(true /* isBypassable */);
mVpnProfile = builder.build().toVpnProfile();
}
@@ -1787,9 +1789,11 @@
ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class);
ArgumentCaptor<NetworkCapabilities> ncCaptor =
ArgumentCaptor.forClass(NetworkCapabilities.class);
+ ArgumentCaptor<NetworkAgentConfig> nacCaptor =
+ ArgumentCaptor.forClass(NetworkAgentConfig.class);
verify(mTestDeps).newNetworkAgent(
any(), any(), anyString(), ncCaptor.capture(), lpCaptor.capture(),
- any(), any(), any());
+ any(), nacCaptor.capture(), any());
// Check LinkProperties
final LinkProperties lp = lpCaptor.getValue();
@@ -1811,6 +1815,9 @@
// Check NetworkCapabilities
assertEquals(Arrays.asList(TEST_NETWORK), ncCaptor.getValue().getUnderlyingNetworks());
+ // Check if allowBypass is set or not.
+ assertTrue(nacCaptor.getValue().isBypassableVpn());
+
return new PlatformVpnSnapshot(vpn, nwCb, ikeCb, childCb);
}
diff --git a/tools/gen_jarjar.py b/tools/gen_jarjar.py
index 4c2cf54..2ff53fa 100755
--- a/tools/gen_jarjar.py
+++ b/tools/gen_jarjar.py
@@ -115,7 +115,8 @@
jar_classes = _list_jar_classes(jar)
jar_classes.sort()
for clazz in jar_classes:
- if (_get_toplevel_class(clazz) not in excluded_classes and
+ if (not clazz.startswith(args.prefix + '.') and
+ _get_toplevel_class(clazz) not in excluded_classes and
not any(r.fullmatch(clazz) for r in exclude_regexes)):
outfile.write(f'rule {clazz} {args.prefix}.@0\n')
# Also include jarjar rules for unit tests of the class, so the package matches
diff --git a/tools/testdata/java/jarjar/prefix/AlreadyInTargetPackageClass.java b/tools/testdata/java/jarjar/prefix/AlreadyInTargetPackageClass.java
new file mode 100644
index 0000000..6859020
--- /dev/null
+++ b/tools/testdata/java/jarjar/prefix/AlreadyInTargetPackageClass.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package jarjar.prefix;
+
+/**
+ * Sample class to test jarjar rules, already in the "jarjar.prefix" package.
+ */
+public class AlreadyInTargetPackageClass {
+ /** Test inner class that should not be jarjared either */
+ public static class TestInnerClass {}
+}