Merge "Remove ambiguity when using error().code()."
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index 4c58228..50cfb02 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -334,31 +334,3 @@
"//packages/modules/Wifi/service",
],
}
-
-// This file group is deprecated; new users should use net-utils-annotations
-filegroup {
- name: "net-utils-annotations-srcs",
- srcs: [
- "annotations/android/net/annotations/PolicyDirection.java",
- ],
- visibility: [
- "//frameworks/base",
- ],
-}
-
-
-java_library {
- name: "net-utils-annotations",
- srcs: [":net-utils-annotations-srcs"],
- libs: [
- "framework-annotations-lib",
- ],
- sdk_version: "system_current",
- min_sdk_version: "30",
- visibility: ["//visibility:public"],
- apex_available: [
- "//apex_available:anyapex",
- "//apex_available:platform",
- ],
- lint: { strict_updatability_linting: true },
-}
diff --git a/staticlibs/annotations/android/net/annotations/PolicyDirection.java b/staticlibs/annotations/android/net/annotations/PolicyDirection.java
deleted file mode 100644
index febd9b4..0000000
--- a/staticlibs/annotations/android/net/annotations/PolicyDirection.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.annotations;
-
-import android.annotation.IntDef;
-import android.net.IpSecManager;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * IPsec traffic direction.
- *
- * <p>Mainline modules cannot reference hidden @IntDef. Moving this annotation to a separate class
- * to allow others to statically include it.
- *
- * @hide
- */
-@IntDef(value = {IpSecManager.DIRECTION_IN, IpSecManager.DIRECTION_OUT})
-@Retention(RetentionPolicy.SOURCE)
-public @interface PolicyDirection {}
diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
index c5efcb2..1705f1c 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkRouteMessage.java
@@ -22,6 +22,7 @@
import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY;
import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ANY;
+import android.annotation.SuppressLint;
import android.net.IpPrefix;
import android.system.OsConstants;
@@ -107,6 +108,7 @@
* @param header netlink message header.
* @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
*/
+ @SuppressLint("NewApi")
@Nullable
public static RtNetlinkRouteMessage parse(@NonNull final StructNlMsgHdr header,
@NonNull final ByteBuffer byteBuffer) {
diff --git a/staticlibs/device/com/android/net/module/util/netlink/StructNdOptPref64.java b/staticlibs/device/com/android/net/module/util/netlink/StructNdOptPref64.java
index f6b2e0e..8226346 100644
--- a/staticlibs/device/com/android/net/module/util/netlink/StructNdOptPref64.java
+++ b/staticlibs/device/com/android/net/module/util/netlink/StructNdOptPref64.java
@@ -16,6 +16,7 @@
package com.android.net.module.util.netlink;
+import android.annotation.SuppressLint;
import android.net.IpPrefix;
import android.util.Log;
@@ -107,6 +108,7 @@
this.lifetime = lifetime & 0xfff8;
}
+ @SuppressLint("NewApi")
private StructNdOptPref64(@NonNull ByteBuffer buf) {
super(buf.get(), Byte.toUnsignedInt(buf.get()));
if (type != TYPE) throw new IllegalArgumentException("Invalid type " + type);
diff --git a/staticlibs/framework/com/android/net/module/util/BestClock.java b/staticlibs/framework/com/android/net/module/util/BestClock.java
new file mode 100644
index 0000000..35391ad
--- /dev/null
+++ b/staticlibs/framework/com/android/net/module/util/BestClock.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util;
+
+import android.util.Log;
+
+import java.time.Clock;
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.util.Arrays;
+
+/**
+ * Single {@link Clock} that will return the best available time from a set of
+ * prioritized {@link Clock} instances.
+ * <p>
+ * For example, when {@link SystemClock#currentNetworkTimeClock()} isn't able to
+ * provide the time, this class could use {@link Clock#systemUTC()} instead.
+ *
+ * Note that this is re-implemented based on {@code android.os.BestClock} to be used inside
+ * the mainline module. And the class does NOT support serialization.
+ *
+ * @hide
+ */
+final public class BestClock extends Clock {
+ private static final String TAG = "BestClock";
+ private final ZoneId mZone;
+ private final Clock[] mClocks;
+
+ public BestClock(ZoneId zone, Clock... clocks) {
+ super();
+ this.mZone = zone;
+ this.mClocks = clocks;
+ }
+
+ @Override
+ public long millis() {
+ for (Clock clock : mClocks) {
+ try {
+ return clock.millis();
+ } catch (DateTimeException e) {
+ // Ignore and attempt the next clock
+ Log.w(TAG, e.toString());
+ }
+ }
+ throw new DateTimeException(
+ "No clocks in " + Arrays.toString(mClocks) + " were able to provide time");
+ }
+
+ @Override
+ public ZoneId getZone() {
+ return mZone;
+ }
+
+ @Override
+ public Clock withZone(ZoneId zone) {
+ return new BestClock(zone, mClocks);
+ }
+
+ @Override
+ public Instant instant() {
+ return Instant.ofEpochMilli(millis());
+ }
+}
diff --git a/staticlibs/framework/com/android/net/module/util/CollectionUtils.java b/staticlibs/framework/com/android/net/module/util/CollectionUtils.java
index 6e1af55..312ca48 100644
--- a/staticlibs/framework/com/android/net/module/util/CollectionUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/CollectionUtils.java
@@ -180,4 +180,17 @@
}
return matches;
}
+
+ /**
+ * Return sum of the given long array.
+ */
+ public static long total(@Nullable long[] array) {
+ long total = 0;
+ if (array != null) {
+ for (long value : array) {
+ total += value;
+ }
+ }
+ return total;
+ }
}
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java b/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java
index 903214e..d6222a7 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkCapabilitiesUtils.java
@@ -16,9 +16,11 @@
package com.android.net.module.util;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
@@ -26,8 +28,11 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_MCX;
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM;
import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
@@ -74,43 +79,6 @@
};
/**
- * See android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE
- * TODO: Use API constant when all downstream branches are S-based
- */
- public static final int NET_CAPABILITY_OEM_PRIVATE = 26;
-
- /**
- * See android.net.NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL
- * TODO: Use API constant when all downstream branches are S-based
- */
- public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27;
-
- /**
- * See android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
- * TODO: Use API constant when all downstream branches are S-based
- */
- public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
-
- /**
- * See android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE
- * TODO: Use API constant when all downstream branches are S-based
- */
- public static final int NET_CAPABILITY_ENTERPRISE = 29;
-
- /**
- * See android.net.NetworkCapabilities.NET_CAPABILITY_VSIM
- * TODO: Use API constant when all downstream branches are S-based
- */
- public static final int NET_CAPABILITY_VSIM = 30;
-
- /**
- * See android.net.NetworkCapabilities.NET_CAPABILITY_BIP
- * TODO: Use API constant when all downstream branches are S-based
- */
- public static final int NET_CAPABILITY_BIP = 31;
-
-
- /**
* Capabilities that suggest that a network is restricted.
* See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted},
* and {@code FORCE_RESTRICTED_CAPABILITIES}.
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkStatsUtils.java b/staticlibs/framework/com/android/net/module/util/NetworkStatsUtils.java
new file mode 100644
index 0000000..d4ad1f2
--- /dev/null
+++ b/staticlibs/framework/com/android/net/module/util/NetworkStatsUtils.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util;
+
+/**
+ * Various utilities used for NetworkStats related code.
+ *
+ * @hide
+ */
+public class NetworkStatsUtils {
+ /**
+ * Safely multiple a value by a rational.
+ * <p>
+ * Internally it uses integer-based math whenever possible, but switches
+ * over to double-based math if values would overflow.
+ * @hide
+ */
+ public static long multiplySafeByRational(long value, long num, long den) {
+ if (den == 0) {
+ throw new ArithmeticException("Invalid Denominator");
+ }
+ long x = value;
+ long y = num;
+
+ // Logic shamelessly borrowed from Math.multiplyExact()
+ long r = x * y;
+ long ax = Math.abs(x);
+ long ay = Math.abs(y);
+ if (((ax | ay) >>> 31 != 0)) {
+ // Some bits greater than 2^31 that might cause overflow
+ // Check the result using the divide operator
+ // and check for the special case of Long.MIN_VALUE * -1
+ if (((y != 0) && (r / y != x))
+ || (x == Long.MIN_VALUE && y == -1)) {
+ // Use double math to avoid overflowing
+ return (long) (((double) num / den) * value);
+ }
+ }
+ return r / den;
+ }
+
+ /**
+ * Value of the match rule of the subscriberId to match networks with specific subscriberId.
+ *
+ * @hide
+ */
+ public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0;
+ /**
+ * Value of the match rule of the subscriberId to match networks with any subscriberId which
+ * includes null and non-null.
+ *
+ * @hide
+ */
+ public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1;
+
+ /**
+ * Return the constrained value by given the lower and upper bounds.
+ */
+ public static int constrain(int amount, int low, int high) {
+ if (low > high) throw new IllegalArgumentException("low(" + low + ") > high(" + high + ")");
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
+ /**
+ * Return the constrained value by given the lower and upper bounds.
+ */
+ public static long constrain(long amount, long low, long high) {
+ if (low > high) throw new IllegalArgumentException("low(" + low + ") > high(" + high + ")");
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+}
diff --git a/staticlibs/framework/com/android/net/module/util/PermissionUtils.java b/staticlibs/framework/com/android/net/module/util/PermissionUtils.java
index 10eda57..0f3dc15 100644
--- a/staticlibs/framework/com/android/net/module/util/PermissionUtils.java
+++ b/staticlibs/framework/com/android/net/module/util/PermissionUtils.java
@@ -16,13 +16,18 @@
package com.android.net.module.util;
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
+import android.os.Binder;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -80,4 +85,63 @@
permissions.add(PERMISSION_MAINLINE_NETWORK_STACK);
enforceAnyPermissionOf(context, permissions.toArray(new String[0]));
}
+
+ /**
+ * If the CONNECTIVITY_USE_RESTRICTED_NETWORKS is not allowed for a particular process, throw a
+ * {@link SecurityException}.
+ *
+ * @param context {@link android.content.Context} for the process.
+ * @param message A message to include in the exception if it is thrown.
+ */
+ public static void enforceRestrictedNetworkPermission(
+ final @NonNull Context context, final @Nullable String message) {
+ context.enforceCallingOrSelfPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, message);
+ }
+
+ /**
+ * If the ACCESS_NETWORK_STATE is not allowed for a particular process, throw a
+ * {@link SecurityException}.
+ *
+ * @param context {@link android.content.Context} for the process.
+ * @param message A message to include in the exception if it is thrown.
+ */
+ public static void enforceAccessNetworkStatePermission(
+ final @NonNull Context context, final @Nullable String message) {
+ context.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, message);
+ }
+
+ /**
+ * Return true if the context has DUMP permission.
+ */
+ public static boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+ if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump " + tag + " from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " due to missing android.permission.DUMP permission");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Enforce that a given feature is available and if not, throw an
+ * {@link UnsupportedOperationException}.
+ *
+ * @param context {@link android.content.Context} for the process.
+ * @param feature the feature name to enforce.
+ * @param errorMessage an optional error message to include.
+ */
+ public static void enforceSystemFeature(final @NonNull Context context,
+ final @NonNull String feature, final @Nullable String errorMessage) {
+ final boolean hasSystemFeature =
+ context.getPackageManager().hasSystemFeature(feature);
+ if (!hasSystemFeature) {
+ if (null == errorMessage) {
+ throw new UnsupportedOperationException();
+ }
+ throw new UnsupportedOperationException(errorMessage);
+ }
+ }
}
diff --git a/staticlibs/native/bpf_map_utils/Android.bp b/staticlibs/native/bpf_headers/Android.bp
similarity index 90%
rename from staticlibs/native/bpf_map_utils/Android.bp
rename to staticlibs/native/bpf_headers/Android.bp
index e14c259..06ba1b0 100644
--- a/staticlibs/native/bpf_map_utils/Android.bp
+++ b/staticlibs/native/bpf_headers/Android.bp
@@ -17,15 +17,18 @@
}
cc_library_headers {
- name: "bpf_map_utils",
- vendor_available: true,
+ name: "bpf_headers",
+ vendor_available: false,
host_supported: true,
native_bridge_supported: true,
+ header_libs: ["bpf_syscall_wrappers"],
+ export_header_lib_headers: ["bpf_syscall_wrappers"],
export_include_dirs: ["include"],
cflags: [
"-Wall",
"-Werror",
],
+ sdk_version: "30",
min_sdk_version: "30",
apex_available: [
"//apex_available:platform",
@@ -40,6 +43,7 @@
"//frameworks/native/services/gpuservice/gpumem",
"//frameworks/native/services/gpuservice/tests/unittests",
"//frameworks/native/services/gpuservice/tracing",
+ "//packages/modules/Connectivity/bpf_progs",
"//packages/modules/Connectivity/netd",
"//packages/modules/Connectivity/tests/unit/jni",
"//packages/modules/DnsResolver/tests",
diff --git a/staticlibs/native/bpf_map_utils/BpfMapTest.cpp b/staticlibs/native/bpf_headers/BpfMapTest.cpp
similarity index 100%
rename from staticlibs/native/bpf_map_utils/BpfMapTest.cpp
rename to staticlibs/native/bpf_headers/BpfMapTest.cpp
diff --git a/staticlibs/native/bpf_map_utils/TEST_MAPPING b/staticlibs/native/bpf_headers/TEST_MAPPING
similarity index 100%
rename from staticlibs/native/bpf_map_utils/TEST_MAPPING
rename to staticlibs/native/bpf_headers/TEST_MAPPING
diff --git a/staticlibs/native/bpf_map_utils/include/bpf/BpfMap.h b/staticlibs/native/bpf_headers/include/bpf/BpfMap.h
similarity index 100%
rename from staticlibs/native/bpf_map_utils/include/bpf/BpfMap.h
rename to staticlibs/native/bpf_headers/include/bpf/BpfMap.h
diff --git a/staticlibs/native/bpf_map_utils/include/bpf/BpfUtils.h b/staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
similarity index 100%
rename from staticlibs/native/bpf_map_utils/include/bpf/BpfUtils.h
rename to staticlibs/native/bpf_headers/include/bpf/BpfUtils.h
diff --git a/staticlibs/native/bpf_map_utils/include/bpf/WaitForProgsLoaded.h b/staticlibs/native/bpf_headers/include/bpf/WaitForProgsLoaded.h
similarity index 100%
rename from staticlibs/native/bpf_map_utils/include/bpf/WaitForProgsLoaded.h
rename to staticlibs/native/bpf_headers/include/bpf/WaitForProgsLoaded.h
diff --git a/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h b/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h
new file mode 100644
index 0000000..878bb10
--- /dev/null
+++ b/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h
@@ -0,0 +1,216 @@
+/* Common BPF helpers to be used by all BPF programs loaded by Android */
+
+#include <linux/bpf.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "bpf_map_def.h"
+
+/******************************************************************************
+ * WARNING: CHANGES TO THIS FILE OUTSIDE OF AOSP/MASTER ARE LIKELY TO BREAK *
+ * DEVICE COMPATIBILITY WITH MAINLINE MODULES SHIPPING EBPF CODE. *
+ * *
+ * THIS WILL LIKELY RESULT IN BRICKED DEVICES AT SOME ARBITRARY FUTURE TIME *
+ * *
+ * THAT GOES ESPECIALLY FOR THE 'SECTION' 'LICENSE' AND 'CRITICAL' MACROS *
+ * *
+ * We strongly suggest that if you need changes to bpfloader functionality *
+ * you get your changes reviewed and accepted into aosp/master. *
+ * *
+ ******************************************************************************/
+
+/* For mainline module use, you can #define BPFLOADER_{MIN/MAX}_VER
+ * before #include "bpf_helpers.h" to change which bpfloaders will
+ * process the resulting .o file.
+ *
+ * While this will work outside of mainline too, there just is no point to
+ * using it when the .o and the bpfloader ship in sync with each other.
+ */
+#ifndef BPFLOADER_MIN_VER
+#define BPFLOADER_MIN_VER DEFAULT_BPFLOADER_MIN_VER
+#endif
+
+#ifndef BPFLOADER_MAX_VER
+#define BPFLOADER_MAX_VER DEFAULT_BPFLOADER_MAX_VER
+#endif
+
+/* place things in different elf sections */
+#define SECTION(NAME) __attribute__((section(NAME), used))
+
+/* Must be present in every program, example usage:
+ * LICENSE("GPL"); or LICENSE("Apache 2.0");
+ *
+ * We also take this opportunity to embed a bunch of other useful values in
+ * the resulting .o (This is to enable some limited forward compatibility
+ * with mainline module shipped ebpf programs)
+ *
+ * The bpfloader_{min/max}_ver defines the [min, max) range of bpfloader
+ * versions that should load this .o file (bpfloaders outside of this range
+ * will simply ignore/skip this *entire* .o)
+ * The [inclusive,exclusive) matches what we do for kernel ver dependencies.
+ *
+ * The size_of_bpf_{map,prog}_def allow the bpfloader to load programs where
+ * these structures have been extended with additional fields (they will of
+ * course simply be ignored then).
+ *
+ * If missing, bpfloader_{min/max}_ver default to 0/0x10000 ie. [v0.0, v1.0),
+ * while size_of_bpf_{map/prog}_def default to 32/20 which are the v0.0 sizes.
+ */
+#define LICENSE(NAME) \
+ unsigned int _bpfloader_min_ver SECTION("bpfloader_min_ver") = BPFLOADER_MIN_VER; \
+ unsigned int _bpfloader_max_ver SECTION("bpfloader_max_ver") = BPFLOADER_MAX_VER; \
+ size_t _size_of_bpf_map_def SECTION("size_of_bpf_map_def") = sizeof(struct bpf_map_def); \
+ size_t _size_of_bpf_prog_def SECTION("size_of_bpf_prog_def") = sizeof(struct bpf_prog_def); \
+ char _license[] SECTION("license") = (NAME)
+
+/* flag the resulting bpf .o file as critical to system functionality,
+ * loading all kernel version appropriate programs in it must succeed
+ * for bpfloader success
+ */
+#define CRITICAL(REASON) char _critical[] SECTION("critical") = (REASON)
+
+/*
+ * Helper functions called from eBPF programs written in C. These are
+ * implemented in the kernel sources.
+ */
+
+#define KVER_NONE 0
+#define KVER(a, b, c) (((a) << 24) + ((b) << 16) + (c))
+#define KVER_INF 0xFFFFFFFFu
+
+/* generic functions */
+
+/*
+ * Type-unsafe bpf map functions - avoid if possible.
+ *
+ * Using these it is possible to pass in keys/values of the wrong type/size,
+ * or, for 'bpf_map_lookup_elem_unsafe' receive into a pointer to the wrong type.
+ * You will not get a compile time failure, and for certain types of errors you
+ * might not even get a failure from the kernel's ebpf verifier during program load,
+ * instead stuff might just not work right at runtime.
+ *
+ * Instead please use:
+ * DEFINE_BPF_MAP(foo_map, TYPE, KeyType, ValueType, num_entries)
+ * where TYPE can be something like HASH or ARRAY, and num_entries is an integer.
+ *
+ * This defines the map (hence this should not be used in a header file included
+ * from multiple locations) and provides type safe accessors:
+ * ValueType * bpf_foo_map_lookup_elem(const KeyType *)
+ * int bpf_foo_map_update_elem(const KeyType *, const ValueType *, flags)
+ * int bpf_foo_map_delete_elem(const KeyType *)
+ *
+ * This will make sure that if you change the type of a map you'll get compile
+ * errors at any spots you forget to update with the new type.
+ *
+ * Note: these all take pointers to const map because from the C/eBPF point of view
+ * the map struct is really just a readonly map definition of the in kernel object.
+ * Runtime modification of the map defining struct is meaningless, since
+ * the contents is only ever used during bpf program loading & map creation
+ * by the bpf loader, and not by the eBPF program itself.
+ */
+static void* (*bpf_map_lookup_elem_unsafe)(const struct bpf_map_def* map,
+ const void* key) = (void*)BPF_FUNC_map_lookup_elem;
+static int (*bpf_map_update_elem_unsafe)(const struct bpf_map_def* map, const void* key,
+ const void* value, unsigned long long flags) = (void*)
+ BPF_FUNC_map_update_elem;
+static int (*bpf_map_delete_elem_unsafe)(const struct bpf_map_def* map,
+ const void* key) = (void*)BPF_FUNC_map_delete_elem;
+
+/* type safe macro to declare a map and related accessor functions */
+#define DEFINE_BPF_MAP_UGM(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, usr, grp, md) \
+ const struct bpf_map_def SECTION("maps") the_map = { \
+ .type = BPF_MAP_TYPE_##TYPE, \
+ .key_size = sizeof(TypeOfKey), \
+ .value_size = sizeof(TypeOfValue), \
+ .max_entries = (num_entries), \
+ .map_flags = 0, \
+ .uid = (usr), \
+ .gid = (grp), \
+ .mode = (md), \
+ .bpfloader_min_ver = DEFAULT_BPFLOADER_MIN_VER, \
+ .bpfloader_max_ver = DEFAULT_BPFLOADER_MAX_VER, \
+ .min_kver = KVER_NONE, \
+ .max_kver = KVER_INF, \
+ }; \
+ \
+ static inline __always_inline __unused TypeOfValue* bpf_##the_map##_lookup_elem( \
+ const TypeOfKey* k) { \
+ return bpf_map_lookup_elem_unsafe(&the_map, k); \
+ }; \
+ \
+ static inline __always_inline __unused int bpf_##the_map##_update_elem( \
+ const TypeOfKey* k, const TypeOfValue* v, unsigned long long flags) { \
+ return bpf_map_update_elem_unsafe(&the_map, k, v, flags); \
+ }; \
+ \
+ static inline __always_inline __unused int bpf_##the_map##_delete_elem(const TypeOfKey* k) { \
+ return bpf_map_delete_elem_unsafe(&the_map, k); \
+ };
+
+#define DEFINE_BPF_MAP(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \
+ DEFINE_BPF_MAP_UGM(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, AID_ROOT, AID_ROOT, 0600)
+
+#define DEFINE_BPF_MAP_GWO(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, gid) \
+ DEFINE_BPF_MAP_UGM(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, AID_ROOT, gid, 0620)
+
+#define DEFINE_BPF_MAP_GRO(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, gid) \
+ DEFINE_BPF_MAP_UGM(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, AID_ROOT, gid, 0640)
+
+#define DEFINE_BPF_MAP_GRW(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, gid) \
+ DEFINE_BPF_MAP_UGM(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries, AID_ROOT, gid, 0660)
+
+static int (*bpf_probe_read)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read;
+static int (*bpf_probe_read_str)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read_str;
+static unsigned long long (*bpf_ktime_get_ns)(void) = (void*) BPF_FUNC_ktime_get_ns;
+static unsigned long long (*bpf_ktime_get_boot_ns)(void) = (void*)BPF_FUNC_ktime_get_boot_ns;
+static int (*bpf_trace_printk)(const char* fmt, int fmt_size, ...) = (void*) BPF_FUNC_trace_printk;
+static unsigned long long (*bpf_get_current_pid_tgid)(void) = (void*) BPF_FUNC_get_current_pid_tgid;
+static unsigned long long (*bpf_get_current_uid_gid)(void) = (void*) BPF_FUNC_get_current_uid_gid;
+static unsigned long long (*bpf_get_smp_processor_id)(void) = (void*) BPF_FUNC_get_smp_processor_id;
+
+#define DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
+ opt) \
+ const struct bpf_prog_def SECTION("progs") the_prog##_def = { \
+ .uid = (prog_uid), \
+ .gid = (prog_gid), \
+ .min_kver = (min_kv), \
+ .max_kver = (max_kv), \
+ .optional = (opt), \
+ .bpfloader_min_ver = DEFAULT_BPFLOADER_MIN_VER, \
+ .bpfloader_max_ver = DEFAULT_BPFLOADER_MAX_VER, \
+ }; \
+ SECTION(SECTION_NAME) \
+ int the_prog
+
+// Programs (here used in the sense of functions/sections) marked optional are allowed to fail
+// to load (for example due to missing kernel patches).
+// The bpfloader will just ignore these failures and continue processing the next section.
+//
+// A non-optional program (function/section) failing to load causes a failure and aborts
+// processing of the entire .o, if the .o is additionally marked critical, this will result
+// in the entire bpfloader process terminating with a failure and not setting the bpf.progs_loaded
+// system property. This in turn results in waitForProgsLoaded() never finishing.
+//
+// ie. a non-optional program in a critical .o is mandatory for kernels matching the min/max kver.
+
+// programs requiring a kernel version >= min_kv && < max_kv
+#define DEFINE_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, \
+ false)
+#define DEFINE_OPTIONAL_BPF_PROG_KVER_RANGE(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, \
+ max_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, max_kv, true)
+
+// programs requiring a kernel version >= min_kv
+#define DEFINE_BPF_PROG_KVER(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, KVER_INF, \
+ false)
+#define DEFINE_OPTIONAL_BPF_PROG_KVER(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, min_kv, KVER_INF, \
+ true)
+
+// programs with no kernel version requirements
+#define DEFINE_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, 0, KVER_INF, false)
+#define DEFINE_OPTIONAL_BPF_PROG(SECTION_NAME, prog_uid, prog_gid, the_prog) \
+ DEFINE_BPF_PROG_KVER_RANGE_OPT(SECTION_NAME, prog_uid, prog_gid, the_prog, 0, KVER_INF, true)
diff --git a/staticlibs/native/bpf_headers/include/bpf/bpf_map_def.h b/staticlibs/native/bpf_headers/include/bpf/bpf_map_def.h
new file mode 100644
index 0000000..02b2096
--- /dev/null
+++ b/staticlibs/native/bpf_headers/include/bpf/bpf_map_def.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/* This file is separate because it's included both by eBPF programs (via include
+ * in bpf_helpers.h) and directly by the boot time bpfloader (Loader.cpp).
+ */
+
+#include <linux/bpf.h>
+
+// Pull in AID_* constants from //system/core/libcutils/include/private/android_filesystem_config.h
+#include <private/android_filesystem_config.h>
+
+/******************************************************************************
+ * *
+ * ! ! ! W A R N I N G ! ! ! *
+ * *
+ * CHANGES TO THESE STRUCTURE DEFINITIONS OUTSIDE OF AOSP/MASTER *WILL* BREAK *
+ * MAINLINE MODULE COMPATIBILITY *
+ * *
+ * AND THUS MAY RESULT IN YOUR DEVICE BRICKING AT SOME ARBITRARY POINT IN *
+ * THE FUTURE *
+ * *
+ * (and even in aosp/master you may only append new fields at the very end, *
+ * you may *never* delete fields, change their types, ordering, insert in *
+ * the middle, etc. If a mainline module using the old definition has *
+ * already shipped (which happens roughly monthly), then it's set in stone) *
+ * *
+ ******************************************************************************/
+
+// These are the values used if these fields are missing
+#define DEFAULT_BPFLOADER_MIN_VER 0u // v0.0 (this is inclusive ie. >= v0.0)
+#define DEFAULT_BPFLOADER_MAX_VER 0x10000u // v1.0 (this is exclusive ie. < v1.0)
+#define DEFAULT_SIZEOF_BPF_MAP_DEF 32 // v0.0 struct: enum (uint sized) + 7 uint
+#define DEFAULT_SIZEOF_BPF_PROG_DEF 20 // v0.0 struct: 4 uint + bool + 3 byte alignment pad
+
+/*
+ * The bpf_{map,prog}_def structures are compiled for different architectures.
+ * Once by the BPF compiler for the BPF architecture, and once by a C++
+ * compiler for the native Android architecture for the bpfloader.
+ *
+ * For things to work, their layout must be the same between the two.
+ * The BPF architecture is platform independent ('64-bit LSB bpf').
+ * So this effectively means these structures must be the same layout
+ * on 5 architectures, all of them little endian:
+ * 64-bit BPF, x86_64, arm and 32-bit x86 and arm
+ *
+ * As such for any types we use inside of these structs we must make sure that
+ * the size and alignment are the same, so the same amount of padding is used.
+ *
+ * Currently we only use: bool, enum bpf_map_type and unsigned int.
+ * Additionally we use char for padding.
+ *
+ * !!! WARNING: HERE BE DRAGONS !!!
+ *
+ * Be particularly careful with 64-bit integers.
+ * You will need to manually override their alignment to 8 bytes.
+ *
+ * To quote some parts of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560
+ *
+ * Some types have weaker alignment requirements when they are structure members.
+ *
+ * unsigned long long on x86 is such a type.
+ *
+ * C distinguishes C11 _Alignof (the minimum alignment the type is guaranteed
+ * to have in all contexts, so 4, see min_align_of_type) from GNU C __alignof
+ * (the normal alignment of the type, so 8).
+ *
+ * alignof / _Alignof == minimum alignment required by target ABI
+ * __alignof / __alignof__ == preferred alignment
+ *
+ * When in a struct, apparently the minimum alignment is used.
+ */
+
+_Static_assert(sizeof(bool) == 1, "sizeof bool != 1");
+_Static_assert(__alignof__(bool) == 1, "__alignof__ bool != 1");
+_Static_assert(_Alignof(bool) == 1, "_Alignof bool != 1");
+
+_Static_assert(sizeof(char) == 1, "sizeof char != 1");
+_Static_assert(__alignof__(char) == 1, "__alignof__ char != 1");
+_Static_assert(_Alignof(char) == 1, "_Alignof char != 1");
+
+// This basically verifies that an enum is 'just' a 32-bit int
+_Static_assert(sizeof(enum bpf_map_type) == 4, "sizeof enum bpf_map_type != 4");
+_Static_assert(__alignof__(enum bpf_map_type) == 4, "__alignof__ enum bpf_map_type != 4");
+_Static_assert(_Alignof(enum bpf_map_type) == 4, "_Alignof enum bpf_map_type != 4");
+
+// Linux kernel requires sizeof(int) == 4, sizeof(void*) == sizeof(long), sizeof(long long) == 8
+_Static_assert(sizeof(unsigned int) == 4, "sizeof unsigned int != 4");
+_Static_assert(__alignof__(unsigned int) == 4, "__alignof__ unsigned int != 4");
+_Static_assert(_Alignof(unsigned int) == 4, "_Alignof unsigned int != 4");
+
+// We don't currently use any 64-bit types in these structs, so this is purely to document issue.
+// Here sizeof & __alignof__ are consistent, but _Alignof is not: compile for 'aosp_cf_x86_phone'
+_Static_assert(sizeof(unsigned long long) == 8, "sizeof unsigned long long != 8");
+_Static_assert(__alignof__(unsigned long long) == 8, "__alignof__ unsigned long long != 8");
+// BPF wants 8, but 32-bit x86 wants 4
+//_Static_assert(_Alignof(unsigned long long) == 8, "_Alignof unsigned long long != 8");
+
+/*
+ * Map structure to be used by Android eBPF C programs. The Android eBPF loader
+ * uses this structure from eBPF object to create maps at boot time.
+ *
+ * The eBPF C program should define structure in the maps section using
+ * SECTION("maps") otherwise it will be ignored by the eBPF loader.
+ *
+ * For example:
+ * const struct bpf_map_def SECTION("maps") mymap { .type=... , .key_size=... }
+ *
+ * See 'bpf_helpers.h' for helpful macros for eBPF program use.
+ */
+struct bpf_map_def {
+ enum bpf_map_type type;
+ unsigned int key_size;
+ unsigned int value_size;
+ unsigned int max_entries;
+ unsigned int map_flags;
+
+ // The following are not supported by the Android bpfloader:
+ // unsigned int inner_map_idx;
+ // unsigned int numa_node;
+
+ unsigned int uid; // uid_t
+ unsigned int gid; // gid_t
+ unsigned int mode; // mode_t
+
+ // The following fields were added in version 0.1
+ unsigned int bpfloader_min_ver; // if missing, defaults to 0, ie. v0.0
+ unsigned int bpfloader_max_ver; // if missing, defaults to 0x10000, ie. v1.0
+
+ // The following fields were added in version 0.2
+ // kernelVersion() must be >= min_kver and < max_kver
+ unsigned int min_kver;
+ unsigned int max_kver;
+};
+
+// This needs to be updated whenever the above structure definition is expanded.
+_Static_assert(sizeof(struct bpf_map_def) == 48, "sizeof struct bpf_map_def != 48");
+_Static_assert(__alignof__(struct bpf_map_def) == 4, "__alignof__ struct bpf_map_def != 4");
+_Static_assert(_Alignof(struct bpf_map_def) == 4, "_Alignof struct bpf_map_def != 4");
+
+struct bpf_prog_def {
+ unsigned int uid;
+ unsigned int gid;
+
+ // kernelVersion() must be >= min_kver and < max_kver
+ unsigned int min_kver;
+ unsigned int max_kver;
+
+ bool optional; // program section (ie. function) may fail to load, continue onto next func.
+ char pad0[3];
+
+ // The following fields were added in version 0.1
+ unsigned int bpfloader_min_ver; // if missing, defaults to 0, ie. v0.0
+ unsigned int bpfloader_max_ver; // if missing, defaults to 0x10000, ie. v1.0
+
+ // No new fields in version 0.2
+};
+
+// This needs to be updated whenever the above structure definition is expanded.
+_Static_assert(sizeof(struct bpf_prog_def) == 28, "sizeof struct bpf_prog_def != 28");
+_Static_assert(__alignof__(struct bpf_prog_def) == 4, "__alignof__ struct bpf_prog_def != 4");
+_Static_assert(_Alignof(struct bpf_prog_def) == 4, "_Alignof struct bpf_prog_def != 4");
diff --git a/staticlibs/native/bpf_syscall_wrappers/Android.bp b/staticlibs/native/bpf_syscall_wrappers/Android.bp
index 037e10d..1a1b53c 100644
--- a/staticlibs/native/bpf_syscall_wrappers/Android.bp
+++ b/staticlibs/native/bpf_syscall_wrappers/Android.bp
@@ -19,7 +19,7 @@
cc_library_headers {
name: "bpf_syscall_wrappers",
vendor_available: false,
- host_supported: false,
+ host_supported: true,
native_bridge_supported: true,
export_include_dirs: ["include"],
cflags: [
@@ -34,6 +34,7 @@
"com.android.tethering",
],
visibility: [
+ "//frameworks/libs/net/common/native/bpf_headers",
"//frameworks/libs/net/common/native/bpfmapjni",
"//packages/modules/Connectivity/netd",
"//packages/modules/Connectivity/service",
diff --git a/staticlibs/native/ip_checksum/Android.bp b/staticlibs/native/ip_checksum/Android.bp
index d7e195d..9878d73 100644
--- a/staticlibs/native/ip_checksum/Android.bp
+++ b/staticlibs/native/ip_checksum/Android.bp
@@ -37,4 +37,10 @@
//
// TODO: delete libnetutils from the VNDK in T, and remove this.
vendor_available: true,
+
+ min_sdk_version: "30",
+ apex_available: [
+ "com.android.tethering",
+ "//apex_available:platform",
+ ],
}
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/CollectionUtilsTest.kt b/staticlibs/tests/unit/src/com/android/net/module/util/CollectionUtilsTest.kt
index 96648a5..911483a 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/CollectionUtilsTest.kt
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/CollectionUtilsTest.kt
@@ -77,4 +77,13 @@
assertFalse(CollectionUtils.contains(arrayOf("A", "B", "C"), "D"))
assertFalse(CollectionUtils.contains(null, "A"))
}
+
+ @Test
+ fun testTotal() {
+ assertEquals(10, CollectionUtils.total(longArrayOf(3, 6, 1)))
+ assertEquals(10, CollectionUtils.total(longArrayOf(6, 1, 3)))
+ assertEquals(10, CollectionUtils.total(longArrayOf(1, 3, 6)))
+ assertEquals(3, CollectionUtils.total(longArrayOf(1, 1, 1)))
+ assertEquals(0, CollectionUtils.total(null))
+ }
}
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/IpRangeTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/IpRangeTest.java
index f44b17d..20bbd4a 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/IpRangeTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/IpRangeTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.annotation.SuppressLint;
import android.net.InetAddresses;
import android.net.IpPrefix;
@@ -92,6 +93,7 @@
}
}
+ @SuppressLint("NewApi")
@Test
public void testConstructor() {
IpRange r = new IpRange(new IpPrefix(IPV4_ADDR, 32));
@@ -119,6 +121,7 @@
assertEquals(IPV6_RANGE_END, r.getEndAddr());
}
+ @SuppressLint("NewApi")
@Test
public void testContainsRangeEqualRanges() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 35));
@@ -129,6 +132,7 @@
assertEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testContainsRangeSubset() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 64));
@@ -139,6 +143,7 @@
assertNotEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testContainsRangeTruncatesLowerOrderBits() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 100));
@@ -149,6 +154,7 @@
assertEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testContainsRangeSubsetSameStartAddr() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 35));
@@ -159,6 +165,7 @@
assertNotEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testContainsRangeOverlapping() {
final IpRange r1 = new IpRange(new IpPrefix(address("2001:db9::"), 32));
@@ -169,6 +176,7 @@
assertNotEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testOverlapsRangeEqualRanges() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 35));
@@ -179,6 +187,7 @@
assertEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testOverlapsRangeSubset() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 35));
@@ -189,6 +198,7 @@
assertNotEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testOverlapsRangeDisjoint() {
final IpRange r1 = new IpRange(new IpPrefix(IPV6_ADDR, 32));
@@ -199,6 +209,7 @@
assertNotEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testOverlapsRangePartialOverlapLow() {
final IpRange r1 = new IpRange(new IpPrefix(address("2001:db9::"), 32));
@@ -209,6 +220,7 @@
assertNotEquals(r1, r2);
}
+ @SuppressLint("NewApi")
@Test
public void testOverlapsRangePartialOverlapHigh() {
final IpRange r1 = new IpRange(new IpPrefix(address("2001:db7::"), 32));
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java
index 3d2d6eb..09f0490 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/LinkPropertiesUtilsTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.annotation.SuppressLint;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
@@ -46,6 +47,7 @@
@RunWith(AndroidJUnit4.class)
public final class LinkPropertiesUtilsTest {
+ @SuppressLint("NewApi")
private static final IpPrefix PREFIX = new IpPrefix(toInetAddress("75.208.6.0"), 24);
private static final InetAddress V4_ADDR = toInetAddress("75.208.6.1");
private static final InetAddress V6_ADDR = toInetAddress(
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/NetworkStatsUtilsTest.kt b/staticlibs/tests/unit/src/com/android/net/module/util/NetworkStatsUtilsTest.kt
new file mode 100644
index 0000000..ff839fe
--- /dev/null
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/NetworkStatsUtilsTest.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.net.module.util
+
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NetworkStatsUtilsTest {
+ @Test
+ fun testMultiplySafeByRational() {
+ // Verify basic cases that the method equals to a * b / c.
+ assertEquals(3 * 5 / 2, NetworkStatsUtils.multiplySafeByRational(3, 5, 2))
+
+ // Verify input with zeros.
+ assertEquals(0 * 7 / 3, NetworkStatsUtils.multiplySafeByRational(0, 7, 3))
+ assertEquals(7 * 0 / 3, NetworkStatsUtils.multiplySafeByRational(7, 0, 3))
+ assertEquals(0 * 0 / 1, NetworkStatsUtils.multiplySafeByRational(0, 0, 1))
+ assertEquals(0, NetworkStatsUtils.multiplySafeByRational(0, Long.MAX_VALUE, Long.MAX_VALUE))
+ assertEquals(0, NetworkStatsUtils.multiplySafeByRational(Long.MAX_VALUE, 0, Long.MAX_VALUE))
+ assertFailsWith<ArithmeticException> {
+ NetworkStatsUtils.multiplySafeByRational(7, 3, 0)
+ }
+ assertFailsWith<ArithmeticException> {
+ NetworkStatsUtils.multiplySafeByRational(0, 0, 0)
+ }
+
+ // Verify cases where a * b overflows.
+ assertEquals(101, NetworkStatsUtils.multiplySafeByRational(
+ 101, Long.MAX_VALUE, Long.MAX_VALUE))
+ assertEquals(721, NetworkStatsUtils.multiplySafeByRational(
+ Long.MAX_VALUE, 721, Long.MAX_VALUE))
+ assertEquals(Long.MAX_VALUE, NetworkStatsUtils.multiplySafeByRational(
+ Long.MAX_VALUE, Long.MAX_VALUE, Long.MAX_VALUE))
+ assertFailsWith<ArithmeticException> {
+ NetworkStatsUtils.multiplySafeByRational(Long.MAX_VALUE, Long.MAX_VALUE, 0)
+ }
+ }
+
+ @Test
+ fun testConstrain() {
+ assertFailsWith<IllegalArgumentException> {
+ NetworkStatsUtils.constrain(5, 6, 3) // low > high
+ }
+ assertEquals(3, NetworkStatsUtils.constrain(5, 1, 3))
+ assertEquals(3, NetworkStatsUtils.constrain(3, 1, 3))
+ assertEquals(2, NetworkStatsUtils.constrain(2, 1, 3))
+ assertEquals(1, NetworkStatsUtils.constrain(1, 1, 3))
+ assertEquals(1, NetworkStatsUtils.constrain(0, 1, 3))
+
+ assertEquals(11, NetworkStatsUtils.constrain(15, 11, 11))
+ assertEquals(11, NetworkStatsUtils.constrain(11, 11, 11))
+ assertEquals(11, NetworkStatsUtils.constrain(1, 11, 11))
+ }
+}
\ No newline at end of file
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/PermissionUtilsTest.kt b/staticlibs/tests/unit/src/com/android/net/module/util/PermissionUtilsTest.kt
index 6da5e7d..1b6cbcb 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/PermissionUtilsTest.kt
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/PermissionUtilsTest.kt
@@ -18,22 +18,28 @@
import android.Manifest.permission.NETWORK_STACK
import android.content.Context
+import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_DENIED
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.net.module.util.PermissionUtils.checkAnyPermissionOf
+import com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf
import com.android.net.module.util.PermissionUtils.enforceNetworkStackPermission
import com.android.net.module.util.PermissionUtils.enforceNetworkStackPermissionOr
-import com.android.net.module.util.PermissionUtils.enforceAnyPermissionOf
+import com.android.net.module.util.PermissionUtils.enforceSystemFeature
+import org.junit.Assert
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
+import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
/** Tests for PermissionUtils */
@@ -43,6 +49,12 @@
private val TEST_PERMISSION1 = "android.permission.TEST_PERMISSION1"
private val TEST_PERMISSION2 = "android.permission.TEST_PERMISSION2"
private val context = mock(Context::class.java)
+ private val packageManager = mock(PackageManager::class.java)
+
+ @Before
+ fun setup() {
+ doReturn(packageManager).`when`(context).packageManager
+ }
@Test
fun testEnforceAnyPermissionOf() {
@@ -90,4 +102,26 @@
assertFailsWith<SecurityException>("Expect fail but permission granted.") {
enforceNetworkStackPermissionOr(context, TEST_PERMISSION2) }
}
+
+ private fun mockHasSystemFeature(featureName: String, hasFeature: Boolean) {
+ doReturn(hasFeature).`when`(packageManager)
+ .hasSystemFeature(ArgumentMatchers.eq(featureName))
+ }
+
+ @Test
+ fun testEnforceSystemFeature() {
+ val systemFeature = "test.system.feature"
+ val exceptionMessage = "test exception message"
+ mockHasSystemFeature(featureName = systemFeature, hasFeature = false)
+ val e = assertFailsWith<UnsupportedOperationException>("Should fail without feature") {
+ enforceSystemFeature(context, systemFeature, exceptionMessage) }
+ assertEquals(exceptionMessage, e.message)
+
+ mockHasSystemFeature(featureName = systemFeature, hasFeature = true)
+ try {
+ enforceSystemFeature(context, systemFeature, "")
+ } catch (e: UnsupportedOperationException) {
+ Assert.fail("Exception should have not been thrown with system feature enabled")
+ }
+ }
}
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java
index eabc14b..4e46210 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import android.annotation.SuppressLint;
import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.MacAddress;
@@ -453,6 +454,7 @@
}
}
+ @SuppressLint("NewApi")
private void verifyPrefixByteArrayParsing(final PrefixMessage msg) throws Exception {
// The original PREF64 option message has just 12 bytes for prefix byte array
// (Highest 96 bits of the Prefix), copyOf pads the 128-bits IPv6 address with
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/StructNdOptPref64Test.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/StructNdOptPref64Test.java
index 57248ea..beed838 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/StructNdOptPref64Test.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/StructNdOptPref64Test.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import android.annotation.SuppressLint;
import android.net.IpPrefix;
import androidx.test.filters.SmallTest;
@@ -51,6 +52,7 @@
return prefixBytes;
}
+ @SuppressLint("NewApi")
private static IpPrefix prefix(String addrString, int prefixLength) throws Exception {
return new IpPrefix(InetAddress.getByName(addrString), prefixLength);
}