Move isUidNetworkingBlocked to BpfNetMapsUtils
This is a preparation to add isUidNetworkingBlocked method to BpfNetMaps
without duplicating codes.
Bug: 328732146
Test: TH
Change-Id: I50a46931f6c80a1f4cfca5d9e78b2ab742a793f2
diff --git a/framework/src/android/net/BpfNetMapsUtils.java b/framework/src/android/net/BpfNetMapsUtils.java
index 0be30bb..cb2b770 100644
--- a/framework/src/android/net/BpfNetMapsUtils.java
+++ b/framework/src/android/net/BpfNetMapsUtils.java
@@ -18,17 +18,22 @@
import static android.net.BpfNetMapsConstants.ALLOW_CHAINS;
import static android.net.BpfNetMapsConstants.BACKGROUND_MATCH;
+import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED;
+import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_KEY;
import static android.net.BpfNetMapsConstants.DENY_CHAINS;
import static android.net.BpfNetMapsConstants.DOZABLE_MATCH;
+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.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.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_BACKGROUND;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
@@ -41,9 +46,16 @@
import static android.system.OsConstants.EINVAL;
import android.os.ServiceSpecificException;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.Pair;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.IBpfMap;
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.S32;
+import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.U8;
import java.util.StringJoiner;
@@ -56,6 +68,26 @@
// Because modules could have different copies of this class if this is statically linked,
// which would be problematic if the definitions in these modules are not synchronized.
public class BpfNetMapsUtils {
+ // Bitmaps for calculating whether a given uid is blocked by firewall chains.
+ private static final long sMaskDropIfSet;
+ private static final long sMaskDropIfUnset;
+
+ static {
+ long maskDropIfSet = 0L;
+ long maskDropIfUnset = 0L;
+
+ for (int chain : BpfNetMapsConstants.ALLOW_CHAINS) {
+ final long match = getMatchByFirewallChain(chain);
+ maskDropIfUnset |= match;
+ }
+ for (int chain : BpfNetMapsConstants.DENY_CHAINS) {
+ final long match = getMatchByFirewallChain(chain);
+ maskDropIfSet |= match;
+ }
+ sMaskDropIfSet = maskDropIfSet;
+ sMaskDropIfUnset = maskDropIfUnset;
+ }
+
// Prevent this class from being accidental instantiated.
private BpfNetMapsUtils() {}
@@ -133,4 +165,72 @@
throw new UnsupportedOperationException(msg);
}
}
+
+
+ /**
+ * Return whether the network is blocked by firewall chains for the given uid.
+ *
+ * Note that {@link #getDataSaverEnabled(IBpfMap)} has a latency before V.
+ *
+ * @param uid The target uid.
+ * @param isNetworkMetered Whether the target network is metered.
+ *
+ * @return True if the network is blocked. Otherwise, false.
+ * @throws ServiceSpecificException if the read fails.
+ *
+ * @hide
+ */
+ public static boolean isUidNetworkingBlocked(final int uid, boolean isNetworkMetered,
+ IBpfMap<S32, U32> configurationMap,
+ IBpfMap<S32, UidOwnerValue> uidOwnerMap,
+ IBpfMap<S32, U8> dataSaverEnabledMap
+ ) {
+ throwIfPreT("isUidBlockedByFirewallChains is not available on pre-T devices");
+
+ final long uidRuleConfig;
+ final long uidMatch;
+ try {
+ uidRuleConfig = configurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val;
+ final UidOwnerValue value = uidOwnerMap.getValue(new Struct.S32(uid));
+ uidMatch = (value != null) ? value.rule : 0L;
+ } catch (ErrnoException e) {
+ throw new ServiceSpecificException(e.errno,
+ "Unable to get firewall chain status: " + Os.strerror(e.errno));
+ }
+
+ final boolean blockedByAllowChains = 0 != (uidRuleConfig & ~uidMatch & sMaskDropIfUnset);
+ final boolean blockedByDenyChains = 0 != (uidRuleConfig & uidMatch & sMaskDropIfSet);
+ if (blockedByAllowChains || blockedByDenyChains) {
+ return true;
+ }
+
+ if (!isNetworkMetered) return false;
+ if ((uidMatch & PENALTY_BOX_MATCH) != 0) return true;
+ if ((uidMatch & HAPPY_BOX_MATCH) != 0) return false;
+ return getDataSaverEnabled(dataSaverEnabledMap);
+ }
+
+ /**
+ * Get Data Saver enabled or disabled
+ *
+ * Note that before V, the data saver status in bpf is written by ConnectivityService
+ * when receiving {@link ConnectivityManager#ACTION_RESTRICT_BACKGROUND_CHANGED}. Thus,
+ * the status is not synchronized.
+ * On V+, the data saver status is set by platform code when enabling/disabling
+ * data saver, which is synchronized.
+ *
+ * @return whether Data Saver is enabled or disabled.
+ * @throws ServiceSpecificException in case of failure, with an error code indicating the
+ * cause of the failure.
+ */
+ public static boolean getDataSaverEnabled(IBpfMap<S32, U8> dataSaverEnabledMap) {
+ throwIfPreT("getDataSaverEnabled is not available on pre-T devices");
+
+ try {
+ return dataSaverEnabledMap.getValue(DATA_SAVER_ENABLED_KEY).val == DATA_SAVER_ENABLED;
+ } catch (ErrnoException e) {
+ throw new ServiceSpecificException(e.errno, "Unable to get data saver: "
+ + Os.strerror(e.errno));
+ }
+ }
}
diff --git a/framework/src/android/net/NetworkStackBpfNetMaps.java b/framework/src/android/net/NetworkStackBpfNetMaps.java
index 346c997..1a1e449 100644
--- a/framework/src/android/net/NetworkStackBpfNetMaps.java
+++ b/framework/src/android/net/NetworkStackBpfNetMaps.java
@@ -17,11 +17,7 @@
package android.net;
import static android.net.BpfNetMapsConstants.CONFIGURATION_MAP_PATH;
-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.PENALTY_BOX_MATCH;
import static android.net.BpfNetMapsConstants.UID_OWNER_MAP_PATH;
import static android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY;
import static android.net.BpfNetMapsUtils.getMatchByFirewallChain;
@@ -67,26 +63,6 @@
private final IBpfMap<S32, U8> mDataSaverEnabledMap;
private final Dependencies mDeps;
- // Bitmaps for calculating whether a given uid is blocked by firewall chains.
- private static final long sMaskDropIfSet;
- private static final long sMaskDropIfUnset;
-
- static {
- long maskDropIfSet = 0L;
- long maskDropIfUnset = 0L;
-
- for (int chain : BpfNetMapsConstants.ALLOW_CHAINS) {
- final long match = getMatchByFirewallChain(chain);
- maskDropIfUnset |= match;
- }
- for (int chain : BpfNetMapsConstants.DENY_CHAINS) {
- final long match = getMatchByFirewallChain(chain);
- maskDropIfSet |= match;
- }
- sMaskDropIfSet = maskDropIfSet;
- sMaskDropIfUnset = maskDropIfUnset;
- }
-
private static class SingletonHolder {
static final NetworkStackBpfNetMaps sInstance = new NetworkStackBpfNetMaps();
}
@@ -245,29 +221,8 @@
* @hide
*/
public boolean isUidNetworkingBlocked(final int uid, boolean isNetworkMetered) {
- throwIfPreT("isUidBlockedByFirewallChains is not available on pre-T devices");
-
- final long uidRuleConfig;
- final long uidMatch;
- try {
- uidRuleConfig = mConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val;
- final UidOwnerValue value = mUidOwnerMap.getValue(new S32(uid));
- uidMatch = (value != null) ? value.rule : 0L;
- } catch (ErrnoException e) {
- throw new ServiceSpecificException(e.errno,
- "Unable to get firewall chain status: " + Os.strerror(e.errno));
- }
-
- final boolean blockedByAllowChains = 0 != (uidRuleConfig & ~uidMatch & sMaskDropIfUnset);
- final boolean blockedByDenyChains = 0 != (uidRuleConfig & uidMatch & sMaskDropIfSet);
- if (blockedByAllowChains || blockedByDenyChains) {
- return true;
- }
-
- if (!isNetworkMetered) return false;
- if ((uidMatch & PENALTY_BOX_MATCH) != 0) return true;
- if ((uidMatch & HAPPY_BOX_MATCH) != 0) return false;
- return getDataSaverEnabled();
+ return BpfNetMapsUtils.isUidNetworkingBlocked(uid, isNetworkMetered,
+ mConfigurationMap, mUidOwnerMap, mDataSaverEnabledMap);
}
/**
@@ -284,13 +239,6 @@
* cause of the failure.
*/
public boolean getDataSaverEnabled() {
- throwIfPreT("getDataSaverEnabled is not available on pre-T devices");
-
- try {
- return mDataSaverEnabledMap.getValue(DATA_SAVER_ENABLED_KEY).val == DATA_SAVER_ENABLED;
- } catch (ErrnoException e) {
- throw new ServiceSpecificException(e.errno, "Unable to get data saver: "
- + Os.strerror(e.errno));
- }
+ return BpfNetMapsUtils.getDataSaverEnabled(mDataSaverEnabledMap);
}
}