Support java BpfMap in BpfNetMaps#setNetPermForUids

Bug: 217624062
Test: atest BpfNetMapsTest
Change-Id: Ia32a73a49ee6a0b05e1abd0c09766e7769e7e760
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index 594223c..231a47f 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -26,6 +26,8 @@
 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
+import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_UNINSTALLED;
 import static android.system.OsConstants.EINVAL;
 import static android.system.OsConstants.ENODEV;
 import static android.system.OsConstants.ENOENT;
@@ -45,6 +47,7 @@
 import com.android.net.module.util.BpfMap;
 import com.android.net.module.util.DeviceConfigUtils;
 import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.U8;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -85,6 +88,8 @@
             "/sys/fs/bpf/netd_shared/map_netd_configuration_map";
     private static final String UID_OWNER_MAP_PATH =
             "/sys/fs/bpf/netd_shared/map_netd_uid_owner_map";
+    private static final String UID_PERMISSION_MAP_PATH =
+            "/sys/fs/bpf/netd_shared/map_netd_uid_permission_map";
     private static final U32 UID_RULES_CONFIGURATION_KEY = new U32(0);
     private static final U32 CURRENT_STATS_MAP_CONFIGURATION_KEY = new U32(1);
     private static final long UID_RULES_DEFAULT_CONFIGURATION = 0;
@@ -94,6 +99,7 @@
     private static BpfMap<U32, U32> sConfigurationMap = null;
     // BpfMap for UID_OWNER_MAP_PATH. This map is not accessed by others.
     private static BpfMap<U32, UidOwnerValue> sUidOwnerMap = null;
+    private static BpfMap<U32, U8> sUidPermissionMap = null;
 
     // LINT.IfChange(match_type)
     @VisibleForTesting public static final long NO_MATCH = 0;
@@ -135,6 +141,14 @@
         sUidOwnerMap = uidOwnerMap;
     }
 
+    /**
+     * Set uidPermissionMap for test.
+     */
+    @VisibleForTesting
+    public static void setUidPermissionMapForTest(BpfMap<U32, U8> uidPermissionMap) {
+        sUidPermissionMap = uidPermissionMap;
+    }
+
     private static BpfMap<U32, U32> getConfigurationMap() {
         try {
             return new BpfMap<>(
@@ -153,6 +167,15 @@
         }
     }
 
+    private static BpfMap<U32, U8> getUidPermissionMap() {
+        try {
+            return new BpfMap<>(
+                    UID_PERMISSION_MAP_PATH, BpfMap.BPF_F_RDWR, U32.class, U8.class);
+        } catch (ErrnoException e) {
+            throw new IllegalStateException("Cannot open uid permission map", e);
+        }
+    }
+
     private static void initBpfMaps() {
         if (sConfigurationMap == null) {
             sConfigurationMap = getConfigurationMap();
@@ -178,6 +201,10 @@
         } catch (ErrnoException e) {
             throw new IllegalStateException("Failed to initialize uid owner map", e);
         }
+
+        if (sUidPermissionMap == null) {
+            sUidPermissionMap = getUidPermissionMap();
+        }
     }
 
     /**
@@ -719,7 +746,31 @@
             mNetd.trafficSetNetPermForUids(permissions, uids);
             return;
         }
-        native_setPermissionForUids(permissions, uids);
+
+        if (sEnableJavaBpfMap) {
+            // Remove the entry if package is uninstalled or uid has only INTERNET permission.
+            if (permissions == PERMISSION_UNINSTALLED || permissions == PERMISSION_INTERNET) {
+                for (final int uid : uids) {
+                    try {
+                        sUidPermissionMap.deleteEntry(new U32(uid));
+                    } catch (ErrnoException e) {
+                        Log.e(TAG, "Failed to remove uid " + uid + " from permission map: " + e);
+                    }
+                }
+                return;
+            }
+
+            for (final int uid : uids) {
+                try {
+                    sUidPermissionMap.updateEntry(new U32(uid), new U8((short) permissions));
+                } catch (ErrnoException e) {
+                    Log.e(TAG, "Failed to set permission "
+                            + permissions + " to uid " + uid + ": " + e);
+                }
+            }
+        } else {
+            native_setPermissionForUids(permissions, uids);
+        }
     }
 
     /**