Merge "Don't attempt to override compat changes on user builds." into tm-dev
diff --git a/bpf_progs/bpf_shared.h b/bpf_progs/bpf_shared.h
index 634fbf4..706dd1d 100644
--- a/bpf_progs/bpf_shared.h
+++ b/bpf_progs/bpf_shared.h
@@ -133,6 +133,9 @@
LOW_POWER_STANDBY_MATCH = (1 << 6),
IIF_MATCH = (1 << 7),
LOCKDOWN_VPN_MATCH = (1 << 8),
+ OEM_DENY_1_MATCH = (1 << 9),
+ OEM_DENY_2_MATCH = (1 << 10),
+ OEM_DENY_3_MATCH = (1 << 11),
};
enum BpfPermissionMatch {
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index b4ef7eb..d754616 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -216,6 +216,15 @@
if ((enabledRules & LOW_POWER_STANDBY_MATCH) && !(uidRules & LOW_POWER_STANDBY_MATCH)) {
return BPF_DROP;
}
+ if ((enabledRules & OEM_DENY_1_MATCH) && (uidRules & OEM_DENY_1_MATCH)) {
+ return BPF_DROP;
+ }
+ if ((enabledRules & OEM_DENY_2_MATCH) && (uidRules & OEM_DENY_2_MATCH)) {
+ return BPF_DROP;
+ }
+ if ((enabledRules & OEM_DENY_3_MATCH) && (uidRules & OEM_DENY_3_MATCH)) {
+ return BPF_DROP;
+ }
}
if (direction == BPF_INGRESS && skb->ifindex != 1) {
if (uidRules & IIF_MATCH) {
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 4ecc8a1..f741c2b 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -992,6 +992,27 @@
*/
public static final int FIREWALL_CHAIN_LOCKDOWN_VPN = 6;
+ /**
+ * Firewall chain used for OEM-specific application restrictions.
+ * Denylist of apps that will not have network access due to OEM-specific restrictions.
+ * @hide
+ */
+ public static final int FIREWALL_CHAIN_OEM_DENY_1 = 7;
+
+ /**
+ * Firewall chain used for OEM-specific application restrictions.
+ * Denylist of apps that will not have network access due to OEM-specific restrictions.
+ * @hide
+ */
+ public static final int FIREWALL_CHAIN_OEM_DENY_2 = 8;
+
+ /**
+ * Firewall chain used for OEM-specific application restrictions.
+ * Denylist of apps that will not have network access due to OEM-specific restrictions.
+ * @hide
+ */
+ public static final int FIREWALL_CHAIN_OEM_DENY_3 = 9;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = false, prefix = "FIREWALL_CHAIN_", value = {
@@ -1000,7 +1021,10 @@
FIREWALL_CHAIN_POWERSAVE,
FIREWALL_CHAIN_RESTRICTED,
FIREWALL_CHAIN_LOW_POWER_STANDBY,
- FIREWALL_CHAIN_LOCKDOWN_VPN
+ FIREWALL_CHAIN_LOCKDOWN_VPN,
+ FIREWALL_CHAIN_OEM_DENY_1,
+ FIREWALL_CHAIN_OEM_DENY_2,
+ FIREWALL_CHAIN_OEM_DENY_3
})
public @interface FirewallChain {}
// LINT.ThenChange(packages/modules/Connectivity/service/native/include/Common.h)
diff --git a/nearby/tests/multidevices/host/Android.bp b/nearby/tests/multidevices/host/Android.bp
index ff795e8..b81032d 100644
--- a/nearby/tests/multidevices/host/Android.bp
+++ b/nearby/tests/multidevices/host/Android.bp
@@ -16,16 +16,16 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-// Run the tests: atest -v CtsNearbyMultiDevicesTestSuite
+// Run the tests: atest -v NearbyMultiDevicesTestSuite
// Check go/run-nearby-mainline-e2e for more details.
python_test_host {
- name: "CtsNearbyMultiDevicesTestSuite",
+ name: "NearbyMultiDevicesTestSuite",
main: "suite_main.py",
srcs: ["*.py"],
libs: ["NearbyMultiDevicesHostHelper"],
test_suites: [
- "cts",
"general-tests",
+ "mts-tethering",
],
test_options: {
unit_test: false,
diff --git a/nearby/tests/multidevices/host/AndroidTest.xml b/nearby/tests/multidevices/host/AndroidTest.xml
index 43cf136..c1f6a70 100644
--- a/nearby/tests/multidevices/host/AndroidTest.xml
+++ b/nearby/tests/multidevices/host/AndroidTest.xml
@@ -11,7 +11,17 @@
limitations under the License.
-->
<configuration description="Config for CTS Nearby Mainline multi devices end-to-end test suite">
- <option name="test-suite-tag" value="cts" />
+ <!-- Only run tests if the device under test is SDK version 33 (Android 13) or above. -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.Sdk33ModuleController" />
+ <!-- Only run NearbyMultiDevicesTestSuite in MTS if the Nearby Mainline module is installed. -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.tethering" />
+ </object>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="NearbyMultiDevicesTestSuite" />
<option name="config-descriptor:metadata" key="component" value="wifi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
@@ -124,7 +134,7 @@
<test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest">
<!-- The mobly-par-file-name should match the module name -->
- <option name="mobly-par-file-name" value="CtsNearbyMultiDevicesTestSuite" />
+ <option name="mobly-par-file-name" value="NearbyMultiDevicesTestSuite" />
<!-- Timeout limit in milliseconds for all test cases of the python binary -->
<option name="mobly-test-timeout" value="60000" />
</test>
diff --git a/netd/BpfHandlerTest.cpp b/netd/BpfHandlerTest.cpp
index 12ae916..1bd222d 100644
--- a/netd/BpfHandlerTest.cpp
+++ b/netd/BpfHandlerTest.cpp
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
+#define TEST_BPF_MAP
#include "BpfHandler.h"
using namespace android::bpf; // NOLINT(google-build-using-namespace): exempted
@@ -55,39 +56,31 @@
std::lock_guard guard(mBh.mMutex);
ASSERT_EQ(0, setrlimitForTest());
- mFakeCookieTagMap.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(uint64_t), sizeof(UidTagValue),
- TEST_MAP_SIZE, 0));
+ mFakeCookieTagMap.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeCookieTagMap);
- mFakeStatsMapA.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(StatsKey), sizeof(StatsValue),
- TEST_MAP_SIZE, 0));
+ mFakeStatsMapA.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeStatsMapA);
- mFakeConfigurationMap.reset(
- createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint8_t), 1, 0));
+ mFakeConfigurationMap.resetMap(BPF_MAP_TYPE_HASH, 1);
ASSERT_VALID(mFakeConfigurationMap);
- mFakeUidPermissionMap.reset(
- createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint8_t), TEST_MAP_SIZE, 0));
+ mFakeUidPermissionMap.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE, 0);
ASSERT_VALID(mFakeUidPermissionMap);
- mBh.mCookieTagMap.reset(dupFd(mFakeCookieTagMap.getMap()));
+ mBh.mCookieTagMap = mFakeCookieTagMap;
ASSERT_VALID(mBh.mCookieTagMap);
- mBh.mStatsMapA.reset(dupFd(mFakeStatsMapA.getMap()));
+ mBh.mStatsMapA = mFakeStatsMapA;
ASSERT_VALID(mBh.mStatsMapA);
- mBh.mConfigurationMap.reset(dupFd(mFakeConfigurationMap.getMap()));
+ mBh.mConfigurationMap = mFakeConfigurationMap;
ASSERT_VALID(mBh.mConfigurationMap);
// Always write to stats map A by default.
ASSERT_RESULT_OK(mBh.mConfigurationMap.writeValue(CURRENT_STATS_MAP_CONFIGURATION_KEY,
SELECT_MAP_A, BPF_ANY));
- mBh.mUidPermissionMap.reset(dupFd(mFakeUidPermissionMap.getMap()));
+ mBh.mUidPermissionMap = mFakeUidPermissionMap;
ASSERT_VALID(mBh.mUidPermissionMap);
}
- int dupFd(const android::base::unique_fd& mapFd) {
- return fcntl(mapFd.get(), F_DUPFD_CLOEXEC, 0);
- }
-
int setUpSocketAndTag(int protocol, uint64_t* cookie, uint32_t tag, uid_t uid,
uid_t realUid) {
int sock = socket(protocol, SOCK_STREAM | SOCK_CLOEXEC, 0);
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 709b774..1ab7515 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -229,7 +229,7 @@
*/
protected void broadcastInterfaceStateChange(@NonNull String iface) {
ensureRunningOnEthernetServiceThread();
- final int state = mFactory.getInterfaceState(iface);
+ final int state = getInterfaceState(iface);
final int role = getInterfaceRole(iface);
final IpConfiguration config = getIpConfigurationForCallback(iface, state);
final int n = mListeners.beginBroadcast();
@@ -436,15 +436,34 @@
if (mDefaultInterface != null) {
removeInterface(mDefaultInterface);
addInterface(mDefaultInterface);
+ // when this broadcast is sent, any calls to notifyTetheredInterfaceAvailable or
+ // notifyTetheredInterfaceUnavailable have already happened
+ broadcastInterfaceStateChange(mDefaultInterface);
}
}
+ private int getInterfaceState(final String iface) {
+ if (mFactory.hasInterface(iface)) {
+ return mFactory.getInterfaceState(iface);
+ }
+ if (getInterfaceMode(iface) == INTERFACE_MODE_SERVER) {
+ // server mode interfaces are not tracked by the factory.
+ // TODO(b/234743836): interface state for server mode interfaces is not tracked
+ // properly; just return link up.
+ return EthernetManager.STATE_LINK_UP;
+ }
+ return EthernetManager.STATE_ABSENT;
+ }
+
private int getInterfaceRole(final String iface) {
- if (!mFactory.hasInterface(iface)) return EthernetManager.ROLE_NONE;
- final int mode = getInterfaceMode(iface);
- return (mode == INTERFACE_MODE_CLIENT)
- ? EthernetManager.ROLE_CLIENT
- : EthernetManager.ROLE_SERVER;
+ if (mFactory.hasInterface(iface)) {
+ // only client mode interfaces are tracked by the factory.
+ return EthernetManager.ROLE_CLIENT;
+ }
+ if (getInterfaceMode(iface) == INTERFACE_MODE_SERVER) {
+ return EthernetManager.ROLE_SERVER;
+ }
+ return EthernetManager.ROLE_NONE;
}
private int getInterfaceMode(final String iface) {
diff --git a/service/ServiceConnectivityResources/res/values-or/strings.xml b/service/ServiceConnectivityResources/res/values-or/strings.xml
index 8b85884..49a773a 100644
--- a/service/ServiceConnectivityResources/res/values-or/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-or/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="connectivityResourcesAppLabel" msgid="2476261877900882974">"ସିଷ୍ଟମର ସଂଯୋଗ ସମ୍ବନ୍ଧିତ ରିସୋର୍ସଗୁଡ଼ିକ"</string>
+ <string name="connectivityResourcesAppLabel" msgid="2476261877900882974">"ସିଷ୍ଟମ କନେକ୍ଟିଭିଟୀ ରିସୋର୍ସ"</string>
<string name="wifi_available_sign_in" msgid="8041178343789805553">"ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍-ଇନ୍ କରନ୍ତୁ"</string>
<string name="network_available_sign_in" msgid="2622520134876355561">"ନେଟ୍ୱର୍କରେ ସାଇନ୍ ଇନ୍ କରନ୍ତୁ"</string>
<!-- no translation found for network_available_sign_in_detailed (8439369644697866359) -->
diff --git a/service/ServiceConnectivityResources/res/values-sq/strings.xml b/service/ServiceConnectivityResources/res/values-sq/strings.xml
index 385c75c..85bd84f 100644
--- a/service/ServiceConnectivityResources/res/values-sq/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-sq/strings.xml
@@ -35,7 +35,7 @@
<string-array name="network_switch_type_name">
<item msgid="3004933964374161223">"të dhënat celulare"</item>
<item msgid="5624324321165953608">"Wi-Fi"</item>
- <item msgid="5667906231066981731">"Bluetooth"</item>
+ <item msgid="5667906231066981731">"Bluetooth-i"</item>
<item msgid="346574747471703768">"Eternet"</item>
<item msgid="5734728378097476003">"VPN"</item>
</string-array>
diff --git a/service/native/TrafficController.cpp b/service/native/TrafficController.cpp
index 70c7c34..4923b00 100644
--- a/service/native/TrafficController.cpp
+++ b/service/native/TrafficController.cpp
@@ -74,6 +74,9 @@
const char* TrafficController::LOCAL_POWERSAVE = "fw_powersave";
const char* TrafficController::LOCAL_RESTRICTED = "fw_restricted";
const char* TrafficController::LOCAL_LOW_POWER_STANDBY = "fw_low_power_standby";
+const char* TrafficController::LOCAL_OEM_DENY_1 = "fw_oem_deny_1";
+const char* TrafficController::LOCAL_OEM_DENY_2 = "fw_oem_deny_2";
+const char* TrafficController::LOCAL_OEM_DENY_3 = "fw_oem_deny_3";
static_assert(BPF_PERMISSION_INTERNET == INetd::PERMISSION_INTERNET,
"Mismatch between BPF and AIDL permissions: PERMISSION_INTERNET");
@@ -99,6 +102,9 @@
FLAG_MSG_TRANS(matchType, LOW_POWER_STANDBY_MATCH, match);
FLAG_MSG_TRANS(matchType, IIF_MATCH, match);
FLAG_MSG_TRANS(matchType, LOCKDOWN_VPN_MATCH, match);
+ FLAG_MSG_TRANS(matchType, OEM_DENY_1_MATCH, match);
+ FLAG_MSG_TRANS(matchType, OEM_DENY_2_MATCH, match);
+ FLAG_MSG_TRANS(matchType, OEM_DENY_3_MATCH, match);
if (match) {
return StringPrintf("Unknown match: %u", match);
}
@@ -335,6 +341,12 @@
return ALLOWLIST;
case LOCKDOWN:
return DENYLIST;
+ case OEM_DENY_1:
+ return DENYLIST;
+ case OEM_DENY_2:
+ return DENYLIST;
+ case OEM_DENY_3:
+ return DENYLIST;
case NONE:
default:
return DENYLIST;
@@ -363,6 +375,15 @@
case LOCKDOWN:
res = updateOwnerMapEntry(LOCKDOWN_VPN_MATCH, uid, rule, type);
break;
+ case OEM_DENY_1:
+ res = updateOwnerMapEntry(OEM_DENY_1_MATCH, uid, rule, type);
+ break;
+ case OEM_DENY_2:
+ res = updateOwnerMapEntry(OEM_DENY_2_MATCH, uid, rule, type);
+ break;
+ case OEM_DENY_3:
+ res = updateOwnerMapEntry(OEM_DENY_3_MATCH, uid, rule, type);
+ break;
case NONE:
default:
ALOGW("Unknown child chain: %d", chain);
@@ -440,6 +461,12 @@
res = replaceRulesInMap(RESTRICTED_MATCH, uids);
} else if (!name.compare(LOCAL_LOW_POWER_STANDBY)) {
res = replaceRulesInMap(LOW_POWER_STANDBY_MATCH, uids);
+ } else if (!name.compare(LOCAL_OEM_DENY_1)) {
+ res = replaceRulesInMap(OEM_DENY_1_MATCH, uids);
+ } else if (!name.compare(LOCAL_OEM_DENY_2)) {
+ res = replaceRulesInMap(OEM_DENY_2_MATCH, uids);
+ } else if (!name.compare(LOCAL_OEM_DENY_3)) {
+ res = replaceRulesInMap(OEM_DENY_3_MATCH, uids);
} else {
ALOGE("unknown chain name: %s", name.c_str());
return -EINVAL;
@@ -479,6 +506,15 @@
case LOW_POWER_STANDBY:
match = LOW_POWER_STANDBY_MATCH;
break;
+ case OEM_DENY_1:
+ match = OEM_DENY_1_MATCH;
+ break;
+ case OEM_DENY_2:
+ match = OEM_DENY_2_MATCH;
+ break;
+ case OEM_DENY_3:
+ match = OEM_DENY_3_MATCH;
+ break;
default:
return -EINVAL;
}
diff --git a/service/native/TrafficControllerTest.cpp b/service/native/TrafficControllerTest.cpp
index c44b9d6..c920398 100644
--- a/service/native/TrafficControllerTest.cpp
+++ b/service/native/TrafficControllerTest.cpp
@@ -36,6 +36,7 @@
#include <netdutils/MockSyscalls.h>
+#define TEST_BPF_MAP
#include "TrafficController.h"
#include "bpf/BpfUtils.h"
#include "NetdUpdatablePublic.h"
@@ -73,52 +74,42 @@
std::lock_guard guard(mTc.mMutex);
ASSERT_EQ(0, setrlimitForTest());
- mFakeCookieTagMap.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(uint64_t), sizeof(UidTagValue),
- TEST_MAP_SIZE, 0));
+ mFakeCookieTagMap.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeCookieTagMap);
- mFakeAppUidStatsMap.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(StatsValue),
- TEST_MAP_SIZE, 0));
+ mFakeAppUidStatsMap.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeAppUidStatsMap);
- mFakeStatsMapA.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(StatsKey), sizeof(StatsValue),
- TEST_MAP_SIZE, 0));
+ mFakeStatsMapA.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeStatsMapA);
- mFakeConfigurationMap.reset(
- createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint8_t), 1, 0));
+ mFakeConfigurationMap.resetMap(BPF_MAP_TYPE_HASH, 1);
ASSERT_VALID(mFakeConfigurationMap);
- mFakeUidOwnerMap.reset(createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(UidOwnerValue),
- TEST_MAP_SIZE, 0));
+ mFakeUidOwnerMap.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeUidOwnerMap);
- mFakeUidPermissionMap.reset(
- createMap(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint8_t), TEST_MAP_SIZE, 0));
+ mFakeUidPermissionMap.resetMap(BPF_MAP_TYPE_HASH, TEST_MAP_SIZE);
ASSERT_VALID(mFakeUidPermissionMap);
- mTc.mCookieTagMap.reset(dupFd(mFakeCookieTagMap.getMap()));
+ mTc.mCookieTagMap = mFakeCookieTagMap;
ASSERT_VALID(mTc.mCookieTagMap);
- mTc.mAppUidStatsMap.reset(dupFd(mFakeAppUidStatsMap.getMap()));
+ mTc.mAppUidStatsMap = mFakeAppUidStatsMap;
ASSERT_VALID(mTc.mAppUidStatsMap);
- mTc.mStatsMapA.reset(dupFd(mFakeStatsMapA.getMap()));
+ mTc.mStatsMapA = mFakeStatsMapA;
ASSERT_VALID(mTc.mStatsMapA);
- mTc.mConfigurationMap.reset(dupFd(mFakeConfigurationMap.getMap()));
+ mTc.mConfigurationMap = mFakeConfigurationMap;
ASSERT_VALID(mTc.mConfigurationMap);
// Always write to stats map A by default.
ASSERT_RESULT_OK(mTc.mConfigurationMap.writeValue(CURRENT_STATS_MAP_CONFIGURATION_KEY,
SELECT_MAP_A, BPF_ANY));
- mTc.mUidOwnerMap.reset(dupFd(mFakeUidOwnerMap.getMap()));
+ mTc.mUidOwnerMap = mFakeUidOwnerMap;
ASSERT_VALID(mTc.mUidOwnerMap);
- mTc.mUidPermissionMap.reset(dupFd(mFakeUidPermissionMap.getMap()));
+ mTc.mUidPermissionMap = mFakeUidPermissionMap;
ASSERT_VALID(mTc.mUidPermissionMap);
mTc.mPrivilegedUser.clear();
}
- int dupFd(const android::base::unique_fd& mapFd) {
- return fcntl(mapFd.get(), F_DUPFD_CLOEXEC, 0);
- }
-
void populateFakeStats(uint64_t cookie, uint32_t uid, uint32_t tag, StatsKey* key) {
UidTagValue cookieMapkey = {.uid = (uint32_t)uid, .tag = tag};
EXPECT_RESULT_OK(mFakeCookieTagMap.writeValue(cookie, cookieMapkey, BPF_ANY));
@@ -308,6 +299,9 @@
checkUidOwnerRuleForChain(RESTRICTED, RESTRICTED_MATCH);
checkUidOwnerRuleForChain(LOW_POWER_STANDBY, LOW_POWER_STANDBY_MATCH);
checkUidOwnerRuleForChain(LOCKDOWN, LOCKDOWN_VPN_MATCH);
+ checkUidOwnerRuleForChain(OEM_DENY_1, OEM_DENY_1_MATCH);
+ checkUidOwnerRuleForChain(OEM_DENY_2, OEM_DENY_2_MATCH);
+ checkUidOwnerRuleForChain(OEM_DENY_3, OEM_DENY_3_MATCH);
ASSERT_EQ(-EINVAL, mTc.changeUidOwnerRule(NONE, TEST_UID, ALLOW, ALLOWLIST));
ASSERT_EQ(-EINVAL, mTc.changeUidOwnerRule(INVALID_CHAIN, TEST_UID, ALLOW, ALLOWLIST));
}
@@ -319,6 +313,9 @@
checkUidMapReplace("fw_powersave", uids, POWERSAVE_MATCH);
checkUidMapReplace("fw_restricted", uids, RESTRICTED_MATCH);
checkUidMapReplace("fw_low_power_standby", uids, LOW_POWER_STANDBY_MATCH);
+ checkUidMapReplace("fw_oem_deny_1", uids, OEM_DENY_1_MATCH);
+ checkUidMapReplace("fw_oem_deny_2", uids, OEM_DENY_2_MATCH);
+ checkUidMapReplace("fw_oem_deny_3", uids, OEM_DENY_3_MATCH);
ASSERT_EQ(-EINVAL, mTc.replaceUidOwnerMap("unknow", true, uids));
}
@@ -673,7 +670,7 @@
BpfMap<uint64_t, UidTagValue> mCookieTagMap;
void SetUp() {
- mCookieTagMap.reset(android::bpf::mapRetrieveRW(COOKIE_TAG_MAP_PATH));
+ mCookieTagMap.init(COOKIE_TAG_MAP_PATH);
ASSERT_TRUE(mCookieTagMap.isValid());
}
diff --git a/service/native/include/Common.h b/service/native/include/Common.h
index 847acec..2427aa9 100644
--- a/service/native/include/Common.h
+++ b/service/native/include/Common.h
@@ -36,6 +36,9 @@
RESTRICTED = 4,
LOW_POWER_STANDBY = 5,
LOCKDOWN = 6,
+ OEM_DENY_1 = 7,
+ OEM_DENY_2 = 8,
+ OEM_DENY_3 = 9,
INVALID_CHAIN
};
// LINT.ThenChange(packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java)
diff --git a/service/native/include/TrafficController.h b/service/native/include/TrafficController.h
index d3d52e2..c019ce7 100644
--- a/service/native/include/TrafficController.h
+++ b/service/native/include/TrafficController.h
@@ -88,6 +88,9 @@
static const char* LOCAL_POWERSAVE;
static const char* LOCAL_RESTRICTED;
static const char* LOCAL_LOW_POWER_STANDBY;
+ static const char* LOCAL_OEM_DENY_1;
+ static const char* LOCAL_OEM_DENY_2;
+ static const char* LOCAL_OEM_DENY_3;
private:
/*
@@ -149,7 +152,7 @@
* the map right now:
* - Entry with UID_RULES_CONFIGURATION_KEY:
* Store the configuration for the current uid rules. It indicates the device
- * is in doze/powersave/standby/restricted/low power standby mode.
+ * is in doze/powersave/standby/restricted/low power standby/oem deny mode.
* - Entry with CURRENT_STATS_MAP_CONFIGURATION_KEY:
* Stores the current live stats map that kernel program is writing to.
* Userspace can do scraping and cleaning job on the other one depending on the
diff --git a/service/proguard.flags b/service/proguard.flags
index 94397ab..cffa490 100644
--- a/service/proguard.flags
+++ b/service/proguard.flags
@@ -8,11 +8,10 @@
# Prevent proguard from stripping out any nearby-service and fast-pair-lite-protos fields.
-keep class com.android.server.nearby.NearbyService { *; }
--keep class com.android.server.nearby.service.proto { *; }
# The lite proto runtime uses reflection to access fields based on the names in
# the schema, keep all the fields.
# This replicates the base proguard rule used by the build by default
# (proguard_basic_keeps.flags), but needs to be specified here because the
# com.google.protobuf package is jarjared to the below package.
--keepclassmembers class * extends com.android.connectivity.com.google.protobuf.MessageLite { <fields>; }
+-keepclassmembers class * extends android.net.connectivity.com.google.protobuf.MessageLite { <fields>; }
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 0a6c2bd..d0cb294 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -11363,6 +11363,9 @@
final int defaultRule;
switch (chain) {
case ConnectivityManager.FIREWALL_CHAIN_STANDBY:
+ case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1:
+ case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2:
+ case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3:
defaultRule = FIREWALL_RULE_ALLOW;
break;
case ConnectivityManager.FIREWALL_CHAIN_DOZABLE:
@@ -11412,6 +11415,15 @@
mBpfNetMaps.replaceUidChain("fw_low_power_standby", true /* isAllowList */,
uids);
break;
+ case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1:
+ mBpfNetMaps.replaceUidChain("fw_oem_deny_1", false /* isAllowList */, uids);
+ break;
+ case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2:
+ mBpfNetMaps.replaceUidChain("fw_oem_deny_2", false /* isAllowList */, uids);
+ break;
+ case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3:
+ mBpfNetMaps.replaceUidChain("fw_oem_deny_3", false /* isAllowList */, uids);
+ break;
default:
throw new IllegalArgumentException("replaceFirewallChain with invalid chain: "
+ chain);
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java
index 098f295..10775d0 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/ConnOnActivityStartTest.java
@@ -75,6 +75,8 @@
@RequiredProperties({DOZE_MODE})
public void testStartActivity_doze() throws Exception {
setDozeMode(true);
+ // TODO (235284115): We need to turn on Doze every time before starting
+ // the activity.
assertLaunchedActivityHasNetworkAccess("testStartActivity_doze");
}
@@ -83,6 +85,8 @@
public void testStartActivity_appStandby() throws Exception {
turnBatteryOn();
setAppIdle(true);
+ // TODO (235284115): We need to put the app into app standby mode every
+ // time before starting the activity.
assertLaunchedActivityHasNetworkAccess("testStartActivity_appStandby");
}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java b/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java
index 3387fd7..cfd3130 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideConnOnActivityStartTest.java
@@ -16,6 +16,8 @@
package com.android.cts.net;
+import android.platform.test.annotations.FlakyTest;
+
public class HostsideConnOnActivityStartTest extends HostsideNetworkTestCase {
private static final String TEST_CLASS = TEST_PKG + ".ConnOnActivityStartTest";
@Override
@@ -41,6 +43,7 @@
runDeviceTests(TEST_PKG, TEST_CLASS, "testStartActivity_dataSaver");
}
+ @FlakyTest(bugId = 231440256)
public void testStartActivity_doze() throws Exception {
runDeviceTests(TEST_PKG, TEST_CLASS, "testStartActivity_doze");
}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index bdda82a..c00bbf4 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -37,6 +37,11 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.EXTRA_NETWORK;
import static android.net.ConnectivityManager.EXTRA_NETWORK_REQUEST;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
+import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
+import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -195,6 +200,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -204,6 +210,8 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
import java.net.Inet6Address;
@@ -218,6 +226,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Objects;
+import java.util.Random;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
@@ -255,6 +264,7 @@
private static final int NETWORK_CALLBACK_TIMEOUT_MS = 30_000;
private static final int LISTEN_ACTIVITY_TIMEOUT_MS = 5_000;
private static final int NO_CALLBACK_TIMEOUT_MS = 100;
+ private static final int SOCKET_TIMEOUT_MS = 100;
private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20;
private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500;
// device could have only one interface: data, wifi.
@@ -3279,14 +3289,16 @@
// TODD: Have a significant signal to know the uids has been sent to netd.
assertBindSocketToNetworkSuccess(network);
- // Uid is in allowed list. Try file network request again.
- requestNetwork(restrictedRequest, restrictedNetworkCb);
- // Verify that the network is restricted.
- restrictedNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
- NETWORK_CALLBACK_TIMEOUT_MS,
- entry -> network.equals(entry.getNetwork())
- && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
- .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
+ if (TestUtils.shouldTestTApis()) {
+ // Uid is in allowed list. Try file network request again.
+ requestNetwork(restrictedRequest, restrictedNetworkCb);
+ // Verify that the network is restricted.
+ restrictedNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> network.equals(entry.getNetwork())
+ && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
+ }
} finally {
agent.unregister();
@@ -3316,6 +3328,113 @@
assertTrue(dumpOutput, dumpOutput.contains("BPF map content"));
}
+ private void checkFirewallBlocking(final DatagramSocket srcSock, final DatagramSocket dstSock,
+ final boolean expectBlock) throws Exception {
+ final Random random = new Random();
+ final byte[] sendData = new byte[100];
+ random.nextBytes(sendData);
+
+ final DatagramPacket pkt = new DatagramPacket(sendData, sendData.length,
+ InetAddresses.parseNumericAddress("::1"), dstSock.getLocalPort());
+ try {
+ srcSock.send(pkt);
+ } catch (IOException e) {
+ if (expectBlock) {
+ return;
+ }
+ fail("Expect not to be blocked by firewall but sending packet was blocked");
+ }
+
+ if (expectBlock) {
+ fail("Expect to be blocked by firewall but sending packet was not blocked");
+ }
+
+ dstSock.receive(pkt);
+ assertArrayEquals(sendData, pkt.getData());
+ }
+
+ private static final boolean EXPECT_PASS = false;
+ private static final boolean EXPECT_BLOCK = true;
+
+ private void doTestFirewallBlockingDenyRule(final int chain) {
+ runWithShellPermissionIdentity(() -> {
+ try (DatagramSocket srcSock = new DatagramSocket();
+ DatagramSocket dstSock = new DatagramSocket()) {
+ dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
+
+ // No global config, No uid config
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+
+ // Has global config, No uid config
+ mCm.setFirewallChainEnabled(chain, true /* enable */);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+
+ // Has global config, Has uid config
+ mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_BLOCK);
+
+ // No global config, Has uid config
+ mCm.setFirewallChainEnabled(chain, false /* enable */);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+
+ // No global config, No uid config
+ mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ } finally {
+ mCm.setFirewallChainEnabled(chain, false /* enable */);
+ mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
+ }
+ }, NETWORK_SETTINGS);
+ }
+
+ private void doTestFirewallBlockingAllowRule(final int chain) {
+ runWithShellPermissionIdentity(() -> {
+ try (DatagramSocket srcSock = new DatagramSocket();
+ DatagramSocket dstSock = new DatagramSocket()) {
+ dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
+
+ // No global config, No uid config
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+
+ // Has global config, No uid config
+ mCm.setFirewallChainEnabled(chain, true /* enable */);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_BLOCK);
+
+ // Has global config, Has uid config
+ mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+
+ // No global config, Has uid config
+ mCm.setFirewallChainEnabled(chain, false /* enable */);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+
+ // No global config, No uid config
+ mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
+ checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ } finally {
+ mCm.setFirewallChainEnabled(chain, false /* enable */);
+ mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
+ }
+ }, NETWORK_SETTINGS);
+ }
+
+ @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
+ @Test @IgnoreUpTo(SC_V2)
+ public void testFirewallBlocking() {
+ // Following tests affect the actual state of networking on the device after the test.
+ // This might cause unexpected behaviour of the device. So, we skip them for now.
+ // We will enable following tests after adding the logic of firewall state restoring.
+ // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_DOZABLE);
+ // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_POWERSAVE);
+ // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_RESTRICTED);
+ // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_LOW_POWER_STANDBY);
+
+ // doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_STANDBY);
+ doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_1);
+ doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_2);
+ doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_3);
+ }
+
private void assumeTestSApis() {
// Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
// shims, and @IgnoreUpTo does not check that.
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index bfc9b29..293da67 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -20,6 +20,16 @@
import android.Manifest.permission.NETWORK_SETTINGS
import android.content.Context
import android.net.ConnectivityManager
+import android.net.EthernetManager
+import android.net.EthernetManager.InterfaceStateListener
+import android.net.EthernetManager.ROLE_CLIENT
+import android.net.EthernetManager.ROLE_NONE
+import android.net.EthernetManager.ROLE_SERVER
+import android.net.EthernetManager.STATE_ABSENT
+import android.net.EthernetManager.STATE_LINK_DOWN
+import android.net.EthernetManager.STATE_LINK_UP
+import android.net.EthernetManager.TetheredInterfaceCallback
+import android.net.EthernetManager.TetheredInterfaceRequest
import android.net.EthernetNetworkSpecifier
import android.net.InetAddresses
import android.net.IpConfiguration
@@ -32,47 +42,47 @@
import android.net.TestNetworkInterface
import android.net.TestNetworkManager
import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
+import android.os.Build
import android.os.Handler
import android.os.HandlerExecutor
import android.os.Looper
+import android.os.SystemProperties
import android.platform.test.annotations.AppModeFull
import android.util.ArraySet
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.runner.AndroidJUnit4
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
-import com.android.networkstack.apishim.EthernetManagerShimImpl
-import com.android.networkstack.apishim.common.EthernetManagerShim.InterfaceStateListener
-import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_CLIENT
-import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_NONE
-import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_ABSENT
-import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_DOWN
-import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_UP
import com.android.testutils.anyNetwork
import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
import com.android.testutils.RouterAdvertisementResponder
-import com.android.testutils.SC_V2
import com.android.testutils.TapPacketReader
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.runAsShell
import com.android.testutils.waitForIdle
import org.junit.After
+import org.junit.Assume.assumeFalse
import org.junit.Before
-import org.junit.Rule
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import java.net.Inet6Address
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.ExecutionException
+import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
import kotlin.test.fail
-private const val TIMEOUT_MS = 1000L
+// TODO: try to lower this timeout in the future. Currently, ethernet tests are still flaky because
+// the interface is not ready fast enough (mostly due to the up / up / down / up issue).
+private const val TIMEOUT_MS = 2000L
private const val NO_CALLBACK_TIMEOUT_MS = 200L
private val DEFAULT_IP_CONFIGURATION = IpConfiguration(IpConfiguration.IpAssignment.DHCP,
IpConfiguration.ProxySettings.NONE, null, null)
@@ -83,14 +93,13 @@
.build()
@AppModeFull(reason = "Instant apps can't access EthernetManager")
-@RunWith(AndroidJUnit4::class)
+// EthernetManager is not updatable before T, so tests do not need to be backwards compatible.
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
class EthernetManagerTest {
- // EthernetManager is not updatable before T, so tests do not need to be backwards compatible
- @get:Rule
- val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
- private val em by lazy { EthernetManagerShimImpl.newInstance(context) }
+ private val em by lazy { context.getSystemService(EthernetManager::class.java) }
private val cm by lazy { context.getSystemService(ConnectivityManager::class.java) }
private val ifaceListener = EthernetStateListener()
@@ -98,6 +107,8 @@
private val addedListeners = ArrayList<EthernetStateListener>()
private val networkRequests = ArrayList<TestableNetworkCallback>()
+ private var tetheredInterfaceRequest: TetheredInterfaceRequest? = null
+
private class EthernetTestInterface(
context: Context,
private val handler: Handler
@@ -162,11 +173,11 @@
}
fun expectCallback(iface: EthernetTestInterface, state: Int, role: Int) {
- expectCallback(createChangeEvent(iface, state, role))
+ expectCallback(createChangeEvent(iface.interfaceName, state, role))
}
- fun createChangeEvent(iface: EthernetTestInterface, state: Int, role: Int) =
- InterfaceStateChanged(iface.interfaceName, state, role,
+ fun createChangeEvent(iface: String, state: Int, role: Int) =
+ InterfaceStateChanged(iface, state, role,
if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null)
fun pollForNextCallback(): CallbackEntry {
@@ -175,8 +186,12 @@
fun eventuallyExpect(expected: CallbackEntry) = events.poll(TIMEOUT_MS) { it == expected }
+ fun eventuallyExpect(interfaceName: String, state: Int, role: Int) {
+ assertNotNull(eventuallyExpect(createChangeEvent(interfaceName, state, role)))
+ }
+
fun eventuallyExpect(iface: EthernetTestInterface, state: Int, role: Int) {
- assertNotNull(eventuallyExpect(createChangeEvent(iface, state, role)))
+ eventuallyExpect(iface.interfaceName, state, role)
}
fun assertNoCallback() {
@@ -185,6 +200,34 @@
}
}
+ private class TetheredInterfaceListener : TetheredInterfaceCallback {
+ private val available = CompletableFuture<String>()
+
+ override fun onAvailable(iface: String) {
+ available.complete(iface)
+ }
+
+ override fun onUnavailable() {
+ available.completeExceptionally(IllegalStateException("onUnavailable was called"))
+ }
+
+ fun expectOnAvailable(): String {
+ return available.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
+ }
+
+ fun expectOnUnavailable() {
+ // Assert that the future fails with the IllegalStateException from the
+ // completeExceptionally() call inside onUnavailable.
+ assertFailsWith(IllegalStateException::class) {
+ try {
+ available.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
+ } catch (e: ExecutionException) {
+ throw e.cause!!
+ }
+ }
+ }
+ }
+
@Before
fun setUp() {
setIncludeTestInterfaces(true)
@@ -202,6 +245,7 @@
em.removeInterfaceStateListener(listener)
}
networkRequests.forEach { cm.unregisterNetworkCallback(it) }
+ releaseTetheredInterface()
}
private fun addInterfaceStateListener(listener: EthernetStateListener) {
@@ -248,6 +292,19 @@
networkRequests.remove(cb)
}
+ private fun requestTetheredInterface() = TetheredInterfaceListener().also {
+ tetheredInterfaceRequest = runAsShell(NETWORK_SETTINGS) {
+ em.requestTetheredInterface(HandlerExecutor(Handler(Looper.getMainLooper())), it)
+ }
+ }
+
+ private fun releaseTetheredInterface() {
+ runAsShell(NETWORK_SETTINGS) {
+ tetheredInterfaceRequest?.release()
+ tetheredInterfaceRequest = null
+ }
+ }
+
private fun NetworkRequest.createCopyWithEthernetSpecifier(ifaceName: String) =
NetworkRequest.Builder(NetworkRequest(ETH_REQUEST))
.setNetworkSpecifier(EthernetNetworkSpecifier(ifaceName)).build()
@@ -301,6 +358,35 @@
}
}
+ // TODO: this function is now used in two places (EthernetManagerTest and
+ // EthernetTetheringTest), so it should be moved to testutils.
+ private fun isAdbOverNetwork(): Boolean {
+ // If adb TCP port opened, this test may running by adb over network.
+ return (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1 ||
+ SystemProperties.getInt("service.adb.tcp.port", -1) > -1)
+ }
+
+ @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
+ @Test
+ fun testCallbacks_forServerModeInterfaces() {
+ // do not run this test when adb might be connected over ethernet.
+ assumeFalse(isAdbOverNetwork())
+
+ val listener = EthernetStateListener()
+ addInterfaceStateListener(listener)
+
+ // it is possible that a physical interface is present, so it is not guaranteed that iface
+ // will be put into server mode. This should not matter for the test though. Calling
+ // createInterface() makes sure we have at least one interface available.
+ val iface = createInterface()
+ val cb = requestTetheredInterface()
+ val ifaceName = cb.expectOnAvailable()
+ listener.eventuallyExpect(ifaceName, STATE_LINK_UP, ROLE_SERVER)
+
+ releaseTetheredInterface()
+ listener.eventuallyExpect(ifaceName, STATE_LINK_UP, ROLE_CLIENT)
+ }
+
/**
* Validate all interfaces are returned for an EthernetStateListener upon registration.
*/
@@ -316,7 +402,10 @@
assertTrue(ifaces.contains(iface), "Untracked interface $iface returned")
// If the event's iface was created in the test, additional criteria can be validated.
createdIfaces.find { it.interfaceName.equals(iface) }?.let {
- assertEquals(event, listener.createChangeEvent(it, STATE_LINK_UP, ROLE_CLIENT))
+ assertEquals(event,
+ listener.createChangeEvent(it.interfaceName,
+ STATE_LINK_UP,
+ ROLE_CLIENT))
}
}
// Assert all callbacks are accounted for.
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 44550e6..b9a18ab 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -52,8 +52,17 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOCKDOWN_VPN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
+import static android.net.ConnectivityManager.FIREWALL_RULE_DEFAULT;
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
@@ -9547,6 +9556,98 @@
verify(mBpfNetMaps, never()).removeUidInterfaceRules(any());
}
+ private void doTestSetUidFirewallRule(final int chain, final int defaultRule) {
+ final int uid = 1001;
+ mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
+ verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_ALLOW);
+ reset(mBpfNetMaps);
+
+ mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DENY);
+ verify(mBpfNetMaps).setUidRule(chain, uid, FIREWALL_RULE_DENY);
+ reset(mBpfNetMaps);
+
+ mCm.setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
+ verify(mBpfNetMaps).setUidRule(chain, uid, defaultRule);
+ reset(mBpfNetMaps);
+ }
+
+ @Test @IgnoreUpTo(SC_V2)
+ public void testSetUidFirewallRule() throws Exception {
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_DOZABLE, FIREWALL_RULE_DENY);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_STANDBY, FIREWALL_RULE_ALLOW);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_POWERSAVE, FIREWALL_RULE_DENY);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, FIREWALL_RULE_DENY);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, FIREWALL_RULE_DENY);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_1, FIREWALL_RULE_ALLOW);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_2, FIREWALL_RULE_ALLOW);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_3, FIREWALL_RULE_ALLOW);
+ }
+
+ @Test @IgnoreUpTo(SC_V2)
+ public void testSetFirewallChainEnabled() throws Exception {
+ final List<Integer> firewallChains = Arrays.asList(
+ FIREWALL_CHAIN_DOZABLE,
+ FIREWALL_CHAIN_STANDBY,
+ FIREWALL_CHAIN_POWERSAVE,
+ FIREWALL_CHAIN_RESTRICTED,
+ FIREWALL_CHAIN_LOW_POWER_STANDBY,
+ FIREWALL_CHAIN_OEM_DENY_1,
+ FIREWALL_CHAIN_OEM_DENY_2,
+ FIREWALL_CHAIN_OEM_DENY_3);
+ for (final int chain: firewallChains) {
+ mCm.setFirewallChainEnabled(chain, true /* enabled */);
+ verify(mBpfNetMaps).setChildChain(chain, true /* enable */);
+ reset(mBpfNetMaps);
+
+ mCm.setFirewallChainEnabled(chain, false /* enabled */);
+ verify(mBpfNetMaps).setChildChain(chain, false /* enable */);
+ reset(mBpfNetMaps);
+ }
+ }
+
+ private void doTestReplaceFirewallChain(final int chain, final String chainName,
+ final boolean allowList) {
+ final int[] uids = new int[] {1001, 1002};
+ mCm.replaceFirewallChain(chain, uids);
+ verify(mBpfNetMaps).replaceUidChain(chainName, allowList, uids);
+ reset(mBpfNetMaps);
+ }
+
+ @Test @IgnoreUpTo(SC_V2)
+ public void testReplaceFirewallChain() {
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_DOZABLE, "fw_dozable", true);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_STANDBY, "fw_standby", false);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_POWERSAVE, "fw_powersave", true);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_RESTRICTED, "fw_restricted", true);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_LOW_POWER_STANDBY, "fw_low_power_standby", true);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_1, "fw_oem_deny_1", false);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_2, "fw_oem_deny_2", false);
+ doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_3, "fw_oem_deny_3", false);
+ }
+
+ @Test @IgnoreUpTo(SC_V2)
+ public void testInvalidFirewallChain() throws Exception {
+ final int uid = 1001;
+ final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
+ assertThrows(expected,
+ () -> mCm.setUidFirewallRule(-1 /* chain */, uid, FIREWALL_RULE_ALLOW));
+ assertThrows(expected,
+ () -> mCm.setUidFirewallRule(100 /* chain */, uid, FIREWALL_RULE_ALLOW));
+ assertThrows(expected, () -> mCm.replaceFirewallChain(-1 /* chain */, new int[]{uid}));
+ assertThrows(expected, () -> mCm.replaceFirewallChain(100 /* chain */, new int[]{uid}));
+ }
+
+ @Test @IgnoreUpTo(SC_V2)
+ public void testInvalidFirewallRule() throws Exception {
+ final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
+ assertThrows(expected,
+ () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
+ 1001 /* uid */, -1 /* rule */));
+ assertThrows(expected,
+ () -> mCm.setUidFirewallRule(FIREWALL_CHAIN_DOZABLE,
+ 1001 /* uid */, 100 /* rule */));
+ }
+
/**
* Test mutable and requestable network capabilities such as
* {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED} and
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index 115f0e1..e90d55d 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -28,6 +28,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -68,6 +69,7 @@
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -445,7 +447,20 @@
when(mNetd.interfaceGetList()).thenReturn(new String[] {testIface});
when(mNetd.interfaceGetCfg(eq(testIface))).thenReturn(ifaceParcel);
doReturn(new String[] {testIface}).when(mFactory).getAvailableInterfaces(anyBoolean());
- doReturn(EthernetManager.STATE_LINK_UP).when(mFactory).getInterfaceState(eq(testIface));
+
+ final AtomicBoolean ifaceUp = new AtomicBoolean(true);
+ doAnswer(inv -> ifaceUp.get()).when(mFactory).hasInterface(testIface);
+ doAnswer(inv ->
+ ifaceUp.get() ? EthernetManager.STATE_LINK_UP : EthernetManager.STATE_ABSENT)
+ .when(mFactory).getInterfaceState(testIface);
+ doAnswer(inv -> {
+ ifaceUp.set(true);
+ return null;
+ }).when(mFactory).addInterface(eq(testIface), eq(testHwAddr), any(), any());
+ doAnswer(inv -> {
+ ifaceUp.set(false);
+ return null;
+ }).when(mFactory).removeInterface(testIface);
final EthernetStateListener listener = spy(new EthernetStateListener());
tracker.addListener(listener, true /* canUseRestrictedNetworks */);
@@ -456,7 +471,6 @@
verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_ENABLED));
reset(listener);
- doReturn(EthernetManager.STATE_ABSENT).when(mFactory).getInterfaceState(eq(testIface));
tracker.setEthernetEnabled(false);
waitForIdle();
verify(mFactory).removeInterface(eq(testIface));
@@ -465,7 +479,6 @@
anyInt(), any());
reset(listener);
- doReturn(EthernetManager.STATE_LINK_UP).when(mFactory).getInterfaceState(eq(testIface));
tracker.setEthernetEnabled(true);
waitForIdle();
verify(mFactory).addInterface(eq(testIface), eq(testHwAddr), any(), any());