[BR03.1] Expose isUidNetworkingBlocked
Test: atest CtsHostsideNetworkTests:com.android.cts.net.HostsideNetworkCallbackTests
Bug: 297836825
Change-Id: I70b2351b9cd1c3c6fa34258397e0bf22cb8150b2
diff --git a/common/flags.aconfig b/common/flags.aconfig
index 7235202..0c46b48 100644
--- a/common/flags.aconfig
+++ b/common/flags.aconfig
@@ -27,3 +27,10 @@
description: "Set data saver through ConnectivityManager API"
bug: "297836825"
}
+
+flag {
+ name: "support_is_uid_networking_blocked"
+ namespace: "android_core_networking"
+ description: "This flag controls whether isUidNetworkingBlocked is supported"
+ bug: "297836825"
+}
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 782e20a..4d55067 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -14,6 +14,7 @@
method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange();
method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.LinkProperties getRedactedLinkPropertiesForPackage(@NonNull android.net.LinkProperties, int, @NonNull String);
method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public android.net.NetworkCapabilities getRedactedNetworkCapabilitiesForPackage(@NonNull android.net.NetworkCapabilities, int, @NonNull String);
+ method @FlaggedApi("com.android.net.flags.support_is_uid_networking_blocked") @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public boolean isUidNetworkingBlocked(int, boolean);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackForUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void removeUidFromMeteredNetworkAllowList(int);
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index f44fd0e..eb8f8c3 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -133,6 +133,8 @@
public static class Flags {
static final String SET_DATA_SAVER_VIA_CM =
"com.android.net.flags.set_data_saver_via_cm";
+ static final String SUPPORT_IS_UID_NETWORKING_BLOCKED =
+ "com.android.net.flags.support_is_uid_networking_blocked";
}
/**
@@ -6311,8 +6313,8 @@
// is provided by linux file group permission AID_NET_BW_ACCT and the
// selinux context fs_bpf_net*.
// Only the system server process and the network stack have access.
- // TODO: Expose api when ready.
- // @SystemApi(client = MODULE_LIBRARIES)
+ @FlaggedApi(Flags.SUPPORT_IS_UID_NETWORKING_BLOCKED)
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresApi(Build.VERSION_CODES.TIRAMISU) // BPF maps were only mainlined in T
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
public boolean isUidNetworkingBlocked(int uid, boolean isNetworkMetered) {
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 5893de7..bb32052 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -37,6 +37,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.NotificationManager;
@@ -438,6 +439,42 @@
}
/**
+ * Asserts whether the network is blocked by accessing bpf maps if command-line tool supports.
+ */
+ void assertNetworkAccessBlockedByBpf(boolean expectBlocked, int uid, boolean metered) {
+ final String result;
+ try {
+ result = executeShellCommand(
+ "cmd network_stack is-uid-networking-blocked " + uid + " " + metered);
+ } catch (AssertionError e) {
+ // If NetworkStack is too old to support this command, ignore and continue
+ // this test to verify other parts.
+ if (e.getMessage().contains("No shell command implementation.")) {
+ return;
+ }
+ throw e;
+ }
+
+ // Tethering module is too old.
+ if (result.contains("API is unsupported")) {
+ return;
+ }
+
+ assertEquals(expectBlocked, parseBooleanOrThrow(result.trim()));
+ }
+
+ /**
+ * Similar to {@link Boolean#parseBoolean} but throws when the input
+ * is unexpected instead of returning false.
+ */
+ private static boolean parseBooleanOrThrow(@NonNull String s) {
+ // Don't use Boolean.parseBoolean
+ if ("true".equalsIgnoreCase(s)) return true;
+ if ("false".equalsIgnoreCase(s)) return false;
+ throw new IllegalArgumentException("Unexpected: " + s);
+ }
+
+ /**
* Checks whether the network is available as expected.
*
* @return error message with the mismatch (or empty if assertion passed).
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java
index 0715e32..ab3cf14 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkCallbackTest.java
@@ -236,16 +236,19 @@
// Enable restrict background
setRestrictBackground(true);
assertBackgroundNetworkAccess(false);
+ assertNetworkAccessBlockedByBpf(true, mUid, true /* metered */);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true);
// Add to whitelist
addRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(true);
+ assertNetworkAccessBlockedByBpf(false, mUid, true /* metered */);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false);
// Remove from whitelist
removeRestrictBackgroundWhitelist(mUid);
assertBackgroundNetworkAccess(false);
+ assertNetworkAccessBlockedByBpf(true, mUid, true /* metered */);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true);
} finally {
mMeterednessConfiguration.resetNetworkMeteredness();
@@ -257,11 +260,13 @@
true /* hasCapability */, NET_CAPABILITY_NOT_METERED);
try {
assertBackgroundNetworkAccess(true);
+ assertNetworkAccessBlockedByBpf(false, mUid, false /* metered */);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false);
// Disable restrict background, should not trigger callback
setRestrictBackground(false);
assertBackgroundNetworkAccess(true);
+ assertNetworkAccessBlockedByBpf(false, mUid, false /* metered */);
} finally {
mMeterednessConfiguration.resetNetworkMeteredness();
}
@@ -275,11 +280,13 @@
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true);
+ assertNetworkAccessBlockedByBpf(true, mUid, true /* metered */);
// Disable Power Saver
setBatterySaverMode(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false);
+ assertNetworkAccessBlockedByBpf(false, mUid, true /* metered */);
} finally {
mMeterednessConfiguration.resetNetworkMeteredness();
}
@@ -293,11 +300,13 @@
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, true);
+ assertNetworkAccessBlockedByBpf(true, mUid, false /* metered */);
// Disable Power Saver
setBatterySaverMode(false);
assertBackgroundNetworkAccess(true);
mTestNetworkCallback.expectBlockedStatusCallbackEventually(mNetwork, false);
+ assertNetworkAccessBlockedByBpf(false, mUid, false /* metered */);
} finally {
mMeterednessConfiguration.resetNetworkMeteredness();
}