Merge "Fix kotlin nullable errors in net-test-utils and NetworkStaticLibTests" into main
diff --git a/staticlibs/device/com/android/net/module/util/BpfMap.java b/staticlibs/device/com/android/net/module/util/BpfMap.java
index 9df2b03..d45cace 100644
--- a/staticlibs/device/com/android/net/module/util/BpfMap.java
+++ b/staticlibs/device/com/android/net/module/util/BpfMap.java
@@ -194,9 +194,11 @@
}
private K getNextKeyInternal(@Nullable K key) throws ErrnoException {
- final byte[] rawKey = getNextRawKey(
- key == null ? null : key.writeToBytes());
- if (rawKey == null) return null;
+ byte[] rawKey = new byte[mKeySize];
+
+ if (!nativeGetNextMapKey(mMapFd.getFd(),
+ key == null ? null : key.writeToBytes(),
+ rawKey)) return null;
final ByteBuffer buffer = ByteBuffer.wrap(rawKey);
buffer.order(ByteOrder.nativeOrder());
@@ -215,13 +217,6 @@
return getNextKeyInternal(key);
}
- private byte[] getNextRawKey(@Nullable final byte[] key) throws ErrnoException {
- byte[] nextKey = new byte[mKeySize];
- if (nativeGetNextMapKey(mMapFd.getFd(), key, nextKey)) return nextKey;
-
- return null;
- }
-
/** Get the first key of eBpf map. */
@Override
public K getFirstKey() throws ErrnoException {
@@ -233,30 +228,23 @@
public boolean containsKey(@NonNull K key) throws ErrnoException {
Objects.requireNonNull(key);
- final byte[] rawValue = getRawValue(key.writeToBytes());
- return rawValue != null;
+ byte[] rawValue = new byte[mValueSize];
+ return nativeFindMapEntry(mMapFd.getFd(), key.writeToBytes(), rawValue);
}
/** Retrieve a value from the map. Return null if there is no such key. */
@Override
public V getValue(@NonNull K key) throws ErrnoException {
Objects.requireNonNull(key);
- final byte[] rawValue = getRawValue(key.writeToBytes());
- if (rawValue == null) return null;
+ byte[] rawValue = new byte[mValueSize];
+ if (!nativeFindMapEntry(mMapFd.getFd(), key.writeToBytes(), rawValue)) return null;
final ByteBuffer buffer = ByteBuffer.wrap(rawValue);
buffer.order(ByteOrder.nativeOrder());
return Struct.parse(mValueClass, buffer);
}
- private byte[] getRawValue(final byte[] key) throws ErrnoException {
- byte[] value = new byte[mValueSize];
- if (nativeFindMapEntry(mMapFd.getFd(), key, value)) return value;
-
- return null;
- }
-
/**
* Iterate through the map and handle each key -> value retrieved base on the given BiConsumer.
* The given BiConsumer may to delete the passed-in entry, but is not allowed to perform any
diff --git a/staticlibs/device/com/android/net/module/util/DeviceConfigUtils.java b/staticlibs/device/com/android/net/module/util/DeviceConfigUtils.java
index bea227d..caa2b05 100644
--- a/staticlibs/device/com/android/net/module/util/DeviceConfigUtils.java
+++ b/staticlibs/device/com/android/net/module/util/DeviceConfigUtils.java
@@ -207,8 +207,9 @@
* null.
* @return true if this feature is enabled, or false if disabled.
*/
- public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace,
- @NonNull String name, @NonNull String moduleName, boolean defaultEnabled) {
+ public static boolean isTetheringFeatureEnabled(@NonNull Context context,
+ @NonNull String namespace, @NonNull String name, @NonNull String moduleName,
+ boolean defaultEnabled) {
// TODO: migrate callers to a non-generic isTetheringFeatureEnabled method.
if (!TETHERING_MODULE_NAME.equals(moduleName)) {
throw new IllegalArgumentException(
@@ -335,15 +336,19 @@
/**
* Check whether one specific experimental feature in tethering module from {@link DeviceConfig}
- * is disabled by setting a non-zero value in the property.
+ * is not disabled. Feature can be disabled by setting a non-zero value in the property.
+ * If the feature is enabled by default and disabled by flag push (kill switch), this method
+ * should be used.
+ * If the feature is disabled by default and enabled by flag push,
+ * {@link #isTetheringFeatureEnabled} should be used.
*
* @param name The name of the property to look up.
- * @return true if this feature is force disabled, or false if not disabled.
+ * @return true if this feature is enabled, or false if disabled.
*/
- public static boolean isTetheringFeatureForceDisabled(String name) {
+ public static boolean isTetheringFeatureNotChickenedOut(String name) {
final int propertyVersion = getDeviceConfigPropertyInt(NAMESPACE_TETHERING, name,
0 /* default value */);
- return propertyVersion != 0;
+ return propertyVersion == 0;
}
/**
diff --git a/staticlibs/device/com/android/net/module/util/FeatureVersions.java b/staticlibs/device/com/android/net/module/util/FeatureVersions.java
index 4986a58..149756c 100644
--- a/staticlibs/device/com/android/net/module/util/FeatureVersions.java
+++ b/staticlibs/device/com/android/net/module/util/FeatureVersions.java
@@ -22,13 +22,24 @@
* @hide
*/
public class FeatureVersions {
- public static final long MODULE_MASK = 0xFF00_000000000L;
- public static final long VERSION_MASK = 0x0000_FFFFFFFFFL;
- public static final long CONNECTIVITY_MODULE_ID = 0x0100_000000000L;
- public static final long NETWORK_STACK_MODULE_ID = 0x0200_000000000L;
+ /**
+ * This constant is used to do bitwise shift operation to create module ids.
+ * The module version is composed with 9 digits which is placed in the lower 36 bits.
+ */
+ private static final int MODULE_SHIFT = 36;
+ /**
+ * The bitmask to do bitwise-and(i.e. {@code &}) operation to get the module id.
+ */
+ public static final long MODULE_MASK = 0xFF0_0000_0000L;
+ /**
+ * The bitmask to do bitwise-and(i.e. {@code &}) operation to get the module version.
+ */
+ public static final long VERSION_MASK = 0x00F_FFFF_FFFFL;
+ public static final long CONNECTIVITY_MODULE_ID = 0x01L << MODULE_SHIFT;
+ public static final long NETWORK_STACK_MODULE_ID = 0x02L << MODULE_SHIFT;
// CLAT_ADDRESS_TRANSLATE is a feature of the network stack, which doesn't throw when system
// try to add a NAT-T keepalive packet filter with v6 address, introduced in version
// M-2023-Sept on July 3rd, 2023.
public static final long FEATURE_CLAT_ADDRESS_TRANSLATE =
- NETWORK_STACK_MODULE_ID + 340900000L;
+ NETWORK_STACK_MODULE_ID + 34_09_00_000L;
}
diff --git a/staticlibs/device/com/android/net/module/util/SharedLog.java b/staticlibs/device/com/android/net/module/util/SharedLog.java
index 17b061e..6b12c80 100644
--- a/staticlibs/device/com/android/net/module/util/SharedLog.java
+++ b/staticlibs/device/com/android/net/module/util/SharedLog.java
@@ -46,6 +46,8 @@
ERROR,
MARK,
WARN,
+ VERBOSE,
+ TERRIBLE,
}
private final LocalLog mLocalLog;
@@ -159,6 +161,41 @@
Log.w(mTag, record(Category.WARN, msg));
}
+ /**
+ * Log a verbose message.
+ *
+ * <p>The log entry will be also added to the system log.
+ */
+ public void v(String msg) {
+ Log.v(mTag, record(Category.VERBOSE, msg));
+ }
+
+ /**
+ * Log a terrible failure message.
+ *
+ * <p>The log entry will be also added to the system log and will trigger system reporting
+ * for terrible failures.
+ */
+ public void wtf(String msg) {
+ Log.wtf(mTag, record(Category.TERRIBLE, msg));
+ }
+
+ /**
+ * Log a terrible failure due to an exception, with the exception stacktrace if provided.
+ *
+ * <p>The error and exception message appear in the shared log, but the stacktrace is only
+ * logged in general log output (logcat). The log entry will be also added to the system log
+ * and will trigger system reporting for terrible failures.
+ */
+ public void wtf(@NonNull String msg, @Nullable Throwable exception) {
+ if (exception == null) {
+ e(msg);
+ return;
+ }
+ Log.wtf(mTag, record(Category.TERRIBLE, msg + ": " + exception.getMessage()), exception);
+ }
+
+
//////
// Methods that only log an entry (and do NOT emit to the system log).
//////
diff --git a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
index 24aabbc..9149160 100644
--- a/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
+++ b/staticlibs/framework/com/android/net/module/util/NetworkStackConstants.java
@@ -17,6 +17,7 @@
package com.android.net.module.util;
import android.net.InetAddresses;
+import android.net.IpPrefix;
import java.net.Inet4Address;
import java.net.Inet6Address;
@@ -99,6 +100,8 @@
public static final int IPV4_ADDR_LEN = 4;
public static final int IPV4_FLAG_MF = 0x2000;
public static final int IPV4_FLAG_DF = 0x4000;
+ // getSockOpt() for v4 MTU
+ public static final int IP_MTU = 14;
public static final Inet4Address IPV4_ADDR_ALL = makeInet4Address(
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff);
public static final Inet4Address IPV4_ADDR_ANY = makeInet4Address(
@@ -108,6 +111,12 @@
(byte) 0, (byte) 0, (byte) 0, (byte) 0,
(byte) 0, (byte) 0, (byte) 0, (byte) 0,
(byte) 0, (byte) 0, (byte) 0, (byte) 0 });
+
+ /**
+ * CLAT constants
+ */
+ public static final IpPrefix CLAT_PREFIX = new IpPrefix("192.0.0.0/29");
+
/**
* IPv6 constants.
*
@@ -121,6 +130,10 @@
public static final int IPV6_SRC_ADDR_OFFSET = 8;
public static final int IPV6_DST_ADDR_OFFSET = 24;
public static final int IPV6_MIN_MTU = 1280;
+ public static final int IPV6_FRAGMENT_HEADER_LEN = 8;
+ public static final int RFC7421_PREFIX_LENGTH = 64;
+ // getSockOpt() for v6 MTU
+ public static final int IPV6_MTU = 24;
public static final Inet6Address IPV6_ADDR_ALL_NODES_MULTICAST =
(Inet6Address) InetAddresses.parseNumericAddress("ff02::1");
public static final Inet6Address IPV6_ADDR_ALL_ROUTERS_MULTICAST =
diff --git a/staticlibs/lint-baseline.xml b/staticlibs/lint-baseline.xml
new file mode 100644
index 0000000..d413b2a
--- /dev/null
+++ b/staticlibs/lint-baseline.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 30 (current min is 29): `android.net.LinkProperties#getAddresses`"
+ errorLine1=" final Collection<InetAddress> leftAddresses = left.getAddresses();"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/libs/net/common/framework/com/android/net/module/util/LinkPropertiesUtils.java"
+ line="158"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 30 (current min is 29): `android.net.LinkProperties#getAddresses`"
+ errorLine1=" final Collection<InetAddress> rightAddresses = right.getAddresses();"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/libs/net/common/framework/com/android/net/module/util/LinkPropertiesUtils.java"
+ line="159"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 30 (current min is 29): `android.net.NetworkStats#addEntry`"
+ errorLine1=" stats = stats.addEntry(entry);"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/libs/net/common/framework/com/android/net/module/util/NetworkStatsUtils.java"
+ line="113"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 30 (current min is 29): `new android.net.NetworkStats.Entry`"
+ errorLine1=" return new android.net.NetworkStats.Entry("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/libs/net/common/framework/com/android/net/module/util/NetworkStatsUtils.java"
+ line="120"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 30 (current min is 29): `new android.net.NetworkStats`"
+ errorLine1=" android.net.NetworkStats stats = new android.net.NetworkStats(0L, 0);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/libs/net/common/framework/com/android/net/module/util/NetworkStatsUtils.java"
+ line="108"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 29): `new android.system.NetlinkSocketAddress`"
+ errorLine1=" return new NetlinkSocketAddress(portId, groupsMask);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/libs/net/common/device/com/android/net/module/util/SocketUtils.java"
+ line="44"
+ column="16"/>
+ </issue>
+
+</issues>
\ No newline at end of file
diff --git a/staticlibs/native/bpf_headers/include/bpf/BpfMap.h b/staticlibs/native/bpf_headers/include/bpf/BpfMap.h
index 51e6d16..d0c3b45 100644
--- a/staticlibs/native/bpf_headers/include/bpf/BpfMap.h
+++ b/staticlibs/native/bpf_headers/include/bpf/BpfMap.h
@@ -29,6 +29,10 @@
namespace android {
namespace bpf {
+using base::Result;
+using base::unique_fd;
+using std::function;
+
// This is a class wrapper for eBPF maps. The eBPF map is a special in-kernel
// data structure that stores data in <Key, Value> pairs. It can be read/write
// from userspace by passing syscalls with the map file descriptor. This class
@@ -80,7 +84,7 @@
}
#endif
- base::Result<Key> getFirstKey() const {
+ Result<Key> getFirstKey() const {
Key firstKey;
if (getFirstMapKey(mMapFd, &firstKey)) {
return ErrnoErrorf("Get firstKey map {} failed", mMapFd.get());
@@ -88,7 +92,7 @@
return firstKey;
}
- base::Result<Key> getNextKey(const Key& key) const {
+ Result<Key> getNextKey(const Key& key) const {
Key nextKey;
if (getNextMapKey(mMapFd, &key, &nextKey)) {
return ErrnoErrorf("Get next key of map {} failed", mMapFd.get());
@@ -96,14 +100,14 @@
return nextKey;
}
- base::Result<void> writeValue(const Key& key, const Value& value, uint64_t flags) {
+ Result<void> writeValue(const Key& key, const Value& value, uint64_t flags) {
if (writeToMapEntry(mMapFd, &key, &value, flags)) {
return ErrnoErrorf("Write to map {} failed", mMapFd.get());
}
return {};
}
- base::Result<Value> readValue(const Key key) const {
+ Result<Value> readValue(const Key key) const {
Value value;
if (findMapEntry(mMapFd, &key, &value)) {
return ErrnoErrorf("Read value of map {} failed", mMapFd.get());
@@ -111,7 +115,7 @@
return value;
}
- base::Result<void> deleteValue(const Key& key) {
+ Result<void> deleteValue(const Key& key) {
if (deleteMapEntry(mMapFd, &key)) {
return ErrnoErrorf("Delete entry from map {} failed", mMapFd.get());
}
@@ -119,7 +123,7 @@
}
protected:
- [[clang::reinitializes]] base::Result<void> init(const char* path, int fd) {
+ [[clang::reinitializes]] Result<void> init(const char* path, int fd) {
mMapFd.reset(fd);
if (!mMapFd.ok()) {
return ErrnoErrorf("Pinned map not accessible or does not exist: ({})", path);
@@ -134,7 +138,7 @@
public:
// Function that tries to get map from a pinned path.
- [[clang::reinitializes]] base::Result<void> init(const char* path) {
+ [[clang::reinitializes]] Result<void> init(const char* path) {
return init(path, mapRetrieveRW(path));
}
@@ -144,7 +148,7 @@
// this should only ever be used by test code, it is equivalent to:
// .reset(createMap(type, keysize, valuesize, max_entries, map_flags)
// TODO: derive map_flags from BpfMap vs BpfMapRO
- [[clang::reinitializes]] base::Result<void> resetMap(bpf_map_type map_type,
+ [[clang::reinitializes]] Result<void> resetMap(bpf_map_type map_type,
uint32_t max_entries,
uint32_t map_flags = 0) {
mMapFd.reset(createMap(map_type, sizeof(Key), sizeof(Value), max_entries, map_flags));
@@ -155,28 +159,28 @@
// Iterate through the map and handle each key retrieved based on the filter
// without modification of map content.
- base::Result<void> iterate(
- const std::function<base::Result<void>(const Key& key, const BpfMap<Key, Value>& map)>&
- filter) const;
+ Result<void> iterate(
+ const function<Result<void>(const Key& key,
+ const BpfMap<Key, Value>& map)>& filter) const;
// Iterate through the map and get each <key, value> pair, handle each <key,
// value> pair based on the filter without modification of map content.
- base::Result<void> iterateWithValue(
- const std::function<base::Result<void>(const Key& key, const Value& value,
- const BpfMap<Key, Value>& map)>& filter) const;
+ Result<void> iterateWithValue(
+ const function<Result<void>(const Key& key, const Value& value,
+ const BpfMap<Key, Value>& map)>& filter) const;
// Iterate through the map and handle each key retrieved based on the filter
- base::Result<void> iterate(
- const std::function<base::Result<void>(const Key& key, BpfMap<Key, Value>& map)>&
- filter);
+ Result<void> iterate(
+ const function<Result<void>(const Key& key,
+ BpfMap<Key, Value>& map)>& filter);
// Iterate through the map and get each <key, value> pair, handle each <key,
// value> pair based on the filter.
- base::Result<void> iterateWithValue(
- const std::function<base::Result<void>(const Key& key, const Value& value,
- BpfMap<Key, Value>& map)>& filter);
+ Result<void> iterateWithValue(
+ const function<Result<void>(const Key& key, const Value& value,
+ BpfMap<Key, Value>& map)>& filter);
- const base::unique_fd& getMap() const { return mMapFd; };
+ const unique_fd& getMap() const { return mMapFd; };
#ifdef BPF_MAP_MAKE_VISIBLE_FOR_TESTING
// Copy assignment operator - due to need for fd duping, should not be used in non-test code.
@@ -197,7 +201,7 @@
return *this;
}
- void reset(base::unique_fd fd) = delete;
+ void reset(unique_fd fd) = delete;
#ifdef BPF_MAP_MAKE_VISIBLE_FOR_TESTING
// Note that unique_fd.reset() carefully saves and restores the errno,
@@ -216,7 +220,7 @@
bool isValid() const { return mMapFd.ok(); }
- base::Result<void> clear() {
+ Result<void> clear() {
while (true) {
auto key = getFirstKey();
if (!key.ok()) {
@@ -233,28 +237,25 @@
}
}
- base::Result<bool> isEmpty() const {
+ Result<bool> isEmpty() const {
auto key = getFirstKey();
- if (!key.ok()) {
- // Return error code ENOENT means the map is empty
- if (key.error().code() == ENOENT) return true;
- return key.error();
- }
- return false;
+ if (key.ok()) return false;
+ if (key.error().code() == ENOENT) return true;
+ return key.error();
}
private:
- base::unique_fd mMapFd;
+ unique_fd mMapFd;
};
template <class Key, class Value>
-base::Result<void> BpfMap<Key, Value>::iterate(
- const std::function<base::Result<void>(const Key& key, const BpfMap<Key, Value>& map)>&
- filter) const {
- base::Result<Key> curKey = getFirstKey();
+Result<void> BpfMap<Key, Value>::iterate(
+ const function<Result<void>(const Key& key,
+ const BpfMap<Key, Value>& map)>& filter) const {
+ Result<Key> curKey = getFirstKey();
while (curKey.ok()) {
- const base::Result<Key>& nextKey = getNextKey(curKey.value());
- base::Result<void> status = filter(curKey.value(), *this);
+ const Result<Key>& nextKey = getNextKey(curKey.value());
+ Result<void> status = filter(curKey.value(), *this);
if (!status.ok()) return status;
curKey = nextKey;
}
@@ -263,15 +264,15 @@
}
template <class Key, class Value>
-base::Result<void> BpfMap<Key, Value>::iterateWithValue(
- const std::function<base::Result<void>(const Key& key, const Value& value,
- const BpfMap<Key, Value>& map)>& filter) const {
- base::Result<Key> curKey = getFirstKey();
+Result<void> BpfMap<Key, Value>::iterateWithValue(
+ const function<Result<void>(const Key& key, const Value& value,
+ const BpfMap<Key, Value>& map)>& filter) const {
+ Result<Key> curKey = getFirstKey();
while (curKey.ok()) {
- const base::Result<Key>& nextKey = getNextKey(curKey.value());
- base::Result<Value> curValue = readValue(curKey.value());
+ const Result<Key>& nextKey = getNextKey(curKey.value());
+ Result<Value> curValue = readValue(curKey.value());
if (!curValue.ok()) return curValue.error();
- base::Result<void> status = filter(curKey.value(), curValue.value(), *this);
+ Result<void> status = filter(curKey.value(), curValue.value(), *this);
if (!status.ok()) return status;
curKey = nextKey;
}
@@ -280,12 +281,13 @@
}
template <class Key, class Value>
-base::Result<void> BpfMap<Key, Value>::iterate(
- const std::function<base::Result<void>(const Key& key, BpfMap<Key, Value>& map)>& filter) {
- base::Result<Key> curKey = getFirstKey();
+Result<void> BpfMap<Key, Value>::iterate(
+ const function<Result<void>(const Key& key,
+ BpfMap<Key, Value>& map)>& filter) {
+ Result<Key> curKey = getFirstKey();
while (curKey.ok()) {
- const base::Result<Key>& nextKey = getNextKey(curKey.value());
- base::Result<void> status = filter(curKey.value(), *this);
+ const Result<Key>& nextKey = getNextKey(curKey.value());
+ Result<void> status = filter(curKey.value(), *this);
if (!status.ok()) return status;
curKey = nextKey;
}
@@ -294,15 +296,15 @@
}
template <class Key, class Value>
-base::Result<void> BpfMap<Key, Value>::iterateWithValue(
- const std::function<base::Result<void>(const Key& key, const Value& value,
- BpfMap<Key, Value>& map)>& filter) {
- base::Result<Key> curKey = getFirstKey();
+Result<void> BpfMap<Key, Value>::iterateWithValue(
+ const function<Result<void>(const Key& key, const Value& value,
+ BpfMap<Key, Value>& map)>& filter) {
+ Result<Key> curKey = getFirstKey();
while (curKey.ok()) {
- const base::Result<Key>& nextKey = getNextKey(curKey.value());
- base::Result<Value> curValue = readValue(curKey.value());
+ const Result<Key>& nextKey = getNextKey(curKey.value());
+ Result<Value> curValue = readValue(curKey.value());
if (!curValue.ok()) return curValue.error();
- base::Result<void> status = filter(curKey.value(), curValue.value(), *this);
+ Result<void> status = filter(curKey.value(), curValue.value(), *this);
if (!status.ok()) return status;
curKey = nextKey;
}
@@ -319,7 +321,7 @@
: BpfMap<Key, Value>(pathname, BPF_F_RDONLY) {}
// Function that tries to get map from a pinned path.
- [[clang::reinitializes]] base::Result<void> init(const char* path) {
+ [[clang::reinitializes]] Result<void> init(const char* path) {
return BpfMap<Key,Value>::init(path, mapRetrieveRO(path));
}
};
diff --git a/staticlibs/netd/Android.bp b/staticlibs/netd/Android.bp
index 525160d..d135a1c 100644
--- a/staticlibs/netd/Android.bp
+++ b/staticlibs/netd/Android.bp
@@ -187,7 +187,7 @@
srcs: [
"binder/android/net/metrics/INetdEventListener.aidl",
],
- versions: ["1"],
+
backend: {
ndk: {
apex_available: [
@@ -205,6 +205,19 @@
min_sdk_version: "29",
},
},
+ versions_with_info: [
+ {
+ version: "1",
+ imports: [],
+ },
+ {
+ version: "2",
+ imports: [],
+ },
+
+ ],
+ frozen: true,
+
}
java_library {
diff --git a/staticlibs/netd/aidl_api/netd_event_listener_interface/2/.hash b/staticlibs/netd/aidl_api/netd_event_listener_interface/2/.hash
new file mode 100644
index 0000000..67c55b7
--- /dev/null
+++ b/staticlibs/netd/aidl_api/netd_event_listener_interface/2/.hash
@@ -0,0 +1 @@
+1b765b02815e970a124de92e793e42e0ceff5384
diff --git a/staticlibs/netd/aidl_api/netd_event_listener_interface/2/android/net/metrics/INetdEventListener.aidl b/staticlibs/netd/aidl_api/netd_event_listener_interface/2/android/net/metrics/INetdEventListener.aidl
new file mode 100644
index 0000000..1b0fe13
--- /dev/null
+++ b/staticlibs/netd/aidl_api/netd_event_listener_interface/2/android/net/metrics/INetdEventListener.aidl
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2016, 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.metrics;
+/* @hide */
+interface INetdEventListener {
+ oneway void onDnsEvent(int netId, int eventType, int returnCode, int latencyMs, @utf8InCpp String hostname, in @utf8InCpp String[] ipAddresses, int ipAddressesCount, int uid);
+ oneway void onPrivateDnsValidationEvent(int netId, String ipAddress, String hostname, boolean validated);
+ oneway void onConnectEvent(int netId, int error, int latencyMs, String ipAddr, int port, int uid);
+ oneway void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader, in byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs);
+ oneway void onTcpSocketStatsEvent(in int[] networkIds, in int[] sentPackets, in int[] lostPackets, in int[] rttUs, in int[] sentAckDiffMs);
+ oneway void onNat64PrefixEvent(int netId, boolean added, @utf8InCpp String prefixString, int prefixLength);
+ const int EVENT_GETADDRINFO = 1;
+ const int EVENT_GETHOSTBYNAME = 2;
+ const int EVENT_GETHOSTBYADDR = 3;
+ const int EVENT_RES_NSEND = 4;
+ const int REPORTING_LEVEL_NONE = 0;
+ const int REPORTING_LEVEL_METRICS = 1;
+ const int REPORTING_LEVEL_FULL = 2;
+ const int DNS_REPORTED_IP_ADDRESSES_LIMIT = 10;
+}
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/DeviceConfigUtilsTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/DeviceConfigUtilsTest.java
index 7946244..e80fa80 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/DeviceConfigUtilsTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/DeviceConfigUtilsTest.java
@@ -233,7 +233,7 @@
eq(TEST_EXPERIMENT_FLAG)));
assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
}
@@ -243,9 +243,9 @@
eq(TEST_EXPERIMENT_FLAG)));
assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG));
- assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertFalse(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, true /* defaultEnabled */));
}
@@ -258,7 +258,7 @@
eq(TEST_EXPERIMENT_FLAG)));
assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
// Feature should be disabled by flag value "999999999".
@@ -266,7 +266,7 @@
eq(TEST_EXPERIMENT_FLAG)));
assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG));
- assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertFalse(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
// Follow defaultEnabled if the flag is not set
@@ -276,9 +276,9 @@
TEST_EXPERIMENT_FLAG, false /* defaultEnabled */));
assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, true /* defaultEnabled */));
- assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertFalse(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, true /* defaultEnabled */));
}
@@ -293,14 +293,14 @@
assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG));
- assertFalse(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertFalse(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, true /* defaultEnabled */));
doReturn(TEST_FLAG_VALUE_STRING).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
eq(TEST_EXPERIMENT_FLAG)));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
}
@@ -323,9 +323,9 @@
public void testFeatureIsEnabledCaching_APEX() throws Exception {
doReturn(TEST_FLAG_VALUE_STRING).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
eq(TEST_EXPERIMENT_FLAG)));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
- assertTrue(DeviceConfigUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ assertTrue(DeviceConfigUtils.isTetheringFeatureEnabled(mContext, TEST_NAME_SPACE,
TEST_EXPERIMENT_FLAG, TEST_APEX_NAME, false /* defaultEnabled */));
// Package info is only queried once
@@ -424,10 +424,10 @@
public void testIsTetheringFeatureForceDisabled() throws Exception {
doReturn("0").when(() -> DeviceConfig.getProperty(
eq(NAMESPACE_TETHERING), eq(TEST_EXPERIMENT_FLAG)));
- assertFalse(DeviceConfigUtils.isTetheringFeatureForceDisabled(TEST_EXPERIMENT_FLAG));
+ assertTrue(DeviceConfigUtils.isTetheringFeatureNotChickenedOut(TEST_EXPERIMENT_FLAG));
doReturn(TEST_FLAG_VALUE_STRING).when(
() -> DeviceConfig.getProperty(eq(NAMESPACE_TETHERING), eq(TEST_EXPERIMENT_FLAG)));
- assertTrue(DeviceConfigUtils.isTetheringFeatureForceDisabled(TEST_EXPERIMENT_FLAG));
+ assertFalse(DeviceConfigUtils.isTetheringFeatureNotChickenedOut(TEST_EXPERIMENT_FLAG));
}
}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
index 21e84da..35f22b9 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
@@ -19,11 +19,11 @@
import android.os.Build
import androidx.test.InstrumentationRegistry
import com.android.modules.utils.build.UnboundedSdkLevel
+import java.util.regex.Pattern
import org.junit.Assume.assumeTrue
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
-import java.util.regex.Pattern
@Deprecated("Use Build.VERSION_CODES", ReplaceWith("Build.VERSION_CODES.S_V2"))
const val SC_V2 = Build.VERSION_CODES.S_V2
@@ -32,8 +32,22 @@
private val targetSdk = InstrumentationRegistry.getContext().applicationInfo.targetSdkVersion
private fun isDevSdkInRange(minExclusive: String?, maxInclusive: String?): Boolean {
- return (minExclusive == null || !UnboundedSdkLevel.isAtMost(minExclusive)) &&
- (maxInclusive == null || UnboundedSdkLevel.isAtMost(maxInclusive))
+ return (minExclusive == null || !isAtMost(minExclusive)) &&
+ (maxInclusive == null || isAtMost(maxInclusive))
+}
+
+private fun isAtMost(sdkVersionOrCodename: String): Boolean {
+ // UnboundedSdkLevel does not support builds < Q, and may stop supporting Q as well since it
+ // is intended for mainline modules that are now R+.
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
+ // Assume that any codename passed as argument from current code is a more recent build than
+ // Q: this util did not exist before Q, and codenames are only used before the corresponding
+ // build is finalized. This util could list 28 older codenames to check against (as per
+ // ro.build.version.known_codenames in more recent builds), but this does not seem valuable.
+ val intVersion = sdkVersionOrCodename.toIntOrNull() ?: return true
+ return Build.VERSION.SDK_INT <= intVersion
+ }
+ return UnboundedSdkLevel.isAtMost(sdkVersionOrCodename)
}
/**
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
index 4b6aea2..df9c61a 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/TestableNetworkCallback.kt
@@ -389,7 +389,8 @@
from: Int = mark,
crossinline predicate: (T) -> Boolean = { true }
): T = history.poll(timeoutMs, from) { it is T && predicate(it) }.also {
- assertNotNull(it, "Callback ${T::class} not received within ${timeoutMs}ms")
+ assertNotNull(it, "Callback ${T::class} not received within ${timeoutMs}ms. " +
+ "Got ${history.backtrace()}")
} as T
@JvmOverloads
@@ -398,7 +399,8 @@
timeoutMs: Long = defaultTimeoutMs,
predicate: (cb: T) -> Boolean = { true }
) = history.poll(timeoutMs) { type.java.isInstance(it) && predicate(it as T) }.also {
- assertNotNull(it, "Callback ${type.java} not received within ${timeoutMs}ms")
+ assertNotNull(it, "Callback ${type.java} not received within ${timeoutMs}ms. " +
+ "Got ${history.backtrace()}")
} as T
fun <T : CallbackEntry> eventuallyExpect(
@@ -407,7 +409,8 @@
from: Int = mark,
predicate: (cb: T) -> Boolean = { true }
) = history.poll(timeoutMs, from) { type.java.isInstance(it) && predicate(it as T) }.also {
- assertNotNull(it, "Callback ${type.java} not received within ${timeoutMs}ms")
+ assertNotNull(it, "Callback ${type.java} not received within ${timeoutMs}ms. " +
+ "Got ${history.backtrace()}")
} as T
// Expects onAvailable and the callbacks that follow it. These are:
diff --git a/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt b/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt
index efd77d1..f24e4f1 100644
--- a/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt
+++ b/staticlibs/testutils/hostdevice/com/android/net/module/util/TrackRecord.kt
@@ -213,6 +213,9 @@
private val slock = StampedLock()
private var readHead = 0
+ // A special mark used to track the start of the last poll() operation.
+ private var pollMark = 0
+
/**
* @return the current value of the mark.
*/
@@ -223,6 +226,7 @@
val stamp = slock.tryWriteLock()
if (0L == stamp) concurrentAccessDetected()
readHead = v
+ pollMark = v
slock.unlockWrite(stamp)
}
@@ -261,6 +265,7 @@
fun poll(timeoutMs: Long, predicate: (E) -> Boolean = { true }): E? {
val stamp = slock.tryWriteLock()
if (0L == stamp) concurrentAccessDetected()
+ pollMark = readHead
try {
lock.withLock {
val index = pollForIndexReadLocked(timeoutMs, readHead, predicate)
@@ -273,6 +278,25 @@
}
/**
+ * Returns a list of events that were observed since the last time poll() was called on this
+ * ReadHead.
+ *
+ * @return list of events since poll() was called.
+ */
+ fun backtrace(): List<E> {
+ val stamp = slock.tryReadLock()
+ if (0L == stamp) concurrentAccessDetected()
+
+ try {
+ lock.withLock {
+ return ArrayList(subList(pollMark, mark))
+ }
+ } finally {
+ slock.unlockRead(stamp)
+ }
+ }
+
+ /**
* Returns the first element after the mark or null. This never blocks.
*
* This method is subject to threading restrictions. It can be used concurrently on