Add firewall chains for HAPPY_BOX and user/admin PENALTY_BOX
Follow up CLs will update CS to generate blocked reason from bpf map
instead of asking NPMS.
However, one issue is NPMS set PENALTY_BOX for
BLOCKED_METERED_REASON_USER_RESTRICTED and
BLOCKED_METERED_REASON_ADMIN_DISABLED without telling the reason.
So, CS can not know the reason of PENALTY_BOX.
This CL add new firewall chain and match to distinguish reasons.
NPMS must call setUidFirewallRule with
FIREWALL_CHAIN_METERED_DENY_USER or FIREWALL_CHAIN_METERED_DENY_ADMIN
based on the reason so that CS can know the reason of restriction.
Bug: 332628891
Test: atest com.android.cts.net.HostsideRestrictBackgroundNetworkTests
Change-Id: Ia4ad4bdb345abc22c782630e828edfad2452db36
diff --git a/DnsResolver/DnsBpfHelper.cpp b/DnsResolver/DnsBpfHelper.cpp
index de8bef5..0719ade 100644
--- a/DnsResolver/DnsBpfHelper.cpp
+++ b/DnsResolver/DnsBpfHelper.cpp
@@ -69,9 +69,10 @@
// state, making it a trustworthy source. Since this library primarily serves DNS resolvers,
// relying solely on V+ data prevents erroneous blocking of DNS queries.
if (android::modules::sdklevel::IsAtLeastV() && metered) {
- // The background data setting (PENALTY_BOX_MATCH) and unrestricted data usage setting
- // (HAPPY_BOX_MATCH) for individual apps override the system wide Data Saver setting.
- if (uidRules & PENALTY_BOX_MATCH) return true;
+ // The background data setting (PENALTY_BOX_USER_MATCH, PENALTY_BOX_ADMIN_MATCH) and
+ // unrestricted data usage setting (HAPPY_BOX_MATCH) for individual apps override the system
+ // wide Data Saver setting.
+ if (uidRules & (PENALTY_BOX_USER_MATCH | PENALTY_BOX_ADMIN_MATCH)) return true;
if (uidRules & HAPPY_BOX_MATCH) return false;
auto dataSaverSetting = mDataSaverEnabledMap.readValue(DATA_SAVER_ENABLED_KEY);
diff --git a/DnsResolver/DnsBpfHelperTest.cpp b/DnsResolver/DnsBpfHelperTest.cpp
index 67b5b95..18a5df4 100644
--- a/DnsResolver/DnsBpfHelperTest.cpp
+++ b/DnsResolver/DnsBpfHelperTest.cpp
@@ -158,23 +158,33 @@
}
} testConfigs[]{
// clang-format off
- // enabledRules, dataSaverEnabled, uidRules, blocked
- {NO_MATCH, false, NO_MATCH, false},
- {NO_MATCH, false, PENALTY_BOX_MATCH, true},
- {NO_MATCH, false, HAPPY_BOX_MATCH, false},
- {NO_MATCH, false, PENALTY_BOX_MATCH|HAPPY_BOX_MATCH, true},
- {NO_MATCH, true, NO_MATCH, true},
- {NO_MATCH, true, PENALTY_BOX_MATCH, true},
- {NO_MATCH, true, HAPPY_BOX_MATCH, false},
- {NO_MATCH, true, PENALTY_BOX_MATCH|HAPPY_BOX_MATCH, true},
- {STANDBY_MATCH, false, STANDBY_MATCH, true},
- {STANDBY_MATCH, false, STANDBY_MATCH|PENALTY_BOX_MATCH, true},
- {STANDBY_MATCH, false, STANDBY_MATCH|HAPPY_BOX_MATCH, true},
- {STANDBY_MATCH, false, STANDBY_MATCH|PENALTY_BOX_MATCH|HAPPY_BOX_MATCH, true},
- {STANDBY_MATCH, true, STANDBY_MATCH, true},
- {STANDBY_MATCH, true, STANDBY_MATCH|PENALTY_BOX_MATCH, true},
- {STANDBY_MATCH, true, STANDBY_MATCH|HAPPY_BOX_MATCH, true},
- {STANDBY_MATCH, true, STANDBY_MATCH|PENALTY_BOX_MATCH|HAPPY_BOX_MATCH, true},
+ // enabledRules, dataSaverEnabled, uidRules, blocked
+ {NO_MATCH, false, NO_MATCH, false},
+ {NO_MATCH, false, PENALTY_BOX_USER_MATCH, true},
+ {NO_MATCH, false, PENALTY_BOX_ADMIN_MATCH, true},
+ {NO_MATCH, false, PENALTY_BOX_USER_MATCH|PENALTY_BOX_ADMIN_MATCH, true},
+ {NO_MATCH, false, HAPPY_BOX_MATCH, false},
+ {NO_MATCH, false, PENALTY_BOX_USER_MATCH|HAPPY_BOX_MATCH, true},
+ {NO_MATCH, false, PENALTY_BOX_ADMIN_MATCH|HAPPY_BOX_MATCH, true},
+ {NO_MATCH, true, NO_MATCH, true},
+ {NO_MATCH, true, PENALTY_BOX_USER_MATCH, true},
+ {NO_MATCH, true, PENALTY_BOX_ADMIN_MATCH, true},
+ {NO_MATCH, true, PENALTY_BOX_USER_MATCH|PENALTY_BOX_ADMIN_MATCH, true},
+ {NO_MATCH, true, HAPPY_BOX_MATCH, false},
+ {NO_MATCH, true, PENALTY_BOX_USER_MATCH|HAPPY_BOX_MATCH, true},
+ {NO_MATCH, true, PENALTY_BOX_ADMIN_MATCH|HAPPY_BOX_MATCH, true},
+ {STANDBY_MATCH, false, STANDBY_MATCH, true},
+ {STANDBY_MATCH, false, STANDBY_MATCH|PENALTY_BOX_USER_MATCH, true},
+ {STANDBY_MATCH, false, STANDBY_MATCH|PENALTY_BOX_ADMIN_MATCH, true},
+ {STANDBY_MATCH, false, STANDBY_MATCH|HAPPY_BOX_MATCH, true},
+ {STANDBY_MATCH, false, STANDBY_MATCH|PENALTY_BOX_USER_MATCH|HAPPY_BOX_MATCH, true},
+ {STANDBY_MATCH, false, STANDBY_MATCH|PENALTY_BOX_ADMIN_MATCH|HAPPY_BOX_MATCH, true},
+ {STANDBY_MATCH, true, STANDBY_MATCH, true},
+ {STANDBY_MATCH, true, STANDBY_MATCH|PENALTY_BOX_USER_MATCH, true},
+ {STANDBY_MATCH, true, STANDBY_MATCH|PENALTY_BOX_ADMIN_MATCH, true},
+ {STANDBY_MATCH, true, STANDBY_MATCH|HAPPY_BOX_MATCH, true},
+ {STANDBY_MATCH, true, STANDBY_MATCH|PENALTY_BOX_USER_MATCH|HAPPY_BOX_MATCH, true},
+ {STANDBY_MATCH, true, STANDBY_MATCH|PENALTY_BOX_ADMIN_MATCH|HAPPY_BOX_MATCH, true},
// clang-format on
};
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index dfc7699..2aff89c 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -644,7 +644,8 @@
(struct __sk_buff* skb) {
uint32_t sock_uid = bpf_get_socket_uid(skb);
UidOwnerValue* denylistMatch = bpf_uid_owner_map_lookup_elem(&sock_uid);
- if (denylistMatch) return denylistMatch->rule & PENALTY_BOX_MATCH ? BPF_MATCH : BPF_NOMATCH;
+ uint32_t penalty_box = PENALTY_BOX_USER_MATCH | PENALTY_BOX_ADMIN_MATCH;
+ if (denylistMatch) return denylistMatch->rule & penalty_box ? BPF_MATCH : BPF_NOMATCH;
return BPF_NOMATCH;
}
diff --git a/bpf_progs/netd.h b/bpf_progs/netd.h
index 098147f..8a56b4a 100644
--- a/bpf_progs/netd.h
+++ b/bpf_progs/netd.h
@@ -181,7 +181,7 @@
enum UidOwnerMatchType : uint32_t {
NO_MATCH = 0,
HAPPY_BOX_MATCH = (1 << 0),
- PENALTY_BOX_MATCH = (1 << 1),
+ PENALTY_BOX_USER_MATCH = (1 << 1),
DOZABLE_MATCH = (1 << 2),
STANDBY_MATCH = (1 << 3),
POWERSAVE_MATCH = (1 << 4),
@@ -192,7 +192,8 @@
OEM_DENY_1_MATCH = (1 << 9),
OEM_DENY_2_MATCH = (1 << 10),
OEM_DENY_3_MATCH = (1 << 11),
- BACKGROUND_MATCH = (1 << 12)
+ BACKGROUND_MATCH = (1 << 12),
+ PENALTY_BOX_ADMIN_MATCH = (1 << 13),
};
// LINT.ThenChange(../framework/src/android/net/BpfNetMapsConstants.java)
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 026d8a9..b2aafa0 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -56,6 +56,9 @@
field @FlaggedApi("com.android.net.flags.basic_background_restrictions_enabled") public static final int FIREWALL_CHAIN_BACKGROUND = 6; // 0x6
field public static final int FIREWALL_CHAIN_DOZABLE = 1; // 0x1
field public static final int FIREWALL_CHAIN_LOW_POWER_STANDBY = 5; // 0x5
+ field @FlaggedApi("com.android.net.flags.metered_network_firewall_chains") public static final int FIREWALL_CHAIN_METERED_ALLOW = 10; // 0xa
+ field @FlaggedApi("com.android.net.flags.metered_network_firewall_chains") public static final int FIREWALL_CHAIN_METERED_DENY_ADMIN = 12; // 0xc
+ field @FlaggedApi("com.android.net.flags.metered_network_firewall_chains") public static final int FIREWALL_CHAIN_METERED_DENY_USER = 11; // 0xb
field public static final int FIREWALL_CHAIN_OEM_DENY_1 = 7; // 0x7
field public static final int FIREWALL_CHAIN_OEM_DENY_2 = 8; // 0x8
field public static final int FIREWALL_CHAIN_OEM_DENY_3 = 9; // 0x9
diff --git a/framework/src/android/net/BpfNetMapsConstants.java b/framework/src/android/net/BpfNetMapsConstants.java
index 5d0fe73..f3773de 100644
--- a/framework/src/android/net/BpfNetMapsConstants.java
+++ b/framework/src/android/net/BpfNetMapsConstants.java
@@ -19,6 +19,9 @@
import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER;
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;
@@ -67,7 +70,7 @@
// LINT.IfChange(match_type)
public static final long NO_MATCH = 0;
public static final long HAPPY_BOX_MATCH = (1 << 0);
- public static final long PENALTY_BOX_MATCH = (1 << 1);
+ public static final long PENALTY_BOX_USER_MATCH = (1 << 1);
public static final long DOZABLE_MATCH = (1 << 2);
public static final long STANDBY_MATCH = (1 << 3);
public static final long POWERSAVE_MATCH = (1 << 4);
@@ -79,10 +82,11 @@
public static final long OEM_DENY_2_MATCH = (1 << 10);
public static final long OEM_DENY_3_MATCH = (1 << 11);
public static final long BACKGROUND_MATCH = (1 << 12);
+ public static final long PENALTY_BOX_ADMIN_MATCH = (1 << 13);
public static final List<Pair<Long, String>> MATCH_LIST = Arrays.asList(
Pair.create(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"),
- Pair.create(PENALTY_BOX_MATCH, "PENALTY_BOX_MATCH"),
+ Pair.create(PENALTY_BOX_USER_MATCH, "PENALTY_BOX_USER_MATCH"),
Pair.create(DOZABLE_MATCH, "DOZABLE_MATCH"),
Pair.create(STANDBY_MATCH, "STANDBY_MATCH"),
Pair.create(POWERSAVE_MATCH, "POWERSAVE_MATCH"),
@@ -93,11 +97,13 @@
Pair.create(OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH"),
Pair.create(OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH"),
Pair.create(OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH"),
- Pair.create(BACKGROUND_MATCH, "BACKGROUND_MATCH")
+ Pair.create(BACKGROUND_MATCH, "BACKGROUND_MATCH"),
+ Pair.create(PENALTY_BOX_ADMIN_MATCH, "PENALTY_BOX_ADMIN_MATCH")
);
/**
- * List of all firewall allow chains.
+ * List of all firewall allow chains that are applied to all networks regardless of meteredness
+ * See {@link #METERED_ALLOW_CHAINS} for allow chains that are only applied to metered networks.
*
* Allow chains mean the firewall denies all uids by default, uids must be explicitly allowed.
*/
@@ -110,7 +116,8 @@
);
/**
- * List of all firewall deny chains.
+ * List of all firewall deny chains that are applied to all networks regardless of meteredness
+ * See {@link #METERED_DENY_CHAINS} for deny chains that are only applied to metered networks.
*
* Deny chains mean the firewall allows all uids by default, uids must be explicitly denied.
*/
@@ -120,5 +127,24 @@
FIREWALL_CHAIN_OEM_DENY_2,
FIREWALL_CHAIN_OEM_DENY_3
);
+
+ /**
+ * List of all firewall allow chains that are only applied to metered networks.
+ * See {@link #ALLOW_CHAINS} for allow chains that are applied to all networks regardless of
+ * meteredness.
+ */
+ public static final List<Integer> METERED_ALLOW_CHAINS = List.of(
+ FIREWALL_CHAIN_METERED_ALLOW
+ );
+
+ /**
+ * List of all firewall deny chains that are only applied to metered networks.
+ * See {@link #DENY_CHAINS} for deny chains that are applied to all networks regardless of
+ * meteredness.
+ */
+ public static final List<Integer> METERED_DENY_CHAINS = List.of(
+ FIREWALL_CHAIN_METERED_DENY_USER,
+ FIREWALL_CHAIN_METERED_DENY_ADMIN
+ );
// LINT.ThenChange(../../../../bpf_progs/netd.h)
}
diff --git a/framework/src/android/net/BpfNetMapsUtils.java b/framework/src/android/net/BpfNetMapsUtils.java
index 19ecafb..9cbf147 100644
--- a/framework/src/android/net/BpfNetMapsUtils.java
+++ b/framework/src/android/net/BpfNetMapsUtils.java
@@ -25,11 +25,14 @@
import static android.net.BpfNetMapsConstants.HAPPY_BOX_MATCH;
import static android.net.BpfNetMapsConstants.LOW_POWER_STANDBY_MATCH;
import static android.net.BpfNetMapsConstants.MATCH_LIST;
+import static android.net.BpfNetMapsConstants.METERED_ALLOW_CHAINS;
+import static android.net.BpfNetMapsConstants.METERED_DENY_CHAINS;
import static android.net.BpfNetMapsConstants.NO_MATCH;
import static android.net.BpfNetMapsConstants.OEM_DENY_1_MATCH;
import static android.net.BpfNetMapsConstants.OEM_DENY_2_MATCH;
import static android.net.BpfNetMapsConstants.OEM_DENY_3_MATCH;
-import static android.net.BpfNetMapsConstants.PENALTY_BOX_MATCH;
+import static android.net.BpfNetMapsConstants.PENALTY_BOX_ADMIN_MATCH;
+import static android.net.BpfNetMapsConstants.PENALTY_BOX_USER_MATCH;
import static android.net.BpfNetMapsConstants.POWERSAVE_MATCH;
import static android.net.BpfNetMapsConstants.RESTRICTED_MATCH;
import static android.net.BpfNetMapsConstants.STANDBY_MATCH;
@@ -37,6 +40,9 @@
import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER;
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;
@@ -117,6 +123,12 @@
return OEM_DENY_2_MATCH;
case FIREWALL_CHAIN_OEM_DENY_3:
return OEM_DENY_3_MATCH;
+ case FIREWALL_CHAIN_METERED_ALLOW:
+ return HAPPY_BOX_MATCH;
+ case FIREWALL_CHAIN_METERED_DENY_USER:
+ return PENALTY_BOX_USER_MATCH;
+ case FIREWALL_CHAIN_METERED_DENY_ADMIN:
+ return PENALTY_BOX_ADMIN_MATCH;
default:
throw new ServiceSpecificException(EINVAL, "Invalid firewall chain: " + chain);
}
@@ -129,9 +141,9 @@
* DENYLIST means the firewall allows all by default, uids must be explicitly denied
*/
public static boolean isFirewallAllowList(final int chain) {
- if (ALLOW_CHAINS.contains(chain)) {
+ if (ALLOW_CHAINS.contains(chain) || METERED_ALLOW_CHAINS.contains(chain)) {
return true;
- } else if (DENY_CHAINS.contains(chain)) {
+ } else if (DENY_CHAINS.contains(chain) || METERED_DENY_CHAINS.contains(chain)) {
return false;
}
throw new ServiceSpecificException(EINVAL, "Invalid firewall chain: " + chain);
@@ -264,7 +276,7 @@
}
if (!isNetworkMetered) return false;
- if ((uidMatch & PENALTY_BOX_MATCH) != 0) return true;
+ if ((uidMatch & (PENALTY_BOX_USER_MATCH | PENALTY_BOX_ADMIN_MATCH)) != 0) return true;
if ((uidMatch & HAPPY_BOX_MATCH) != 0) return false;
return getDataSaverEnabled(dataSaverEnabledMap);
}
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index b1e636d..7823258 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -128,6 +128,8 @@
"com.android.net.flags.support_is_uid_networking_blocked";
static final String BASIC_BACKGROUND_RESTRICTIONS_ENABLED =
"com.android.net.flags.basic_background_restrictions_enabled";
+ static final String METERED_NETWORK_FIREWALL_CHAINS =
+ "com.android.net.flags.metered_network_firewall_chains";
}
/**
@@ -1068,6 +1070,61 @@
@SystemApi(client = MODULE_LIBRARIES)
public static final int FIREWALL_CHAIN_OEM_DENY_3 = 9;
+ /**
+ * Firewall chain for allow list on metered networks
+ *
+ * UIDs added to this chain have access to metered networks, unless they're also in one of the
+ * denylist, {@link #FIREWALL_CHAIN_METERED_DENY_USER},
+ * {@link #FIREWALL_CHAIN_METERED_DENY_ADMIN}
+ *
+ * Note that this chain is used from a separate bpf program that is triggered by iptables and
+ * can not be controlled by {@link ConnectivityManager#setFirewallChainEnabled}.
+ *
+ * @hide
+ */
+ // TODO: Merge this chain with data saver and support setFirewallChainEnabled
+ @FlaggedApi(Flags.METERED_NETWORK_FIREWALL_CHAINS)
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int FIREWALL_CHAIN_METERED_ALLOW = 10;
+
+ /**
+ * Firewall chain for user-set restrictions on metered networks
+ *
+ * UIDs added to this chain do not have access to metered networks.
+ * UIDs should be added to this chain based on user settings.
+ * To restrict metered network based on admin configuration (e.g. enterprise policies),
+ * {@link #FIREWALL_CHAIN_METERED_DENY_ADMIN} should be used.
+ * This chain corresponds to {@link #BLOCKED_METERED_REASON_USER_RESTRICTED}
+ *
+ * Note that this chain is used from a separate bpf program that is triggered by iptables and
+ * can not be controlled by {@link ConnectivityManager#setFirewallChainEnabled}.
+ *
+ * @hide
+ */
+ // TODO: Support setFirewallChainEnabled to control this chain
+ @FlaggedApi(Flags.METERED_NETWORK_FIREWALL_CHAINS)
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int FIREWALL_CHAIN_METERED_DENY_USER = 11;
+
+ /**
+ * Firewall chain for admin-set restrictions on metered networks
+ *
+ * UIDs added to this chain do not have access to metered networks.
+ * UIDs should be added to this chain based on admin configuration (e.g. enterprise policies).
+ * To restrict metered network based on user settings, {@link #FIREWALL_CHAIN_METERED_DENY_USER}
+ * should be used.
+ * This chain corresponds to {@link #BLOCKED_METERED_REASON_ADMIN_DISABLED}
+ *
+ * Note that this chain is used from a separate bpf program that is triggered by iptables and
+ * can not be controlled by {@link ConnectivityManager#setFirewallChainEnabled}.
+ *
+ * @hide
+ */
+ // TODO: Support setFirewallChainEnabled to control this chain
+ @FlaggedApi(Flags.METERED_NETWORK_FIREWALL_CHAINS)
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int FIREWALL_CHAIN_METERED_DENY_ADMIN = 12;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = false, prefix = "FIREWALL_CHAIN_", value = {
@@ -1079,7 +1136,10 @@
FIREWALL_CHAIN_BACKGROUND,
FIREWALL_CHAIN_OEM_DENY_1,
FIREWALL_CHAIN_OEM_DENY_2,
- FIREWALL_CHAIN_OEM_DENY_3
+ FIREWALL_CHAIN_OEM_DENY_3,
+ FIREWALL_CHAIN_METERED_ALLOW,
+ FIREWALL_CHAIN_METERED_DENY_USER,
+ FIREWALL_CHAIN_METERED_DENY_ADMIN
})
public @interface FirewallChain {}
@@ -6065,7 +6125,7 @@
})
public void addUidToMeteredNetworkAllowList(final int uid) {
try {
- mService.updateMeteredNetworkAllowList(uid, true /* add */);
+ mService.setUidFirewallRule(FIREWALL_CHAIN_METERED_ALLOW, uid, FIREWALL_RULE_ALLOW);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6088,7 +6148,7 @@
})
public void removeUidFromMeteredNetworkAllowList(final int uid) {
try {
- mService.updateMeteredNetworkAllowList(uid, false /* remove */);
+ mService.setUidFirewallRule(FIREWALL_CHAIN_METERED_ALLOW, uid, FIREWALL_RULE_DENY);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6098,10 +6158,17 @@
* Adds the specified UID to the list of UIDs that are not allowed to use background data on
* metered networks. Takes precedence over {@link #addUidToMeteredNetworkAllowList}.
*
+ * On V+, {@link #setUidFirewallRule} should be used with
+ * {@link #FIREWALL_CHAIN_METERED_DENY_USER} or {@link #FIREWALL_CHAIN_METERED_DENY_ADMIN}
+ * based on the reason so that users can receive {@link #BLOCKED_METERED_REASON_USER_RESTRICTED}
+ * or {@link #BLOCKED_METERED_REASON_ADMIN_DISABLED}, respectively.
+ * This API always uses {@link #FIREWALL_CHAIN_METERED_DENY_USER}.
+ *
* @param uid uid of target app
* @throws IllegalStateException if updating deny list failed.
* @hide
*/
+ // TODO(b/332649177): Deprecate this API after V
@SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_SETTINGS,
@@ -6110,7 +6177,7 @@
})
public void addUidToMeteredNetworkDenyList(final int uid) {
try {
- mService.updateMeteredNetworkDenyList(uid, true /* add */);
+ mService.setUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_USER, uid, FIREWALL_RULE_DENY);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6121,10 +6188,17 @@
* networks if background data is not restricted. The deny list takes precedence over the
* allow list.
*
+ * On V+, {@link #setUidFirewallRule} should be used with
+ * {@link #FIREWALL_CHAIN_METERED_DENY_USER} or {@link #FIREWALL_CHAIN_METERED_DENY_ADMIN}
+ * based on the reason so that users can receive {@link #BLOCKED_METERED_REASON_USER_RESTRICTED}
+ * or {@link #BLOCKED_METERED_REASON_ADMIN_DISABLED}, respectively.
+ * This API always uses {@link #FIREWALL_CHAIN_METERED_DENY_USER}.
+ *
* @param uid uid of target app
* @throws IllegalStateException if updating deny list failed.
* @hide
*/
+ // TODO(b/332649177): Deprecate this API after V
@SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_SETTINGS,
@@ -6133,7 +6207,7 @@
})
public void removeUidFromMeteredNetworkDenyList(final int uid) {
try {
- mService.updateMeteredNetworkDenyList(uid, false /* remove */);
+ mService.setUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_USER, uid, FIREWALL_RULE_ALLOW);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6191,6 +6265,10 @@
/**
* Enables or disables the specified firewall chain.
*
+ * Note that metered firewall chains can not be controlled by this API.
+ * See {@link #FIREWALL_CHAIN_METERED_ALLOW}, {@link #FIREWALL_CHAIN_METERED_DENY_USER}, and
+ * {@link #FIREWALL_CHAIN_METERED_DENY_ADMIN} for more detail.
+ *
* @param chain target chain.
* @param enable whether the chain should be enabled.
* @throws UnsupportedOperationException if called on pre-T devices.
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index d3a02b9..55c7085 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -242,10 +242,6 @@
void setDataSaverEnabled(boolean enable);
- void updateMeteredNetworkAllowList(int uid, boolean add);
-
- void updateMeteredNetworkDenyList(int uid, boolean add);
-
void setUidFirewallRule(int chain, int uid, int rule);
int getUidFirewallRule(int chain, int uid);
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index fc6d8c4..01bd71e 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -23,11 +23,9 @@
import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED;
import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_KEY;
import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_MAP_PATH;
-import static android.net.BpfNetMapsConstants.HAPPY_BOX_MATCH;
import static android.net.BpfNetMapsConstants.IIF_MATCH;
import static android.net.BpfNetMapsConstants.INGRESS_DISCARD_MAP_PATH;
import static android.net.BpfNetMapsConstants.LOCKDOWN_VPN_MATCH;
-import static android.net.BpfNetMapsConstants.PENALTY_BOX_MATCH;
import static android.net.BpfNetMapsConstants.UID_OWNER_MAP_PATH;
import static android.net.BpfNetMapsConstants.UID_PERMISSION_MAP_PATH;
import static android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY;
@@ -446,62 +444,6 @@
}
/**
- * Add naughty app bandwidth rule for specific app
- *
- * @param uid uid of target app
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- public void addNaughtyApp(final int uid) {
- throwIfPreT("addNaughtyApp is not available on pre-T devices");
-
- addRule(uid, PENALTY_BOX_MATCH, "addNaughtyApp");
- }
-
- /**
- * Remove naughty app bandwidth rule for specific app
- *
- * @param uid uid of target app
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- public void removeNaughtyApp(final int uid) {
- throwIfPreT("removeNaughtyApp is not available on pre-T devices");
-
- removeRule(uid, PENALTY_BOX_MATCH, "removeNaughtyApp");
- }
-
- /**
- * Add nice app bandwidth rule for specific app
- *
- * @param uid uid of target app
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- public void addNiceApp(final int uid) {
- throwIfPreT("addNiceApp is not available on pre-T devices");
-
- addRule(uid, HAPPY_BOX_MATCH, "addNiceApp");
- }
-
- /**
- * Remove nice app bandwidth rule for specific app
- *
- * @param uid uid of target app
- * @throws ServiceSpecificException in case of failure, with an error code indicating the
- * cause of the failure.
- */
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- public void removeNiceApp(final int uid) {
- throwIfPreT("removeNiceApp is not available on pre-T devices");
-
- removeRule(uid, HAPPY_BOX_MATCH, "removeNiceApp");
- }
-
- /**
* Set target firewall child chain
*
* @param childChain target chain to enable
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index a15a2bf..0ea3366 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -24,6 +24,8 @@
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.net.BpfNetMapsConstants.METERED_ALLOW_CHAINS;
+import static android.net.BpfNetMapsConstants.METERED_DENY_CHAINS;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT;
@@ -13474,36 +13476,6 @@
}
}
- @Override
- public void updateMeteredNetworkAllowList(final int uid, final boolean add) {
- enforceNetworkStackOrSettingsPermission();
-
- try {
- if (add) {
- mBpfNetMaps.addNiceApp(uid);
- } else {
- mBpfNetMaps.removeNiceApp(uid);
- }
- } catch (ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void updateMeteredNetworkDenyList(final int uid, final boolean add) {
- enforceNetworkStackOrSettingsPermission();
-
- try {
- if (add) {
- mBpfNetMaps.addNaughtyApp(uid);
- } else {
- mBpfNetMaps.removeNaughtyApp(uid);
- }
- } catch (ServiceSpecificException e) {
- throw new IllegalStateException(e);
- }
- }
-
private int setPackageFirewallRule(final int chain, final String packageName, final int rule)
throws PackageManager.NameNotFoundException {
final PackageManager pm = mContext.getPackageManager();
@@ -13563,6 +13535,8 @@
case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1:
case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2:
case ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3:
+ case ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER:
+ case ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN:
defaultRule = FIREWALL_RULE_ALLOW;
break;
case ConnectivityManager.FIREWALL_CHAIN_DOZABLE:
@@ -13570,6 +13544,7 @@
case ConnectivityManager.FIREWALL_CHAIN_RESTRICTED:
case ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY:
case ConnectivityManager.FIREWALL_CHAIN_BACKGROUND:
+ case ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW:
defaultRule = FIREWALL_RULE_DENY;
break;
default:
@@ -13606,6 +13581,12 @@
+ " the feature is disabled.");
return;
}
+ if (METERED_ALLOW_CHAINS.contains(chain) || METERED_DENY_CHAINS.contains(chain)) {
+ // Metered chains are used from a separate bpf program that is triggered by iptables
+ // and can not be controlled by setFirewallChainEnabled.
+ throw new UnsupportedOperationException(
+ "Chain (" + chain + ") can not be controlled by setFirewallChainEnabled");
+ }
try {
mBpfNetMaps.setChildChain(chain, enable);
@@ -13626,6 +13607,13 @@
public boolean getFirewallChainEnabled(final int chain) {
enforceNetworkStackOrSettingsPermission();
+ if (METERED_ALLOW_CHAINS.contains(chain) || METERED_DENY_CHAINS.contains(chain)) {
+ // Metered chains are used from a separate bpf program that is triggered by iptables
+ // and can not be controlled by setFirewallChainEnabled.
+ throw new UnsupportedOperationException(
+ "getFirewallChainEnabled can not return status of chain (" + chain + ")");
+ }
+
return mBpfNetMaps.isChainEnabled(chain);
}
diff --git a/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt b/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt
index a9ccbdd..b5d78f3 100644
--- a/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt
+++ b/tests/unit/java/android/net/NetworkStackBpfNetMapsTest.kt
@@ -21,7 +21,8 @@
import android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_KEY
import android.net.BpfNetMapsConstants.DOZABLE_MATCH
import android.net.BpfNetMapsConstants.HAPPY_BOX_MATCH
-import android.net.BpfNetMapsConstants.PENALTY_BOX_MATCH
+import android.net.BpfNetMapsConstants.PENALTY_BOX_ADMIN_MATCH
+import android.net.BpfNetMapsConstants.PENALTY_BOX_USER_MATCH
import android.net.BpfNetMapsConstants.STANDBY_MATCH
import android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY
import android.net.BpfNetMapsUtils.getMatchByFirewallChain
@@ -48,9 +49,9 @@
private const val TEST_UID3 = TEST_UID2 + 1
private const val NO_IIF = 0
-// pre-T devices does not support Bpf.
+// NetworkStack can not use this before U due to b/326143935
@RunWith(DevSdkIgnoreRunner::class)
-@IgnoreUpTo(VERSION_CODES.S_V2)
+@IgnoreUpTo(VERSION_CODES.TIRAMISU)
class NetworkStackBpfNetMapsTest {
@Rule
@JvmField
@@ -102,14 +103,18 @@
}
// Verify the size matches, this also verifies no common item in allow and deny chains.
assertEquals(
- BpfNetMapsConstants.ALLOW_CHAINS.size +
- BpfNetMapsConstants.DENY_CHAINS.size,
+ BpfNetMapsConstants.ALLOW_CHAINS.size +
+ BpfNetMapsConstants.DENY_CHAINS.size +
+ BpfNetMapsConstants.METERED_ALLOW_CHAINS.size +
+ BpfNetMapsConstants.METERED_DENY_CHAINS.size,
declaredChains.size
)
declaredChains.forEach {
assertTrue(
- BpfNetMapsConstants.ALLOW_CHAINS.contains(it.get(null)) ||
- BpfNetMapsConstants.DENY_CHAINS.contains(it.get(null))
+ BpfNetMapsConstants.ALLOW_CHAINS.contains(it.get(null)) ||
+ BpfNetMapsConstants.METERED_ALLOW_CHAINS.contains(it.get(null)) ||
+ BpfNetMapsConstants.DENY_CHAINS.contains(it.get(null)) ||
+ BpfNetMapsConstants.METERED_DENY_CHAINS.contains(it.get(null))
)
}
}
@@ -190,7 +195,16 @@
// Add uid1 to penalty box, verify the network is blocked for uid1, while uid2 is not
// affected.
- testUidOwnerMap.updateEntry(S32(TEST_UID1), UidOwnerValue(NO_IIF, PENALTY_BOX_MATCH))
+ testUidOwnerMap.updateEntry(S32(TEST_UID1), UidOwnerValue(NO_IIF, PENALTY_BOX_USER_MATCH))
+ assertTrue(isUidNetworkingBlocked(TEST_UID1, metered = true))
+ assertFalse(isUidNetworkingBlocked(TEST_UID2, metered = true))
+ testUidOwnerMap.updateEntry(S32(TEST_UID1), UidOwnerValue(NO_IIF, PENALTY_BOX_ADMIN_MATCH))
+ assertTrue(isUidNetworkingBlocked(TEST_UID1, metered = true))
+ assertFalse(isUidNetworkingBlocked(TEST_UID2, metered = true))
+ testUidOwnerMap.updateEntry(
+ S32(TEST_UID1),
+ UidOwnerValue(NO_IIF, PENALTY_BOX_USER_MATCH or PENALTY_BOX_ADMIN_MATCH)
+ )
assertTrue(isUidNetworkingBlocked(TEST_UID1, metered = true))
assertFalse(isUidNetworkingBlocked(TEST_UID2, metered = true))
@@ -206,7 +220,14 @@
// priority.
testUidOwnerMap.updateEntry(
S32(TEST_UID1),
- UidOwnerValue(NO_IIF, PENALTY_BOX_MATCH or HAPPY_BOX_MATCH)
+ UidOwnerValue(NO_IIF, PENALTY_BOX_USER_MATCH or HAPPY_BOX_MATCH)
+ )
+ assertTrue(isUidNetworkingBlocked(TEST_UID1, metered = true))
+ assertTrue(isUidNetworkingBlocked(TEST_UID2, metered = true))
+ assertFalse(isUidNetworkingBlocked(TEST_UID3, metered = true))
+ testUidOwnerMap.updateEntry(
+ S32(TEST_UID1),
+ UidOwnerValue(NO_IIF, PENALTY_BOX_ADMIN_MATCH or HAPPY_BOX_MATCH)
)
assertTrue(isUidNetworkingBlocked(TEST_UID1, metered = true))
assertTrue(isUidNetworkingBlocked(TEST_UID2, metered = true))
@@ -240,7 +261,7 @@
for (uid in FIRST_APPLICATION_UID - 5..FIRST_APPLICATION_UID + 5) {
// system uid is not blocked regardless of firewall chains
val expectBlocked = uid >= FIRST_APPLICATION_UID
- testUidOwnerMap.updateEntry(S32(uid), UidOwnerValue(NO_IIF, PENALTY_BOX_MATCH))
+ testUidOwnerMap.updateEntry(S32(uid), UidOwnerValue(NO_IIF, PENALTY_BOX_USER_MATCH))
assertEquals(
expectBlocked,
isUidNetworkingBlocked(uid, metered = true),
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
index ea905d5..fa79795 100644
--- a/tests/unit/java/com/android/server/BpfNetMapsTest.java
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -31,13 +31,17 @@
import static android.net.BpfNetMapsConstants.OEM_DENY_1_MATCH;
import static android.net.BpfNetMapsConstants.OEM_DENY_2_MATCH;
import static android.net.BpfNetMapsConstants.OEM_DENY_3_MATCH;
-import static android.net.BpfNetMapsConstants.PENALTY_BOX_MATCH;
+import static android.net.BpfNetMapsConstants.PENALTY_BOX_ADMIN_MATCH;
+import static android.net.BpfNetMapsConstants.PENALTY_BOX_USER_MATCH;
import static android.net.BpfNetMapsConstants.POWERSAVE_MATCH;
import static android.net.BpfNetMapsConstants.RESTRICTED_MATCH;
import static android.net.BpfNetMapsConstants.STANDBY_MATCH;
import static android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER;
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;
@@ -334,146 +338,6 @@
}
}
- private void doTestRemoveNaughtyApp(final int iif, final long match) throws Exception {
- mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match));
-
- mBpfNetMaps.removeNaughtyApp(TEST_UID);
-
- checkUidOwnerValue(TEST_UID, iif, match & ~PENALTY_BOX_MATCH);
- }
-
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.S_V2)
- public void testRemoveNaughtyApp() throws Exception {
- doTestRemoveNaughtyApp(NO_IIF, PENALTY_BOX_MATCH);
-
- // PENALTY_BOX_MATCH with other matches
- doTestRemoveNaughtyApp(NO_IIF, PENALTY_BOX_MATCH | DOZABLE_MATCH | POWERSAVE_MATCH);
-
- // PENALTY_BOX_MATCH with IIF_MATCH
- doTestRemoveNaughtyApp(TEST_IF_INDEX, PENALTY_BOX_MATCH | IIF_MATCH);
-
- // PENALTY_BOX_MATCH is not enabled
- doTestRemoveNaughtyApp(NO_IIF, DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH);
- }
-
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.S_V2)
- public void testRemoveNaughtyAppMissingUid() {
- // UidOwnerMap does not have entry for TEST_UID
- assertThrows(ServiceSpecificException.class,
- () -> mBpfNetMaps.removeNaughtyApp(TEST_UID));
- }
-
- @Test
- @IgnoreAfter(Build.VERSION_CODES.S_V2)
- public void testRemoveNaughtyAppBeforeT() {
- assertThrows(UnsupportedOperationException.class,
- () -> mBpfNetMaps.removeNaughtyApp(TEST_UID));
- }
-
- private void doTestAddNaughtyApp(final int iif, final long match) throws Exception {
- if (match != NO_MATCH) {
- mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match));
- }
-
- mBpfNetMaps.addNaughtyApp(TEST_UID);
-
- checkUidOwnerValue(TEST_UID, iif, match | PENALTY_BOX_MATCH);
- }
-
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.S_V2)
- public void testAddNaughtyApp() throws Exception {
- doTestAddNaughtyApp(NO_IIF, NO_MATCH);
-
- // Other matches are enabled
- doTestAddNaughtyApp(NO_IIF, DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH);
-
- // IIF_MATCH is enabled
- doTestAddNaughtyApp(TEST_IF_INDEX, IIF_MATCH);
-
- // PENALTY_BOX_MATCH is already enabled
- doTestAddNaughtyApp(NO_IIF, PENALTY_BOX_MATCH | DOZABLE_MATCH);
- }
-
- @Test
- @IgnoreAfter(Build.VERSION_CODES.S_V2)
- public void testAddNaughtyAppBeforeT() {
- assertThrows(UnsupportedOperationException.class,
- () -> mBpfNetMaps.addNaughtyApp(TEST_UID));
- }
-
- private void doTestRemoveNiceApp(final int iif, final long match) throws Exception {
- mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match));
-
- mBpfNetMaps.removeNiceApp(TEST_UID);
-
- checkUidOwnerValue(TEST_UID, iif, match & ~HAPPY_BOX_MATCH);
- }
-
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.S_V2)
- public void testRemoveNiceApp() throws Exception {
- doTestRemoveNiceApp(NO_IIF, HAPPY_BOX_MATCH);
-
- // HAPPY_BOX_MATCH with other matches
- doTestRemoveNiceApp(NO_IIF, HAPPY_BOX_MATCH | DOZABLE_MATCH | POWERSAVE_MATCH);
-
- // HAPPY_BOX_MATCH with IIF_MATCH
- doTestRemoveNiceApp(TEST_IF_INDEX, HAPPY_BOX_MATCH | IIF_MATCH);
-
- // HAPPY_BOX_MATCH is not enabled
- doTestRemoveNiceApp(NO_IIF, DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH);
- }
-
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.S_V2)
- public void testRemoveNiceAppMissingUid() {
- // UidOwnerMap does not have entry for TEST_UID
- assertThrows(ServiceSpecificException.class,
- () -> mBpfNetMaps.removeNiceApp(TEST_UID));
- }
-
- @Test
- @IgnoreAfter(Build.VERSION_CODES.S_V2)
- public void testRemoveNiceAppBeforeT() {
- assertThrows(UnsupportedOperationException.class,
- () -> mBpfNetMaps.removeNiceApp(TEST_UID));
- }
-
- private void doTestAddNiceApp(final int iif, final long match) throws Exception {
- if (match != NO_MATCH) {
- mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match));
- }
-
- mBpfNetMaps.addNiceApp(TEST_UID);
-
- checkUidOwnerValue(TEST_UID, iif, match | HAPPY_BOX_MATCH);
- }
-
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.S_V2)
- public void testAddNiceApp() throws Exception {
- doTestAddNiceApp(NO_IIF, NO_MATCH);
-
- // Other matches are enabled
- doTestAddNiceApp(NO_IIF, DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH);
-
- // IIF_MATCH is enabled
- doTestAddNiceApp(TEST_IF_INDEX, IIF_MATCH);
-
- // HAPPY_BOX_MATCH is already enabled
- doTestAddNiceApp(NO_IIF, HAPPY_BOX_MATCH | DOZABLE_MATCH);
- }
-
- @Test
- @IgnoreAfter(Build.VERSION_CODES.S_V2)
- public void testAddNiceAppBeforeT() {
- assertThrows(UnsupportedOperationException.class,
- () -> mBpfNetMaps.addNiceApp(TEST_UID));
- }
-
private void doTestUpdateUidLockdownRule(final int iif, final long match, final boolean add)
throws Exception {
if (match != NO_MATCH) {
@@ -658,6 +522,9 @@
doTestSetUidRule(FIREWALL_CHAIN_OEM_DENY_1);
doTestSetUidRule(FIREWALL_CHAIN_OEM_DENY_2);
doTestSetUidRule(FIREWALL_CHAIN_OEM_DENY_3);
+ doTestSetUidRule(FIREWALL_CHAIN_METERED_ALLOW);
+ doTestSetUidRule(FIREWALL_CHAIN_METERED_DENY_USER);
+ doTestSetUidRule(FIREWALL_CHAIN_METERED_DENY_ADMIN);
}
@Test
@@ -1079,7 +946,7 @@
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
public void testDumpUidOwnerMap() throws Exception {
doTestDumpUidOwnerMap(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH");
- doTestDumpUidOwnerMap(PENALTY_BOX_MATCH, "PENALTY_BOX_MATCH");
+ doTestDumpUidOwnerMap(PENALTY_BOX_USER_MATCH, "PENALTY_BOX_USER_MATCH");
doTestDumpUidOwnerMap(DOZABLE_MATCH, "DOZABLE_MATCH");
doTestDumpUidOwnerMap(STANDBY_MATCH, "STANDBY_MATCH");
doTestDumpUidOwnerMap(POWERSAVE_MATCH, "POWERSAVE_MATCH");
@@ -1089,6 +956,7 @@
doTestDumpUidOwnerMap(OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH");
doTestDumpUidOwnerMap(OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH");
doTestDumpUidOwnerMap(OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH");
+ doTestDumpUidOwnerMap(PENALTY_BOX_ADMIN_MATCH, "PENALTY_BOX_ADMIN_MATCH");
doTestDumpUidOwnerMap(HAPPY_BOX_MATCH | POWERSAVE_MATCH,
"HAPPY_BOX_MATCH POWERSAVE_MATCH");
@@ -1137,7 +1005,6 @@
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
public void testDumpUidOwnerMapConfig() throws Exception {
doTestDumpOwnerMatchConfig(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH");
- doTestDumpOwnerMatchConfig(PENALTY_BOX_MATCH, "PENALTY_BOX_MATCH");
doTestDumpOwnerMatchConfig(DOZABLE_MATCH, "DOZABLE_MATCH");
doTestDumpOwnerMatchConfig(STANDBY_MATCH, "STANDBY_MATCH");
doTestDumpOwnerMatchConfig(POWERSAVE_MATCH, "POWERSAVE_MATCH");
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index ce49533..59e7d22 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -63,6 +63,9 @@
import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER;
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;
@@ -10497,6 +10500,9 @@
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);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_ALLOW, FIREWALL_RULE_DENY);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_USER, FIREWALL_RULE_ALLOW);
+ doTestSetUidFirewallRule(FIREWALL_CHAIN_METERED_DENY_ADMIN, FIREWALL_RULE_ALLOW);
}
@Test @IgnoreUpTo(SC_V2)
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSFirewallChainTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSFirewallChainTest.kt
index 16de4da..83ccccd 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSFirewallChainTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSFirewallChainTest.kt
@@ -16,7 +16,14 @@
package com.android.server
-import android.net.ConnectivityManager
+import android.net.BpfNetMapsConstants.METERED_ALLOW_CHAINS
+import android.net.BpfNetMapsConstants.METERED_DENY_CHAINS
+import android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND
+import android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW
+import android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER
+import android.net.ConnectivityManager.FIREWALL_RULE_ALLOW
+import android.net.ConnectivityManager.FIREWALL_RULE_DEFAULT
+import android.net.ConnectivityManager.FIREWALL_RULE_DENY
import android.os.Build
import androidx.test.filters.SmallTest
import com.android.server.connectivity.ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN
@@ -24,6 +31,7 @@
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertThrows
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -52,13 +60,13 @@
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun setFirewallChainEnabled_backgroundChainEnabled_afterU() {
- cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, true)
- verify(bpfNetMaps).setChildChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, true)
+ cm.setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true)
+ verify(bpfNetMaps).setChildChain(FIREWALL_CHAIN_BACKGROUND, true)
clearInvocations(bpfNetMaps)
- cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, false)
- verify(bpfNetMaps).setChildChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, false)
+ cm.setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, false)
+ verify(bpfNetMaps).setChildChain(FIREWALL_CHAIN_BACKGROUND, false)
}
@Test
@@ -69,10 +77,10 @@
}
private fun verifySetFirewallChainEnabledOnBackgroundDoesNothing() {
- cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, true)
+ cm.setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, true)
verify(bpfNetMaps, never()).setChildChain(anyInt(), anyBoolean())
- cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, false)
+ cm.setFirewallChainEnabled(FIREWALL_CHAIN_BACKGROUND, false)
verify(bpfNetMaps, never()).setChildChain(anyInt(), anyBoolean())
}
@@ -88,8 +96,8 @@
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun replaceFirewallChain_backgroundChainEnabled_afterU() {
val uids = intArrayOf(53, 42, 79)
- cm.replaceFirewallChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uids)
- verify(bpfNetMaps).replaceUidChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uids)
+ cm.replaceFirewallChain(FIREWALL_CHAIN_BACKGROUND, uids)
+ verify(bpfNetMaps).replaceUidChain(FIREWALL_CHAIN_BACKGROUND, uids)
}
@Test
@@ -101,7 +109,7 @@
private fun verifyReplaceFirewallChainOnBackgroundDoesNothing() {
val uids = intArrayOf(53, 42, 79)
- cm.replaceFirewallChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uids)
+ cm.replaceFirewallChain(FIREWALL_CHAIN_BACKGROUND, uids)
verify(bpfNetMaps, never()).replaceUidChain(anyInt(), any(IntArray::class.java))
}
@@ -118,24 +126,18 @@
fun setUidFirewallRule_backgroundChainEnabled_afterU() {
val uid = 2345
- cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
- ConnectivityManager.FIREWALL_RULE_DEFAULT)
- verify(bpfNetMaps).setUidRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
- ConnectivityManager.FIREWALL_RULE_DENY)
+ cm.setUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_DEFAULT)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_DENY)
clearInvocations(bpfNetMaps)
- cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
- ConnectivityManager.FIREWALL_RULE_DENY)
- verify(bpfNetMaps).setUidRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
- ConnectivityManager.FIREWALL_RULE_DENY)
+ cm.setUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_DENY)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_DENY)
clearInvocations(bpfNetMaps)
- cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
- ConnectivityManager.FIREWALL_RULE_ALLOW)
- verify(bpfNetMaps).setUidRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
- ConnectivityManager.FIREWALL_RULE_ALLOW)
+ cm.setUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_ALLOW)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_BACKGROUND, uid, FIREWALL_RULE_ALLOW)
}
@Test
@@ -148,10 +150,49 @@
private fun verifySetUidFirewallRuleOnBackgroundDoesNothing() {
val uid = 2345
- listOf(ConnectivityManager.FIREWALL_RULE_DEFAULT, ConnectivityManager.FIREWALL_RULE_ALLOW,
- ConnectivityManager.FIREWALL_RULE_DENY).forEach { rule ->
- cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid, rule)
+ listOf(FIREWALL_RULE_DEFAULT, FIREWALL_RULE_ALLOW, FIREWALL_RULE_DENY).forEach { rule ->
+ cm.setUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, uid, rule)
verify(bpfNetMaps, never()).setUidRule(anyInt(), anyInt(), anyInt())
}
}
+
+ @Test
+ fun testSetFirewallChainEnabled_meteredChain() {
+ (METERED_ALLOW_CHAINS + METERED_DENY_CHAINS).forEach {
+ assertThrows(UnsupportedOperationException::class.java) {
+ cm.setFirewallChainEnabled(it, true)
+ }
+ assertThrows(UnsupportedOperationException::class.java) {
+ cm.setFirewallChainEnabled(it, false)
+ }
+ }
+ }
+
+ @Test
+ fun testAddUidToMeteredNetworkAllowList() {
+ val uid = 1001
+ cm.addUidToMeteredNetworkAllowList(uid)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_METERED_ALLOW, uid, FIREWALL_RULE_ALLOW)
+ }
+
+ @Test
+ fun testRemoveUidFromMeteredNetworkAllowList() {
+ val uid = 1001
+ cm.removeUidFromMeteredNetworkAllowList(uid)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_METERED_ALLOW, uid, FIREWALL_RULE_DENY)
+ }
+
+ @Test
+ fun testAddUidToMeteredNetworkDenyList() {
+ val uid = 1001
+ cm.addUidToMeteredNetworkDenyList(uid)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_METERED_DENY_USER, uid, FIREWALL_RULE_DENY)
+ }
+
+ @Test
+ fun testRemoveUidFromMeteredNetworkDenyList() {
+ val uid = 1001
+ cm.removeUidFromMeteredNetworkDenyList(uid)
+ verify(bpfNetMaps).setUidRule(FIREWALL_CHAIN_METERED_DENY_USER, uid, FIREWALL_RULE_ALLOW)
+ }
}