Merge "Log legacy tether() calls that succeeded" into main
diff --git a/bpf/loader/NetBpfLoad.cpp b/bpf/loader/NetBpfLoad.cpp
index 3dabd90..038786c 100644
--- a/bpf/loader/NetBpfLoad.cpp
+++ b/bpf/loader/NetBpfLoad.cpp
@@ -1409,17 +1409,15 @@
//
// Also note that 'android_get_device_api_level()' is what the
// //system/core/init/apex_init_util.cpp
- // apex init .XXrc parsing code uses for XX filtering.
- //
- // That code has a hack to bump <35 to 35 (to force aosp/main to parse .35rc),
- // but could (should?) perhaps be adjusted to match this.
- const int effective_api_level = android_get_device_api_level() + (int)unreleased;
- const bool isAtLeastT = (effective_api_level >= __ANDROID_API_T__);
- const bool isAtLeastU = (effective_api_level >= __ANDROID_API_U__);
- const bool isAtLeastV = (effective_api_level >= __ANDROID_API_V__);
- const bool isAtLeast25Q2 = (effective_api_level > __ANDROID_API_V__); // TODO: fix >
+ // apex init .XXrc parsing code uses for XX filtering, and that code
+ // (now) similarly uses __ANDROID_API_FUTURE__ for non 'REL' codenames.
+ const int api_level = unreleased ? __ANDROID_API_FUTURE__ : android_get_device_api_level();
+ const bool isAtLeastT = (api_level >= __ANDROID_API_T__);
+ const bool isAtLeastU = (api_level >= __ANDROID_API_U__);
+ const bool isAtLeastV = (api_level >= __ANDROID_API_V__);
+ const bool isAtLeast25Q2 = (api_level > __ANDROID_API_V__); // TODO: fix >
- const int first_api_level = GetIntProperty("ro.board.first_api_level", effective_api_level);
+ const int first_api_level = GetIntProperty("ro.board.first_api_level", api_level);
// last in U QPR2 beta1
const bool has_platform_bpfloader_rc = exists("/system/etc/init/bpfloader.rc");
@@ -1435,7 +1433,7 @@
if (isAtLeast25Q2) ++bpfloader_ver; // [47] BPFLOADER_MAINLINE_25Q2_VERSION
ALOGI("NetBpfLoad v0.%u (%s) api:%d/%d kver:%07x (%s) uid:%d rc:%d%d",
- bpfloader_ver, argv[0], android_get_device_api_level(), effective_api_level,
+ bpfloader_ver, argv[0], android_get_device_api_level(), api_level,
kernelVersion(), describeArch(), getuid(),
has_platform_bpfloader_rc, has_platform_netbpfload_rc);
@@ -1475,7 +1473,7 @@
return 1;
}
- // W bumps the kernel requirement up to 5.4
+ // 25Q2 bumps the kernel requirement up to 5.4
// see also: //system/netd/tests/kernel_test.cpp TestKernel54
if (isAtLeast25Q2 && !isAtLeastKernelVersion(5, 4, 0)) {
ALOGE("Android 25Q2 requires kernel 5.4.");
diff --git a/framework/src/android/net/L2capNetworkSpecifier.java b/framework/src/android/net/L2capNetworkSpecifier.java
index 3c95dd0..cfc9ed9 100644
--- a/framework/src/android/net/L2capNetworkSpecifier.java
+++ b/framework/src/android/net/L2capNetworkSpecifier.java
@@ -308,6 +308,41 @@
&& mPsm == rhs.mPsm;
}
+ /** @hide */
+ @Override
+ public String toString() {
+ final String role;
+ switch (mRole) {
+ case ROLE_CLIENT:
+ role = "ROLE_CLIENT";
+ break;
+ case ROLE_SERVER:
+ role = "ROLE_SERVER";
+ break;
+ default:
+ role = "ROLE_ANY";
+ break;
+ }
+
+ final String headerCompression;
+ switch (mHeaderCompression) {
+ case HEADER_COMPRESSION_NONE:
+ headerCompression = "HEADER_COMPRESSION_NONE";
+ break;
+ case HEADER_COMPRESSION_6LOWPAN:
+ headerCompression = "HEADER_COMPRESSION_6LOWPAN";
+ break;
+ default:
+ headerCompression = "HEADER_COMPRESSION_ANY";
+ break;
+ }
+
+ final String psm = (mPsm == PSM_ANY) ? "PSM_ANY" : String.valueOf(mPsm);
+
+ return String.format("L2capNetworkSpecifier(%s, %s, RemoteAddress=%s, PSM=%s)",
+ role, headerCompression, Objects.toString(mRemoteAddress), psm);
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/networksecurity/TEST_MAPPING b/networksecurity/TEST_MAPPING
index 20ecbce..f9238c3 100644
--- a/networksecurity/TEST_MAPPING
+++ b/networksecurity/TEST_MAPPING
@@ -1,5 +1,14 @@
{
- "postsubmit": [
+ "presubmit": [
+ {
+ "name": "CtsNetSecConfigCertificateTransparencyTestCases"
+ },
+ {
+ "name": "CtsNetSecConfigCertificateTransparencyDefaultTestCases"
+ },
+ {
+ "name": "NetSecConfigCertificateTransparencySctLogListTestCases"
+ },
{
"name": "NetworkSecurityUnitTests"
}
diff --git a/networksecurity/service/src/com/android/server/net/ct/CompatibilityVersion.java b/networksecurity/service/src/com/android/server/net/ct/CompatibilityVersion.java
index fdeb746..9d60163 100644
--- a/networksecurity/service/src/com/android/server/net/ct/CompatibilityVersion.java
+++ b/networksecurity/service/src/com/android/server/net/ct/CompatibilityVersion.java
@@ -46,6 +46,7 @@
private final String mMetadataUrl;
private final String mContentUrl;
+ private final File mRootDirectory;
private final File mVersionDirectory;
private final File mCurrentLogsDirSymlink;
@@ -54,6 +55,7 @@
mCompatVersion = compatVersion;
mMetadataUrl = metadataUrl;
mContentUrl = contentUrl;
+ mRootDirectory = rootDirectory;
mVersionDirectory = new File(rootDirectory, compatVersion);
mCurrentLogsDirSymlink = new File(mVersionDirectory, CURRENT_LOGS_DIR_SYMLINK_NAME);
}
@@ -86,7 +88,8 @@
// To support atomically replacing the old configuration directory with the new
// there's a bunch of steps. We create a new directory with the logs and then do
// an atomic update of the current symlink to point to the new directory.
- // 1. Ensure the path to the root directory exists and is readable.
+ // 1. Ensure the path to the root and version directories exist and are readable.
+ DirectoryUtils.makeDir(mRootDirectory);
DirectoryUtils.makeDir(mVersionDirectory);
File newLogsDir = new File(mVersionDirectory, LOGS_DIR_PREFIX + version);
diff --git a/networksecurity/service/src/com/android/server/net/ct/DirectoryUtils.java b/networksecurity/service/src/com/android/server/net/ct/DirectoryUtils.java
index 54e277a..ba42a82 100644
--- a/networksecurity/service/src/com/android/server/net/ct/DirectoryUtils.java
+++ b/networksecurity/service/src/com/android/server/net/ct/DirectoryUtils.java
@@ -25,7 +25,7 @@
class DirectoryUtils {
static void makeDir(File dir) throws IOException {
- dir.mkdirs();
+ dir.mkdir();
if (!dir.isDirectory()) {
throw new IOException("Unable to make directory " + dir.getCanonicalPath());
}
diff --git a/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs b/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs
index 9add6df..1d43d38 100644
--- a/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs
+++ b/remoteauth/service/jni/src/remoteauth_jni_android_platform.rs
@@ -140,6 +140,7 @@
}
impl Platform for JavaPlatform {
+ #[allow(clippy::unit_arg)]
fn send_request(
&mut self,
connection_id: i32,
diff --git a/remoteauth/service/jni/src/unique_jvm.rs b/remoteauth/service/jni/src/unique_jvm.rs
index 46cc361..ddbb16f 100644
--- a/remoteauth/service/jni/src/unique_jvm.rs
+++ b/remoteauth/service/jni/src/unique_jvm.rs
@@ -41,6 +41,7 @@
Ok(())
}
/// Gets a 'static reference to the unique JavaVM. Returns None if set_once() was never called.
+#[allow(static_mut_refs)]
pub(crate) fn get_static_ref() -> Option<&'static Arc<JavaVM>> {
// Safety: follows [this pattern](https://doc.rust-lang.org/std/sync/struct.Once.html).
// Modification to static mut is nested inside call_once.
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 4a9410e..eedf427 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -51,7 +51,6 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.HandlerUtils;
import com.android.net.module.util.NetdUtils;
-import com.android.net.module.util.PermissionUtils;
import com.android.net.module.util.SharedLog;
import com.android.net.module.util.ip.NetlinkMonitor;
import com.android.net.module.util.netlink.NetlinkConstants;
@@ -624,7 +623,7 @@
nc = mNetworkCapabilities.get(hwAddress);
if (nc == null) {
final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP);
- nc = createDefaultNetworkCapabilities(isTestIface);
+ nc = createDefaultNetworkCapabilities(isTestIface, /* overrideTransport */ null);
}
}
@@ -739,9 +738,13 @@
*/
private void parseEthernetConfig(String configString) {
final EthernetTrackerConfig config = createEthernetTrackerConfig(configString);
- NetworkCapabilities nc = createNetworkCapabilities(
- !TextUtils.isEmpty(config.mCapabilities) /* clear default capabilities */,
- config.mCapabilities, config.mTransport).build();
+ NetworkCapabilities nc;
+ if (TextUtils.isEmpty(config.mCapabilities)) {
+ boolean isTestIface = config.mIface.matches(TEST_IFACE_REGEXP);
+ nc = createDefaultNetworkCapabilities(isTestIface, config.mTransport);
+ } else {
+ nc = createNetworkCapabilities(config.mCapabilities, config.mTransport).build();
+ }
mNetworkCapabilities.put(config.mIface, nc);
if (null != config.mIpConfig) {
@@ -756,15 +759,16 @@
return new EthernetTrackerConfig(configString.split(";", /* limit of tokens */ 4));
}
- private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) {
- NetworkCapabilities.Builder builder = createNetworkCapabilities(
- false /* clear default capabilities */, null, null)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
+ private static NetworkCapabilities createDefaultNetworkCapabilities(
+ boolean isTestIface, @Nullable String overrideTransport) {
+ NetworkCapabilities.Builder builder =
+ createNetworkCapabilities(/* commaSeparatedCapabilities */ null, overrideTransport)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
if (isTestIface) {
builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
@@ -778,7 +782,6 @@
/**
* Parses a static list of network capabilities
*
- * @param clearDefaultCapabilities Indicates whether or not to clear any default capabilities
* @param commaSeparatedCapabilities A comma separated string list of integer encoded
* NetworkCapability.NET_CAPABILITY_* values
* @param overrideTransport A string representing a single integer encoded override transport
@@ -788,12 +791,12 @@
*/
@VisibleForTesting
static NetworkCapabilities.Builder createNetworkCapabilities(
- boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities,
- @Nullable String overrideTransport) {
+ @Nullable String commaSeparatedCapabilities, @Nullable String overrideTransport) {
- final NetworkCapabilities.Builder builder = clearDefaultCapabilities
- ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
- : new NetworkCapabilities.Builder();
+ final NetworkCapabilities.Builder builder =
+ TextUtils.isEmpty(commaSeparatedCapabilities)
+ ? new NetworkCapabilities.Builder()
+ : NetworkCapabilities.Builder.withoutDefaultCapabilities();
// Determine the transport type. If someone has tried to define an override transport then
// attempt to add it. Since we can only have one override, all errors with it will
diff --git a/service/Android.bp b/service/Android.bp
index 2659ebf..c4e2ef0 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -113,7 +113,6 @@
":services.connectivity-netstats-jni-sources",
"jni/com_android_server_connectivity_ClatCoordinator.cpp",
"jni/com_android_server_ServiceManagerWrapper.cpp",
- "jni/com_android_server_TestNetworkService.cpp",
"jni/onload.cpp",
],
header_libs: [
@@ -125,7 +124,7 @@
"libmodules-utils-build",
"libnetjniutils",
"libnet_utils_device_common_bpfjni",
- "libnet_utils_device_common_timerfdjni",
+ "libserviceconnectivityjni",
"netd_aidl_interface-lateststable-ndk",
],
shared_libs: [
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
deleted file mode 100644
index 08d31a3..0000000
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "TestNetworkServiceJni"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <linux/ipv6_route.h>
-#include <linux/route.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <log/log.h>
-
-#include "jni.h"
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
-#include <bpf/KernelUtils.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-
-#ifndef IFF_NO_CARRIER
-#define IFF_NO_CARRIER 0x0040
-#endif
-
-namespace android {
-
-//------------------------------------------------------------------------------
-
-static void throwException(JNIEnv* env, int error, const char* action, const char* iface) {
- const std::string& msg = "Error: " + std::string(action) + " " + std::string(iface) + ": "
- + std::string(strerror(error));
- jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
-}
-
-// enable or disable carrier on tun / tap interface.
-static void setTunTapCarrierEnabledImpl(JNIEnv* env, const char* iface, int tunFd, bool enabled) {
- uint32_t carrierOn = enabled;
- if (ioctl(tunFd, TUNSETCARRIER, &carrierOn)) {
- throwException(env, errno, "set carrier", iface);
- }
-}
-
-static int createTunTapImpl(JNIEnv* env, bool isTun, bool hasCarrier, bool setIffMulticast,
- const char* iface) {
- base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
- ifreq ifr{};
-
- // Allocate interface.
- ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
- if (!hasCarrier) {
- // Using IFF_NO_CARRIER is supported starting in kernel version >= 6.0
- // Up until then, unsupported flags are ignored.
- if (!bpf::isAtLeastKernelVersion(6, 0, 0)) {
- throwException(env, EOPNOTSUPP, "IFF_NO_CARRIER not supported", ifr.ifr_name);
- return -1;
- }
- ifr.ifr_flags |= IFF_NO_CARRIER;
- }
- strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
- if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
- throwException(env, errno, "allocating", ifr.ifr_name);
- return -1;
- }
-
- // Mark some TAP interfaces as supporting multicast
- if (setIffMulticast && !isTun) {
- base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
- ifr.ifr_flags = IFF_MULTICAST;
-
- if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
- throwException(env, errno, "set IFF_MULTICAST", ifr.ifr_name);
- return -1;
- }
- }
-
- return tun.release();
-}
-
-static void bringUpInterfaceImpl(JNIEnv* env, const char* iface) {
- // Activate interface using an unconnected datagram socket.
- base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
-
- ifreq ifr{};
- strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
- if (ioctl(inet6CtrlSock.get(), SIOCGIFFLAGS, &ifr)) {
- throwException(env, errno, "read flags", iface);
- return;
- }
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
- throwException(env, errno, "set IFF_UP", iface);
- return;
- }
-}
-
-//------------------------------------------------------------------------------
-
-
-
-static void setTunTapCarrierEnabled(JNIEnv* env, jclass /* clazz */, jstring
- jIface, jint tunFd, jboolean enabled) {
- ScopedUtfChars iface(env, jIface);
- if (!iface.c_str()) {
- jniThrowNullPointerException(env, "iface");
- return;
- }
- setTunTapCarrierEnabledImpl(env, iface.c_str(), tunFd, enabled);
-}
-
-static jint createTunTap(JNIEnv* env, jclass /* clazz */, jboolean isTun,
- jboolean hasCarrier, jboolean setIffMulticast, jstring jIface) {
- ScopedUtfChars iface(env, jIface);
- if (!iface.c_str()) {
- jniThrowNullPointerException(env, "iface");
- return -1;
- }
-
- return createTunTapImpl(env, isTun, hasCarrier, setIffMulticast, iface.c_str());
-}
-
-static void bringUpInterface(JNIEnv* env, jclass /* clazz */, jstring jIface) {
- ScopedUtfChars iface(env, jIface);
- if (!iface.c_str()) {
- jniThrowNullPointerException(env, "iface");
- return;
- }
- bringUpInterfaceImpl(env, iface.c_str());
-}
-
-//------------------------------------------------------------------------------
-
-static const JNINativeMethod gMethods[] = {
- {"nativeSetTunTapCarrierEnabled", "(Ljava/lang/String;IZ)V", (void*)setTunTapCarrierEnabled},
- {"nativeCreateTunTap", "(ZZZLjava/lang/String;)I", (void*)createTunTap},
- {"nativeBringUpInterface", "(Ljava/lang/String;)V", (void*)bringUpInterface},
-};
-
-int register_com_android_server_TestNetworkService(JNIEnv* env) {
- return jniRegisterNativeMethods(env,
- "android/net/connectivity/com/android/server/TestNetworkService", gMethods,
- NELEM(gMethods));
-}
-
-}; // namespace android
diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp
index 8e01260..f87470d 100644
--- a/service/jni/onload.cpp
+++ b/service/jni/onload.cpp
@@ -21,12 +21,11 @@
namespace android {
-int register_com_android_server_TestNetworkService(JNIEnv* env);
int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env);
int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
int register_android_server_net_NetworkStatsService(JNIEnv* env);
int register_com_android_server_ServiceManagerWrapper(JNIEnv* env);
-int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
+int register_com_android_net_module_util_ServiceConnectivityJni(JNIEnv *env,
char const *class_name);
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
@@ -36,10 +35,6 @@
return JNI_ERR;
}
- if (register_com_android_server_TestNetworkService(env) < 0) {
- return JNI_ERR;
- }
-
if (register_com_android_server_ServiceManagerWrapper(env) < 0) {
return JNI_ERR;
}
@@ -58,9 +53,9 @@
}
}
- if (register_com_android_net_module_util_TimerFdUtils(
+ if (register_com_android_net_module_util_ServiceConnectivityJni(
env, "android/net/connectivity/com/android/net/module/util/"
- "TimerFdUtils") < 0) {
+ "ServiceConnectivityJni") < 0) {
return JNI_ERR;
}
diff --git a/service/src/com/android/server/L2capNetworkProvider.java b/service/src/com/android/server/L2capNetworkProvider.java
index 34968e7..c5ec9ee 100644
--- a/service/src/com/android/server/L2capNetworkProvider.java
+++ b/service/src/com/android/server/L2capNetworkProvider.java
@@ -20,6 +20,7 @@
import static android.net.L2capNetworkSpecifier.HEADER_COMPRESSION_ANY;
import static android.net.L2capNetworkSpecifier.PSM_ANY;
import static android.net.L2capNetworkSpecifier.ROLE_SERVER;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
@@ -32,6 +33,7 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.L2capNetworkSpecifier;
import android.net.NetworkCapabilities;
@@ -41,6 +43,7 @@
import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.util.ArrayMap;
import android.util.Log;
@@ -53,6 +56,8 @@
public class L2capNetworkProvider {
private static final String TAG = L2capNetworkProvider.class.getSimpleName();
private final Dependencies mDeps;
+ private final Context mContext;
+ private final HandlerThread mHandlerThread;
private final Handler mHandler;
private final NetworkProvider mProvider;
private final BlanketReservationOffer mBlanketOffer;
@@ -78,6 +83,8 @@
.build();
NetworkCapabilities caps = NetworkCapabilities.Builder.withoutDefaultCapabilities()
.addTransportType(TRANSPORT_BLUETOOTH)
+ // TODO: consider removing NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED.
+ .addCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)
.addCapability(NET_CAPABILITY_NOT_CONGESTED)
.addCapability(NET_CAPABILITY_NOT_METERED)
.addCapability(NET_CAPABILITY_NOT_ROAMING)
@@ -198,26 +205,40 @@
public NetworkProvider getNetworkProvider(Context context, Looper looper) {
return new NetworkProvider(context, looper, TAG);
}
+
+ /** Get the HandlerThread for L2capNetworkProvider to run on */
+ public HandlerThread getHandlerThread() {
+ final HandlerThread thread = new HandlerThread("L2capNetworkProviderThread");
+ thread.start();
+ return thread;
+ }
}
- public L2capNetworkProvider(Context context, Handler handler) {
- this(new Dependencies(), context, handler);
+ public L2capNetworkProvider(Context context) {
+ this(new Dependencies(), context);
}
@VisibleForTesting
- public L2capNetworkProvider(Dependencies deps, Context context, Handler handler) {
+ public L2capNetworkProvider(Dependencies deps, Context context) {
mDeps = deps;
- mHandler = handler;
- mProvider = mDeps.getNetworkProvider(context, handler.getLooper());
+ mContext = context;
+ mHandlerThread = mDeps.getHandlerThread();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ mProvider = mDeps.getNetworkProvider(context, mHandlerThread.getLooper());
mBlanketOffer = new BlanketReservationOffer();
+ }
- final boolean isBleSupported =
- context.getPackageManager().hasSystemFeature(FEATURE_BLUETOOTH_LE);
- if (isBleSupported) {
- context.getSystemService(ConnectivityManager.class).registerNetworkProvider(mProvider);
+ /**
+ * Start L2capNetworkProvider.
+ *
+ * Called on CS Handler thread.
+ */
+ public void start() {
+ final PackageManager pm = mContext.getPackageManager();
+ if (pm.hasSystemFeature(FEATURE_BLUETOOTH_LE)) {
+ mContext.getSystemService(ConnectivityManager.class).registerNetworkProvider(mProvider);
mProvider.registerNetworkOffer(BlanketReservationOffer.SCORE,
BlanketReservationOffer.CAPABILITIES, mHandler::post, mBlanketOffer);
}
}
}
-
diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java
index 4d39d7d..96f4e20 100644
--- a/service/src/com/android/server/TestNetworkService.java
+++ b/service/src/com/android/server/TestNetworkService.java
@@ -48,6 +48,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.NetworkStackConstants;
+import com.android.net.module.util.ServiceConnectivityJni;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -75,15 +76,6 @@
@NonNull private final ConnectivityManager mCm;
@NonNull private final NetworkProvider mNetworkProvider;
- // Native method stubs
- private static native int nativeCreateTunTap(boolean isTun, boolean hasCarrier,
- boolean setIffMulticast, @NonNull String iface);
-
- private static native void nativeSetTunTapCarrierEnabled(@NonNull String iface, int tunFd,
- boolean enabled);
-
- private static native void nativeBringUpInterface(String iface);
-
@VisibleForTesting
protected TestNetworkService(@NonNull Context context) {
mHandlerThread = new HandlerThread("TestNetworkServiceThread");
@@ -143,7 +135,8 @@
// flags atomically.
final boolean setIffMulticast = bringUp;
ParcelFileDescriptor tunIntf = ParcelFileDescriptor.adoptFd(
- nativeCreateTunTap(isTun, hasCarrier, setIffMulticast, interfaceName));
+ ServiceConnectivityJni.createTunTap(
+ isTun, hasCarrier, setIffMulticast, interfaceName));
// Disable DAD and remove router_solicitation_delay before assigning link addresses.
if (disableIpv6ProvisioningDelay) {
@@ -160,7 +153,7 @@
}
if (bringUp) {
- nativeBringUpInterface(interfaceName);
+ ServiceConnectivityJni.bringUpInterface(interfaceName);
}
return new TestNetworkInterface(tunIntf, interfaceName);
@@ -403,11 +396,11 @@
@Override
public void setCarrierEnabled(@NonNull TestNetworkInterface iface, boolean enabled) {
enforceTestNetworkPermissions(mContext);
- nativeSetTunTapCarrierEnabled(iface.getInterfaceName(), iface.getFileDescriptor().getFd(),
- enabled);
+ ServiceConnectivityJni.setTunTapCarrierEnabled(iface.getInterfaceName(),
+ iface.getFileDescriptor().getFd(), enabled);
// Explicitly close fd after use to prevent StrictMode from complaining.
// Also, explicitly referencing iface guarantees that the object is not garbage collected
- // before nativeSetTunTapCarrierEnabled() executes.
+ // before setTunTapCarrierEnabled() executes.
try {
iface.getFileDescriptor().close();
} catch (IOException e) {
diff --git a/staticlibs/device/com/android/net/module/util/RealtimeScheduler.java b/staticlibs/device/com/android/net/module/util/RealtimeScheduler.java
index bc3b3a5..c8fdf72 100644
--- a/staticlibs/device/com/android/net/module/util/RealtimeScheduler.java
+++ b/staticlibs/device/com/android/net/module/util/RealtimeScheduler.java
@@ -25,6 +25,8 @@
import android.os.MessageQueue;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
+import android.system.ErrnoException;
+import android.system.Os;
import android.util.CloseGuard;
import android.util.Log;
@@ -253,6 +255,10 @@
if (!isRunning()) {
return 0;
}
+ if ((events & EVENT_ERROR) != 0) {
+ Log.wtf(TAG, "Got EVENT_ERROR from FileDescriptorEventListener.");
+ return 0;
+ }
if ((events & EVENT_INPUT) != 0) {
handleExpiration();
}
@@ -265,6 +271,26 @@
}
private void handleExpiration() {
+ // The data from the FileDescriptor must be read after the timer expires. Otherwise,
+ // expiration callbacks will continue to be sent, notifying of unread data. The content(the
+ // number of expirations) can be ignored, as the callback is the only item of interest.
+ // Refer to https://man7.org/linux/man-pages/man2/timerfd_create.2.html
+ // read(2)
+ // If the timer has already expired one or more times since
+ // its settings were last modified using timerfd_settime(),
+ // or since the last successful read(2), then the buffer
+ // given to read(2) returns an unsigned 8-byte integer
+ // (uint64_t) containing the number of expirations that have
+ // occurred. (The returned value is in host byte order—that
+ // is, the native byte order for integers on the host
+ // machine.)
+ final byte[] readBuffer = new byte[8];
+ try {
+ Os.read(mParcelFileDescriptor.getFileDescriptor(), readBuffer, 0, readBuffer.length);
+ } catch (IOException | ErrnoException exception) {
+ Log.wtf(TAG, "Read FileDescriptor failed. ", exception);
+ }
+
long currentTimeMs = SystemClock.elapsedRealtime();
while (!mTaskQueue.isEmpty()) {
final Task task = mTaskQueue.peek();
@@ -276,7 +302,6 @@
mTaskQueue.poll();
}
-
if (!mTaskQueue.isEmpty()) {
// Using currentTimeMs ensures that the calculated expiration time
// is always positive.
@@ -286,10 +311,6 @@
Log.wtf(TAG, "Failed to set expiration time");
mTaskQueue.clear();
}
- } else {
- // We have to clean up the timer if no tasks are left. Otherwise, the timer will keep
- // being triggered.
- TimerFdUtils.setExpirationTime(mFdInt, 0);
}
}
diff --git a/staticlibs/device/com/android/net/module/util/ServiceConnectivityJni.java b/staticlibs/device/com/android/net/module/util/ServiceConnectivityJni.java
new file mode 100644
index 0000000..4a5dd4f
--- /dev/null
+++ b/staticlibs/device/com/android/net/module/util/ServiceConnectivityJni.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2025 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.annotation.NonNull;
+
+import java.io.IOException;
+
+/**
+ * Contains JNI functions for use in service-connectivity
+ */
+public class ServiceConnectivityJni {
+ static {
+ final String libName = JniUtil.getJniLibraryName(ServiceConnectivityJni.class.getPackage());
+ if (libName.equals("android_net_connectivity_com_android_net_module_util_jni")) {
+ // This library is part of service-connectivity.jar when in the system server,
+ // so libservice-connectivity.so is the library to load.
+ System.loadLibrary("service-connectivity");
+ } else {
+ System.loadLibrary(libName);
+ }
+ }
+
+ /**
+ * Create a timerfd.
+ *
+ * @throws IOException if the timerfd creation is failed.
+ */
+ public static native int createTimerFd() throws IOException;
+
+ /**
+ * Set given time to the timerfd.
+ *
+ * @param timeMs target time
+ * @throws IOException if setting expiration time is failed.
+ */
+ public static native void setTimerFdTime(int fd, long timeMs) throws IOException;
+
+ /** Create tun/tap interface */
+ public static native int createTunTap(boolean isTun, boolean hasCarrier,
+ boolean setIffMulticast, @NonNull String iface);
+
+ /** Enable carrier on tun/tap interface */
+ public static native void setTunTapCarrierEnabled(@NonNull String iface, int tunFd,
+ boolean enabled);
+
+ /** Bring up tun/tap interface */
+ public static native void bringUpInterface(String iface);
+}
diff --git a/staticlibs/device/com/android/net/module/util/TimerFdUtils.java b/staticlibs/device/com/android/net/module/util/TimerFdUtils.java
index f0de142..10bc595 100644
--- a/staticlibs/device/com/android/net/module/util/TimerFdUtils.java
+++ b/staticlibs/device/com/android/net/module/util/TimerFdUtils.java
@@ -25,40 +25,14 @@
* Contains mostly timerfd functionality.
*/
public class TimerFdUtils {
- static {
- final String jniLibName = JniUtil.getJniLibraryName(TimerFdUtils.class.getPackage());
- if (jniLibName.equals("android_net_connectivity_com_android_net_module_util_jni")) {
- // This library is part of service-connectivity.jar when in the system server,
- // so libservice-connectivity.so is the library to load.
- System.loadLibrary("service-connectivity");
- } else {
- System.loadLibrary(jniLibName);
- }
- }
-
private static final String TAG = TimerFdUtils.class.getSimpleName();
/**
- * Create a timerfd.
- *
- * @throws IOException if the timerfd creation is failed.
- */
- private static native int createTimerFd() throws IOException;
-
- /**
- * Set given time to the timerfd.
- *
- * @param timeMs target time
- * @throws IOException if setting expiration time is failed.
- */
- private static native void setTime(int fd, long timeMs) throws IOException;
-
- /**
* Create a timerfd
*/
static int createTimerFileDescriptor() {
try {
- return createTimerFd();
+ return ServiceConnectivityJni.createTimerFd();
} catch (IOException e) {
Log.e(TAG, "createTimerFd failed", e);
return -1;
@@ -70,7 +44,7 @@
*/
static boolean setExpirationTime(int fd, long expirationTimeMs) {
try {
- setTime(fd, expirationTimeMs);
+ ServiceConnectivityJni.setTimerFdTime(fd, expirationTimeMs);
} catch (IOException e) {
Log.e(TAG, "setExpirationTime failed", e);
return false;
diff --git a/staticlibs/native/timerfdutils/Android.bp b/staticlibs/native/serviceconnectivityjni/Android.bp
similarity index 86%
rename from staticlibs/native/timerfdutils/Android.bp
rename to staticlibs/native/serviceconnectivityjni/Android.bp
index 939a2d2..18246dd 100644
--- a/staticlibs/native/timerfdutils/Android.bp
+++ b/staticlibs/native/serviceconnectivityjni/Android.bp
@@ -18,17 +18,20 @@
}
cc_library_static {
- name: "libnet_utils_device_common_timerfdjni",
+ name: "libserviceconnectivityjni",
srcs: [
- "com_android_net_module_util_TimerFdUtils.cpp",
+ "com_android_net_module_util_ServiceConnectivityJni.cpp",
],
header_libs: [
+ "bpf_headers",
"jni_headers",
+ "libbase_headers",
],
shared_libs: [
"liblog",
"libnativehelper_compat_libc++",
],
+ stl: "libc++_static",
cflags: [
"-Wall",
"-Werror",
diff --git a/staticlibs/native/serviceconnectivityjni/com_android_net_module_util_ServiceConnectivityJni.cpp b/staticlibs/native/serviceconnectivityjni/com_android_net_module_util_ServiceConnectivityJni.cpp
new file mode 100644
index 0000000..8767589
--- /dev/null
+++ b/staticlibs/native/serviceconnectivityjni/com_android_net_module_util_ServiceConnectivityJni.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <jni.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/ipv6_route.h>
+#include <linux/route.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <sys/epoll.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/timerfd.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <android-base/unique_fd.h>
+#include <bpf/KernelUtils.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/scoped_utf_chars.h>
+
+#define MSEC_PER_SEC 1000
+#define NSEC_PER_MSEC 1000000
+
+#ifndef IFF_NO_CARRIER
+#define IFF_NO_CARRIER 0x0040
+#endif
+
+namespace android {
+
+static jint createTimerFd(JNIEnv *env, jclass clazz) {
+ int tfd;
+ // For safety, the file descriptor should have O_NONBLOCK(TFD_NONBLOCK) set
+ // using fcntl during creation. This ensures that, in the worst-case scenario,
+ // an EAGAIN error is returned when reading.
+ tfd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK);
+ if (tfd == -1) {
+ jniThrowErrnoException(env, "createTimerFd", tfd);
+ }
+ return tfd;
+}
+
+static void setTimerFdTime(JNIEnv *env, jclass clazz, jint tfd,
+ jlong milliseconds) {
+ struct itimerspec new_value;
+ new_value.it_value.tv_sec = milliseconds / MSEC_PER_SEC;
+ new_value.it_value.tv_nsec = (milliseconds % MSEC_PER_SEC) * NSEC_PER_MSEC;
+ // Set the interval time to 0 because it's designed for repeated timer
+ // expirations after the initial expiration, which doesn't fit the current
+ // usage.
+ new_value.it_interval.tv_sec = 0;
+ new_value.it_interval.tv_nsec = 0;
+
+ int ret = timerfd_settime(tfd, 0, &new_value, NULL);
+ if (ret == -1) {
+ jniThrowErrnoException(env, "setTimerFdTime", ret);
+ }
+}
+
+static void throwException(JNIEnv *env, int error, const char *action,
+ const char *iface) {
+ const std::string &msg = "Error: " + std::string(action) + " " +
+ std::string(iface) + ": " +
+ std::string(strerror(error));
+ jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
+}
+
+// enable or disable carrier on tun / tap interface.
+static void setTunTapCarrierEnabledImpl(JNIEnv *env, const char *iface,
+ int tunFd, bool enabled) {
+ uint32_t carrierOn = enabled;
+ if (ioctl(tunFd, TUNSETCARRIER, &carrierOn)) {
+ throwException(env, errno, "set carrier", iface);
+ }
+}
+
+static int createTunTapImpl(JNIEnv *env, bool isTun, bool hasCarrier,
+ bool setIffMulticast, const char *iface) {
+ base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
+ ifreq ifr{};
+
+ // Allocate interface.
+ ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
+ if (!hasCarrier) {
+ // Using IFF_NO_CARRIER is supported starting in kernel version >= 6.0
+ // Up until then, unsupported flags are ignored.
+ if (!bpf::isAtLeastKernelVersion(6, 0, 0)) {
+ throwException(env, EOPNOTSUPP, "IFF_NO_CARRIER not supported",
+ ifr.ifr_name);
+ return -1;
+ }
+ ifr.ifr_flags |= IFF_NO_CARRIER;
+ }
+ strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
+ if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
+ throwException(env, errno, "allocating", ifr.ifr_name);
+ return -1;
+ }
+
+ // Mark some TAP interfaces as supporting multicast
+ if (setIffMulticast && !isTun) {
+ base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+ ifr.ifr_flags = IFF_MULTICAST;
+
+ if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+ throwException(env, errno, "set IFF_MULTICAST", ifr.ifr_name);
+ return -1;
+ }
+ }
+
+ return tun.release();
+}
+
+static void bringUpInterfaceImpl(JNIEnv *env, const char *iface) {
+ // Activate interface using an unconnected datagram socket.
+ base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+
+ ifreq ifr{};
+ strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
+ if (ioctl(inet6CtrlSock.get(), SIOCGIFFLAGS, &ifr)) {
+ throwException(env, errno, "read flags", iface);
+ return;
+ }
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+ throwException(env, errno, "set IFF_UP", iface);
+ return;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static void setTunTapCarrierEnabled(JNIEnv *env, jclass /* clazz */,
+ jstring jIface, jint tunFd,
+ jboolean enabled) {
+ ScopedUtfChars iface(env, jIface);
+ if (!iface.c_str()) {
+ jniThrowNullPointerException(env, "iface");
+ return;
+ }
+ setTunTapCarrierEnabledImpl(env, iface.c_str(), tunFd, enabled);
+}
+
+static jint createTunTap(JNIEnv *env, jclass /* clazz */, jboolean isTun,
+ jboolean hasCarrier, jboolean setIffMulticast,
+ jstring jIface) {
+ ScopedUtfChars iface(env, jIface);
+ if (!iface.c_str()) {
+ jniThrowNullPointerException(env, "iface");
+ return -1;
+ }
+
+ return createTunTapImpl(env, isTun, hasCarrier, setIffMulticast,
+ iface.c_str());
+}
+
+static void bringUpInterface(JNIEnv *env, jclass /* clazz */, jstring jIface) {
+ ScopedUtfChars iface(env, jIface);
+ if (!iface.c_str()) {
+ jniThrowNullPointerException(env, "iface");
+ return;
+ }
+ bringUpInterfaceImpl(env, iface.c_str());
+}
+
+//------------------------------------------------------------------------------
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ {"createTimerFd", "()I", (void *)createTimerFd},
+ {"setTimerFdTime", "(IJ)V", (void *)setTimerFdTime},
+ {"setTunTapCarrierEnabled", "(Ljava/lang/String;IZ)V",
+ (void *)setTunTapCarrierEnabled},
+ {"createTunTap", "(ZZZLjava/lang/String;)I", (void *)createTunTap},
+ {"bringUpInterface", "(Ljava/lang/String;)V", (void *)bringUpInterface},
+};
+
+int register_com_android_net_module_util_ServiceConnectivityJni(
+ JNIEnv *env, char const *class_name) {
+ return jniRegisterNativeMethods(env, class_name, gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/staticlibs/native/timerfdutils/com_android_net_module_util_TimerFdUtils.cpp b/staticlibs/native/timerfdutils/com_android_net_module_util_TimerFdUtils.cpp
deleted file mode 100644
index c4c960d..0000000
--- a/staticlibs/native/timerfdutils/com_android_net_module_util_TimerFdUtils.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2024 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.
- */
-
-#include <errno.h>
-#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/scoped_utf_chars.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <sys/timerfd.h>
-#include <time.h>
-#include <unistd.h>
-
-#define MSEC_PER_SEC 1000
-#define NSEC_PER_MSEC 1000000
-
-namespace android {
-
-static jint
-com_android_net_module_util_TimerFdUtils_createTimerFd(JNIEnv *env,
- jclass clazz) {
- int tfd;
- tfd = timerfd_create(CLOCK_BOOTTIME, 0);
- if (tfd == -1) {
- jniThrowErrnoException(env, "createTimerFd", tfd);
- }
- return tfd;
-}
-
-static void
-com_android_net_module_util_TimerFdUtils_setTime(JNIEnv *env, jclass clazz,
- jint tfd, jlong milliseconds) {
- struct itimerspec new_value;
- new_value.it_value.tv_sec = milliseconds / MSEC_PER_SEC;
- new_value.it_value.tv_nsec = (milliseconds % MSEC_PER_SEC) * NSEC_PER_MSEC;
- // Set the interval time to 0 because it's designed for repeated timer expirations after the
- // initial expiration, which doesn't fit the current usage.
- new_value.it_interval.tv_sec = 0;
- new_value.it_interval.tv_nsec = 0;
-
- int ret = timerfd_settime(tfd, 0, &new_value, NULL);
- if (ret == -1) {
- jniThrowErrnoException(env, "setTime", ret);
- }
-}
-
-/*
- * JNI registration.
- */
-static const JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- {"createTimerFd", "()I",
- (void *)com_android_net_module_util_TimerFdUtils_createTimerFd},
- {"setTime", "(IJ)V",
- (void *)com_android_net_module_util_TimerFdUtils_setTime},
-};
-
-int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
- char const *class_name) {
- return jniRegisterNativeMethods(env, class_name, gMethods, NELEM(gMethods));
-}
-
-}; // namespace android
diff --git a/staticlibs/tests/unit/jni/Android.bp b/staticlibs/tests/unit/jni/Android.bp
index e456471..c444159 100644
--- a/staticlibs/tests/unit/jni/Android.bp
+++ b/staticlibs/tests/unit/jni/Android.bp
@@ -30,7 +30,7 @@
"com_android_net_moduletests_util/onload.cpp",
],
static_libs: [
- "libnet_utils_device_common_timerfdjni",
+ "libserviceconnectivityjni",
],
shared_libs: [
"liblog",
diff --git a/staticlibs/tests/unit/jni/com_android_net_moduletests_util/onload.cpp b/staticlibs/tests/unit/jni/com_android_net_moduletests_util/onload.cpp
index a035540..af4810f 100644
--- a/staticlibs/tests/unit/jni/com_android_net_moduletests_util/onload.cpp
+++ b/staticlibs/tests/unit/jni/com_android_net_moduletests_util/onload.cpp
@@ -22,7 +22,7 @@
namespace android {
-int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
+int register_com_android_net_module_util_ServiceConnectivityJni(JNIEnv *env,
char const *class_name);
extern "C" jint JNI_OnLoad(JavaVM *vm, void *) {
@@ -32,8 +32,8 @@
return JNI_ERR;
}
- if (register_com_android_net_module_util_TimerFdUtils(
- env, "com/android/net/moduletests/util/TimerFdUtils") < 0)
+ if (register_com_android_net_module_util_ServiceConnectivityJni(
+ env, "com/android/net/moduletests/util/ServiceConnectivityJni") < 0)
return JNI_ERR;
return JNI_VERSION_1_6;
diff --git a/staticlibs/testutils/Android.bp b/staticlibs/testutils/Android.bp
index 86aa8f1..ec486fb 100644
--- a/staticlibs/testutils/Android.bp
+++ b/staticlibs/testutils/Android.bp
@@ -93,6 +93,7 @@
libs: ["tradefed"],
test_suites: [
"ats",
+ "automotive-general-tests",
"device-tests",
"general-tests",
"cts",
diff --git a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt
index 8e27c62..c42d9e5 100644
--- a/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt
+++ b/staticlibs/testutils/app/connectivitychecker/src/com/android/testutils/connectivitypreparer/ConnectivityCheckTest.kt
@@ -19,7 +19,7 @@
import android.Manifest.permission.NETWORK_SETTINGS
import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.content.pm.PackageManager.FEATURE_WIFI
-import android.net.LinkAddress
+import android.net.InetAddresses.parseNumericAddress
import android.net.Network
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.TRANSPORT_WIFI
@@ -66,7 +66,8 @@
// Skip IPv6 checks on virtual devices which do not support it. Tests that require IPv6 will
// still fail even if the preparer does not.
private fun ipv6Unsupported(wifiSsid: String?) = ConnectUtil.VIRTUAL_SSIDS.contains(
- WifiInfo.sanitizeSsid(wifiSsid))
+ WifiInfo.sanitizeSsid(wifiSsid)
+ )
@Test
fun testCheckWifiSetup() {
@@ -89,13 +90,25 @@
pos = 0,
timeoutMs = 30_000L
) {
- it is LinkPropertiesChanged &&
- it.network == network &&
- it.lp.allLinkAddresses.any(LinkAddress::isIpv4) &&
- (ipv6Unsupported(ssid) || it.lp.hasGlobalIpv6Address())
+ if (it !is LinkPropertiesChanged || it.network != network) {
+ false
+ } else {
+ // Same check as used by DnsResolver for AI_ADDRCONFIG (have_ipv4)
+ val ipv4Reachable = it.lp.isReachable(parseNumericAddress("8.8.8.8"))
+ // Same check as used by DnsResolver for AI_ADDRCONFIG (have_ipv6)
+ val ipv6Reachable = it.lp.isReachable(parseNumericAddress("2000::"))
+ ipv4Reachable && (ipv6Unsupported(ssid) || ipv6Reachable)
+ }
}
- assertNotNull(lpChange, "Wifi network $network needs an IPv4 address" +
- if (ipv6Unsupported(ssid)) "" else " and a global IPv6 address")
+ assertNotNull(
+ lpChange,
+ "Wifi network $network needs an IPv4 address and default route" +
+ if (ipv6Unsupported(ssid)) {
+ ""
+ } else {
+ " and a global IPv6 address and default route"
+ }
+ )
Pair(network, ssid)
}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt
new file mode 100644
index 0000000..a93ae3e
--- /dev/null
+++ b/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2025 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.testutils.com.android.testutils
+
+import android.Manifest.permission.MODIFY_PHONE_STATE
+import android.Manifest.permission.READ_PHONE_STATE
+import android.os.PersistableBundle
+import android.telephony.CarrierConfigManager
+import android.util.Log
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.modules.utils.build.SdkLevel.isAtLeastU
+import com.android.testutils.runAsShell
+import com.android.testutils.tryTest
+import kotlin.test.assertNotNull
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+private val TAG = CarrierConfigRule::class.simpleName
+
+/**
+ * A [TestRule] that helps set [CarrierConfigManager] overrides for tests and clean up the test
+ * configuration automatically on teardown.
+ */
+class CarrierConfigRule : TestRule {
+ private val ccm by lazy { InstrumentationRegistry.getInstrumentation().context.getSystemService(
+ CarrierConfigManager::class.java
+ ) }
+
+ // Map of (subId) -> (original values of overridden settings)
+ private val originalConfigs = mutableMapOf<Int, PersistableBundle>()
+
+ override fun apply(base: Statement, description: Description): Statement {
+ return CarrierConfigStatement(base, description)
+ }
+
+ private inner class CarrierConfigStatement(
+ private val base: Statement,
+ private val description: Description
+ ) : Statement() {
+ override fun evaluate() {
+ tryTest {
+ base.evaluate()
+ } cleanup {
+ cleanUpNow()
+ }
+ }
+ }
+
+ /**
+ * Add carrier config overrides with the specified configuration.
+ *
+ * The overrides will automatically be cleaned up when the test case finishes.
+ */
+ fun addConfigOverrides(subId: Int, config: PersistableBundle) {
+ val originalConfig = originalConfigs.computeIfAbsent(subId) { PersistableBundle() }
+ val overrideKeys = config.keySet()
+ val previousValues = runAsShell(READ_PHONE_STATE) {
+ ccm.getConfigForSubIdCompat(subId, overrideKeys)
+ }
+ // If a key is already in the originalConfig, keep the oldest original overrides
+ originalConfig.keySet().forEach {
+ previousValues.remove(it)
+ }
+ originalConfig.putAll(previousValues)
+
+ runAsShell(MODIFY_PHONE_STATE) {
+ ccm.overrideConfig(subId, config)
+ }
+ }
+
+ /**
+ * Cleanup overrides that were added by the test case.
+ *
+ * This will be called automatically on test teardown, so it does not need to be called by the
+ * test case unless cleaning up earlier is required.
+ */
+ fun cleanUpNow() {
+ runAsShell(MODIFY_PHONE_STATE) {
+ originalConfigs.forEach { (subId, config) ->
+ try {
+ // Do not use overrideConfig with null, as it would reset configs that may
+ // have been set by target preparers such as
+ // ConnectivityTestTargetPreparer / CarrierConfigSetupTest.
+ ccm.overrideConfig(subId, config)
+ } catch (e: Throwable) {
+ Log.e(TAG, "Error resetting carrier config for subId $subId")
+ }
+ }
+ originalConfigs.clear()
+ }
+ }
+}
+
+private fun CarrierConfigManager.getConfigForSubIdCompat(
+ subId: Int,
+ keys: Set<String>
+): PersistableBundle {
+ return if (isAtLeastU()) {
+ // This method is U+
+ getConfigForSubId(subId, *keys.toTypedArray())
+ } else {
+ @Suppress("DEPRECATION")
+ val config = assertNotNull(getConfigForSubId(subId))
+ val allKeys = config.keySet().toList()
+ allKeys.forEach {
+ if (!keys.contains(it)) {
+ config.remove(it)
+ }
+ }
+ config
+ }
+}
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
index 0624e5f..c7d6850 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
@@ -168,7 +168,8 @@
.addCapability(NET_CAPABILITY_INTERNET)
.addTransportType(TRANSPORT_WIFI)
.addTransportType(TRANSPORT_CELLULAR)
- .build(), networkCallback
+ .build(),
+ networkCallback
)
}
}
@@ -184,9 +185,12 @@
// when iterating on failing tests.
if (!runOnFailure(failure.exception)) return
if (outputFiles.size >= MAX_DUMPS) return
- Log.i(TAG, "Collecting diagnostics for test failure. Disable by running tests with: " +
+ Log.i(
+ TAG,
+ "Collecting diagnostics for test failure. Disable by running tests with: " +
"atest MyModule -- " +
- "--module-arg MyModule:instrumentation-arg:$ARG_RUN_ON_FAILURE:=false")
+ "--module-arg MyModule:instrumentation-arg:$ARG_RUN_ON_FAILURE:=false"
+ )
collectTestFailureDiagnostics(failure.exception)
val baseFilename = "${description.className}#${description.methodName}_failure"
@@ -326,8 +330,11 @@
}
}
} else {
- Log.w(TAG, "The test is still holding shell permissions, cannot collect privileged " +
- "device info")
+ Log.w(
+ TAG,
+ "The test is still holding shell permissions, cannot collect privileged " +
+ "device info"
+ )
headerObj.put("shellPermissionsUnavailable", true)
}
failureHeader = headerObj.apply {
@@ -379,7 +386,9 @@
cbHelper.registerNetworkCallback(
NetworkRequest.Builder()
.addTransportType(TRANSPORT_WIFI)
- .addCapability(NET_CAPABILITY_INTERNET).build(), cb)
+ .addCapability(NET_CAPABILITY_INTERNET).build(),
+ cb
+ )
return try {
cb.wifiInfoFuture.get(1L, TimeUnit.SECONDS)
} catch (e: TimeoutException) {
@@ -410,15 +419,29 @@
* @param exceptionContext An exception to write a stacktrace to the dump for context.
*/
fun collectDumpsysConnectivity(exceptionContext: Throwable? = null) {
- Log.i(TAG, "Collecting dumpsys connectivity for test artifacts")
+ collectDumpsys("connectivity --dump-priority HIGH", exceptionContext)
+ }
+
+ /**
+ * Add a dumpsys to the test data dump.
+ *
+ * <p>The dump will be collected immediately, and exported to a test artifact file when the
+ * test ends.
+ * @param dumpsysCmd The dumpsys command to run (for example "connectivity").
+ * @param exceptionContext An exception to write a stacktrace to the dump for context.
+ */
+ fun collectDumpsys(dumpsysCmd: String, exceptionContext: Throwable? = null) {
+ Log.i(TAG, "Collecting dumpsys $dumpsysCmd for test artifacts")
PrintWriter(buffer).let {
- it.println("--- Dumpsys connectivity at ${ZonedDateTime.now()} ---")
+ it.println("--- Dumpsys $dumpsysCmd at ${ZonedDateTime.now()} ---")
maybeWriteExceptionContext(it, exceptionContext)
it.flush()
}
ParcelFileDescriptor.AutoCloseInputStream(
InstrumentationRegistry.getInstrumentation().uiAutomation.executeShellCommand(
- "dumpsys connectivity --dump-priority HIGH")).use {
+ "dumpsys $dumpsysCmd"
+ )
+ ).use {
it.copyTo(buffer)
}
}
@@ -437,4 +460,4 @@
writer.println("At: ")
exceptionContext.printStackTrace(writer)
}
-}
\ No newline at end of file
+}
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index a9ac29c..1ba581a 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -95,6 +95,7 @@
"NetworkStackApiCurrentShims",
],
test_suites: [
+ "automotive-general-tests",
"cts",
"mts-tethering",
"mcts-tethering",
@@ -160,6 +161,7 @@
min_sdk_version: "30",
// Tag this module as a cts test artifact
test_suites: [
+ "automotive-general-tests",
"cts",
"general-tests",
],
diff --git a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
index 324078a..3ab6c0d 100644
--- a/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
+++ b/tests/cts/net/src/android/net/cts/ApfIntegrationTest.kt
@@ -60,6 +60,8 @@
import android.system.OsConstants
import android.system.OsConstants.AF_INET6
import android.system.OsConstants.ETH_P_IPV6
+import android.system.OsConstants.ICMP6_ECHO_REPLY
+import android.system.OsConstants.ICMP6_ECHO_REQUEST
import android.system.OsConstants.IPPROTO_ICMPV6
import android.system.OsConstants.SOCK_DGRAM
import android.system.OsConstants.SOCK_NONBLOCK
@@ -212,8 +214,13 @@
handler: Handler,
private val network: Network
) : PacketReader(handler, RCV_BUFFER_SIZE) {
+ private data class PingContext(
+ val futureReply: CompletableFuture<List<ByteArray>>,
+ val expectReplyCount: Int,
+ val replyPayloads: MutableList<ByteArray> = mutableListOf()
+ )
private var sockFd: FileDescriptor? = null
- private var futureReply: CompletableFuture<ByteArray>? = null
+ private var pingContext: PingContext? = null
override fun createFd(): FileDescriptor {
// sockFd is closed by calling super.stop()
@@ -225,6 +232,8 @@
}
override fun handlePacket(recvbuf: ByteArray, length: Int) {
+ val context = pingContext ?: return
+
// If zero-length or Type is not echo reply: ignore.
if (length == 0 || recvbuf[0] != 0x81.toByte()) {
return
@@ -232,10 +241,14 @@
// Only copy the ping data and complete the future.
val result = recvbuf.sliceArray(8..<length)
Log.i(TAG, "Received ping reply: ${result.toHexString()}")
- futureReply!!.complete(recvbuf.sliceArray(8..<length))
+ context.replyPayloads.add(recvbuf.sliceArray(8..<length))
+ if (context.replyPayloads.size == context.expectReplyCount) {
+ context.futureReply.complete(context.replyPayloads)
+ pingContext = null
+ }
}
- fun sendPing(data: ByteArray, payloadSize: Int) {
+ fun sendPing(data: ByteArray, payloadSize: Int, expectReplyCount: Int = 1) {
require(data.size == payloadSize)
// rfc4443#section-4.1: Echo Request Message
@@ -251,17 +264,20 @@
val icmp6Header = byteArrayOf(0x80.toByte(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
val packet = icmp6Header + data
Log.i(TAG, "Sent ping: ${packet.toHexString()}")
- futureReply = CompletableFuture<ByteArray>()
+ pingContext = PingContext(
+ futureReply = CompletableFuture<List<ByteArray>>(),
+ expectReplyCount = expectReplyCount
+ )
Os.sendto(sockFd!!, packet, 0, packet.size, 0, PING_DESTINATION)
}
- fun expectPingReply(timeoutMs: Long = TIMEOUT_MS): ByteArray {
- return futureReply!!.get(timeoutMs, TimeUnit.MILLISECONDS)
+ fun expectPingReply(timeoutMs: Long = TIMEOUT_MS): List<ByteArray> {
+ return pingContext!!.futureReply.get(timeoutMs, TimeUnit.MILLISECONDS)
}
fun expectPingDropped() {
assertFailsWith(TimeoutException::class) {
- futureReply!!.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
+ pingContext!!.futureReply.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
}
}
@@ -503,7 +519,7 @@
}
val data = ByteArray(payloadSize).also { Random.nextBytes(it) }
packetReader.sendPing(data, payloadSize)
- assertThat(packetReader.expectPingReply()).isEqualTo(data)
+ assertThat(packetReader.expectPingReply()[0]).isEqualTo(data)
// Generate an APF program that drops the next ping
val gen = ApfV4Generator(
@@ -715,69 +731,76 @@
// increase PASSED_IPV6_ICMP counter
// pass
// else
- // transmit a ICMPv6 echo request packet with the first byte of the payload in the reply
+ // transmit 3 ICMPv6 echo requests with random first byte
// increase DROPPED_IPV6_NS_REPLIED_NON_DAD counter
// drop
- val program = gen
- .addLoad16(R0, ETH_ETHERTYPE_OFFSET)
+ gen.addLoad16(R0, ETH_ETHERTYPE_OFFSET)
.addJumpIfR0NotEquals(ETH_P_IPV6.toLong(), skipPacketLabel)
.addLoad8(R0, IPV6_NEXT_HEADER_OFFSET)
.addJumpIfR0NotEquals(IPPROTO_ICMPV6.toLong(), skipPacketLabel)
.addLoad8(R0, ICMP6_TYPE_OFFSET)
- .addJumpIfR0NotEquals(0x81, skipPacketLabel) // Echo reply type
+ .addJumpIfR0NotEquals(ICMP6_ECHO_REPLY.toLong(), skipPacketLabel)
.addLoadFromMemory(R0, MemorySlot.PACKET_SIZE)
.addCountAndPassIfR0Equals(
- (ETHER_HEADER_LEN + IPV6_HEADER_LEN + PING_HEADER_LENGTH + firstByte.size)
- .toLong(),
- PASSED_IPV6_ICMP
+ (ETHER_HEADER_LEN + IPV6_HEADER_LEN + PING_HEADER_LENGTH + firstByte.size)
+ .toLong(),
+ PASSED_IPV6_ICMP
)
- // Ping Packet Generation
- .addAllocate(pingRequestPktLen)
- // Eth header
- .addPacketCopy(ETHER_SRC_ADDR_OFFSET, ETHER_ADDR_LEN) // dst MAC address
- .addPacketCopy(ETHER_DST_ADDR_OFFSET, ETHER_ADDR_LEN) // src MAC address
- .addWriteU16(ETH_P_IPV6) // IPv6 type
- // IPv6 Header
- .addWrite32(0x60000000) // IPv6 Header: version, traffic class, flowlabel
- // payload length (2 bytes) | next header: ICMPv6 (1 byte) | hop limit (1 byte)
- .addWrite32(pingRequestIpv6PayloadLen shl 16 or (IPPROTO_ICMPV6 shl 8 or 64))
- .addPacketCopy(IPV6_DEST_ADDR_OFFSET, IPV6_ADDR_LEN) // src ip
- .addPacketCopy(IPV6_SRC_ADDR_OFFSET, IPV6_ADDR_LEN) // dst ip
- // ICMPv6
- .addWriteU8(0x80) // type: echo request
- .addWriteU8(0) // code
- .addWriteU16(pingRequestIpv6PayloadLen) // checksum
- // identifier
- .addPacketCopy(ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_MIN_LEN, 2)
- .addWriteU16(0) // sequence number
- .addDataCopy(firstByte) // data
- .addTransmitL4(
+
+ val numOfPacketToTransmit = 3
+ val expectReplyPayloads = (0 until numOfPacketToTransmit).map { Random.nextBytes(1) }
+ expectReplyPayloads.forEach { replyPingPayload ->
+ // Ping Packet Generation
+ gen.addAllocate(pingRequestPktLen)
+ // Eth header
+ .addPacketCopy(ETHER_SRC_ADDR_OFFSET, ETHER_ADDR_LEN) // dst MAC address
+ .addPacketCopy(ETHER_DST_ADDR_OFFSET, ETHER_ADDR_LEN) // src MAC address
+ .addWriteU16(ETH_P_IPV6) // IPv6 type
+ // IPv6 Header
+ .addWrite32(0x60000000) // IPv6 Header: version, traffic class, flowlabel
+ // payload length (2 bytes) | next header: ICMPv6 (1 byte) | hop limit (1 byte)
+ .addWrite32(pingRequestIpv6PayloadLen shl 16 or (IPPROTO_ICMPV6 shl 8 or 64))
+ .addPacketCopy(IPV6_DEST_ADDR_OFFSET, IPV6_ADDR_LEN) // src ip
+ .addPacketCopy(IPV6_SRC_ADDR_OFFSET, IPV6_ADDR_LEN) // dst ip
+ // ICMPv6
+ .addWriteU8(ICMP6_ECHO_REQUEST)
+ .addWriteU8(0) // code
+ .addWriteU16(pingRequestIpv6PayloadLen) // checksum
+ // identifier
+ .addPacketCopy(ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_MIN_LEN, 2)
+ .addWriteU16(0) // sequence number
+ .addDataCopy(replyPingPayload) // data
+ .addTransmitL4(
ETHER_HEADER_LEN, // ip_ofs
ICMP6_CHECKSUM_OFFSET, // csum_ofs
IPV6_SRC_ADDR_OFFSET, // csum_start
IPPROTO_ICMPV6, // partial_sum
false // udp
- )
- // Warning: the program abuse DROPPED_IPV6_NS_REPLIED_NON_DAD for debugging purpose
- .addCountAndDrop(DROPPED_IPV6_NS_REPLIED_NON_DAD)
- .defineLabel(skipPacketLabel)
- .addPass()
- .generate()
+ )
+ }
+ // Warning: the program abuse DROPPED_IPV6_NS_REPLIED_NON_DAD for debugging purpose
+ gen.addCountAndDrop(DROPPED_IPV6_NS_REPLIED_NON_DAD)
+ .defineLabel(skipPacketLabel)
+ .addPass()
+
+ val program = gen.generate()
installAndVerifyProgram(program)
- packetReader.sendPing(payload, payloadSize)
-
- val replyPayload = try {
+ packetReader.sendPing(payload, payloadSize, expectReplyCount = numOfPacketToTransmit)
+ val replyPayloads = try {
packetReader.expectPingReply(TIMEOUT_MS * 2)
} catch (e: TimeoutException) {
- byteArrayOf() // Empty payload if timeout occurs
+ emptyList()
}
val apfCounterTracker = ApfCounterTracker()
apfCounterTracker.updateCountersFromData(readProgram())
Log.i(TAG, "counter map: ${apfCounterTracker.counters}")
- assertThat(replyPayload).isEqualTo(firstByte)
+ assertThat(replyPayloads.size).isEqualTo(expectReplyPayloads.size)
+ for (i in replyPayloads.indices) {
+ assertThat(replyPayloads[i]).isEqualTo(expectReplyPayloads[i])
+ }
}
}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
index ceb48d4..faaadee 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
@@ -88,9 +88,11 @@
import com.android.net.module.util.ArrayTrackRecord;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
+import com.android.testutils.com.android.testutils.CarrierConfigRule;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -110,6 +112,9 @@
public class ConnectivityDiagnosticsManagerTest {
private static final String TAG = ConnectivityDiagnosticsManagerTest.class.getSimpleName();
+ @Rule
+ public final CarrierConfigRule mCarrierConfigRule = new CarrierConfigRule();
+
private static final int CALLBACK_TIMEOUT_MILLIS = 5000;
private static final int NO_CALLBACK_INVOKED_TIMEOUT = 500;
private static final long TIMESTAMP = 123456789L;
@@ -264,9 +269,6 @@
doBroadcastCarrierConfigsAndVerifyOnConnectivityReportAvailable(
subId, carrierConfigReceiver, testNetworkCallback);
}, () -> {
- runWithShellPermissionIdentity(
- () -> mCarrierConfigManager.overrideConfig(subId, null),
- android.Manifest.permission.MODIFY_PHONE_STATE);
mConnectivityManager.unregisterNetworkCallback(testNetworkCallback);
mContext.unregisterReceiver(carrierConfigReceiver);
});
@@ -291,9 +293,9 @@
CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
new String[] {getCertHashForThisPackage()});
+ mCarrierConfigRule.addConfigOverrides(subId, carrierConfigs);
runWithShellPermissionIdentity(
() -> {
- mCarrierConfigManager.overrideConfig(subId, carrierConfigs);
mCarrierConfigManager.notifyConfigChangedForSubId(subId);
},
android.Manifest.permission.MODIFY_PHONE_STATE);
diff --git a/tests/cts/net/src/android/net/cts/DnsResolverTest.java b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
index fa44ae9..b66b853 100644
--- a/tests/cts/net/src/android/net/cts/DnsResolverTest.java
+++ b/tests/cts/net/src/android/net/cts/DnsResolverTest.java
@@ -58,6 +58,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.net.module.util.DnsPacket;
+import com.android.testutils.ConnectivityDiagnosticsCollector;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DeviceConfigRule;
@@ -394,7 +395,22 @@
@Test
@DnsResolverModuleTest
public void testRawQueryNXDomainWithPrivateDns() throws Exception {
- doTestRawQueryNXDomainWithPrivateDns(mExecutor);
+ try {
+ doTestRawQueryNXDomainWithPrivateDns(mExecutor);
+ } catch (Throwable e) {
+ final ConnectivityDiagnosticsCollector collector =
+ ConnectivityDiagnosticsCollector.getInstance();
+ if (collector != null) {
+ // IWLAN on U QPR3 release may cause failures in this test, see
+ // CarrierConfigSetupTest which is supposed to avoid the issue. Collect IWLAN
+ // related dumpsys if the test still fails.
+ collector.collectDumpsys("carrier_config", e);
+ collector.collectDumpsys("telecom", e);
+ collector.collectDumpsys("telephony_ims", e);
+ collector.collectDumpsys("telephony.registry", e);
+ }
+ throw e;
+ }
}
@Test
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 815c3a5..286e08c 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -117,13 +117,13 @@
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.PollPacketReader
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.RecorderCallback.CallbackEntry.Losing
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
-import com.android.testutils.PollPacketReader
import com.android.testutils.TestableNetworkAgent
import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAddKeepalivePacketFilter
import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnAutomaticReconnectDisabled
@@ -140,6 +140,7 @@
import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnValidationStatus
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.assertThrows
+import com.android.testutils.com.android.testutils.CarrierConfigRule
import com.android.testutils.runAsShell
import com.android.testutils.tryTest
import com.android.testutils.waitForIdle
@@ -149,8 +150,8 @@
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket
-import java.security.MessageDigest
import java.nio.ByteBuffer
+import java.security.MessageDigest
import java.time.Duration
import java.util.Arrays
import java.util.Random
@@ -167,6 +168,7 @@
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
@@ -178,10 +180,12 @@
import org.mockito.Mockito.verify
private const val TAG = "NetworkAgentTest"
+
// This test doesn't really have a constraint on how fast the methods should return. If it's
// going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio
// without affecting the run time of successful runs. Thus, set a very high timeout.
private const val DEFAULT_TIMEOUT_MS = 5000L
+
// When waiting for a NetworkCallback to determine there was no timeout, waiting is the
// only possible thing (the relevant handler is the one in the real ConnectivityService,
// and then there is the Binder call), so have a short timeout for this as it will be
@@ -223,6 +227,9 @@
@IgnoreUpTo(Build.VERSION_CODES.R)
@RunWith(DevSdkIgnoreRunner::class)
class NetworkAgentTest {
+ @get:Rule
+ val carrierConfigRule = CarrierConfigRule()
+
private val LOCAL_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.1")
private val REMOTE_IPV4_ADDRESS = InetAddresses.parseNumericAddress("192.0.2.2")
@@ -378,8 +385,12 @@
// Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
requestNetwork(makeTestNetworkRequest(specifier), callback)
val nc = makeTestNetworkCapabilities(specifier, transports)
- val agent = createNetworkAgent(context, initialConfig = initialConfig, initialLp = lp,
- initialNc = nc)
+ val agent = createNetworkAgent(
+ context,
+ initialConfig = initialConfig,
+ initialLp = lp,
+ initialNc = nc
+ )
agent.setTeardownDelayMillis(0)
// Connect the agent and verify initial status callbacks.
agent.register()
@@ -414,7 +425,8 @@
private fun createTunInterface(addrs: Collection<LinkAddress> = emptyList()):
TestNetworkInterface = realContext.getSystemService(
- TestNetworkManager::class.java)!!.createTunInterface(addrs).also {
+ TestNetworkManager::class.java
+ )!!.createTunInterface(addrs).also {
ifacesToCleanUp.add(it)
}
@@ -546,9 +558,12 @@
@Test
fun testSocketKeepalive(): Unit = createNetworkAgentWithFakeCS().let { agent ->
val packet = NattKeepalivePacketData(
- LOCAL_IPV4_ADDRESS /* srcAddress */, 1234 /* srcPort */,
- REMOTE_IPV4_ADDRESS /* dstAddress */, 4567 /* dstPort */,
- ByteArray(100 /* size */))
+ LOCAL_IPV4_ADDRESS /* srcAddress */,
+ 1234 /* srcPort */,
+ REMOTE_IPV4_ADDRESS /* dstAddress */,
+ 4567 /* dstPort */,
+ ByteArray(100 /* size */)
+ )
val slot = 4
val interval = 37
@@ -653,8 +668,13 @@
uid: Int,
expectUidsPresent: Boolean
) {
- doTestAllowedUids(intArrayOf(transport), uid, expectUidsPresent,
- specifier = null, transportInfo = null)
+ doTestAllowedUids(
+ intArrayOf(transport),
+ uid,
+ expectUidsPresent,
+ specifier = null,
+ transportInfo = null
+ )
}
private fun doTestAllowedUidsWithSubId(
@@ -689,15 +709,16 @@
private fun setHoldCarrierPrivilege(hold: Boolean, subId: Int) {
fun getCertHash(): String {
- val pkgInfo = realContext.packageManager.getPackageInfo(realContext.opPackageName,
- PackageManager.GET_SIGNATURES)
+ val pkgInfo = realContext.packageManager.getPackageInfo(
+ realContext.opPackageName,
+ PackageManager.GET_SIGNATURES
+ )
val digest = MessageDigest.getInstance("SHA-256")
val certHash = digest.digest(pkgInfo.signatures!![0]!!.toByteArray())
return UiccUtil.bytesToHexString(certHash)!!
}
val tm = realContext.getSystemService(TelephonyManager::class.java)!!
- val ccm = realContext.getSystemService(CarrierConfigManager::class.java)!!
val cv = ConditionVariable()
val cpb = PrivilegeWaiterCallback(cv)
@@ -717,16 +738,13 @@
return@tryTest
}
cv.close()
- runAsShell(MODIFY_PHONE_STATE) {
- val carrierConfigs = if (hold) {
- PersistableBundle().also {
- it.putStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
- arrayOf(getCertHash()))
- }
- } else {
- null
- }
- ccm.overrideConfig(subId, carrierConfigs)
+ if (hold) {
+ carrierConfigRule.addConfigOverrides(subId, PersistableBundle().also {
+ it.putStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
+ arrayOf(getCertHash()))
+ })
+ } else {
+ carrierConfigRule.cleanUpNow()
}
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't change carrier privilege")
} cleanup {
@@ -799,14 +817,19 @@
val uid = try {
realContext.packageManager.getApplicationInfo(servicePackage, 0).uid
} catch (e: PackageManager.NameNotFoundException) {
- fail("$servicePackage could not be installed, please check the SuiteApkInstaller" +
- " installed CtsCarrierServicePackage.apk", e)
+ fail(
+ "$servicePackage could not be installed, please check the SuiteApkInstaller" +
+ " installed CtsCarrierServicePackage.apk",
+ e
+ )
}
val tm = realContext.getSystemService(TelephonyManager::class.java)!!
val defaultSubId = SubscriptionManager.getDefaultSubscriptionId()
- assertTrue(defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- "getDefaultSubscriptionId returns INVALID_SUBSCRIPTION_ID")
+ assertTrue(
+ defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "getDefaultSubscriptionId returns INVALID_SUBSCRIPTION_ID"
+ )
tryTest {
// This process is not the carrier service UID, so allowedUids should be ignored in all
// the following cases.
@@ -910,8 +933,10 @@
// If using the int ranking, agent1 must be upgraded to a better score so that there is
// no ambiguity when agent2 connects that agent1 is still better. If using policy
// ranking, this is not necessary.
- agent1.sendNetworkScore(NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE)
- .build())
+ agent1.sendNetworkScore(
+ NetworkScore.Builder().setLegacyInt(BETTER_NETWORK_SCORE)
+ .build()
+ )
// Connect the second agent.
val (agent2, _) = createConnectedNetworkAgent()
@@ -920,10 +945,12 @@
// virtue of already satisfying the request.
callback.assertNoCallback(NO_CALLBACK_TIMEOUT)
// Now downgrade the score and expect the callback now prefers agent2
- agent1.sendNetworkScore(NetworkScore.Builder()
+ agent1.sendNetworkScore(
+ NetworkScore.Builder()
.setLegacyInt(WORSE_NETWORK_SCORE)
.setExiting(true)
- .build())
+ .build()
+ )
callback.expect<Available>(agent2.network!!)
// tearDown() will unregister the requests and agents
@@ -968,16 +995,20 @@
// Check that the default network's transport is propagated to the VPN.
var vpnNc = mCM.getNetworkCapabilities(agent.network!!)
assertNotNull(vpnNc)
- assertEquals(VpnManager.TYPE_VPN_SERVICE,
- (vpnNc.transportInfo as VpnTransportInfo).type)
+ assertEquals(
+ VpnManager.TYPE_VPN_SERVICE,
+ (vpnNc.transportInfo as VpnTransportInfo).type
+ )
assertEquals(mySessionId, (vpnNc.transportInfo as VpnTransportInfo).sessionId)
val testAndVpn = intArrayOf(TRANSPORT_TEST, TRANSPORT_VPN)
assertTrue(vpnNc.hasAllTransports(testAndVpn))
assertFalse(vpnNc.hasCapability(NET_CAPABILITY_NOT_VPN))
- assertTrue(vpnNc.hasAllTransports(defaultNetworkTransports),
- "VPN transports ${Arrays.toString(vpnNc.transportTypes)}" +
- " lacking transports from ${Arrays.toString(defaultNetworkTransports)}")
+ assertTrue(
+ vpnNc.hasAllTransports(defaultNetworkTransports),
+ "VPN transports ${Arrays.toString(vpnNc.transportTypes)}" +
+ " lacking transports from ${Arrays.toString(defaultNetworkTransports)}"
+ )
// Check that when no underlying networks are announced the underlying transport disappears.
agent.setUnderlyingNetworks(listOf<Network>())
@@ -999,9 +1030,11 @@
// underlying networks, and because not congested, not roaming, and not suspended are the
// default anyway. It's still useful as an extra check though.
vpnNc = mCM.getNetworkCapabilities(agent.network!!)!!
- for (cap in listOf(NET_CAPABILITY_NOT_CONGESTED,
- NET_CAPABILITY_NOT_ROAMING,
- NET_CAPABILITY_NOT_SUSPENDED)) {
+ for (cap in listOf(
+ NET_CAPABILITY_NOT_CONGESTED,
+ NET_CAPABILITY_NOT_ROAMING,
+ NET_CAPABILITY_NOT_SUSPENDED
+ )) {
val capStr = valueToString(NetworkCapabilities::class.java, "NET_CAPABILITY_", cap)
if (defaultNetworkCapabilities.hasCapability(cap) && !vpnNc.hasCapability(cap)) {
fail("$capStr not propagated from underlying: $defaultNetworkCapabilities")
@@ -1026,13 +1059,15 @@
doReturn(mockCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE)
val agent = createNetworkAgent(mockContext)
agent.register()
- verify(mockCm).registerNetworkAgent(any(),
- argThat<NetworkInfo> { it.detailedState == NetworkInfo.DetailedState.CONNECTING },
- any(LinkProperties::class.java),
- any(NetworkCapabilities::class.java),
- any(NetworkScore::class.java),
- any(NetworkAgentConfig::class.java),
- eq(NetworkProvider.ID_NONE))
+ verify(mockCm).registerNetworkAgent(
+ any(),
+ argThat<NetworkInfo> { it.detailedState == NetworkInfo.DetailedState.CONNECTING },
+ any(LinkProperties::class.java),
+ any(NetworkCapabilities::class.java),
+ any(NetworkScore::class.java),
+ any(NetworkAgentConfig::class.java),
+ eq(NetworkProvider.ID_NONE)
+ )
}
@Test
@@ -1079,8 +1114,10 @@
@Test
fun testValidationStatus() = createNetworkAgentWithFakeCS().let { agent ->
val uri = Uri.parse("http://www.google.com")
- mFakeConnectivityService.agent.onValidationStatusChanged(VALID_NETWORK,
- uri.toString())
+ mFakeConnectivityService.agent.onValidationStatusChanged(
+ VALID_NETWORK,
+ uri.toString()
+ )
agent.expectCallback<OnValidationStatus>().let {
assertEquals(it.status, VALID_NETWORK)
assertEquals(it.uri, uri)
@@ -1155,7 +1192,8 @@
}
assertFailsWith<IllegalArgumentException> {
agentWeaker.setLingerDuration(Duration.ofMillis(
- NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - 1))
+ NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - 1
+ ))
}
// Verify valid linger timer can be set, but it should not take effect since the network
// is still needed.
@@ -1165,11 +1203,14 @@
agentWeaker.setLingerDuration(Duration.ofMillis(NetworkAgent.MIN_LINGER_TIMER_MS.toLong()))
// Make a listener which can observe agentWeaker lost later.
val callbackWeaker = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
- registerNetworkCallback(NetworkRequest.Builder()
+ registerNetworkCallback(
+ NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifierWeaker))
- .build(), callbackWeaker)
+ .build(),
+ callbackWeaker
+ )
callbackWeaker.expectAvailableCallbacks(agentWeaker.network!!)
// Connect the agentStronger with a score better than agentWeaker. Verify the callback for
@@ -1186,8 +1227,10 @@
val expectedRemainingLingerDuration = lingerStart +
NetworkAgent.MIN_LINGER_TIMER_MS.toLong() - SystemClock.elapsedRealtime()
// If the available callback is too late. The remaining duration will be reduced.
- assertTrue(expectedRemainingLingerDuration > 0,
- "expected remaining linger duration is $expectedRemainingLingerDuration")
+ assertTrue(
+ expectedRemainingLingerDuration > 0,
+ "expected remaining linger duration is $expectedRemainingLingerDuration"
+ )
callbackWeaker.assertNoCallback(expectedRemainingLingerDuration)
callbackWeaker.expect<Lost>(agentWeaker.network!!)
}
@@ -1205,20 +1248,24 @@
assertEquals(imsi, testNetworkSnapshot!!.subscriberId)
}
- @Test
- @IgnoreUpTo(Build.VERSION_CODES.R)
// TODO: Refactor helper functions to util class and move this test case to
// {@link android.net.cts.ConnectivityManagerTest}.
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R)
fun testRegisterBestMatchingNetworkCallback() {
// Register best matching network callback with additional condition that will be
// exercised later. This assumes the test network agent has NOT_VCN_MANAGED in it and
// does not have NET_CAPABILITY_TEMPORARILY_NOT_METERED.
val bestMatchingCb = TestableNetworkCallback(timeoutMs = DEFAULT_TIMEOUT_MS)
- registerBestMatchingNetworkCallback(NetworkRequest.Builder()
+ registerBestMatchingNetworkCallback(
+ NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(TRANSPORT_TEST)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
- .build(), bestMatchingCb, mHandlerThread.threadHandler)
+ .build(),
+ bestMatchingCb,
+ mHandlerThread.threadHandler
+ )
val (agent1, _) = createConnectedNetworkAgent(specifier = "AGENT-1")
bestMatchingCb.expectAvailableThenValidatedCallbacks(agent1.network!!)
@@ -1296,8 +1343,10 @@
}
fun assertNoCallback() {
- assertNull(history.poll(NO_CALLBACK_TIMEOUT),
- "Callback received")
+ assertNull(
+ history.poll(NO_CALLBACK_TIMEOUT),
+ "Callback received"
+ )
}
}
@@ -1312,7 +1361,8 @@
private fun setupForQosDatagram() = setupForQosCallbackTest {
agent: TestableNetworkAgent -> DatagramSocket(
- InetSocketAddress(InetAddress.getLoopbackAddress(), 0))
+ InetSocketAddress(InetAddress.getLoopbackAddress(), 0)
+ )
.also { assertNotNull(agent.network?.bindSocket(it)) }
}
@@ -1345,7 +1395,8 @@
assertFailsWith<QosCallbackRegistrationException>(
"The same callback cannot be " +
- "registered more than once without first being unregistered") {
+ "registered more than once without first being unregistered"
+ ) {
mCM.registerQosCallback(info, executor, qosCallback)
}
} finally {
@@ -1438,8 +1489,10 @@
qosCallback.expectCallback<OnQosSessionAvailable>()
// Check that onError is coming through correctly
- agent.sendQosCallbackError(callbackId,
- QosCallbackException.EX_TYPE_FILTER_NOT_SUPPORTED)
+ agent.sendQosCallbackError(
+ callbackId,
+ QosCallbackException.EX_TYPE_FILTER_NOT_SUPPORTED
+ )
qosCallback.expectCallback<OnError> {
it.ex.cause is UnsupportedOperationException
}
@@ -1534,13 +1587,20 @@
val remoteAddresses = ArrayList<InetSocketAddress>()
remoteAddresses.add(InetSocketAddress(REMOTE_ADDRESS, 80))
return EpsBearerQosSessionAttributes(
- qci, 2, 3, 4, 5,
- remoteAddresses
+ qci,
+ 2,
+ 3,
+ 4,
+ 5,
+ remoteAddresses
)
}
- fun sendAndExpectUdpPacket(net: Network,
- reader: PollPacketReader, iface: TestNetworkInterface) {
+ fun sendAndExpectUdpPacket(
+ net: Network,
+ reader: PollPacketReader,
+ iface: TestNetworkInterface
+ ) {
val s = Os.socket(AF_INET6, SOCK_DGRAM, 0)
net.bindSocket(s)
val content = ByteArray(16)
@@ -1553,8 +1613,11 @@
it[IPV6_PROTOCOL_OFFSET].toInt() == IPPROTO_UDP &&
Arrays.equals(content, it.copyOfRange(udpStart, udpStart + content.size))
}
- assertNotNull(match, "Did not receive matching packet on ${iface.interfaceName} " +
- " after ${DEFAULT_TIMEOUT_MS}ms")
+ assertNotNull(
+ match,
+ "Did not receive matching packet on ${iface.interfaceName} " +
+ " after ${DEFAULT_TIMEOUT_MS}ms"
+ )
}
fun createInterfaceAndReader(): Triple<TestNetworkInterface, PollPacketReader, LinkProperties> {
@@ -1750,8 +1813,10 @@
assertNotNull(wifiSpecifier)
assertTrue(wifiSpecifier is EthernetNetworkSpecifier)
- val wifiNc = makeTestNetworkCapabilities(wifiSpecifier.interfaceName,
- intArrayOf(TRANSPORT_WIFI))
+ val wifiNc = makeTestNetworkCapabilities(
+ wifiSpecifier.interfaceName,
+ intArrayOf(TRANSPORT_WIFI)
+ )
wifiAgent.sendNetworkCapabilities(wifiNc)
val wifiLp = mCM.getLinkProperties(wifiNetwork)!!
val newRoute = RouteInfo(IpPrefix("192.0.2.42/24"))
@@ -1822,8 +1887,12 @@
val nc = makeTestNetworkCapabilities(ifName, transports).also {
if (transports.contains(TRANSPORT_VPN)) {
val sessionId = "NetworkAgentTest-${Process.myPid()}"
- it.setTransportInfo(VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, sessionId,
- /*bypassable=*/ false, /*longLivedTcpConnectionsExpensive=*/ false))
+ it.setTransportInfo(VpnTransportInfo(
+ VpnManager.TYPE_VPN_PLATFORM,
+ sessionId,
+ /*bypassable=*/ false,
+ /*longLivedTcpConnectionsExpensive=*/ false
+ ))
it.underlyingNetworks = listOf()
}
}
@@ -1868,9 +1937,11 @@
listenCallback.expect<Available>(network)
requestCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability(
- NET_CAPABILITY_TEMPORARILY_NOT_METERED) }
+ NET_CAPABILITY_TEMPORARILY_NOT_METERED
+ ) }
listenCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability(
- NET_CAPABILITY_TEMPORARILY_NOT_METERED) }
+ NET_CAPABILITY_TEMPORARILY_NOT_METERED
+ ) }
requestCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) }
listenCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) }
@@ -1896,7 +1967,8 @@
fun testNativeNetworkCreation_PhysicalNetwork() {
doTestNativeNetworkCreation(
expectCreatedImmediately = SHOULD_CREATE_NETWORKS_IMMEDIATELY,
- intArrayOf(TRANSPORT_CELLULAR))
+ intArrayOf(TRANSPORT_CELLULAR)
+ )
}
@Test
diff --git a/tests/cts/net/src/android/net/cts/NetworkReservationTest.kt b/tests/cts/net/src/android/net/cts/NetworkReservationTest.kt
index 0b10ef6..f05bf15 100644
--- a/tests/cts/net/src/android/net/cts/NetworkReservationTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkReservationTest.kt
@@ -33,6 +33,7 @@
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
+import android.platform.test.annotations.AppModeFull
import androidx.test.platform.app.InstrumentationRegistry
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
@@ -71,6 +72,7 @@
private const val NO_CB_TIMEOUT_MS = 200L
// TODO: integrate with CSNetworkReservationTest and move to common tests.
+@AppModeFull(reason = "CHANGE_NETWORK_STATE, MANAGE_TEST_NETWORKS not grantable to instant apps")
@ConnectivityModuleTest
@RunWith(DevSdkIgnoreRunner::class)
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
diff --git a/tests/cts/netpermission/updatestatspermission/Android.bp b/tests/cts/netpermission/updatestatspermission/Android.bp
index b324dc8..0ff98e7 100644
--- a/tests/cts/netpermission/updatestatspermission/Android.bp
+++ b/tests/cts/netpermission/updatestatspermission/Android.bp
@@ -33,6 +33,7 @@
// Tag this module as a cts test artifact
test_suites: [
+ "automotive-general-tests",
"cts",
"general-tests",
],
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 2420026..d103f75 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -88,9 +88,11 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.net.flags.Flags;
import com.android.testutils.ParcelUtils;
+import com.android.testutils.com.android.testutils.CarrierConfigRule;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -106,6 +108,8 @@
@RunWith(AndroidJUnit4.class)
public class TetheringManagerTest {
+ @Rule
+ public final CarrierConfigRule mCarrierConfigRule = new CarrierConfigRule();
private Context mContext;
@@ -551,22 +555,13 @@
// Override carrier config to ignore entitlement check.
final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, false);
- overrideCarrierConfig(bundle);
+ mCarrierConfigRule.addConfigOverrides(
+ SubscriptionManager.getDefaultSubscriptionId(), bundle);
// Verify that requestLatestTetheringEntitlementResult() can get entitlement
// result TETHER_ERROR_NO_ERROR due to provisioning bypassed.
assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult(
TETHERING_WIFI, false, c -> c.run(), listener), TETHER_ERROR_NO_ERROR);
-
- // Reset carrier config.
- overrideCarrierConfig(null);
- }
-
- private void overrideCarrierConfig(PersistableBundle bundle) {
- final CarrierConfigManager configManager = (CarrierConfigManager) mContext
- .getSystemService(Context.CARRIER_CONFIG_SERVICE);
- final int subId = SubscriptionManager.getDefaultSubscriptionId();
- runAsShell(MODIFY_PHONE_STATE, () -> configManager.overrideConfig(subId, bundle));
}
private boolean isTetheringApnRequired() {
diff --git a/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt b/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt
index ffa9828..5a7515e 100644
--- a/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt
+++ b/tests/unit/java/com/android/server/L2capNetworkProviderTest.kt
@@ -81,6 +81,7 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
doReturn(provider).`when`(deps).getNetworkProvider(any(), any())
+ doReturn(handlerThread).`when`(deps).getHandlerThread()
doReturn(cm).`when`(context).getSystemService(eq(ConnectivityManager::class.java))
doReturn(pm).`when`(context).getPackageManager()
doReturn(true).`when`(pm).hasSystemFeature(FEATURE_BLUETOOTH_LE)
@@ -94,7 +95,7 @@
@Test
fun testNetworkProvider_registeredWhenSupported() {
- L2capNetworkProvider(deps, context, handler)
+ L2capNetworkProvider(deps, context).start()
verify(cm).registerNetworkProvider(eq(provider))
verify(provider).registerNetworkOffer(any(), any(), any(), any())
}
@@ -102,13 +103,13 @@
@Test
fun testNetworkProvider_notRegisteredWhenNotSupported() {
doReturn(false).`when`(pm).hasSystemFeature(FEATURE_BLUETOOTH_LE)
- L2capNetworkProvider(deps, context, handler)
+ L2capNetworkProvider(deps, context).start()
verify(cm, never()).registerNetworkProvider(eq(provider))
}
fun doTestBlanketOfferIgnoresRequest(request: NetworkRequest) {
clearInvocations(provider)
- L2capNetworkProvider(deps, context, handler)
+ L2capNetworkProvider(deps, context).start()
val blanketOfferCaptor = ArgumentCaptor.forClass(NetworkOfferCallback::class.java)
verify(provider).registerNetworkOffer(any(), any(), any(), blanketOfferCaptor.capture())
@@ -122,7 +123,7 @@
reservation: NetworkCapabilities
) {
clearInvocations(provider)
- L2capNetworkProvider(deps, context, handler)
+ L2capNetworkProvider(deps, context).start()
val blanketOfferCaptor = ArgumentCaptor.forClass(NetworkOfferCallback::class.java)
verify(provider).registerNetworkOffer(any(), any(), any(), blanketOfferCaptor.capture())
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index e6aba22..b7cfaf9 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -166,9 +166,10 @@
EthernetTracker.parseStaticIpConfiguration(configAsString));
}
- private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) {
+ private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearDefaults) {
final NetworkCapabilities.Builder builder =
- clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
+ clearDefaults
+ ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
: new NetworkCapabilities.Builder();
return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
@@ -176,21 +177,20 @@
}
/**
- * Test: Attempt to create a capabilties with various valid sets of capabilities/transports
+ * Test: Attempt to create a capabilities with various valid sets of capabilities/transports
*/
@Test
public void createNetworkCapabilities() {
-
// Particularly common expected results
- NetworkCapabilities defaultEthernetCleared =
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ NetworkCapabilities defaultCapabilities =
+ makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build();
NetworkCapabilities ethernetClearedWithCommonCaps =
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ makeEthernetCapabilitiesBuilder(true /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
@@ -200,89 +200,71 @@
.addCapability(15)
.build();
- // Empty capabilities and transports lists with a "please clear defaults" should
- // yield an empty capabilities set with TRANPORT_ETHERNET
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "");
+ // Empty capabilities and transports should return the default capabilities set
+ // with TRANSPORT_ETHERNET
+ assertParsedNetworkCapabilities(defaultCapabilities, "", "");
- // Empty capabilities and transports without the clear defaults flag should return the
- // default capabilities set with TRANSPORT_ETHERNET
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(false /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .build(),
- false, "", "");
-
- // A list of capabilities without the clear defaults flag should return the default
- // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET
- assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(false /* clearAll */)
- .setLinkUpstreamBandwidthKbps(100000)
- .setLinkDownstreamBandwidthKbps(100000)
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .addCapability(11)
- .addCapability(12)
- .build(),
- false, "11,12", "");
-
- // Adding a list of capabilities with a clear defaults will leave exactly those capabilities
- // with a default TRANSPORT_ETHERNET since no overrides are specified
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", "");
+ // Adding a list of capabilities will leave exactly those capabilities with a default
+ // TRANSPORT_ETHERNET since no overrides are specified
+ assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "12,13,14,15", "");
// Adding any invalid capabilities to the list will cause them to be ignored
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", "");
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", "");
+ assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "12,13,14,15,65,73", "");
+ assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "12,13,14,15,abcdefg", "");
// Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport
- // and apply only the override to the capabiltities object
+ // and apply only the override to the capabilities object
assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addTransportType(0)
.build(),
- true, "", "0");
+ "",
+ "0");
assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addTransportType(1)
.build(),
- true, "", "1");
+ "",
+ "1");
assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addTransportType(2)
.build(),
- true, "", "2");
+ "",
+ "2");
assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ makeEthernetCapabilitiesBuilder(false /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addTransportType(3)
.build(),
- true, "", "3");
+ "",
+ "3");
- // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "4");
+ // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANSPORT_ETHERNET
+ assertParsedNetworkCapabilities(defaultCapabilities, "", "4");
// "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE
// conversion. When that becomes available, this test must be updated
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "5");
+ assertParsedNetworkCapabilities(defaultCapabilities, "", "5");
// "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE
// conversion. When that becomes available, this test must be updated
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "6");
+ assertParsedNetworkCapabilities(defaultCapabilities, "", "6");
// Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET
- assertParsedNetworkCapabilities(defaultEthernetCleared,true, "", "100");
- assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg");
+ assertParsedNetworkCapabilities(defaultCapabilities, "", "100");
+ assertParsedNetworkCapabilities(defaultCapabilities, "", "abcdefg");
// Ensure the adding of both capabilities and transports work
assertParsedNetworkCapabilities(
- makeEthernetCapabilitiesBuilder(true /* clearAll */)
+ makeEthernetCapabilitiesBuilder(true /* clearDefaults */)
.setLinkUpstreamBandwidthKbps(100000)
.setLinkDownstreamBandwidthKbps(100000)
.addCapability(12)
@@ -291,17 +273,21 @@
.addCapability(15)
.addTransportType(3)
.build(),
- true, "12,13,14,15", "3");
+ "12,13,14,15",
+ "3");
// Ensure order does not matter for capability list
- assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", "");
+ assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, "13,12,15,14", "");
}
- private void assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities,
- boolean clearCapabilties, String configCapabiltiies,String configTransports) {
- assertEquals(expectedNetworkCapabilities,
- EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies,
- configTransports).build());
+ private void assertParsedNetworkCapabilities(
+ NetworkCapabilities expectedNetworkCapabilities,
+ String configCapabiltiies,
+ String configTransports) {
+ assertEquals(
+ expectedNetworkCapabilities,
+ EthernetTracker.createNetworkCapabilities(configCapabiltiies, configTransports)
+ .build());
}
@Test
diff --git a/tests/unit/jni/Android.bp b/tests/unit/jni/Android.bp
index 50971e7..1a833e1 100644
--- a/tests/unit/jni/Android.bp
+++ b/tests/unit/jni/Android.bp
@@ -42,7 +42,7 @@
],
static_libs: [
"libnet_utils_device_common_bpfjni",
- "libnet_utils_device_common_timerfdjni",
+ "libserviceconnectivityjni",
"libtcutils",
],
shared_libs: [
diff --git a/tests/unit/jni/android_net_frameworktests_util/onload.cpp b/tests/unit/jni/android_net_frameworktests_util/onload.cpp
index a0ce4f8..f70b04b 100644
--- a/tests/unit/jni/android_net_frameworktests_util/onload.cpp
+++ b/tests/unit/jni/android_net_frameworktests_util/onload.cpp
@@ -24,7 +24,7 @@
int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
int register_com_android_net_module_util_TcUtils(JNIEnv* env, char const* class_name);
-int register_com_android_net_module_util_TimerFdUtils(JNIEnv *env,
+int register_com_android_net_module_util_ServiceConnectivityJni(JNIEnv *env,
char const *class_name);
extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
@@ -40,8 +40,8 @@
if (register_com_android_net_module_util_TcUtils(env,
"android/net/frameworktests/util/TcUtils") < 0) return JNI_ERR;
- if (register_com_android_net_module_util_TimerFdUtils(
- env, "android/net/frameworktests/util/TimerFdUtils") < 0)
+ if (register_com_android_net_module_util_ServiceConnectivityJni(
+ env, "android/net/frameworktests/util/ServiceConnectivityJni") < 0)
return JNI_ERR;
return JNI_VERSION_1_6;