Merge "Specify the desired callback type to deflake the tests" into main
diff --git a/Cronet/tests/mts/AndroidTest.xml b/Cronet/tests/mts/AndroidTest.xml
index bccbe29..513b988 100644
--- a/Cronet/tests/mts/AndroidTest.xml
+++ b/Cronet/tests/mts/AndroidTest.xml
@@ -53,6 +53,8 @@
<option name="exclude-filter" value="org.chromium.net.NetworkChangesTest" />
<!-- b/316550794 -->
<option name="exclude-filter" value="org.chromium.net.impl.CronetLoggerTest#testEngineCreation" />
+ <!-- b/327182569 -->
+ <option name="exclude-filter" value="org.chromium.net.urlconnection.CronetURLStreamHandlerFactoryTest#testSetUrlStreamFactoryUsesCronetForNative" />
<option name="hidden-api-checks" value="false"/>
<option name="isolated-storage" value="false"/>
</test>
@@ -62,4 +64,4 @@
class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
<option name="mainline-module-package-name" value="com.google.android.tethering" />
</object>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/Cronet/tools/import/copy.bara.sky b/Cronet/tools/import/copy.bara.sky
deleted file mode 100644
index 61e3ba4..0000000
--- a/Cronet/tools/import/copy.bara.sky
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright 2023 Google Inc. All rights reserved.
-#
-# 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.
-
-common_excludes = [
- # Exclude all Android build files
- "**/Android.bp",
- "**/Android.mk",
-
- # Exclude existing *OWNERS files
- "**/*OWNERS",
- "**/.git/**",
- "**/.gitignore",
-]
-
-cronet_origin_files = glob(
- include = [
- "base/**",
- "build/**",
- "build/buildflag.h",
- "chrome/VERSION",
- "components/cronet/**",
- "components/metrics/**",
- "components/nacl/**",
- "components/prefs/**",
- "crypto/**",
- "ipc/**",
- "net/**",
- # Note: Only used for tests.
- "testing/**",
- "url/**",
- "LICENSE",
- ],
- exclude = common_excludes + [
- # Per aosp/2367109
- "build/android/CheckInstallApk-debug.apk",
- "build/android/unused_resources/**",
- "build/linux/**",
-
- # Per aosp/2374766
- "components/cronet/ios/**",
- "components/cronet/native/**",
-
- # Per aosp/2399270
- "testing/buildbot/**",
-
- # Exclude all third-party directories. Those are specified explicitly
- # below, so no dependency can accidentally creep in.
- "**/third_party/**",
- ],
-) + glob(
- # Explicitly include third-party dependencies.
- # Note: some third-party dependencies include a third_party folder within
- # them. So far, this has not become a problem.
- include = [
- "base/third_party/cityhash/**",
- "base/third_party/cityhash_v103/**",
- "base/third_party/double_conversion/**",
- "base/third_party/dynamic_annotations/**",
- "base/third_party/icu/**",
- "base/third_party/nspr/**",
- "base/third_party/superfasthash/**",
- "base/third_party/valgrind/**",
- # Those are temporarily needed until Chromium finish the migration
- # of libc++[abi]
- "buildtools/third_party/libc++/**",
- "buildtools/third_party/libc++abi/**",
- # Note: Only used for tests.
- "net/third_party/nist-pkits/**",
- "net/third_party/quiche/**",
- "net/third_party/uri_template/**",
- "third_party/abseil-cpp/**",
- "third_party/android_ndk/sources/android/cpufeatures/**",
- "third_party/ashmem/**",
- "third_party/boringssl/**",
- "third_party/brotli/**",
- # Note: Only used for tests.
- "third_party/ced/**",
- "third_party/cpu_features/**",
- # Note: Only used for tests.
- "third_party/google_benchmark/**",
- # Note: Only used for tests.
- "third_party/googletest/**",
- "third_party/icu/**",
- "third_party/jni_zero/**",
- "third_party/libc++/**",
- "third_party/libc++abi/**",
- "third_party/libevent/**",
- # Note: Only used for tests.
- "third_party/libxml/**",
- # Note: Only used for tests.
- "third_party/lss/**",
- "third_party/metrics_proto/**",
- "third_party/modp_b64/**",
- "third_party/protobuf/**",
- # Note: Only used for tests.
- "third_party/quic_trace/**",
- # Note: Cronet currently uses Android's zlib
- # "third_party/zlib/**",
- "url/third_party/mozilla/**",
- ],
- exclude = common_excludes,
-)
-
-core.workflow(
- name = "import_cronet",
- authoring = authoring.overwrite("Cronet Mainline Eng <cronet-mainline-eng+copybara@google.com>"),
- # Origin folder is specified via source_ref argument, see import_cronet.sh
- origin = folder.origin(),
- origin_files = cronet_origin_files,
- destination = git.destination(
- # The destination URL is set by the invoking script.
- url = "overwritten/by/script",
- push = "upstream-import",
- ),
- mode = "SQUASH",
-)
diff --git a/Cronet/tools/import/import_cronet.sh b/Cronet/tools/import/import_cronet.sh
deleted file mode 100755
index 0f04af7..0000000
--- a/Cronet/tools/import/import_cronet.sh
+++ /dev/null
@@ -1,146 +0,0 @@
-#!/bin/bash
-
-# Copyright 2023 Google Inc. All rights reserved.
-#
-# 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.
-
-# Script to invoke copybara locally to import Cronet into Android.
-# Inputs:
-# Environment:
-# ANDROID_BUILD_TOP: path the root of the current Android directory.
-# Arguments:
-# -l rev: The last revision that was imported.
-# Optional Arguments:
-# -n rev: The new revision to import.
-# -f: Force copybara to ignore a failure to find the last imported revision.
-
-set -e -x
-
-OPTSTRING=fl:n:
-
-usage() {
- cat <<EOF
-Usage: import_cronet.sh -n new-rev [-l last-rev] [-f]
-EOF
- exit 1
-}
-
-COPYBARA_FOLDER_ORIGIN="/tmp/copybara-origin"
-
-#######################################
-# Create local upstream-import branch in external/cronet.
-# Globals:
-# ANDROID_BUILD_TOP
-# Arguments:
-# none
-#######################################
-setup_upstream_import_branch() {
- local git_dir="${ANDROID_BUILD_TOP}/external/cronet"
-
- (cd "${git_dir}" && git fetch aosp upstream-import:upstream-import)
-}
-
-#######################################
-# Setup folder.origin for copybara inside /tmp
-# Globals:
-# COPYBARA_FOLDER_ORIGIN
-# Arguments:
-# new_rev, string
-#######################################
-setup_folder_origin() (
- local _new_rev=$1
- mkdir -p "${COPYBARA_FOLDER_ORIGIN}"
- cd "${COPYBARA_FOLDER_ORIGIN}"
-
- if [ -d src ]; then
- (cd src && git fetch --tags && git checkout "${_new_rev}")
- else
- # For this to work _new_rev must be a branch or a tag.
- git clone --depth=1 --branch "${_new_rev}" https://chromium.googlesource.com/chromium/src.git
- fi
-
-
- cat <<EOF >.gclient
-solutions = [
- {
- "name": "src",
- "url": "https://chromium.googlesource.com/chromium/src.git",
- "managed": False,
- "custom_deps": {},
- "custom_vars": {},
- },
-]
-target_os = ["android"]
-EOF
- cd src
- # Set appropriate gclient flags to speed up syncing.
- gclient sync \
- --no-history \
- --shallow \
- --delete_unversioned_trees
-)
-
-#######################################
-# Runs the copybara import of Chromium
-# Globals:
-# ANDROID_BUILD_TOP
-# COPYBARA_FOLDER_ORIGIN
-# Arguments:
-# last_rev, string or empty
-# force, string or empty
-#######################################
-do_run_copybara() {
- local _last_rev=$1
- local _force=$2
-
- local -a flags
- flags+=(--git-destination-url="file://${ANDROID_BUILD_TOP}/external/cronet")
- flags+=(--repo-timeout 3m)
-
- # buildtools/third_party/libc++ contains an invalid symlink
- flags+=(--folder-origin-ignore-invalid-symlinks)
- flags+=(--git-no-verify)
-
- if [ ! -z "${_force}" ]; then
- flags+=(--force)
- fi
-
- if [ ! -z "${_last_rev}" ]; then
- flags+=(--last-rev "${_last_rev}")
- fi
-
- /google/bin/releases/copybara/public/copybara/copybara \
- "${flags[@]}" \
- "${ANDROID_BUILD_TOP}/packages/modules/Connectivity/Cronet/tools/import/copy.bara.sky" \
- import_cronet "${COPYBARA_FOLDER_ORIGIN}/src"
-}
-
-while getopts $OPTSTRING opt; do
- case "${opt}" in
- f) force=true ;;
- l) last_rev="${OPTARG}" ;;
- n) new_rev="${OPTARG}" ;;
- ?) usage ;;
- *) echo "'${opt}' '${OPTARG}'"
- esac
-done
-
-if [ -z "${new_rev}" ]; then
- echo "-n argument required"
- usage
-fi
-
-setup_upstream_import_branch
-setup_folder_origin "${new_rev}"
-do_run_copybara "${last_rev}" "${force}"
-
diff --git a/OWNERS_core_networking_xts b/OWNERS_core_networking_xts
index 7612210..b24e3ac 100644
--- a/OWNERS_core_networking_xts
+++ b/OWNERS_core_networking_xts
@@ -3,6 +3,8 @@
# For cherry-picks of CLs that are already merged in aosp/master, or flaky test fixes.
jchalard@google.com #{LAST_RESORT_SUGGESTION}
+# In addition to cherry-picks and flaky test fixes, also for APF firmware tests
+# (to verify correct behaviour of the wifi APF interpreter)
maze@google.com #{LAST_RESORT_SUGGESTION}
# In addition to cherry-picks and flaky test fixes, also for incremental changes on NsdManager tests
# to increase coverage for existing behavior, and testing of bug fixes in NsdManager
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 30bdf37..4bae221 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -103,9 +103,9 @@
"dscpPolicy.o",
"netd.o",
"offload.o",
- "offload@btf.o",
+ "offload@mainline.o",
"test.o",
- "test@btf.o",
+ "test@mainline.o",
],
apps: [
"ServiceConnectivityResources",
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 674cd98..1958aa8 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -94,13 +94,13 @@
}
bpf {
- name: "offload@btf.o",
- srcs: ["offload@btf.c"],
+ name: "offload@mainline.o",
+ srcs: ["offload@mainline.c"],
btf: true,
cflags: [
"-Wall",
"-Werror",
- "-DBTF",
+ "-DMAINLINE",
],
}
@@ -114,13 +114,13 @@
}
bpf {
- name: "test@btf.o",
- srcs: ["test@btf.c"],
+ name: "test@mainline.o",
+ srcs: ["test@mainline.c"],
btf: true,
cflags: [
"-Wall",
"-Werror",
- "-DBTF",
+ "-DMAINLINE",
],
}
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index 90f96a1..dd59dca 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -24,16 +24,16 @@
#define __kernel_udphdr udphdr
#include <linux/udp.h>
-#ifdef BTF
+#ifdef MAINLINE
// BTF is incompatible with bpfloaders < v0.10, hence for S (v0.2) we must
// ship a different file than for later versions, but we need bpfloader v0.25+
// for obj@ver.o support
#define BPFLOADER_MIN_VER BPFLOADER_OBJ_AT_VER_VERSION
-#else /* BTF */
+#else /* MAINLINE */
// The resulting .o needs to load on the Android S bpfloader
#define BPFLOADER_MIN_VER BPFLOADER_S_VERSION
#define BPFLOADER_MAX_VER BPFLOADER_OBJ_AT_VER_VERSION
-#endif /* BTF */
+#endif /* MAINLINE */
// Warning: values other than AID_ROOT don't work for map uid on BpfLoader < v0.21
#define TETHERING_UID AID_ROOT
diff --git a/bpf_progs/offload@btf.c b/bpf_progs/offload@mainline.c
similarity index 100%
rename from bpf_progs/offload@btf.c
rename to bpf_progs/offload@mainline.c
diff --git a/bpf_progs/test.c b/bpf_progs/test.c
index 70b08b7..e2b8ea5 100644
--- a/bpf_progs/test.c
+++ b/bpf_progs/test.c
@@ -18,16 +18,16 @@
#include <linux/in.h>
#include <linux/ip.h>
-#ifdef BTF
+#ifdef MAINLINE
// BTF is incompatible with bpfloaders < v0.10, hence for S (v0.2) we must
// ship a different file than for later versions, but we need bpfloader v0.25+
// for obj@ver.o support
#define BPFLOADER_MIN_VER BPFLOADER_OBJ_AT_VER_VERSION
-#else /* BTF */
+#else /* MAINLINE */
// The resulting .o needs to load on the Android S bpfloader
#define BPFLOADER_MIN_VER BPFLOADER_S_VERSION
#define BPFLOADER_MAX_VER BPFLOADER_OBJ_AT_VER_VERSION
-#endif /* BTF */
+#endif /* MAINLINE */
// Warning: values other than AID_ROOT don't work for map uid on BpfLoader < v0.21
#define TETHERING_UID AID_ROOT
diff --git a/bpf_progs/test@btf.c b/bpf_progs/test@mainline.c
similarity index 100%
rename from bpf_progs/test@btf.c
rename to bpf_progs/test@mainline.c
diff --git a/common/flags.aconfig b/common/flags.aconfig
index 19b522c..30931df 100644
--- a/common/flags.aconfig
+++ b/common/flags.aconfig
@@ -6,6 +6,7 @@
flag {
name: "set_data_saver_via_cm"
+ is_exported: true
namespace: "android_core_networking"
description: "Set data saver through ConnectivityManager API"
bug: "297836825"
@@ -13,6 +14,7 @@
flag {
name: "support_is_uid_networking_blocked"
+ is_exported: true
namespace: "android_core_networking"
description: "This flag controls whether isUidNetworkingBlocked is supported"
bug: "297836825"
@@ -20,6 +22,7 @@
flag {
name: "basic_background_restrictions_enabled"
+ is_exported: true
namespace: "android_core_networking"
description: "Block network access for apps in a low importance background state"
bug: "304347838"
@@ -27,6 +30,7 @@
flag {
name: "ipsec_transform_state"
+ is_exported: true
namespace: "android_core_networking_ipsec"
description: "The flag controls the access for getIpSecTransformState and IpSecTransformState"
bug: "308011229"
@@ -34,6 +38,7 @@
flag {
name: "tethering_request_with_soft_ap_config"
+ is_exported: true
namespace: "android_core_networking"
description: "The flag controls the access for the parcelable TetheringRequest with getSoftApConfiguration/setSoftApConfiguration API"
bug: "216524590"
@@ -41,6 +46,7 @@
flag {
name: "request_restricted_wifi"
+ is_exported: true
namespace: "android_core_networking"
description: "Flag for API to support requesting restricted wifi"
bug: "315835605"
@@ -48,6 +54,7 @@
flag {
name: "net_capability_local_network"
+ is_exported: true
namespace: "android_core_networking"
description: "Flag for local network capability API"
bug: "313000440"
@@ -55,6 +62,7 @@
flag {
name: "support_transport_satellite"
+ is_exported: true
namespace: "android_core_networking"
description: "Flag for satellite transport API"
bug: "320514105"
@@ -62,6 +70,7 @@
flag {
name: "nsd_subtypes_support_enabled"
+ is_exported: true
namespace: "android_core_networking"
description: "Flag for API to support nsd subtypes"
bug: "265095929"
@@ -69,6 +78,7 @@
flag {
name: "register_nsd_offload_engine_api"
+ is_exported: true
namespace: "android_core_networking"
description: "Flag for API to register nsd offload engine"
bug: "301713539"
diff --git a/common/nearby_flags.aconfig b/common/nearby_flags.aconfig
index b957d33..b733849 100644
--- a/common/nearby_flags.aconfig
+++ b/common/nearby_flags.aconfig
@@ -3,6 +3,7 @@
flag {
name: "powered_off_finding"
+ is_exported: true
namespace: "nearby"
description: "Controls whether the Powered Off Finding feature is enabled"
bug: "307898240"
diff --git a/common/thread_flags.aconfig b/common/thread_flags.aconfig
index 09595a6..43fc147 100644
--- a/common/thread_flags.aconfig
+++ b/common/thread_flags.aconfig
@@ -3,6 +3,7 @@
flag {
name: "thread_enabled"
+ is_exported: true
namespace: "thread_network"
description: "Controls whether the Android Thread feature is enabled"
bug: "301473012"
diff --git a/framework-t/src/android/net/nsd/AdvertisingRequest.java b/framework-t/src/android/net/nsd/AdvertisingRequest.java
index 2895b0c..6afb2d5 100644
--- a/framework-t/src/android/net/nsd/AdvertisingRequest.java
+++ b/framework-t/src/android/net/nsd/AdvertisingRequest.java
@@ -110,8 +110,9 @@
}
/**
- * Returns the time interval that the resource records may be cached on a DNS resolver or
- * {@code null} if not specified.
+ * Returns the time interval that the resource records may be cached on a DNS resolver.
+ *
+ * The value will be {@code null} if it's not specified with the {@link #Builder}.
*
* @hide
*/
@@ -161,7 +162,7 @@
dest.writeParcelable(mServiceInfo, flags);
dest.writeInt(mProtocolType);
dest.writeLong(mAdvertisingConfig);
- dest.writeLong(mTtl == null ? -1 : mTtl.getSeconds());
+ dest.writeLong(mTtl == null ? -1L : mTtl.getSeconds());
}
// @FlaggedApi(NsdManager.Flags.ADVERTISE_REQUEST_API)
@@ -205,7 +206,9 @@
* When registering a service, {@link NsdManager#FAILURE_BAD_PARAMETERS} will be returned
* if {@code ttl} is smaller than 30 seconds.
*
- * Note: only number of seconds of {@code ttl} is used.
+ * Note: the value after the decimal point (in unit of seconds) will be discarded. For
+ * example, {@code 30} seconds will be used when {@code Duration.ofSeconds(30L, 50_000L)}
+ * is provided.
*
* @param ttl the maximum duration that the DNS resource records will be cached
*
diff --git a/framework-t/src/android/net/nsd/NsdServiceInfo.java b/framework-t/src/android/net/nsd/NsdServiceInfo.java
index f4cc2ac..dba08a1 100644
--- a/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ b/framework-t/src/android/net/nsd/NsdServiceInfo.java
@@ -70,7 +70,8 @@
private int mInterfaceIndex;
- // The timestamp that all resource records associated with this service are considered invalid.
+ // The timestamp that one or more resource records associated with this service are considered
+ // invalid.
@Nullable
private Instant mExpirationTime;
@@ -497,7 +498,9 @@
/**
* Sets the timestamp after when this service is expired.
*
- * Note: only number of seconds of {@code expirationTime} is used.
+ * Note: the value after the decimal point (in unit of seconds) will be discarded. For
+ * example, {@code 30} seconds will be used when {@code Duration.ofSeconds(30L, 50_000L)}
+ * is provided.
*
* @hide
*/
diff --git a/framework/Android.bp b/framework/Android.bp
index 52f2c7c..aef0f74 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -116,7 +116,6 @@
static_libs: [
"httpclient_api",
"httpclient_impl",
- "http_client_logging",
// Framework-connectivity-pre-jarjar is identical to framework-connectivity
// implementation, but without the jarjar rules. However, framework-connectivity
// is not based on framework-connectivity-pre-jarjar, it's rebuilt from source
@@ -145,7 +144,6 @@
],
impl_only_static_libs: [
"httpclient_impl",
- "http_client_logging",
],
}
diff --git a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
index dfe5867..a80db85 100644
--- a/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
+++ b/framework/src/android/net/connectivity/ConnectivityCompatChanges.java
@@ -84,6 +84,21 @@
@ChangeId
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public static final long ENABLE_PLATFORM_MDNS_BACKEND = 270306772L;
+
+ /**
+ * Apps targeting Android V or higher receive network callbacks from local networks as default
+ *
+ * Apps targeting lower than {@link android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM} need
+ * to add {@link android.net.NetworkCapabilities#NET_CAPABILITY_LOCAL_NETWORK} to the
+ * {@link android.net.NetworkCapabilities} of the {@link android.net.NetworkRequest} to receive
+ * {@link android.net.ConnectivityManager.NetworkCallback} from local networks.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final long ENABLE_MATCH_LOCAL_NETWORK = 319212206L;
+
private ConnectivityCompatChanges() {
}
}
diff --git a/netbpfload/Android.bp b/netbpfload/Android.bp
index f397b37..c39b46c 100644
--- a/netbpfload/Android.bp
+++ b/netbpfload/Android.bp
@@ -19,19 +19,15 @@
}
install_symlink {
- name: "platform_ethtool_symlink",
+ name: "mainline_tethering_platform_components",
+
symlink_target: "/apex/com.android.tethering/bin/ethtool",
// installed_location is relative to /system because that's the default partition for soong
// modules, unless we add something like `system_ext_specific: true` like in hwservicemanager.
installed_location: "bin/ethtool",
-}
-phony {
- name: "mainline_tethering_platform_components",
- required: [
- "netbpfload",
- "platform_ethtool_symlink",
- ],
+ init_rc: ["netbpfload.rc"],
+ required: ["bpfloader"],
}
cc_binary {
@@ -65,9 +61,7 @@
// module "netbpfload" variant "android_x86_apex30": should support
// min_sdk_version(30) for "com.android.tethering": newer SDK(34).
min_sdk_version: "30",
-
- init_rc: ["netbpfload.rc"],
- required: ["bpfloader"],
+ installable: false,
}
// Versioned netbpfload init rc: init system will process it only on api T/33+ devices
diff --git a/netbpfload/NetBpfLoad.cpp b/netbpfload/NetBpfLoad.cpp
index ed7d048..0688e88 100644
--- a/netbpfload/NetBpfLoad.cpp
+++ b/netbpfload/NetBpfLoad.cpp
@@ -171,8 +171,6 @@
#define APEX_MOUNT_POINT "/apex/com.android.tethering"
const char * const platformBpfLoader = "/system/bin/bpfloader";
-const char * const platformNetBpfLoad = "/system/bin/netbpfload";
-const char * const apexNetBpfLoad = APEX_MOUNT_POINT "/bin/netbpfload";
int logTetheringApexVersion(void) {
char * found_blockdev = NULL;
@@ -232,12 +230,6 @@
ALOGI("NetBpfLoad '%s' starting...", argv[0]);
- // true iff we are running from the module
- const bool is_mainline = !strcmp(argv[0], apexNetBpfLoad);
-
- // true iff we are running from the platform
- const bool is_platform = !strcmp(argv[0], platformNetBpfLoad);
-
const int device_api_level = android_get_device_api_level();
const bool isAtLeastT = (device_api_level >= __ANDROID_API_T__);
const bool isAtLeastU = (device_api_level >= __ANDROID_API_U__);
@@ -248,24 +240,11 @@
// first in U QPR2 beta~2
const bool has_platform_netbpfload_rc = exists("/system/etc/init/netbpfload.rc");
- ALOGI("NetBpfLoad api:%d/%d kver:%07x platform:%d mainline:%d rc:%d%d",
+ ALOGI("NetBpfLoad api:%d/%d kver:%07x rc:%d%d",
android_get_application_target_sdk_version(), device_api_level,
- android::bpf::kernelVersion(), is_platform, is_mainline,
+ android::bpf::kernelVersion(),
has_platform_bpfloader_rc, has_platform_netbpfload_rc);
- if (!is_platform && !is_mainline) {
- ALOGE("Unable to determine if we're platform or mainline netbpfload.");
- return 1;
- }
-
- if (is_platform) {
- ALOGI("Executing apex netbpfload...");
- const char * args[] = { apexNetBpfLoad, NULL, };
- execve(args[0], (char**)args, envp);
- ALOGE("exec '%s' fail: %d[%s]", apexNetBpfLoad, errno, strerror(errno));
- return 1;
- }
-
if (!has_platform_bpfloader_rc && !has_platform_netbpfload_rc) {
ALOGE("Unable to find platform's bpfloader & netbpfload init scripts.");
return 1;
@@ -278,7 +257,7 @@
logTetheringApexVersion();
- if (is_mainline && has_platform_bpfloader_rc && !has_platform_netbpfload_rc) {
+ if (has_platform_bpfloader_rc && !has_platform_netbpfload_rc) {
// Tethering apex shipped initrc file causes us to reach here
// but we're not ready to correctly handle anything before U QPR2
// in which the 'bpfloader' vs 'netbpfload' split happened
diff --git a/netbpfload/loader.cpp b/netbpfload/loader.cpp
index c534b2c..3026655 100644
--- a/netbpfload/loader.cpp
+++ b/netbpfload/loader.cpp
@@ -31,13 +31,13 @@
#include <sys/wait.h>
#include <unistd.h>
-// This is BpfLoader v0.41
+// This is Network BpfLoader v0.42
// WARNING: If you ever hit cherrypick conflicts here you're doing it wrong:
// You are NOT allowed to cherrypick bpfloader related patches out of order.
// (indeed: cherrypicking is probably a bad idea and you should merge instead)
// Mainline supports ONLY the published versions of the bpfloader for each Android release.
#define BPFLOADER_VERSION_MAJOR 0u
-#define BPFLOADER_VERSION_MINOR 41u
+#define BPFLOADER_VERSION_MINOR 42u
#define BPFLOADER_VERSION ((BPFLOADER_VERSION_MAJOR << 16) | BPFLOADER_VERSION_MINOR)
#include "BpfSyscallWrappers.h"
@@ -413,9 +413,6 @@
size_t sizeOfBpfProgDef) {
vector<char> pdData;
int ret = readSectionByName("progs", elfFile, pdData);
- // Older file formats do not require a 'progs' section at all.
- // (We should probably figure out whether this is behaviour which is safe to remove now.)
- if (ret == -2) return 0;
if (ret) return ret;
if (pdData.size() % sizeOfBpfProgDef) {
@@ -574,6 +571,14 @@
static bool mapMatchesExpectations(const unique_fd& fd, const string& mapName,
const struct bpf_map_def& mapDef, const enum bpf_map_type type) {
+ // bpfGetFd... family of functions require at minimum a 4.14 kernel,
+ // so on 4.9-T kernels just pretend the map matches our expectations.
+ // Additionally we'll get almost equivalent test coverage on newer devices/kernels.
+ // This is because the primary failure mode we're trying to detect here
+ // is either a source code misconfiguration (which is likely kernel independent)
+ // or a newly introduced kernel feature/bug (which is unlikely to get backported to 4.9).
+ if (!isAtLeastKernelVersion(4, 14, 0)) return true;
+
// Assuming fd is a valid Bpf Map file descriptor then
// all the following should always succeed on a 4.14+ kernel.
// If they somehow do fail, they'll return -1 (and set errno),
@@ -711,6 +716,16 @@
}
enum bpf_map_type type = md[i].type;
+ if (type == BPF_MAP_TYPE_DEVMAP && !isAtLeastKernelVersion(4, 14, 0)) {
+ // On Linux Kernels older than 4.14 this map type doesn't exist, but it can kind
+ // of be approximated: ARRAY has the same userspace api, though it is not usable
+ // by the same ebpf programs. However, that's okay because the bpf_redirect_map()
+ // helper doesn't exist on 4.9-T anyway (so the bpf program would fail to load,
+ // and thus needs to be tagged as 4.14+ either way), so there's nothing useful you
+ // could do with a DEVMAP anyway (that isn't already provided by an ARRAY)...
+ // Hence using an ARRAY instead of a DEVMAP simply makes life easier for userspace.
+ type = BPF_MAP_TYPE_ARRAY;
+ }
if (type == BPF_MAP_TYPE_DEVMAP_HASH && !isAtLeastKernelVersion(5, 4, 0)) {
// On Linux Kernels older than 5.4 this map type doesn't exist, but it can kind
// of be approximated: HASH has the same userspace visible api.
diff --git a/netbpfload/netbpfload.rc b/netbpfload/netbpfload.rc
index 14181dc..e1af47f 100644
--- a/netbpfload/netbpfload.rc
+++ b/netbpfload/netbpfload.rc
@@ -17,15 +17,18 @@
on load_bpf_programs
exec_start bpfloader
-service bpfloader /system/bin/netbpfload
+# Note: This will actually execute /apex/com.android.tethering/bin/netbpfload
+# by virtue of 'service bpfloader' being overridden by the apex shipped .rc
+# Warning: most of the below settings are irrelevant unless the apex is missing.
+service bpfloader /system/bin/false
# netbpfload will do network bpf loading, then execute /system/bin/bpfloader
- capabilities CHOWN SYS_ADMIN NET_ADMIN
+ #! capabilities CHOWN SYS_ADMIN NET_ADMIN
# The following group memberships are a workaround for lack of DAC_OVERRIDE
# and allow us to open (among other things) files that we created and are
# no longer root owned (due to CHOWN) but still have group read access to
# one of the following groups. This is not perfect, but a more correct
# solution requires significantly more effort to implement.
- group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system
+ #! group root graphics network_stack net_admin net_bw_acct net_bw_stats net_raw system
user root
#
# Set RLIMIT_MEMLOCK to 1GiB for bpfloader
@@ -55,7 +58,7 @@
#
# As such we simply use 1GiB as a reasonable approximation of infinity.
#
- rlimit memlock 1073741824 1073741824
+ #! rlimit memlock 1073741824 1073741824
oneshot
#
# How to debug bootloops caused by 'bpfloader-failed'.
@@ -81,6 +84,5 @@
# 'cannot prove return value is 0 or 1' or 'unsupported / unknown operation / helper',
# 'invalid bpf_context access', etc.
#
- reboot_on_failure reboot,bpfloader-failed
- # we're not really updatable, but want to be able to load bpf programs shipped in apexes
+ reboot_on_failure reboot,netbpfload-missing
updatable
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
index f60a95e..1ec9e39 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java
@@ -94,57 +94,6 @@
@NonNull
private final Instant expirationTime;
- /** Constructs a {@link MdnsServiceInfo} object with default values. */
- public MdnsServiceInfo(
- String serviceInstanceName,
- String[] serviceType,
- @Nullable List<String> subtypes,
- String[] hostName,
- int port,
- @Nullable String ipv4Address,
- @Nullable String ipv6Address,
- @Nullable List<String> textStrings) {
- this(
- serviceInstanceName,
- serviceType,
- subtypes,
- hostName,
- port,
- List.of(ipv4Address),
- List.of(ipv6Address),
- textStrings,
- /* textEntries= */ null,
- /* interfaceIndex= */ INTERFACE_INDEX_UNSPECIFIED,
- /* network= */ null,
- /* expirationTime= */ Instant.MAX);
- }
-
- /** Constructs a {@link MdnsServiceInfo} object with default values. */
- public MdnsServiceInfo(
- String serviceInstanceName,
- String[] serviceType,
- List<String> subtypes,
- String[] hostName,
- int port,
- @Nullable String ipv4Address,
- @Nullable String ipv6Address,
- @Nullable List<String> textStrings,
- @Nullable List<TextEntry> textEntries) {
- this(
- serviceInstanceName,
- serviceType,
- subtypes,
- hostName,
- port,
- List.of(ipv4Address),
- List.of(ipv6Address),
- textStrings,
- textEntries,
- /* interfaceIndex= */ INTERFACE_INDEX_UNSPECIFIED,
- /* network= */ null,
- /* expirationTime= */ Instant.MAX);
- }
-
/**
* Constructs a {@link MdnsServiceInfo} object with default values.
*
diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java
index 21cf351..cab29e3 100644
--- a/service-t/src/com/android/server/net/NetworkStatsObservers.java
+++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java
@@ -32,7 +32,6 @@
import android.net.NetworkTemplate;
import android.net.netstats.IUsageCallback;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -46,6 +45,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.PerUidCounter;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -78,8 +78,11 @@
// Sequence number of DataUsageRequests
private final AtomicInteger mNextDataUsageRequestId = new AtomicInteger();
- // Lazily instantiated when an observer is registered.
- private volatile Handler mHandler;
+ private final Handler mHandler;
+
+ NetworkStatsObservers(@NonNull Looper looper) {
+ mHandler = new Handler(Objects.requireNonNull(looper), mHandlerCallback);
+ }
/**
* Creates a wrapper that contains the caller context and a normalized request.
@@ -100,7 +103,7 @@
if (LOG) Log.d(TAG, "Registering observer for " + requestInfo);
mDataUsageRequestsPerUid.incrementCountOrThrow(callingUid);
- getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
return request;
}
@@ -110,7 +113,7 @@
* <p>It will unregister the observer asynchronously, so it is safe to call from any thread.
*/
public void unregister(DataUsageRequest request, int callingUid) {
- getHandler().sendMessage(mHandler.obtainMessage(MSG_UNREGISTER, callingUid, 0 /* ignore */,
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_UNREGISTER, callingUid, 0 /* ignore */,
request));
}
@@ -125,34 +128,10 @@
long currentTime) {
StatsContext statsContext = new StatsContext(xtSnapshot, uidSnapshot, activeIfaces,
activeUidIfaces, currentTime);
- getHandler().sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext));
}
- private Handler getHandler() {
- if (mHandler == null) {
- synchronized (this) {
- if (mHandler == null) {
- if (LOGV) Log.v(TAG, "Creating handler");
- mHandler = new Handler(getHandlerLooperLocked(), mHandlerCallback);
- }
- }
- }
- return mHandler;
- }
-
- @VisibleForTesting
- protected Looper getHandlerLooperLocked() {
- // TODO: Currently, callbacks are dispatched on this thread if the caller register
- // callback without supplying a Handler. To ensure that the service handler thread
- // is not blocked by client code, the observers must create their own thread. Once
- // all callbacks are dispatched outside of the handler thread, the service handler
- // thread can be used here.
- HandlerThread handlerThread = new HandlerThread(TAG);
- handlerThread.start();
- return handlerThread.getLooper();
- }
-
- private Handler.Callback mHandlerCallback = new Handler.Callback() {
+ private final Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 9684d18..64b17eb 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -593,7 +593,7 @@
INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
alarmManager, wakeLock, getDefaultClock(),
new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context),
- new NetworkStatsObservers(), new Dependencies());
+ new Dependencies());
return service;
}
@@ -603,8 +603,7 @@
@VisibleForTesting
NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager,
PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings,
- NetworkStatsFactory factory, NetworkStatsObservers statsObservers,
- @NonNull Dependencies deps) {
+ NetworkStatsFactory factory, @NonNull Dependencies deps) {
mContext = Objects.requireNonNull(context, "missing Context");
mNetd = Objects.requireNonNull(netd, "missing Netd");
mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
@@ -612,7 +611,6 @@
mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
mStatsFactory = Objects.requireNonNull(factory, "missing factory");
- mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
mDeps = Objects.requireNonNull(deps, "missing Dependencies");
mStatsDir = mDeps.getOrCreateStatsDir();
if (!mStatsDir.exists()) {
@@ -622,6 +620,7 @@
final HandlerThread handlerThread = mDeps.makeHandlerThread();
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
+ mStatsObservers = new NetworkStatsObservers(handlerThread.getLooper());
mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
(command) -> mHandler.post(command) , this);
mContentResolver = mContext.getContentResolver();
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 30b14b2..8f09a40 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -97,6 +97,8 @@
import static android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST;
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
+import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK;
+import static android.net.connectivity.ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION;
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
import static android.system.OsConstants.ETH_P_ALL;
@@ -214,7 +216,6 @@
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnTransportInfo;
-import android.net.connectivity.ConnectivityCompatChanges;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netd.aidl.NativeUidRangeConfig;
@@ -2607,7 +2608,7 @@
// Not the system, so it's an app requesting on its own behalf.
type = RequestType.RT_APP.getNumber();
}
- countPerType.put(type, countPerType.get(type, 0));
+ countPerType.put(type, countPerType.get(type, 0) + 1);
}
for (int i = countPerType.size() - 1; i >= 0; --i) {
final RequestCountForType.Builder r = RequestCountForType.newBuilder();
@@ -3020,6 +3021,23 @@
}
}
+ private void maybeDisableLocalNetworkMatching(NetworkCapabilities nc, int callingUid) {
+ if (mDeps.isChangeEnabled(ENABLE_MATCH_LOCAL_NETWORK, callingUid)) {
+ return;
+ }
+ // If NET_CAPABILITY_LOCAL_NETWORK is not added to capability, request should not be
+ // satisfied by local networks.
+ if (!nc.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) {
+ nc.addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK);
+ }
+ }
+
+ private void restrictRequestNetworkCapabilitiesForCaller(NetworkCapabilities nc,
+ int callingUid, String callerPackageName) {
+ restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callerPackageName);
+ maybeDisableLocalNetworkMatching(nc, callingUid);
+ }
+
@Override
public @RestrictBackgroundStatus int getRestrictBackgroundStatusByCaller() {
enforceAccessPermission();
@@ -7708,10 +7726,12 @@
// the state of the app when the request is filed, but we never change the
// request if the app changes network state. http://b/29964605
enforceMeteredApnPolicy(networkCapabilities);
+ maybeDisableLocalNetworkMatching(networkCapabilities, callingUid);
break;
case LISTEN_FOR_BEST:
enforceAccessPermission();
networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ maybeDisableLocalNetworkMatching(networkCapabilities, callingUid);
break;
default:
throw new IllegalArgumentException("Unsupported request type " + reqType);
@@ -7798,7 +7818,7 @@
final UserHandle user = UserHandle.getUserHandleForUid(callingUid);
// Only run the check if the change is enabled.
if (!mDeps.isChangeEnabled(
- ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION,
+ ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION,
callingPackageName, user)) {
return false;
}
@@ -7950,8 +7970,8 @@
ensureRequestableCapabilities(networkCapabilities);
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName);
- restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
- callingUid, callingPackageName);
+ restrictRequestNetworkCapabilitiesForCaller(
+ networkCapabilities, callingUid, callingPackageName);
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
@@ -8011,7 +8031,7 @@
NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName);
- restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
+ restrictRequestNetworkCapabilitiesForCaller(nc, callingUid, callingPackageName);
// Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
// make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
// onLost and onAvailable callbacks when networks move in and out of the background.
@@ -8044,7 +8064,7 @@
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName);
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
- restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
+ restrictRequestNetworkCapabilitiesForCaller(nc, callingUid, callingPackageName);
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
@@ -12017,7 +12037,7 @@
// This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
// and administrator uids to be safe.
final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities);
- restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
+ restrictRequestNetworkCapabilitiesForCaller(nc, callingUid, callingPackageName);
final NetworkRequest requestWithId =
new NetworkRequest(
diff --git a/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h b/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h
index baff09b..ac922cd 100644
--- a/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h
+++ b/staticlibs/native/bpf_headers/include/bpf/bpf_helpers.h
@@ -39,6 +39,9 @@
// Android U / 14 (api level 34) - various new program types added
#define BPFLOADER_U_VERSION 37u
+// Android V / 15 (api level 35) - this bpfloader should eventually go back to T
+#define BPFLOADER_MAINLINE_VERSION 42u
+
/* For mainline module use, you can #define BPFLOADER_{MIN/MAX}_VER
* before #include "bpf_helpers.h" to change which bpfloaders will
* process the resulting .o file.
@@ -111,10 +114,12 @@
#define KVER_NONE KVER_(0)
#define KVER_4_14 KVER(4, 14, 0)
#define KVER_4_19 KVER(4, 19, 0)
-#define KVER_5_4 KVER(5, 4, 0)
-#define KVER_5_8 KVER(5, 8, 0)
-#define KVER_5_9 KVER(5, 9, 0)
+#define KVER_5_4 KVER(5, 4, 0)
+#define KVER_5_8 KVER(5, 8, 0)
+#define KVER_5_9 KVER(5, 9, 0)
#define KVER_5_15 KVER(5, 15, 0)
+#define KVER_6_1 KVER(6, 1, 0)
+#define KVER_6_6 KVER(6, 6, 0)
#define KVER_INF KVER_(0xFFFFFFFFu)
#define KVER_IS_AT_LEAST(kver, a, b, c) ((kver).kver >= KVER(a, b, c).kver)
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 2ca8832..1241e18 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -160,6 +160,10 @@
private static final long BROADCAST_TIMEOUT_MS = 5_000;
+ // Should be kept in sync with the constant in NetworkPolicyManagerService.
+ // TODO: b/322115994 - remove once the feature is in staging.
+ private static final boolean ALWAYS_RESTRICT_BACKGROUND_NETWORK = false;
+
protected Context mContext;
protected Instrumentation mInstrumentation;
protected ConnectivityManager mCm;
@@ -229,9 +233,8 @@
}
final String output = executeShellCommand("device_config get backstage_power"
+ " com.android.server.net.network_blocked_for_top_sleeping_and_above");
- return Boolean.parseBoolean(output);
+ return Boolean.parseBoolean(output) && ALWAYS_RESTRICT_BACKGROUND_NETWORK;
}
-
protected int getUid(String packageName) throws Exception {
return mContext.getPackageManager().getPackageUid(packageName, 0);
}
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index 3928961..1023173 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -47,6 +47,7 @@
// Change to system current when TetheringManager move to bootclass path.
platform_apis: true,
+ min_sdk_version: "30",
host_required: ["net-tests-utils-host-common"],
}
@@ -80,8 +81,8 @@
// Tethering CTS tests for development and release. These tests always target the platform SDK
// version, and are subject to all the restrictions appropriate to that version. Before SDK
-// finalization, these tests have a min_sdk_version of 10000, and cannot be installed on release
-// devices.
+// finalization, these tests have a min_sdk_version of 10000, but they can still be installed on
+// release devices as their min_sdk_version is set to a production version.
android_test {
name: "CtsTetheringTest",
defaults: ["CtsTetheringTestDefaults"],
@@ -93,6 +94,14 @@
// Tag this module as a cts test artifact
test_suites: [
"cts",
+ "mts-dnsresolver",
+ "mts-networking",
+ "mts-tethering",
+ "mts-wifi",
+ "mcts-dnsresolver",
+ "mcts-networking",
+ "mcts-tethering",
+ "mcts-wifi",
"general-tests",
],
diff --git a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 361d68c..035f607 100644
--- a/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -66,6 +66,8 @@
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.tryTest
+import java.util.function.BiConsumer
+import java.util.function.Consumer
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@@ -87,8 +89,6 @@
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import org.mockito.Spy
-import java.util.function.Consumer
-import java.util.function.BiConsumer
const val SERVICE_BIND_TIMEOUT_MS = 5_000L
const val TEST_TIMEOUT_MS = 10_000L
@@ -225,6 +225,7 @@
override fun getSystemProperties() = mock(MockableSystemProperties::class.java)
override fun makeNetIdManager() = TestNetIdManager()
override fun getBpfNetMaps(context: Context?, netd: INetd?) = mock(BpfNetMaps::class.java)
+ override fun isChangeEnabled(changeId: Long, uid: Int) = true
override fun makeMultinetworkPolicyTracker(
c: Context,
diff --git a/tests/unit/java/android/net/nsd/AdvertisingRequestTest.kt b/tests/unit/java/android/net/nsd/AdvertisingRequestTest.kt
index 332f2a3..c491f37 100644
--- a/tests/unit/java/android/net/nsd/AdvertisingRequestTest.kt
+++ b/tests/unit/java/android/net/nsd/AdvertisingRequestTest.kt
@@ -54,17 +54,17 @@
assertEquals(beforeParcel.advertisingConfig, afterParcel.advertisingConfig)
}
-@Test
-fun testBuilder_setNullTtl_success() {
- val info = NsdServiceInfo().apply {
- serviceType = "_ipp._tcp"
- }
- val request = AdvertisingRequest.Builder(info, PROTOCOL_DNS_SD)
- .setTtl(null)
- .build()
+ @Test
+ fun testBuilder_setNullTtl_success() {
+ val info = NsdServiceInfo().apply {
+ serviceType = "_ipp._tcp"
+ }
+ val request = AdvertisingRequest.Builder(info, PROTOCOL_DNS_SD)
+ .setTtl(null)
+ .build()
- assertNull(request.ttl)
-}
+ assertNull(request.ttl)
+ }
@Test
fun testBuilder_setPropertiesSuccess() {
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 76a649e..27c4561 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -240,7 +240,7 @@
AdvertisingRequest capturedRequest = getAdvertisingRequest(
req -> verify(mServiceConn).registerService(anyInt(), req.capture()));
- assertEquals(request, capturedRequest);
+ assertEquals(request.getTtl(), capturedRequest.getTtl());
}
private void doTestRegisterService() throws Exception {
diff --git a/tests/unit/java/com/android/metrics/ConnectivitySampleMetricsTest.kt b/tests/unit/java/com/android/metrics/ConnectivitySampleMetricsTest.kt
index 53baee1..8a9286f 100644
--- a/tests/unit/java/com/android/metrics/ConnectivitySampleMetricsTest.kt
+++ b/tests/unit/java/com/android/metrics/ConnectivitySampleMetricsTest.kt
@@ -1,5 +1,6 @@
package com.android.metrics
+import android.net.ConnectivityThread
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.CONNECTIVITY_MANAGED_CAPABILITIES
import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL
@@ -15,13 +16,20 @@
import android.net.NetworkCapabilities.NET_ENTERPRISE_ID_3
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_WIFI
+import android.net.NetworkRequest
import android.net.NetworkScore
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.net.NetworkScore.POLICY_EXITING
import android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY
import android.os.Build
import android.os.Handler
+import android.os.Process
+import android.os.Process.SYSTEM_UID
import android.stats.connectivity.MeteredState
+import android.stats.connectivity.RequestType
+import android.stats.connectivity.RequestType.RT_APP
+import android.stats.connectivity.RequestType.RT_SYSTEM
+import android.stats.connectivity.RequestType.RT_SYSTEM_ON_BEHALF_OF_APP
import android.stats.connectivity.ValidatedState
import androidx.test.filters.SmallTest
import com.android.net.module.util.BitUtils
@@ -31,11 +39,13 @@
import com.android.server.connectivity.FullScore.POLICY_IS_UNMETERED
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
-import org.junit.Test
-import org.junit.runner.RunWith
+import com.android.testutils.TestableNetworkCallback
import java.util.concurrent.CompletableFuture
import kotlin.test.assertEquals
import kotlin.test.fail
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
private fun <T> Handler.onHandler(f: () -> T): T {
val future = CompletableFuture<T>()
@@ -80,7 +90,7 @@
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
class ConnectivitySampleMetricsTest : CSTest() {
@Test
- fun testSampleConnectivityState() {
+ fun testSampleConnectivityState_Network() {
val wifi1Caps = NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_WIFI)
.addCapability(NET_CAPABILITY_NOT_METERED)
@@ -179,4 +189,61 @@
"expected ${expectedWifi2Policies.toPolicyString()}, " +
"found ${foundWifi2.scorePolicies.toPolicyString()}")
}
+
+ private fun fileNetworkRequest(requestType: RequestType, requestCount: Int, uid: Int? = null) {
+ if (uid != null) {
+ deps.setCallingUid(uid)
+ }
+ try {
+ repeat(requestCount) {
+ when (requestType) {
+ RT_APP, RT_SYSTEM -> cm.requestNetwork(
+ NetworkRequest.Builder().build(),
+ TestableNetworkCallback()
+ )
+
+ RT_SYSTEM_ON_BEHALF_OF_APP -> cm.registerDefaultNetworkCallbackForUid(
+ Process.myUid(),
+ TestableNetworkCallback(),
+ Handler(ConnectivityThread.getInstanceLooper()))
+
+ else -> fail("invalid requestType: " + requestType)
+ }
+ }
+ } finally {
+ deps.unmockCallingUid()
+ }
+ }
+
+
+ @Test
+ fun testSampleConnectivityState_NetworkRequest() {
+ val requestCount = 5
+ fileNetworkRequest(RT_APP, requestCount);
+ fileNetworkRequest(RT_SYSTEM, requestCount, SYSTEM_UID);
+ fileNetworkRequest(RT_SYSTEM_ON_BEHALF_OF_APP, requestCount, SYSTEM_UID);
+
+ val stats = csHandler.onHandler { service.sampleConnectivityState() }
+
+ assertEquals(3, stats.networkRequestCount.requestCountForTypeList.size)
+ val appRequest = stats.networkRequestCount.requestCountForTypeList.find {
+ it.requestType == RT_APP
+ } ?: fail("Can't find RT_APP request")
+ val systemRequest = stats.networkRequestCount.requestCountForTypeList.find {
+ it.requestType == RT_SYSTEM
+ } ?: fail("Can't find RT_SYSTEM request")
+ val systemOnBehalfOfAppRequest = stats.networkRequestCount.requestCountForTypeList.find {
+ it.requestType == RT_SYSTEM_ON_BEHALF_OF_APP
+ } ?: fail("Can't find RT_SYSTEM_ON_BEHALF_OF_APP request")
+
+ // Verify request count is equal or larger than the number of request this test filed
+ // since ConnectivityService internally files network requests
+ assertTrue("Unexpected RT_APP count, expected >= $requestCount, " +
+ "found ${appRequest.requestCount}", appRequest.requestCount >= requestCount)
+ assertTrue("Unexpected RT_SYSTEM count, expected >= $requestCount, " +
+ "found ${systemRequest.requestCount}", systemRequest.requestCount >= requestCount)
+ assertTrue("Unexpected RT_SYSTEM_ON_BEHALF_OF_APP count, expected >= $requestCount, " +
+ "found ${systemOnBehalfOfAppRequest.requestCount}",
+ systemOnBehalfOfAppRequest.requestCount >= requestCount)
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
index 8d1dff6..c69b1e1 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsRecordRepositoryTest.kt
@@ -38,6 +38,7 @@
import java.net.InetSocketAddress
import java.net.NetworkInterface
import java.util.Collections
+import java.time.Duration
import kotlin.test.assertContentEquals
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
@@ -146,7 +147,7 @@
val repository = MdnsRecordRepository(thread.looper, deps, TEST_HOSTNAME, makeFlags())
assertEquals(0, repository.servicesCount)
assertEquals(-1,
- repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, null /* ttl */))
+ repository.addService(TEST_SERVICE_ID_1, TEST_SERVICE_1, Duration.ofSeconds(50)))
assertEquals(1, repository.servicesCount)
val probingInfo = repository.setServiceProbing(TEST_SERVICE_ID_1)
@@ -169,7 +170,7 @@
assertEquals(MdnsServiceRecord(expectedName,
0L /* receiptTimeMillis */,
false /* cacheFlush */,
- SHORT_TTL /* ttlMillis */,
+ 50_000L /* ttlMillis */,
0 /* servicePriority */, 0 /* serviceWeight */,
TEST_PORT, TEST_HOSTNAME), packet.authorityRecords[0])
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java
index 8740e80..4ce8ba6 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java
@@ -54,7 +54,8 @@
"192.168.1.1",
"2001::1",
List.of("vn=Google Inc.", "mn=Google Nest Hub Max"),
- /* textEntries= */ null);
+ /* textEntries= */ null,
+ INTERFACE_INDEX_UNSPECIFIED);
assertTrue(info.getAttributeByKey("vn").equals("Google Inc."));
assertTrue(info.getAttributeByKey("mn").equals("Google Nest Hub Max"));
@@ -73,7 +74,8 @@
"2001::1",
/* textStrings= */ null,
List.of(MdnsServiceInfo.TextEntry.fromString("vn=Google Inc."),
- MdnsServiceInfo.TextEntry.fromString("mn=Google Nest Hub Max")));
+ MdnsServiceInfo.TextEntry.fromString("mn=Google Nest Hub Max")),
+ INTERFACE_INDEX_UNSPECIFIED);
assertTrue(info.getAttributeByKey("vn").equals("Google Inc."));
assertTrue(info.getAttributeByKey("mn").equals("Google Nest Hub Max"));
@@ -93,7 +95,8 @@
List.of("vn=Alphabet Inc.", "mn=Google Nest Hub Max", "id=12345"),
List.of(
MdnsServiceInfo.TextEntry.fromString("vn=Google Inc."),
- MdnsServiceInfo.TextEntry.fromString("mn=Google Nest Hub Max")));
+ MdnsServiceInfo.TextEntry.fromString("mn=Google Nest Hub Max")),
+ INTERFACE_INDEX_UNSPECIFIED);
assertEquals(Map.of("vn", "Google Inc.", "mn", "Google Nest Hub Max"),
info.getAttributes());
@@ -113,7 +116,8 @@
List.of("vn=Alphabet Inc.", "mn=Google Nest Hub Max", "id=12345"),
List.of(MdnsServiceInfo.TextEntry.fromString("vn=Google Inc."),
MdnsServiceInfo.TextEntry.fromString("mn=Google Nest Hub Max"),
- MdnsServiceInfo.TextEntry.fromString("mn=Google WiFi Router")));
+ MdnsServiceInfo.TextEntry.fromString("mn=Google WiFi Router")),
+ INTERFACE_INDEX_UNSPECIFIED);
assertEquals(Map.of("vn", "Google Inc.", "mn", "Google Nest Hub Max"),
info.getAttributes());
@@ -131,7 +135,8 @@
"192.168.1.1",
"2001::1",
List.of("KEY=Value"),
- /* textEntries= */ null);
+ /* textEntries= */ null,
+ INTERFACE_INDEX_UNSPECIFIED);
assertEquals("Value", info.getAttributeByKey("key"));
assertEquals("Value", info.getAttributeByKey("KEY"));
@@ -150,7 +155,9 @@
12345,
"192.168.1.1",
"2001::1",
- List.of());
+ List.of(),
+ /* textEntries= */ null,
+ INTERFACE_INDEX_UNSPECIFIED);
assertEquals(info.getInterfaceIndex(), INTERFACE_INDEX_UNSPECIFIED);
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt
index c1730a4..83fff87 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSLocalAgentTests.kt
@@ -38,6 +38,7 @@
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.net.NetworkScore.KEEP_CONNECTED_LOCAL_NETWORK
import android.net.RouteInfo
+import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK
import android.os.Build
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
@@ -47,12 +48,15 @@
import kotlin.test.assertFailsWith
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.eq
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
import org.mockito.Mockito.timeout
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
private const val TIMEOUT_MS = 200L
private const val MEDIUM_TIMEOUT_MS = 1_000L
@@ -88,10 +92,10 @@
class CSLocalAgentTests : CSTest() {
val multicastRoutingConfigMinScope =
MulticastRoutingConfig.Builder(MulticastRoutingConfig.FORWARD_WITH_MIN_SCOPE, 4)
- .build();
+ .build()
val multicastRoutingConfigSelected =
MulticastRoutingConfig.Builder(MulticastRoutingConfig.FORWARD_SELECTED)
- .build();
+ .build()
val upstreamSelectorAny = NetworkRequest.Builder()
.addForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK)
.build()
@@ -205,6 +209,9 @@
nc = nc(TRANSPORT_THREAD, NET_CAPABILITY_LOCAL_NETWORK),
lp = lp(name),
lnc = localNetworkConfig,
+ score = FromS(NetworkScore.Builder()
+ .setKeepConnectedReason(KEEP_CONNECTED_LOCAL_NETWORK)
+ .build())
)
return localAgent
}
@@ -219,9 +226,12 @@
nc = nc(TRANSPORT_CELLULAR, NET_CAPABILITY_INTERNET))
}
- private fun sendLocalNetworkConfig(localAgent: CSAgentWrapper,
- upstreamSelector: NetworkRequest?, upstreamConfig: MulticastRoutingConfig,
- downstreamConfig: MulticastRoutingConfig) {
+ private fun sendLocalNetworkConfig(
+ localAgent: CSAgentWrapper,
+ upstreamSelector: NetworkRequest?,
+ upstreamConfig: MulticastRoutingConfig,
+ downstreamConfig: MulticastRoutingConfig
+ ) {
val newLnc = LocalNetworkConfig.Builder()
.setUpstreamSelector(upstreamSelector)
.setUpstreamMulticastRoutingConfig(upstreamConfig)
@@ -458,7 +468,6 @@
wifiAgent.disconnect()
}
-
@Test
fun testUnregisterUpstreamAfterReplacement_SameIfaceName() {
doTestUnregisterUpstreamAfterReplacement(true)
@@ -824,4 +833,59 @@
listenCb.expect<Lost>()
}
+
+ fun doTestLocalNetworkRequest(
+ request: NetworkRequest,
+ enableMatchLocalNetwork: Boolean,
+ expectCallback: Boolean
+ ) {
+ deps.setBuildSdk(VERSION_V)
+ deps.setChangeIdEnabled(enableMatchLocalNetwork, ENABLE_MATCH_LOCAL_NETWORK)
+
+ val requestCb = TestableNetworkCallback()
+ val listenCb = TestableNetworkCallback()
+ cm.requestNetwork(request, requestCb)
+ cm.registerNetworkCallback(request, listenCb)
+
+ val localAgent = createLocalAgent("local0", FromS(LocalNetworkConfig.Builder().build()))
+ localAgent.connect()
+
+ if (expectCallback) {
+ requestCb.expectAvailableCallbacks(localAgent.network, validated = false)
+ listenCb.expectAvailableCallbacks(localAgent.network, validated = false)
+ } else {
+ waitForIdle()
+ requestCb.assertNoCallback(timeoutMs = 0)
+ listenCb.assertNoCallback(timeoutMs = 0)
+ }
+ localAgent.disconnect()
+ }
+
+ @Test
+ fun testLocalNetworkRequest() {
+ val request = NetworkRequest.Builder().build()
+ // If ENABLE_MATCH_LOCAL_NETWORK is false, request is not satisfied by local network
+ doTestLocalNetworkRequest(
+ request,
+ enableMatchLocalNetwork = false,
+ expectCallback = false)
+ // If ENABLE_MATCH_LOCAL_NETWORK is true, request is satisfied by local network
+ doTestLocalNetworkRequest(
+ request,
+ enableMatchLocalNetwork = true,
+ expectCallback = true)
+ }
+
+ @Test
+ fun testLocalNetworkRequest_withCapability() {
+ val request = NetworkRequest.Builder().addCapability(NET_CAPABILITY_LOCAL_NETWORK).build()
+ doTestLocalNetworkRequest(
+ request,
+ enableMatchLocalNetwork = false,
+ expectCallback = true)
+ doTestLocalNetworkRequest(
+ request,
+ enableMatchLocalNetwork = true,
+ expectCallback = true)
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
index d7343b1..7007b16 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
@@ -28,6 +28,7 @@
import android.net.NetworkAgent
import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkProvider
@@ -39,6 +40,9 @@
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
import com.android.testutils.TestableNetworkCallback
+import java.util.concurrent.atomic.AtomicInteger
+import kotlin.test.assertEquals
+import kotlin.test.fail
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
@@ -46,9 +50,6 @@
import org.mockito.Mockito.doNothing
import org.mockito.Mockito.verify
import org.mockito.stubbing.Answer
-import java.util.concurrent.atomic.AtomicInteger
-import kotlin.test.assertEquals
-import kotlin.test.fail
const val SHORT_TIMEOUT_MS = 200L
@@ -140,6 +141,9 @@
val request = NetworkRequest.Builder().apply {
clearCapabilities()
if (nc.transportTypes.isNotEmpty()) addTransportType(nc.transportTypes[0])
+ if (nc.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) {
+ addCapability(NET_CAPABILITY_LOCAL_NETWORK)
+ }
}.build()
val cb = TestableNetworkCallback()
mgr.registerNetworkCallback(request, cb)
@@ -166,6 +170,9 @@
val request = NetworkRequest.Builder().apply {
clearCapabilities()
if (nc.transportTypes.isNotEmpty()) addTransportType(nc.transportTypes[0])
+ if (nc.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) {
+ addCapability(NET_CAPABILITY_LOCAL_NETWORK)
+ }
}.build()
val cb = TestableNetworkCallback(timeoutMs = SHORT_TIMEOUT_MS)
mgr.registerNetworkCallback(request, cb)
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
index 3b83c41..1966cb1 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSTest.kt
@@ -17,6 +17,7 @@
package com.android.server
import android.app.AlarmManager
+import android.app.AppOpsManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -42,6 +43,7 @@
import android.net.NetworkProvider
import android.net.NetworkScore
import android.net.PacProxyManager
+import android.net.connectivity.ConnectivityCompatChanges.ENABLE_MATCH_LOCAL_NETWORK
import android.net.networkstack.NetworkStackClientBase
import android.os.BatteryStatsManager
import android.os.Bundle
@@ -53,7 +55,6 @@
import android.permission.PermissionManager.PermissionResult
import android.telephony.TelephonyManager
import android.testing.TestableContext
-import android.util.ArraySet
import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.app.IBatteryStats
import com.android.internal.util.test.BroadcastInterceptingContext
@@ -75,8 +76,8 @@
import java.util.concurrent.Executors
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit
-import java.util.function.Consumer
import java.util.function.BiConsumer
+import java.util.function.Consumer
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.fail
@@ -103,6 +104,8 @@
internal const val VERSION_V = 5
internal const val VERSION_MAX = VERSION_V
+internal const val CALLING_UID_UNMOCKED = Process.INVALID_UID
+
private fun NetworkCapabilities.getLegacyType() =
when (transportTypes.getOrElse(0) { TRANSPORT_WIFI }) {
TRANSPORT_BLUETOOTH -> ConnectivityManager.TYPE_BLUETOOTH
@@ -176,6 +179,7 @@
val systemConfigManager = makeMockSystemConfigManager()
val batteryStats = mock<IBatteryStats>()
val batteryManager = BatteryStatsManager(batteryStats)
+ val appOpsManager = mock<AppOpsManager>()
val telephonyManager = mock<TelephonyManager>().also {
doReturn(true).`when`(it).isDataCapable()
}
@@ -263,7 +267,7 @@
enabledFeatures[name] ?: fail("Unmocked feature $name, see CSTest.enabledFeatures")
// Mocked change IDs
- private val enabledChangeIds = ArraySet<Long>()
+ private val enabledChangeIds = arrayListOf(ENABLE_MATCH_LOCAL_NETWORK)
fun setChangeIdEnabled(enabled: Boolean, changeId: Long) {
// enabledChangeIds is read on the handler thread and maybe the test thread, so
// make sure both threads see it before continuing.
@@ -298,6 +302,19 @@
override fun isAtLeastT() = if (isSdkUnmocked) super.isAtLeastT() else sdkLevel >= VERSION_T
override fun isAtLeastU() = if (isSdkUnmocked) super.isAtLeastU() else sdkLevel >= VERSION_U
override fun isAtLeastV() = if (isSdkUnmocked) super.isAtLeastV() else sdkLevel >= VERSION_V
+
+ private var callingUid = CALLING_UID_UNMOCKED
+
+ fun unmockCallingUid() {
+ setCallingUid(CALLING_UID_UNMOCKED)
+ }
+
+ fun setCallingUid(callingUid: Int) {
+ visibleOnHandlerThread(csHandler) { this.callingUid = callingUid }
+ }
+
+ override fun getCallingUid() =
+ if (callingUid == CALLING_UID_UNMOCKED) super.getCallingUid() else callingUid
}
inner class CSContext(base: Context) : BroadcastInterceptingContext(base) {
@@ -398,6 +415,7 @@
Context.TELEPHONY_SERVICE -> telephonyManager
Context.BATTERY_STATS_SERVICE -> batteryManager
Context.STATS_MANAGER -> null // Stats manager is final and can't be mocked
+ Context.APP_OPS_SERVICE -> appOpsManager
else -> super.getSystemService(serviceName)
}
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
index e62ac74..0bbc34c 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -47,7 +47,6 @@
import android.net.NetworkTemplate;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
@@ -127,13 +126,7 @@
mObserverHandlerThread = new HandlerThread("NetworkStatsObserversTest");
mObserverHandlerThread.start();
- final Looper observerLooper = mObserverHandlerThread.getLooper();
- mStatsObservers = new NetworkStatsObservers() {
- @Override
- protected Looper getHandlerLooperLocked() {
- return observerLooper;
- }
- };
+ mStatsObservers = new NetworkStatsObservers(mObserverHandlerThread.getLooper());
mActiveIfaces = new ArrayMap<>();
mActiveUidIfaces = new ArrayMap<>();
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 3ed51bc..3d7ad66 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -123,7 +123,6 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.Looper;
import android.os.PowerManager;
import android.os.SimpleClock;
import android.provider.Settings;
@@ -293,7 +292,6 @@
private String mCompareStatsResult = null;
private @Mock Resources mResources;
private Boolean mIsDebuggable;
- private HandlerThread mObserverHandlerThread;
final TestDependencies mDeps = new TestDependencies();
private class MockContext extends BroadcastInterceptingContext {
@@ -377,21 +375,8 @@
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mHandlerThread = new HandlerThread("NetworkStatsServiceTest-HandlerThread");
- // Create a separate thread for observers to run on. This thread cannot be the same
- // as the handler thread, because the observer callback is fired on this thread, and
- // it should not be blocked by client code. Additionally, creating the observers
- // object requires a looper, which can only be obtained after a thread has been started.
- mObserverHandlerThread = new HandlerThread("NetworkStatsServiceTest-ObserversThread");
- mObserverHandlerThread.start();
- final Looper observerLooper = mObserverHandlerThread.getLooper();
- final NetworkStatsObservers statsObservers = new NetworkStatsObservers() {
- @Override
- protected Looper getHandlerLooperLocked() {
- return observerLooper;
- }
- };
mService = new NetworkStatsService(mServiceContext, mNetd, mAlarmManager, wakeLock,
- mClock, mSettings, mStatsFactory, statsObservers, mDeps);
+ mClock, mSettings, mStatsFactory, mDeps);
mElapsedRealtime = 0L;
@@ -589,10 +574,6 @@
mHandlerThread.quitSafely();
mHandlerThread.join();
}
- if (mObserverHandlerThread != null) {
- mObserverHandlerThread.quitSafely();
- mObserverHandlerThread.join();
- }
}
private void initWifiStats(NetworkStateSnapshot snapshot) throws Exception {
diff --git a/thread/tests/integration/src/android/net/thread/BorderRoutingTest.java b/thread/tests/integration/src/android/net/thread/BorderRoutingTest.java
index d84cd20..ee21405 100644
--- a/thread/tests/integration/src/android/net/thread/BorderRoutingTest.java
+++ b/thread/tests/integration/src/android/net/thread/BorderRoutingTest.java
@@ -24,6 +24,7 @@
import static android.net.thread.utils.IntegrationTestUtils.isExpectedIcmpv6Packet;
import static android.net.thread.utils.IntegrationTestUtils.isFromIpv6Source;
import static android.net.thread.utils.IntegrationTestUtils.isInMulticastGroup;
+import static android.net.thread.utils.IntegrationTestUtils.isMulticastRoutingSupported;
import static android.net.thread.utils.IntegrationTestUtils.isSimulatedThreadRadioSupported;
import static android.net.thread.utils.IntegrationTestUtils.isToIpv6Destination;
import static android.net.thread.utils.IntegrationTestUtils.newPacketReader;
@@ -33,7 +34,6 @@
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REPLY_TYPE;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
-import static com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static com.android.testutils.TestPermissionUtil.runAsShell;
@@ -96,7 +96,6 @@
private InfraNetworkDevice mInfraDevice;
private static final int NUM_FTD = 2;
- private static final String KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED = "5.15.0";
private static final Inet6Address GROUP_ADDR_SCOPE_5 =
(Inet6Address) InetAddresses.parseNumericAddress("ff05::1234");
private static final Inet6Address GROUP_ADDR_SCOPE_4 =
@@ -239,7 +238,7 @@
@Test
public void multicastRouting_ftdSubscribedMulticastAddress_infraLinkJoinsMulticastGroup()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -261,7 +260,7 @@
public void
multicastRouting_ftdSubscribedScope3MulticastAddress_infraLinkNotJoinMulticastGroup()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -282,7 +281,7 @@
@Test
public void multicastRouting_ftdSubscribedMulticastAddress_canPingfromInfraLink()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -304,7 +303,7 @@
@Test
public void multicastRouting_inboundForwarding_afterBrRejoinFtdRepliesSubscribedAddress()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
// TODO (b/327311034): Testing bbr state switch from primary mode to secondary mode and back
// to primary mode requires an additional BR in the Thread network. This is not currently
@@ -314,7 +313,7 @@
@Test
public void multicastRouting_ftdSubscribedScope3MulticastAddress_cannotPingfromInfraLink()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -336,7 +335,7 @@
@Test
public void multicastRouting_ftdNotSubscribedMulticastAddress_cannotPingFromInfraDevice()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -357,7 +356,7 @@
@Test
public void multicastRouting_multipleFtdsSubscribedDifferentAddresses_canPingFromInfraDevice()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -393,7 +392,7 @@
@Test
public void multicastRouting_multipleFtdsSubscribedSameAddress_canPingFromInfraDevice()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -427,7 +426,7 @@
@Test
public void multicastRouting_outboundForwarding_scopeLargerThan3IsForwarded() throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -453,7 +452,7 @@
@Test
public void multicastRouting_outboundForwarding_scopeSmallerThan4IsNotForwarded()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -475,7 +474,7 @@
@Test
public void multicastRouting_outboundForwarding_llaToScope4IsNotForwarded() throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -498,7 +497,7 @@
@Test
public void multicastRouting_outboundForwarding_mlaToScope4IsNotForwarded() throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -525,7 +524,7 @@
@Test
public void multicastRouting_infraNetworkSwitch_ftdRepliesToSubscribedAddress()
throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
@@ -553,7 +552,7 @@
@Test
public void multicastRouting_infraNetworkSwitch_outboundPacketIsForwarded() throws Exception {
- assumeTrue(isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED));
+ assumeTrue(isMulticastRoutingSupported());
/*
* <pre>
* Topology:
diff --git a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
index 5f1f76a..3493d9f 100644
--- a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
+++ b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
@@ -46,7 +46,6 @@
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.net.thread.utils.FullThreadDevice;
-import android.net.thread.utils.OtDaemonController;
import android.net.thread.utils.TapTestNetworkTracker;
import android.os.HandlerThread;
diff --git a/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.java b/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.java
index 6e70d24..bb2d973 100644
--- a/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.java
+++ b/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.java
@@ -20,6 +20,7 @@
import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_PIO;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
+import static com.android.testutils.DeviceInfoUtils.isKernelVersionAtLeast;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
@@ -32,6 +33,7 @@
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.VintfRuntimeInfo;
import androidx.annotation.NonNull;
@@ -63,6 +65,8 @@
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;
import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/** Static utility methods relating to Thread integration tests. */
public final class IntegrationTestUtils {
@@ -75,6 +79,9 @@
public static final Duration CALLBACK_TIMEOUT = Duration.ofSeconds(1);
public static final Duration SERVICE_DISCOVERY_TIMEOUT = Duration.ofSeconds(20);
+ private static final String KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED = "5.15.0";
+ private static final int KERNEL_ANDROID_VERSION_MULTICAST_ROUTING_SUPPORTED = 14;
+
private IntegrationTestUtils() {}
/** Returns whether the device supports simulated Thread radio. */
@@ -83,6 +90,24 @@
return SystemProperties.get("ro.product.model").startsWith("Cuttlefish");
}
+ public static boolean isMulticastRoutingSupported() {
+ return isKernelVersionAtLeast(KERNEL_VERSION_MULTICAST_ROUTING_SUPPORTED)
+ && isKernelAndroidVersionAtLeast(
+ KERNEL_ANDROID_VERSION_MULTICAST_ROUTING_SUPPORTED);
+ }
+
+ private static boolean isKernelAndroidVersionAtLeast(int n) {
+ final String osRelease = VintfRuntimeInfo.getOsRelease();
+ final Pattern pattern = Pattern.compile("android(\\d+)");
+ Matcher matcher = pattern.matcher(osRelease);
+
+ if (matcher.find()) {
+ int version = Integer.parseInt(matcher.group(1));
+ return (version >= n);
+ }
+ return false;
+ }
+
/**
* Waits for the given {@link Supplier} to be true until given timeout.
*
diff --git a/thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java b/thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java
index 49b002a..9406a2f 100644
--- a/thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java
+++ b/thread/tests/unit/src/com/android/server/thread/ThreadPersistentSettingsTest.java
@@ -17,7 +17,9 @@
package com.android.server.thread;
import static com.android.server.thread.ThreadPersistentSettings.THREAD_ENABLED;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
@@ -30,13 +32,13 @@
import android.content.res.Resources;
import android.os.PersistableBundle;
import android.util.AtomicFile;
+
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+
import com.android.connectivity.resources.R;
import com.android.server.connectivity.ConnectivityResources;
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -44,6 +46,10 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
/** Unit tests for {@link ThreadPersistentSettings}. */
@RunWith(AndroidJUnit4.class)
@SmallTest