From 7aeef6aab561bd76f4b5e457c20de0be02bfde55 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 14 Dec 2020 18:29:04 +0900 Subject: [PATCH 001/343] Add OWNERS for packages/Connectivity In preparation of future modularization of connectivity classes, a large part of frameworks/base/services/net is planned to be moved to packages/modules/Connectivity. However moving each class "manually" to that git project would lose their commit history, and require many cross-repository topics. To facilitate the work, create frameworks/base/packages/Connectivity, which will be used to move the classes at first, before they can all be moved together with their history to packages/modules/Connectivity. This mirrors the procedure used for NetworkStack, Tethering, CaptivePortalLogin, etc. previously. The added OWNERS file just imports owners from the previous file location. Bug: 171540887 Test: m Change-Id: Ic1c0dbbe8c1f07582c04757ced0ead2fc5b10ca7 --- OWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 OWNERS diff --git a/OWNERS b/OWNERS new file mode 100644 index 0000000000..48e54da82c --- /dev/null +++ b/OWNERS @@ -0,0 +1,3 @@ +set noparent + +include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS From 59262cbcdfbf5939e6cce16b54f984281d0f6015 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 21 Dec 2020 18:40:08 +0900 Subject: [PATCH 002/343] Split connectivity JNI and service jar The VPN JNI code is moving to the tethering APEX with ConnectivityService, so it needs to be split out of libandroid_servers. Also move the service-connectivity.jar build rule to packages/Connectivity together with the jni build rule. Bug: 171540887 Test: m, device boots and VPN (L2TP and VpnService) verified working Change-Id: Ic29096e2280ce928729315f53b2159b620da49d5 --- service/Android.bp | 79 ++++ service/jarjar-rules.txt | 1 + .../com_android_server_TestNetworkService.cpp | 107 +++++ .../com_android_server_connectivity_Vpn.cpp | 377 ++++++++++++++++++ service/jni/onload.cpp | 40 ++ 5 files changed, 604 insertions(+) create mode 100644 service/Android.bp create mode 100644 service/jarjar-rules.txt create mode 100644 service/jni/com_android_server_TestNetworkService.cpp create mode 100644 service/jni/com_android_server_connectivity_Vpn.cpp create mode 100644 service/jni/onload.cpp diff --git a/service/Android.bp b/service/Android.bp new file mode 100644 index 0000000000..a26f715280 --- /dev/null +++ b/service/Android.bp @@ -0,0 +1,79 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_defaults { + name: "libservice-connectivity-defaults", + // TODO: build against the NDK (sdk_version: "30" for example) + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], + srcs: [ + "jni/com_android_server_TestNetworkService.cpp", + "jni/com_android_server_connectivity_Vpn.cpp", + ], + shared_libs: [ + "libbase", + "liblog", + "libnativehelper", + // TODO: remove dependency on ifc_[add/del]_address by having Java code to add/delete + // addresses, and remove dependency on libnetutils. + "libnetutils", + ], +} + +cc_library_shared { + name: "libservice-connectivity", + defaults: ["libservice-connectivity-defaults"], + srcs: [ + "jni/onload.cpp", + ], + apex_available: [ + // TODO: move this library to the tethering APEX and remove libservice-connectivity-static + // "com.android.tethering", + ], +} + +// Static library linked into libservices.core until libservice-connectivity can be loaded from +// the tethering APEX instead. +cc_library_static { + name: "libservice-connectivity-static", + defaults: ["libservice-connectivity-defaults"], +} + +java_library { + name: "service-connectivity", + srcs: [ + ":connectivity-service-srcs", + ], + installable: true, + jarjar_rules: "jarjar-rules.txt", + libs: [ + "android.net.ipsec.ike", + "services.core", + "services.net", + "unsupportedappusage", + ], + static_libs: [ + "net-utils-device-common", + "net-utils-framework-common", + ], + apex_available: [ + "//apex_available:platform", + ], +} diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt new file mode 100644 index 0000000000..ef53ebb43c --- /dev/null +++ b/service/jarjar-rules.txt @@ -0,0 +1 @@ +rule com.android.net.module.util.** com.android.connectivity.util.@1 \ No newline at end of file diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp new file mode 100644 index 0000000000..36a6fde361 --- /dev/null +++ b/service/jni/com_android_server_TestNetworkService.cpp @@ -0,0 +1,107 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "netutils/ifc.h" + +#include "jni.h" +#include +#include +#include +#include + +namespace android { + +//------------------------------------------------------------------------------ + +static void throwException(JNIEnv* env, int error, const char* action, const char* iface) { + const std::string& msg = + android::base::StringPrintf("Error %s %s: %s", action, iface, strerror(error)); + + jniThrowException(env, "java/lang/IllegalStateException", msg.c_str()); +} + +static int createTunTapInterface(JNIEnv* env, bool isTun, 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; + strlcpy(ifr.ifr_name, iface, IFNAMSIZ); + if (ioctl(tun.get(), TUNSETIFF, &ifr)) { + throwException(env, errno, "allocating", ifr.ifr_name); + return -1; + } + + // Activate interface using an unconnected datagram socket. + base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0)); + ifr.ifr_flags = IFF_UP; + + if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) { + throwException(env, errno, "activating", ifr.ifr_name); + return -1; + } + + return tun.release(); +} + +//------------------------------------------------------------------------------ + +static jint create(JNIEnv* env, jobject /* thiz */, jboolean isTun, jstring jIface) { + ScopedUtfChars iface(env, jIface); + if (!iface.c_str()) { + jniThrowNullPointerException(env, "iface"); + return -1; + } + + int tun = createTunTapInterface(env, isTun, iface.c_str()); + + // Any exceptions will be thrown from the createTunTapInterface call + return tun; +} + +//------------------------------------------------------------------------------ + +static const JNINativeMethod gMethods[] = { + {"jniCreateTunTap", "(ZLjava/lang/String;)I", (void*)create}, +}; + +int register_android_server_TestNetworkService(JNIEnv* env) { + return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods, + NELEM(gMethods)); +} + +}; // namespace android diff --git a/service/jni/com_android_server_connectivity_Vpn.cpp b/service/jni/com_android_server_connectivity_Vpn.cpp new file mode 100644 index 0000000000..ea5e7183c9 --- /dev/null +++ b/service/jni/com_android_server_connectivity_Vpn.cpp @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2011 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 "VpnJni" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "netutils/ifc.h" + +#include "jni.h" +#include + +namespace android +{ + +static int inet4 = -1; +static int inet6 = -1; + +static inline in_addr_t *as_in_addr(sockaddr *sa) { + return &((sockaddr_in *)sa)->sin_addr.s_addr; +} + +//------------------------------------------------------------------------------ + +#define SYSTEM_ERROR (-1) +#define BAD_ARGUMENT (-2) + +static int create_interface(int mtu) +{ + int tun = open("/dev/tun", O_RDWR | O_NONBLOCK | O_CLOEXEC); + + ifreq ifr4; + memset(&ifr4, 0, sizeof(ifr4)); + + // Allocate interface. + ifr4.ifr_flags = IFF_TUN | IFF_NO_PI; + if (ioctl(tun, TUNSETIFF, &ifr4)) { + ALOGE("Cannot allocate TUN: %s", strerror(errno)); + goto error; + } + + // Activate interface. + ifr4.ifr_flags = IFF_UP; + if (ioctl(inet4, SIOCSIFFLAGS, &ifr4)) { + ALOGE("Cannot activate %s: %s", ifr4.ifr_name, strerror(errno)); + goto error; + } + + // Set MTU if it is specified. + ifr4.ifr_mtu = mtu; + if (mtu > 0 && ioctl(inet4, SIOCSIFMTU, &ifr4)) { + ALOGE("Cannot set MTU on %s: %s", ifr4.ifr_name, strerror(errno)); + goto error; + } + + return tun; + +error: + close(tun); + return SYSTEM_ERROR; +} + +static int get_interface_name(char *name, int tun) +{ + ifreq ifr4; + if (ioctl(tun, TUNGETIFF, &ifr4)) { + ALOGE("Cannot get interface name: %s", strerror(errno)); + return SYSTEM_ERROR; + } + strncpy(name, ifr4.ifr_name, IFNAMSIZ); + return 0; +} + +static int get_interface_index(const char *name) +{ + ifreq ifr4; + strncpy(ifr4.ifr_name, name, IFNAMSIZ); + if (ioctl(inet4, SIOGIFINDEX, &ifr4)) { + ALOGE("Cannot get index of %s: %s", name, strerror(errno)); + return SYSTEM_ERROR; + } + return ifr4.ifr_ifindex; +} + +static int set_addresses(const char *name, const char *addresses) +{ + int index = get_interface_index(name); + if (index < 0) { + return index; + } + + ifreq ifr4; + memset(&ifr4, 0, sizeof(ifr4)); + strncpy(ifr4.ifr_name, name, IFNAMSIZ); + ifr4.ifr_addr.sa_family = AF_INET; + ifr4.ifr_netmask.sa_family = AF_INET; + + in6_ifreq ifr6; + memset(&ifr6, 0, sizeof(ifr6)); + ifr6.ifr6_ifindex = index; + + char address[65]; + int prefix; + int chars; + int count = 0; + + while (sscanf(addresses, " %64[^/]/%d %n", address, &prefix, &chars) == 2) { + addresses += chars; + + if (strchr(address, ':')) { + // Add an IPv6 address. + if (inet_pton(AF_INET6, address, &ifr6.ifr6_addr) != 1 || + prefix < 0 || prefix > 128) { + count = BAD_ARGUMENT; + break; + } + + ifr6.ifr6_prefixlen = prefix; + if (ioctl(inet6, SIOCSIFADDR, &ifr6)) { + count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; + break; + } + } else { + // Add an IPv4 address. + if (inet_pton(AF_INET, address, as_in_addr(&ifr4.ifr_addr)) != 1 || + prefix < 0 || prefix > 32) { + count = BAD_ARGUMENT; + break; + } + + if (count) { + snprintf(ifr4.ifr_name, sizeof(ifr4.ifr_name), "%s:%d", name, count); + } + if (ioctl(inet4, SIOCSIFADDR, &ifr4)) { + count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; + break; + } + + in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0; + *as_in_addr(&ifr4.ifr_netmask) = htonl(mask); + if (ioctl(inet4, SIOCSIFNETMASK, &ifr4)) { + count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; + break; + } + } + ALOGD("Address added on %s: %s/%d", name, address, prefix); + ++count; + } + + if (count == BAD_ARGUMENT) { + ALOGE("Invalid address: %s/%d", address, prefix); + } else if (count == SYSTEM_ERROR) { + ALOGE("Cannot add address: %s/%d: %s", address, prefix, strerror(errno)); + } else if (*addresses) { + ALOGE("Invalid address: %s", addresses); + count = BAD_ARGUMENT; + } + + return count; +} + +static int reset_interface(const char *name) +{ + ifreq ifr4; + strncpy(ifr4.ifr_name, name, IFNAMSIZ); + ifr4.ifr_flags = 0; + + if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) { + ALOGE("Cannot reset %s: %s", name, strerror(errno)); + return SYSTEM_ERROR; + } + return 0; +} + +static int check_interface(const char *name) +{ + ifreq ifr4; + strncpy(ifr4.ifr_name, name, IFNAMSIZ); + ifr4.ifr_flags = 0; + + if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) { + ALOGE("Cannot check %s: %s", name, strerror(errno)); + } + return ifr4.ifr_flags; +} + +static bool modifyAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, + jint jPrefixLength, bool add) +{ + int error = SYSTEM_ERROR; + const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; + const char *address = jAddress ? env->GetStringUTFChars(jAddress, NULL) : NULL; + + if (!name) { + jniThrowNullPointerException(env, "name"); + } else if (!address) { + jniThrowNullPointerException(env, "address"); + } else { + if (add) { + if ((error = ifc_add_address(name, address, jPrefixLength)) != 0) { + ALOGE("Cannot add address %s/%d on interface %s (%s)", address, jPrefixLength, name, + strerror(-error)); + } + } else { + if ((error = ifc_del_address(name, address, jPrefixLength)) != 0) { + ALOGE("Cannot del address %s/%d on interface %s (%s)", address, jPrefixLength, name, + strerror(-error)); + } + } + } + + if (name) { + env->ReleaseStringUTFChars(jName, name); + } + if (address) { + env->ReleaseStringUTFChars(jAddress, address); + } + return !error; +} + +//------------------------------------------------------------------------------ + +static void throwException(JNIEnv *env, int error, const char *message) +{ + if (error == SYSTEM_ERROR) { + jniThrowException(env, "java/lang/IllegalStateException", message); + } else { + jniThrowException(env, "java/lang/IllegalArgumentException", message); + } +} + +static jint create(JNIEnv *env, jobject /* thiz */, jint mtu) +{ + int tun = create_interface(mtu); + if (tun < 0) { + throwException(env, tun, "Cannot create interface"); + return -1; + } + return tun; +} + +static jstring getName(JNIEnv *env, jobject /* thiz */, jint tun) +{ + char name[IFNAMSIZ]; + if (get_interface_name(name, tun) < 0) { + throwException(env, SYSTEM_ERROR, "Cannot get interface name"); + return NULL; + } + return env->NewStringUTF(name); +} + +static jint setAddresses(JNIEnv *env, jobject /* thiz */, jstring jName, + jstring jAddresses) +{ + const char *name = NULL; + const char *addresses = NULL; + int count = -1; + + name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; + if (!name) { + jniThrowNullPointerException(env, "name"); + goto error; + } + addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL; + if (!addresses) { + jniThrowNullPointerException(env, "addresses"); + goto error; + } + count = set_addresses(name, addresses); + if (count < 0) { + throwException(env, count, "Cannot set address"); + count = -1; + } + +error: + if (name) { + env->ReleaseStringUTFChars(jName, name); + } + if (addresses) { + env->ReleaseStringUTFChars(jAddresses, addresses); + } + return count; +} + +static void reset(JNIEnv *env, jobject /* thiz */, jstring jName) +{ + const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; + if (!name) { + jniThrowNullPointerException(env, "name"); + return; + } + if (reset_interface(name) < 0) { + throwException(env, SYSTEM_ERROR, "Cannot reset interface"); + } + env->ReleaseStringUTFChars(jName, name); +} + +static jint check(JNIEnv *env, jobject /* thiz */, jstring jName) +{ + const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; + if (!name) { + jniThrowNullPointerException(env, "name"); + return 0; + } + int flags = check_interface(name); + env->ReleaseStringUTFChars(jName, name); + return flags; +} + +static bool addAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, + jint jPrefixLength) +{ + return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, true); +} + +static bool delAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, + jint jPrefixLength) +{ + return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, false); +} + +//------------------------------------------------------------------------------ + +static const JNINativeMethod gMethods[] = { + {"jniCreate", "(I)I", (void *)create}, + {"jniGetName", "(I)Ljava/lang/String;", (void *)getName}, + {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses}, + {"jniReset", "(Ljava/lang/String;)V", (void *)reset}, + {"jniCheck", "(Ljava/lang/String;)I", (void *)check}, + {"jniAddAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)addAddress}, + {"jniDelAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)delAddress}, +}; + +int register_android_server_connectivity_Vpn(JNIEnv *env) +{ + if (inet4 == -1) { + inet4 = socket(AF_INET, SOCK_DGRAM, 0); + } + if (inet6 == -1) { + inet6 = socket(AF_INET6, SOCK_DGRAM, 0); + } + return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn", + gMethods, NELEM(gMethods)); +} + +}; diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp new file mode 100644 index 0000000000..3afcb0e8f6 --- /dev/null +++ b/service/jni/onload.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace android { + +int register_android_server_connectivity_Vpn(JNIEnv* env); +int register_android_server_TestNetworkService(JNIEnv* env); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("GetEnv failed"); + return JNI_ERR; + } + + if (register_android_server_connectivity_Vpn(env) < 0 + || register_android_server_TestNetworkService(env) < 0) { + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} + +}; \ No newline at end of file From c2d6a94b35c18fc239a936884de749fa81bb6136 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 23 Oct 2020 17:57:31 +0900 Subject: [PATCH 003/343] Move service-connectivity to the tethering APEX As part of modularization of ConnectivityService and expansion of the Tethering module scope, move service-connectivity.jar into the tethering APEX, and load it from there. Bug: 171540887 Test: m, device boots and connectivity Change-Id: Id7b6a4664ae73224b9ab219c94f56d603a62ee5a --- service/Android.bp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/service/Android.bp b/service/Android.bp index a26f715280..c8f3bd3666 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -14,8 +14,8 @@ // limitations under the License. // -cc_defaults { - name: "libservice-connectivity-defaults", +cc_library_shared { + name: "libservice-connectivity", // TODO: build against the NDK (sdk_version: "30" for example) cflags: [ "-Wall", @@ -26,6 +26,7 @@ cc_defaults { srcs: [ "jni/com_android_server_TestNetworkService.cpp", "jni/com_android_server_connectivity_Vpn.cpp", + "jni/onload.cpp", ], shared_libs: [ "libbase", @@ -35,27 +36,11 @@ cc_defaults { // addresses, and remove dependency on libnetutils. "libnetutils", ], -} - -cc_library_shared { - name: "libservice-connectivity", - defaults: ["libservice-connectivity-defaults"], - srcs: [ - "jni/onload.cpp", - ], apex_available: [ - // TODO: move this library to the tethering APEX and remove libservice-connectivity-static - // "com.android.tethering", + "com.android.tethering", ], } -// Static library linked into libservices.core until libservice-connectivity can be loaded from -// the tethering APEX instead. -cc_library_static { - name: "libservice-connectivity-static", - defaults: ["libservice-connectivity-defaults"], -} - java_library { name: "service-connectivity", srcs: [ @@ -75,5 +60,6 @@ java_library { ], apex_available: [ "//apex_available:platform", + "com.android.tethering", ], } From b145611a1e7738468083e2205460f5e8ec9ff6ea Mon Sep 17 00:00:00 2001 From: Pete Bentley Date: Thu, 7 Jan 2021 13:51:18 +0000 Subject: [PATCH 004/343] Revert "Move service-connectivity to the tethering APEX" Revert submission 1532910-connectivity_jar_in_apex Reason for revert: Breaks boot tests: b/176969905 Reverted Changes: Ie41a5b569:Set setCurrentProxyScriptUrl as public Id7b6a4664:Move service-connectivity to the tethering APEX Ia7cb83834:Add service-connectivity to tethering APEX Change-Id: I1c369dd8a6527513f8fc1a5cacde59d78d104c7e --- service/Android.bp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/service/Android.bp b/service/Android.bp index c8f3bd3666..a26f715280 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -14,8 +14,8 @@ // limitations under the License. // -cc_library_shared { - name: "libservice-connectivity", +cc_defaults { + name: "libservice-connectivity-defaults", // TODO: build against the NDK (sdk_version: "30" for example) cflags: [ "-Wall", @@ -26,7 +26,6 @@ cc_library_shared { srcs: [ "jni/com_android_server_TestNetworkService.cpp", "jni/com_android_server_connectivity_Vpn.cpp", - "jni/onload.cpp", ], shared_libs: [ "libbase", @@ -36,9 +35,25 @@ cc_library_shared { // addresses, and remove dependency on libnetutils. "libnetutils", ], - apex_available: [ - "com.android.tethering", +} + +cc_library_shared { + name: "libservice-connectivity", + defaults: ["libservice-connectivity-defaults"], + srcs: [ + "jni/onload.cpp", ], + apex_available: [ + // TODO: move this library to the tethering APEX and remove libservice-connectivity-static + // "com.android.tethering", + ], +} + +// Static library linked into libservices.core until libservice-connectivity can be loaded from +// the tethering APEX instead. +cc_library_static { + name: "libservice-connectivity-static", + defaults: ["libservice-connectivity-defaults"], } java_library { @@ -60,6 +75,5 @@ java_library { ], apex_available: [ "//apex_available:platform", - "com.android.tethering", ], } From 5bfb9f872c7e86f01ba62490f7a30289c801d45c Mon Sep 17 00:00:00 2001 From: Pete Bentley Date: Thu, 7 Jan 2021 13:51:18 +0000 Subject: [PATCH 005/343] Revert "Move service-connectivity to the tethering APEX" Revert submission 1532910-connectivity_jar_in_apex Reason for revert: Breaks boot tests: b/176969905 Reverted Changes: Ie41a5b569:Set setCurrentProxyScriptUrl as public Id7b6a4664:Move service-connectivity to the tethering APEX Ia7cb83834:Add service-connectivity to tethering APEX Change-Id: I1c369dd8a6527513f8fc1a5cacde59d78d104c7e (cherry picked from commit 3e157018f7745956e03bc82324ef4921366a43fc) --- service/Android.bp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/service/Android.bp b/service/Android.bp index c8f3bd3666..a26f715280 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -14,8 +14,8 @@ // limitations under the License. // -cc_library_shared { - name: "libservice-connectivity", +cc_defaults { + name: "libservice-connectivity-defaults", // TODO: build against the NDK (sdk_version: "30" for example) cflags: [ "-Wall", @@ -26,7 +26,6 @@ cc_library_shared { srcs: [ "jni/com_android_server_TestNetworkService.cpp", "jni/com_android_server_connectivity_Vpn.cpp", - "jni/onload.cpp", ], shared_libs: [ "libbase", @@ -36,9 +35,25 @@ cc_library_shared { // addresses, and remove dependency on libnetutils. "libnetutils", ], - apex_available: [ - "com.android.tethering", +} + +cc_library_shared { + name: "libservice-connectivity", + defaults: ["libservice-connectivity-defaults"], + srcs: [ + "jni/onload.cpp", ], + apex_available: [ + // TODO: move this library to the tethering APEX and remove libservice-connectivity-static + // "com.android.tethering", + ], +} + +// Static library linked into libservices.core until libservice-connectivity can be loaded from +// the tethering APEX instead. +cc_library_static { + name: "libservice-connectivity-static", + defaults: ["libservice-connectivity-defaults"], } java_library { @@ -60,6 +75,5 @@ java_library { ], apex_available: [ "//apex_available:platform", - "com.android.tethering", ], } From eaa9658100c28c73d63e57ed139533148e67a3b9 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 8 Jan 2021 01:19:44 +0000 Subject: [PATCH 006/343] Revert^2 "Move service-connectivity to the tethering APEX" As part of modularization of ConnectivityService and expansion of the Tethering module scope, move service-connectivity.jar into the tethering APEX, and load it from there. This rolls forward the change. The original topic was reverted because of a bad merged-in clause; this is fixed and re-verified in this topic. Bug: 171540887 Test: m, device boots and connectivity Change-Id: I293b09c0dc04c6ccafa30cd0f1a63efe32283604 --- service/Android.bp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/service/Android.bp b/service/Android.bp index a26f715280..c8f3bd3666 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -14,8 +14,8 @@ // limitations under the License. // -cc_defaults { - name: "libservice-connectivity-defaults", +cc_library_shared { + name: "libservice-connectivity", // TODO: build against the NDK (sdk_version: "30" for example) cflags: [ "-Wall", @@ -26,6 +26,7 @@ cc_defaults { srcs: [ "jni/com_android_server_TestNetworkService.cpp", "jni/com_android_server_connectivity_Vpn.cpp", + "jni/onload.cpp", ], shared_libs: [ "libbase", @@ -35,27 +36,11 @@ cc_defaults { // addresses, and remove dependency on libnetutils. "libnetutils", ], -} - -cc_library_shared { - name: "libservice-connectivity", - defaults: ["libservice-connectivity-defaults"], - srcs: [ - "jni/onload.cpp", - ], apex_available: [ - // TODO: move this library to the tethering APEX and remove libservice-connectivity-static - // "com.android.tethering", + "com.android.tethering", ], } -// Static library linked into libservices.core until libservice-connectivity can be loaded from -// the tethering APEX instead. -cc_library_static { - name: "libservice-connectivity-static", - defaults: ["libservice-connectivity-defaults"], -} - java_library { name: "service-connectivity", srcs: [ @@ -75,5 +60,6 @@ java_library { ], apex_available: [ "//apex_available:platform", + "com.android.tethering", ], } From ef337535cee0ae73e673d8c09ebe8212f8966881 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Mon, 18 Jan 2021 11:58:24 +0800 Subject: [PATCH 007/343] Use function inside NetdUtils instead of NetworkManagementService TestNetworkService will be a part of mainline module, to prevent using @hide API of NetworkManagementService in TestNetworkService, use function inside NetdUtils instead. Bug: 170598012 Test: atest CtsNetTestCasesLatestSdk Change-Id: I738066ce2f1bcd616dc582a3ff1fd77bcd660c73 --- service/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/service/Android.bp b/service/Android.bp index c8f3bd3666..8fc3181807 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -57,6 +57,7 @@ java_library { static_libs: [ "net-utils-device-common", "net-utils-framework-common", + "netd-client", ], apex_available: [ "//apex_available:platform", From 66ea68e472a1c16b49da48874ffebfbc2bcdf098 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 15 Jan 2021 16:22:36 +0900 Subject: [PATCH 008/343] Move connectivity-sources to frameworks/base All sources for the connectivity module are being moved to frameworks/base/packages/Connectivity, so that they can all be moved to packages/modules/Connectivity in one move keeping history. INetworkAgent and INetworkAgentRegistry were created in packages/modules/Connectivity directly, but this makes managing the sources until the move harder as the module needs to pull sources from two different locations. Considering that they do not have history to move, just move them to frameworks/base/packages/Connectivity without the commit history. Bug: 171540887 Test: m Change-Id: Ic4353115a98b6235c2b5d5ce24741223e618d0a6 --- framework/Android.bp | 29 +++++++++++ .../connectivity/aidl/INetworkAgent.aidl | 49 +++++++++++++++++++ .../aidl/INetworkAgentRegistry.aidl | 41 ++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 framework/Android.bp create mode 100644 framework/src/com/android/connectivity/aidl/INetworkAgent.aidl create mode 100644 framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl diff --git a/framework/Android.bp b/framework/Android.bp new file mode 100644 index 0000000000..8db8d7699a --- /dev/null +++ b/framework/Android.bp @@ -0,0 +1,29 @@ +// +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// TODO: use a java_library in the bootclasspath instead +filegroup { + name: "framework-connectivity-sources", + srcs: [ + "src/**/*.java", + "src/**/*.aidl", + ], + path: "src", + visibility: [ + "//frameworks/base", + "//packages/modules/Connectivity:__subpackages__", + ], +} \ No newline at end of file diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl b/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl new file mode 100644 index 0000000000..64b556720c --- /dev/null +++ b/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +package com.android.connectivity.aidl; + +import android.net.NattKeepalivePacketData; +import android.net.QosFilterParcelable; +import android.net.TcpKeepalivePacketData; + +import com.android.connectivity.aidl.INetworkAgentRegistry; + +/** + * Interface to notify NetworkAgent of connectivity events. + * @hide + */ +oneway interface INetworkAgent { + void onRegistered(in INetworkAgentRegistry registry); + void onDisconnected(); + void onBandwidthUpdateRequested(); + void onValidationStatusChanged(int validationStatus, + in @nullable String captivePortalUrl); + void onSaveAcceptUnvalidated(boolean acceptUnvalidated); + void onStartNattSocketKeepalive(int slot, int intervalDurationMs, + in NattKeepalivePacketData packetData); + void onStartTcpSocketKeepalive(int slot, int intervalDurationMs, + in TcpKeepalivePacketData packetData); + void onStopSocketKeepalive(int slot); + void onSignalStrengthThresholdsUpdated(in int[] thresholds); + void onPreventAutomaticReconnect(); + void onAddNattKeepalivePacketFilter(int slot, + in NattKeepalivePacketData packetData); + void onAddTcpKeepalivePacketFilter(int slot, + in TcpKeepalivePacketData packetData); + void onRemoveKeepalivePacketFilter(int slot); + void onQosFilterCallbackRegistered(int qosCallbackId, in QosFilterParcelable filterParcel); + void onQosCallbackUnregistered(int qosCallbackId); +} diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl new file mode 100644 index 0000000000..f0193db5c2 --- /dev/null +++ b/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing perNmissions and + * limitations under the License. + */ +package com.android.connectivity.aidl; + +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.net.QosSession; +import android.telephony.data.EpsBearerQosSessionAttributes; + +/** + * Interface for NetworkAgents to send network network properties. + * @hide + */ +oneway interface INetworkAgentRegistry { + void sendNetworkCapabilities(in NetworkCapabilities nc); + void sendLinkProperties(in LinkProperties lp); + // TODO: consider replacing this by "markConnected()" and removing + void sendNetworkInfo(in NetworkInfo info); + void sendScore(int score); + void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial); + void sendSocketKeepaliveEvent(int slot, int reason); + void sendUnderlyingNetworks(in @nullable List networks); + void sendEpsQosSessionAvailable(int callbackId, in QosSession session, in EpsBearerQosSessionAttributes attributes); + void sendQosSessionLost(int qosCallbackId, in QosSession session); + void sendQosCallbackError(int qosCallbackId, int exceptionType); +} From fbbccbce69e782c3994fb1231c1126ea5b0b057d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 15 Jan 2021 18:08:24 +0900 Subject: [PATCH 009/343] Move module sources to packages/Connectivity Files that are planned to be part of the connectivity module are grouped in packages/Connectivity, so they can be built separately and moved in one operation with their history into packages/modules/Connectivity. This places the files in the existing framework-connectivity-sources filegroup instead of the current framework-core-sources filegroup. Both are used the same way in framework-non-updatable-sources. Bug: 171540887 Test: m Change-Id: I62d9d91574ace6f5c4624035d190260c3126b91e --- framework/src/android/net/CaptivePortal.java | 171 + .../src/android/net/CaptivePortalData.aidl | 19 + .../src/android/net/CaptivePortalData.java | 305 + framework/src/android/net/ConnectionInfo.aidl | 20 + framework/src/android/net/ConnectionInfo.java | 83 + .../net/ConnectivityDiagnosticsManager.aidl | 21 + .../net/ConnectivityDiagnosticsManager.java | 777 +++ .../src/android/net/ConnectivityManager.java | 5058 +++++++++++++++++ .../android/net/ConnectivityMetricsEvent.aidl | 20 + .../src/android/net/ConnectivityThread.java | 56 + framework/src/android/net/DhcpInfo.aidl | 19 + framework/src/android/net/DhcpInfo.java | 105 + framework/src/android/net/DnsResolver.java | 577 ++ framework/src/android/net/ICaptivePortal.aidl | 27 + .../net/IConnectivityDiagnosticsCallback.aidl | 28 + .../src/android/net/IConnectivityManager.aidl | 246 + .../android/net/ISocketKeepaliveCallback.aidl | 34 + .../src/android/net/ITestNetworkManager.aidl | 39 + framework/src/android/net/InetAddresses.java | 65 + .../android/net/InterfaceConfiguration.aidl | 19 + .../android/net/InvalidPacketException.java | 66 + .../src/android/net/IpConfiguration.aidl | 19 + .../src/android/net/IpConfiguration.java | 223 + framework/src/android/net/IpPrefix.aidl | 22 + framework/src/android/net/IpPrefix.java | 300 + .../src/android/net/KeepalivePacketData.aidl | 19 + .../src/android/net/KeepalivePacketData.java | 119 + framework/src/android/net/LinkAddress.aidl | 21 + framework/src/android/net/LinkAddress.java | 549 ++ framework/src/android/net/LinkProperties.aidl | 20 + framework/src/android/net/LinkProperties.java | 1823 ++++++ framework/src/android/net/MacAddress.aidl | 20 + framework/src/android/net/MacAddress.java | 400 ++ .../android/net/NattKeepalivePacketData.java | 144 + .../src/android/net/NattSocketKeepalive.java | 77 + framework/src/android/net/Network.aidl | 20 + framework/src/android/net/Network.java | 535 ++ framework/src/android/net/NetworkAgent.java | 1185 ++++ .../src/android/net/NetworkAgentConfig.aidl | 19 + .../src/android/net/NetworkAgentConfig.java | 440 ++ .../src/android/net/NetworkCapabilities.aidl | 21 + .../src/android/net/NetworkCapabilities.java | 2517 ++++++++ framework/src/android/net/NetworkConfig.java | 80 + framework/src/android/net/NetworkInfo.aidl | 19 + framework/src/android/net/NetworkInfo.java | 626 ++ .../src/android/net/NetworkProvider.java | 162 + framework/src/android/net/NetworkRequest.aidl | 20 + framework/src/android/net/NetworkRequest.java | 582 ++ framework/src/android/net/NetworkUtils.java | 425 ++ .../src/android/net/PacProxySelector.java | 138 + framework/src/android/net/Proxy.java | 294 + framework/src/android/net/ProxyInfo.aidl | 21 + framework/src/android/net/ProxyInfo.java | 367 ++ framework/src/android/net/RouteInfo.aidl | 19 + framework/src/android/net/RouteInfo.java | 658 +++ .../src/android/net/SocketKeepalive.java | 301 + .../android/net/StaticIpConfiguration.aidl | 20 + .../android/net/StaticIpConfiguration.java | 332 ++ .../android/net/TcpKeepalivePacketData.java | 163 + .../src/android/net/TcpRepairWindow.java | 48 + .../src/android/net/TcpSocketKeepalive.java | 77 + .../src/android/net/TestNetworkInterface.aidl | 20 + .../src/android/net/TestNetworkInterface.java | 78 + .../src/android/net/TestNetworkManager.java | 178 + framework/src/android/net/TransportInfo.java | 63 + framework/src/android/net/UidRange.aidl | 24 + framework/src/android/net/VpnManager.java | 164 + framework/src/android/net/VpnService.java | 903 +++ .../src/android/net/apf/ApfCapabilities.aidl | 20 + .../src/android/net/apf/ApfCapabilities.java | 133 + framework/src/android/net/util/DnsUtils.java | 379 ++ .../src/android/net/util/KeepaliveUtils.java | 115 + .../net/util/MultinetworkPolicyTracker.java | 217 + .../src/android/net/util/SocketUtils.java | 121 + 74 files changed, 23015 insertions(+) create mode 100644 framework/src/android/net/CaptivePortal.java create mode 100644 framework/src/android/net/CaptivePortalData.aidl create mode 100644 framework/src/android/net/CaptivePortalData.java create mode 100644 framework/src/android/net/ConnectionInfo.aidl create mode 100644 framework/src/android/net/ConnectionInfo.java create mode 100644 framework/src/android/net/ConnectivityDiagnosticsManager.aidl create mode 100644 framework/src/android/net/ConnectivityDiagnosticsManager.java create mode 100644 framework/src/android/net/ConnectivityManager.java create mode 100644 framework/src/android/net/ConnectivityMetricsEvent.aidl create mode 100644 framework/src/android/net/ConnectivityThread.java create mode 100644 framework/src/android/net/DhcpInfo.aidl create mode 100644 framework/src/android/net/DhcpInfo.java create mode 100644 framework/src/android/net/DnsResolver.java create mode 100644 framework/src/android/net/ICaptivePortal.aidl create mode 100644 framework/src/android/net/IConnectivityDiagnosticsCallback.aidl create mode 100644 framework/src/android/net/IConnectivityManager.aidl create mode 100644 framework/src/android/net/ISocketKeepaliveCallback.aidl create mode 100644 framework/src/android/net/ITestNetworkManager.aidl create mode 100644 framework/src/android/net/InetAddresses.java create mode 100644 framework/src/android/net/InterfaceConfiguration.aidl create mode 100644 framework/src/android/net/InvalidPacketException.java create mode 100644 framework/src/android/net/IpConfiguration.aidl create mode 100644 framework/src/android/net/IpConfiguration.java create mode 100644 framework/src/android/net/IpPrefix.aidl create mode 100644 framework/src/android/net/IpPrefix.java create mode 100644 framework/src/android/net/KeepalivePacketData.aidl create mode 100644 framework/src/android/net/KeepalivePacketData.java create mode 100644 framework/src/android/net/LinkAddress.aidl create mode 100644 framework/src/android/net/LinkAddress.java create mode 100644 framework/src/android/net/LinkProperties.aidl create mode 100644 framework/src/android/net/LinkProperties.java create mode 100644 framework/src/android/net/MacAddress.aidl create mode 100644 framework/src/android/net/MacAddress.java create mode 100644 framework/src/android/net/NattKeepalivePacketData.java create mode 100644 framework/src/android/net/NattSocketKeepalive.java create mode 100644 framework/src/android/net/Network.aidl create mode 100644 framework/src/android/net/Network.java create mode 100644 framework/src/android/net/NetworkAgent.java create mode 100644 framework/src/android/net/NetworkAgentConfig.aidl create mode 100644 framework/src/android/net/NetworkAgentConfig.java create mode 100644 framework/src/android/net/NetworkCapabilities.aidl create mode 100644 framework/src/android/net/NetworkCapabilities.java create mode 100644 framework/src/android/net/NetworkConfig.java create mode 100644 framework/src/android/net/NetworkInfo.aidl create mode 100644 framework/src/android/net/NetworkInfo.java create mode 100644 framework/src/android/net/NetworkProvider.java create mode 100644 framework/src/android/net/NetworkRequest.aidl create mode 100644 framework/src/android/net/NetworkRequest.java create mode 100644 framework/src/android/net/NetworkUtils.java create mode 100644 framework/src/android/net/PacProxySelector.java create mode 100644 framework/src/android/net/Proxy.java create mode 100644 framework/src/android/net/ProxyInfo.aidl create mode 100644 framework/src/android/net/ProxyInfo.java create mode 100644 framework/src/android/net/RouteInfo.aidl create mode 100644 framework/src/android/net/RouteInfo.java create mode 100644 framework/src/android/net/SocketKeepalive.java create mode 100644 framework/src/android/net/StaticIpConfiguration.aidl create mode 100644 framework/src/android/net/StaticIpConfiguration.java create mode 100644 framework/src/android/net/TcpKeepalivePacketData.java create mode 100644 framework/src/android/net/TcpRepairWindow.java create mode 100644 framework/src/android/net/TcpSocketKeepalive.java create mode 100644 framework/src/android/net/TestNetworkInterface.aidl create mode 100644 framework/src/android/net/TestNetworkInterface.java create mode 100644 framework/src/android/net/TestNetworkManager.java create mode 100644 framework/src/android/net/TransportInfo.java create mode 100644 framework/src/android/net/UidRange.aidl create mode 100644 framework/src/android/net/VpnManager.java create mode 100644 framework/src/android/net/VpnService.java create mode 100644 framework/src/android/net/apf/ApfCapabilities.aidl create mode 100644 framework/src/android/net/apf/ApfCapabilities.java create mode 100644 framework/src/android/net/util/DnsUtils.java create mode 100644 framework/src/android/net/util/KeepaliveUtils.java create mode 100644 framework/src/android/net/util/MultinetworkPolicyTracker.java create mode 100644 framework/src/android/net/util/SocketUtils.java diff --git a/framework/src/android/net/CaptivePortal.java b/framework/src/android/net/CaptivePortal.java new file mode 100644 index 0000000000..269bbf20c8 --- /dev/null +++ b/framework/src/android/net/CaptivePortal.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed urnder the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; + +/** + * A class allowing apps handling the {@link ConnectivityManager#ACTION_CAPTIVE_PORTAL_SIGN_IN} + * activity to indicate to the system different outcomes of captive portal sign in. This class is + * passed as an extra named {@link ConnectivityManager#EXTRA_CAPTIVE_PORTAL} with the + * {@code ACTION_CAPTIVE_PORTAL_SIGN_IN} activity. + */ +public class CaptivePortal implements Parcelable { + /** + * Response code from the captive portal application, indicating that the portal was dismissed + * and the network should be re-validated. + * @see ICaptivePortal#appResponse(int) + * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) + * @hide + */ + @SystemApi + public static final int APP_RETURN_DISMISSED = 0; + /** + * Response code from the captive portal application, indicating that the user did not login and + * does not want to use the captive portal network. + * @see ICaptivePortal#appResponse(int) + * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) + * @hide + */ + @SystemApi + public static final int APP_RETURN_UNWANTED = 1; + /** + * Response code from the captive portal application, indicating that the user does not wish to + * login but wants to use the captive portal network as-is. + * @see ICaptivePortal#appResponse(int) + * @see android.net.INetworkMonitor#notifyCaptivePortalAppFinished(int) + * @hide + */ + @SystemApi + public static final int APP_RETURN_WANTED_AS_IS = 2; + /** Event offset of request codes from captive portal application. */ + private static final int APP_REQUEST_BASE = 100; + /** + * Request code from the captive portal application, indicating that the network condition may + * have changed and the network should be re-validated. + * @see ICaptivePortal#appRequest(int) + * @see android.net.INetworkMonitor#forceReevaluation(int) + * @hide + */ + @SystemApi + public static final int APP_REQUEST_REEVALUATION_REQUIRED = APP_REQUEST_BASE + 0; + + private final IBinder mBinder; + + /** @hide */ + public CaptivePortal(@NonNull IBinder binder) { + mBinder = binder; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeStrongBinder(mBinder); + } + + public static final @android.annotation.NonNull Parcelable.Creator CREATOR + = new Parcelable.Creator() { + @Override + public CaptivePortal createFromParcel(Parcel in) { + return new CaptivePortal(in.readStrongBinder()); + } + + @Override + public CaptivePortal[] newArray(int size) { + return new CaptivePortal[size]; + } + }; + + /** + * Indicate to the system that the captive portal has been + * dismissed. In response the framework will re-evaluate the network's + * connectivity and might take further action thereafter. + */ + public void reportCaptivePortalDismissed() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_DISMISSED); + } catch (RemoteException e) { + } + } + + /** + * Indicate to the system that the user does not want to pursue signing in to the + * captive portal and the system should continue to prefer other networks + * without captive portals for use as the default active data network. The + * system will not retest the network for a captive portal so as to avoid + * disturbing the user with further sign in to network notifications. + */ + public void ignoreNetwork() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_UNWANTED); + } catch (RemoteException e) { + } + } + + /** + * Indicate to the system the user wants to use this network as is, even though + * the captive portal is still in place. The system will treat the network + * as if it did not have a captive portal when selecting the network to use + * as the default active data network. This may result in this network + * becoming the default active data network, which could disrupt network + * connectivity for apps because the captive portal is still in place. + * @hide + */ + @SystemApi + public void useNetwork() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appResponse(APP_RETURN_WANTED_AS_IS); + } catch (RemoteException e) { + } + } + + /** + * Request that the system reevaluates the captive portal status. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void reevaluateNetwork() { + try { + ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED); + } catch (RemoteException e) { + } + } + + /** + * Log a captive portal login event. + * @param eventId one of the CAPTIVE_PORTAL_LOGIN_* constants in metrics_constants.proto. + * @param packageName captive portal application package name. + * @hide + */ + @SystemApi + public void logEvent(int eventId, @NonNull String packageName) { + try { + ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName); + } catch (RemoteException e) { + } + } +} diff --git a/framework/src/android/net/CaptivePortalData.aidl b/framework/src/android/net/CaptivePortalData.aidl new file mode 100644 index 0000000000..1d57ee7591 --- /dev/null +++ b/framework/src/android/net/CaptivePortalData.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +@JavaOnlyStableParcelable parcelable CaptivePortalData; diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java new file mode 100644 index 0000000000..18467fad8e --- /dev/null +++ b/framework/src/android/net/CaptivePortalData.java @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Metadata sent by captive portals, see https://www.ietf.org/id/draft-ietf-capport-api-03.txt. + * @hide + */ +@SystemApi +public final class CaptivePortalData implements Parcelable { + private final long mRefreshTimeMillis; + @Nullable + private final Uri mUserPortalUrl; + @Nullable + private final Uri mVenueInfoUrl; + private final boolean mIsSessionExtendable; + private final long mByteLimit; + private final long mExpiryTimeMillis; + private final boolean mCaptive; + private final String mVenueFriendlyName; + + private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, + boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, + String venueFriendlyName) { + mRefreshTimeMillis = refreshTimeMillis; + mUserPortalUrl = userPortalUrl; + mVenueInfoUrl = venueInfoUrl; + mIsSessionExtendable = isSessionExtendable; + mByteLimit = byteLimit; + mExpiryTimeMillis = expiryTimeMillis; + mCaptive = captive; + mVenueFriendlyName = venueFriendlyName; + } + + private CaptivePortalData(Parcel p) { + this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), + p.readLong(), p.readLong(), p.readBoolean(), p.readString()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeLong(mRefreshTimeMillis); + dest.writeParcelable(mUserPortalUrl, 0); + dest.writeParcelable(mVenueInfoUrl, 0); + dest.writeBoolean(mIsSessionExtendable); + dest.writeLong(mByteLimit); + dest.writeLong(mExpiryTimeMillis); + dest.writeBoolean(mCaptive); + dest.writeString(mVenueFriendlyName); + } + + /** + * A builder to create new {@link CaptivePortalData}. + */ + public static class Builder { + private long mRefreshTime; + private Uri mUserPortalUrl; + private Uri mVenueInfoUrl; + private boolean mIsSessionExtendable; + private long mBytesRemaining = -1; + private long mExpiryTime = -1; + private boolean mCaptive; + private String mVenueFriendlyName; + + /** + * Create an empty builder. + */ + public Builder() {} + + /** + * Create a builder copying all data from existing {@link CaptivePortalData}. + */ + public Builder(@Nullable CaptivePortalData data) { + if (data == null) return; + setRefreshTime(data.mRefreshTimeMillis) + .setUserPortalUrl(data.mUserPortalUrl) + .setVenueInfoUrl(data.mVenueInfoUrl) + .setSessionExtendable(data.mIsSessionExtendable) + .setBytesRemaining(data.mByteLimit) + .setExpiryTime(data.mExpiryTimeMillis) + .setCaptive(data.mCaptive) + .setVenueFriendlyName(data.mVenueFriendlyName); + } + + /** + * Set the time at which data was last refreshed, as per {@link System#currentTimeMillis()}. + */ + @NonNull + public Builder setRefreshTime(long refreshTime) { + mRefreshTime = refreshTime; + return this; + } + + /** + * Set the URL to be used for users to login to the portal, if captive. + */ + @NonNull + public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) { + mUserPortalUrl = userPortalUrl; + return this; + } + + /** + * Set the URL that can be used by users to view information about the network venue. + */ + @NonNull + public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) { + mVenueInfoUrl = venueInfoUrl; + return this; + } + + /** + * Set whether the portal supports extending a user session on the portal URL page. + */ + @NonNull + public Builder setSessionExtendable(boolean sessionExtendable) { + mIsSessionExtendable = sessionExtendable; + return this; + } + + /** + * Set the number of bytes remaining on the network before the portal closes. + */ + @NonNull + public Builder setBytesRemaining(long bytesRemaining) { + mBytesRemaining = bytesRemaining; + return this; + } + + /** + * Set the time at the session will expire, as per {@link System#currentTimeMillis()}. + */ + @NonNull + public Builder setExpiryTime(long expiryTime) { + mExpiryTime = expiryTime; + return this; + } + + /** + * Set whether the network is captive (portal closed). + */ + @NonNull + public Builder setCaptive(boolean captive) { + mCaptive = captive; + return this; + } + + /** + * Set the venue friendly name. + */ + @NonNull + public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { + mVenueFriendlyName = venueFriendlyName; + return this; + } + + /** + * Create a new {@link CaptivePortalData}. + */ + @NonNull + public CaptivePortalData build() { + return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl, + mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive, + mVenueFriendlyName); + } + } + + /** + * Get the time at which data was last refreshed, as per {@link System#currentTimeMillis()}. + */ + public long getRefreshTimeMillis() { + return mRefreshTimeMillis; + } + + /** + * Get the URL to be used for users to login to the portal, or extend their session if + * {@link #isSessionExtendable()} is true. + */ + @Nullable + public Uri getUserPortalUrl() { + return mUserPortalUrl; + } + + /** + * Get the URL that can be used by users to view information about the network venue. + */ + @Nullable + public Uri getVenueInfoUrl() { + return mVenueInfoUrl; + } + + /** + * Indicates whether the user portal URL can be used to extend sessions, when the user is logged + * in and the session has a time or byte limit. + */ + public boolean isSessionExtendable() { + return mIsSessionExtendable; + } + + /** + * Get the remaining bytes on the captive portal session, at the time {@link CaptivePortalData} + * was refreshed. This may be different from the limit currently enforced by the portal. + * @return The byte limit, or -1 if not set. + */ + public long getByteLimit() { + return mByteLimit; + } + + /** + * Get the time at the session will expire, as per {@link System#currentTimeMillis()}. + * @return The expiry time, or -1 if unset. + */ + public long getExpiryTimeMillis() { + return mExpiryTimeMillis; + } + + /** + * Get whether the network is captive (portal closed). + */ + public boolean isCaptive() { + return mCaptive; + } + + /** + * Get the venue friendly name + */ + @Nullable + public String getVenueFriendlyName() { + return mVenueFriendlyName; + } + + @NonNull + public static final Creator CREATOR = new Creator() { + @Override + public CaptivePortalData createFromParcel(Parcel source) { + return new CaptivePortalData(source); + } + + @Override + public CaptivePortalData[] newArray(int size) { + return new CaptivePortalData[size]; + } + }; + + @Override + public int hashCode() { + return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, + mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CaptivePortalData)) return false; + final CaptivePortalData other = (CaptivePortalData) obj; + return mRefreshTimeMillis == other.mRefreshTimeMillis + && Objects.equals(mUserPortalUrl, other.mUserPortalUrl) + && Objects.equals(mVenueInfoUrl, other.mVenueInfoUrl) + && mIsSessionExtendable == other.mIsSessionExtendable + && mByteLimit == other.mByteLimit + && mExpiryTimeMillis == other.mExpiryTimeMillis + && mCaptive == other.mCaptive + && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName); + } + + @Override + public String toString() { + return "CaptivePortalData {" + + "refreshTime: " + mRefreshTimeMillis + + ", userPortalUrl: " + mUserPortalUrl + + ", venueInfoUrl: " + mVenueInfoUrl + + ", isSessionExtendable: " + mIsSessionExtendable + + ", byteLimit: " + mByteLimit + + ", expiryTime: " + mExpiryTimeMillis + + ", captive: " + mCaptive + + ", venueFriendlyName: " + mVenueFriendlyName + + "}"; + } +} diff --git a/framework/src/android/net/ConnectionInfo.aidl b/framework/src/android/net/ConnectionInfo.aidl new file mode 100644 index 0000000000..07faf8bbbe --- /dev/null +++ b/framework/src/android/net/ConnectionInfo.aidl @@ -0,0 +1,20 @@ +/* +** +** 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. +*/ + +package android.net; + +parcelable ConnectionInfo; diff --git a/framework/src/android/net/ConnectionInfo.java b/framework/src/android/net/ConnectionInfo.java new file mode 100644 index 0000000000..4514a8484d --- /dev/null +++ b/framework/src/android/net/ConnectionInfo.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package android.net; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; + +/** + * Describe a network connection including local and remote address/port of a connection and the + * transport protocol. + * + * @hide + */ +public final class ConnectionInfo implements Parcelable { + public final int protocol; + public final InetSocketAddress local; + public final InetSocketAddress remote; + + @Override + public int describeContents() { + return 0; + } + + public ConnectionInfo(int protocol, InetSocketAddress local, InetSocketAddress remote) { + this.protocol = protocol; + this.local = local; + this.remote = remote; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(protocol); + out.writeByteArray(local.getAddress().getAddress()); + out.writeInt(local.getPort()); + out.writeByteArray(remote.getAddress().getAddress()); + out.writeInt(remote.getPort()); + } + + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { + public ConnectionInfo createFromParcel(Parcel in) { + int protocol = in.readInt(); + InetAddress localAddress; + try { + localAddress = InetAddress.getByAddress(in.createByteArray()); + } catch (UnknownHostException e) { + throw new IllegalArgumentException("Invalid InetAddress"); + } + int localPort = in.readInt(); + InetAddress remoteAddress; + try { + remoteAddress = InetAddress.getByAddress(in.createByteArray()); + } catch (UnknownHostException e) { + throw new IllegalArgumentException("Invalid InetAddress"); + } + int remotePort = in.readInt(); + InetSocketAddress local = new InetSocketAddress(localAddress, localPort); + InetSocketAddress remote = new InetSocketAddress(remoteAddress, remotePort); + return new ConnectionInfo(protocol, local, remote); + } + + public ConnectionInfo[] newArray(int size) { + return new ConnectionInfo[size]; + } + }; +} diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.aidl b/framework/src/android/net/ConnectivityDiagnosticsManager.aidl new file mode 100644 index 0000000000..82ba0ca113 --- /dev/null +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.aidl @@ -0,0 +1,21 @@ +/** + * + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable ConnectivityDiagnosticsManager.ConnectivityReport; +parcelable ConnectivityDiagnosticsManager.DataStallReport; \ No newline at end of file diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.java b/framework/src/android/net/ConnectivityDiagnosticsManager.java new file mode 100644 index 0000000000..5234494973 --- /dev/null +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.java @@ -0,0 +1,777 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.StringDef; +import android.content.Context; +import android.os.Binder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PersistableBundle; +import android.os.RemoteException; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; + +/** + * Class that provides utilities for collecting network connectivity diagnostics information. + * Connectivity information is made available through triggerable diagnostics tools and by listening + * to System validations. Some diagnostics information may be permissions-restricted. + * + *

ConnectivityDiagnosticsManager is intended for use by applications offering network + * connectivity on a user device. These tools will provide several mechanisms for these applications + * to be alerted to network conditions as well as diagnose potential network issues themselves. + * + *

The primary responsibilities of this class are to: + * + *

    + *
  • Allow permissioned applications to register and unregister callbacks for network event + * notifications + *
  • Invoke callbacks for network event notifications, including: + *
      + *
    • Network validations + *
    • Data stalls + *
    • Connectivity reports from applications + *
    + *
+ */ +public class ConnectivityDiagnosticsManager { + /** @hide */ + @VisibleForTesting + public static final Map + sCallbacks = new ConcurrentHashMap<>(); + + private final Context mContext; + private final IConnectivityManager mService; + + /** @hide */ + public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) { + mContext = Preconditions.checkNotNull(context, "missing context"); + mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + } + + /** @hide */ + @VisibleForTesting + public static boolean persistableBundleEquals( + @Nullable PersistableBundle a, @Nullable PersistableBundle b) { + if (a == b) return true; + if (a == null || b == null) return false; + if (!Objects.equals(a.keySet(), b.keySet())) return false; + for (String key : a.keySet()) { + if (!Objects.equals(a.get(key), b.get(key))) return false; + } + return true; + } + + /** Class that includes connectivity information for a specific Network at a specific time. */ + public static final class ConnectivityReport implements Parcelable { + /** + * The overall status of the network is that it is invalid; it neither provides + * connectivity nor has been exempted from validation. + */ + public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; + + /** + * The overall status of the network is that it is valid, this may be because it provides + * full Internet access (all probes succeeded), or because other properties of the network + * caused probes not to be run. + */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID + public static final int NETWORK_VALIDATION_RESULT_VALID = 1; + + /** + * The overall status of the network is that it provides partial connectivity; some + * probed services succeeded but others failed. + */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL; + public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; + + /** + * Due to the properties of the network, validation was not performed. + */ + public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; + + /** @hide */ + @IntDef( + prefix = {"NETWORK_VALIDATION_RESULT_"}, + value = { + NETWORK_VALIDATION_RESULT_INVALID, + NETWORK_VALIDATION_RESULT_VALID, + NETWORK_VALIDATION_RESULT_PARTIALLY_VALID, + NETWORK_VALIDATION_RESULT_SKIPPED + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NetworkValidationResult {} + + /** + * The overall validation result for the Network being reported on. + * + *

The possible values for this key are: + * {@link #NETWORK_VALIDATION_RESULT_INVALID}, + * {@link #NETWORK_VALIDATION_RESULT_VALID}, + * {@link #NETWORK_VALIDATION_RESULT_PARTIALLY_VALID}, + * {@link #NETWORK_VALIDATION_RESULT_SKIPPED}. + * + * @see android.net.NetworkCapabilities#NET_CAPABILITY_VALIDATED + */ + @NetworkValidationResult + public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult"; + + /** DNS probe. */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS + public static final int NETWORK_PROBE_DNS = 0x04; + + /** HTTP probe. */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP + public static final int NETWORK_PROBE_HTTP = 0x08; + + /** HTTPS probe. */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS; + public static final int NETWORK_PROBE_HTTPS = 0x10; + + /** Captive portal fallback probe. */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_FALLBACK + public static final int NETWORK_PROBE_FALLBACK = 0x20; + + /** Private DNS (DNS over TLS) probd. */ + // TODO: link to INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS + public static final int NETWORK_PROBE_PRIVATE_DNS = 0x40; + + /** @hide */ + @IntDef( + prefix = {"NETWORK_PROBE_"}, + value = { + NETWORK_PROBE_DNS, + NETWORK_PROBE_HTTP, + NETWORK_PROBE_HTTPS, + NETWORK_PROBE_FALLBACK, + NETWORK_PROBE_PRIVATE_DNS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NetworkProbe {} + + /** + * A bitmask of network validation probes that succeeded. + * + *

The possible bits values reported by this key are: + * {@link #NETWORK_PROBE_DNS}, + * {@link #NETWORK_PROBE_HTTP}, + * {@link #NETWORK_PROBE_HTTPS}, + * {@link #NETWORK_PROBE_FALLBACK}, + * {@link #NETWORK_PROBE_PRIVATE_DNS}. + */ + @NetworkProbe + public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = + "networkProbesSucceeded"; + + /** + * A bitmask of network validation probes that were attempted. + * + *

These probes may have failed or may be incomplete at the time of this report. + * + *

The possible bits values reported by this key are: + * {@link #NETWORK_PROBE_DNS}, + * {@link #NETWORK_PROBE_HTTP}, + * {@link #NETWORK_PROBE_HTTPS}, + * {@link #NETWORK_PROBE_FALLBACK}, + * {@link #NETWORK_PROBE_PRIVATE_DNS}. + */ + @NetworkProbe + public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = + "networkProbesAttempted"; + + /** @hide */ + @StringDef(prefix = {"KEY_"}, value = { + KEY_NETWORK_VALIDATION_RESULT, KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, + KEY_NETWORK_PROBES_ATTEMPTED_BITMASK}) + @Retention(RetentionPolicy.SOURCE) + public @interface ConnectivityReportBundleKeys {} + + /** The Network for which this ConnectivityReport applied */ + @NonNull private final Network mNetwork; + + /** + * The timestamp for the report. The timestamp is taken from {@link + * System#currentTimeMillis}. + */ + private final long mReportTimestamp; + + /** LinkProperties available on the Network at the reported timestamp */ + @NonNull private final LinkProperties mLinkProperties; + + /** NetworkCapabilities available on the Network at the reported timestamp */ + @NonNull private final NetworkCapabilities mNetworkCapabilities; + + /** PersistableBundle that may contain additional info about the report */ + @NonNull private final PersistableBundle mAdditionalInfo; + + /** + * Constructor for ConnectivityReport. + * + *

Apps should obtain instances through {@link + * ConnectivityDiagnosticsCallback#onConnectivityReportAvailable} instead of instantiating + * their own instances (unless for testing purposes). + * + * @param network The Network for which this ConnectivityReport applies + * @param reportTimestamp The timestamp for the report + * @param linkProperties The LinkProperties available on network at reportTimestamp + * @param networkCapabilities The NetworkCapabilities available on network at + * reportTimestamp + * @param additionalInfo A PersistableBundle that may contain additional info about the + * report + */ + public ConnectivityReport( + @NonNull Network network, + long reportTimestamp, + @NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, + @NonNull PersistableBundle additionalInfo) { + mNetwork = network; + mReportTimestamp = reportTimestamp; + mLinkProperties = new LinkProperties(linkProperties); + mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); + mAdditionalInfo = additionalInfo; + } + + /** + * Returns the Network for this ConnectivityReport. + * + * @return The Network for which this ConnectivityReport applied + */ + @NonNull + public Network getNetwork() { + return mNetwork; + } + + /** + * Returns the epoch timestamp (milliseconds) for when this report was taken. + * + * @return The timestamp for the report. Taken from {@link System#currentTimeMillis}. + */ + public long getReportTimestamp() { + return mReportTimestamp; + } + + /** + * Returns the LinkProperties available when this report was taken. + * + * @return LinkProperties available on the Network at the reported timestamp + */ + @NonNull + public LinkProperties getLinkProperties() { + return new LinkProperties(mLinkProperties); + } + + /** + * Returns the NetworkCapabilities when this report was taken. + * + * @return NetworkCapabilities available on the Network at the reported timestamp + */ + @NonNull + public NetworkCapabilities getNetworkCapabilities() { + return new NetworkCapabilities(mNetworkCapabilities); + } + + /** + * Returns a PersistableBundle with additional info for this report. + * + * @return PersistableBundle that may contain additional info about the report + */ + @NonNull + public PersistableBundle getAdditionalInfo() { + return new PersistableBundle(mAdditionalInfo); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (!(o instanceof ConnectivityReport)) return false; + final ConnectivityReport that = (ConnectivityReport) o; + + // PersistableBundle is optimized to avoid unparcelling data unless fields are + // referenced. Because of this, use {@link ConnectivityDiagnosticsManager#equals} over + // {@link PersistableBundle#kindofEquals}. + return mReportTimestamp == that.mReportTimestamp + && mNetwork.equals(that.mNetwork) + && mLinkProperties.equals(that.mLinkProperties) + && mNetworkCapabilities.equals(that.mNetworkCapabilities) + && persistableBundleEquals(mAdditionalInfo, that.mAdditionalInfo); + } + + @Override + public int hashCode() { + return Objects.hash( + mNetwork, + mReportTimestamp, + mLinkProperties, + mNetworkCapabilities, + mAdditionalInfo); + } + + /** {@inheritDoc} */ + @Override + public int describeContents() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mNetwork, flags); + dest.writeLong(mReportTimestamp); + dest.writeParcelable(mLinkProperties, flags); + dest.writeParcelable(mNetworkCapabilities, flags); + dest.writeParcelable(mAdditionalInfo, flags); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator CREATOR = + new Creator() { + public ConnectivityReport createFromParcel(Parcel in) { + return new ConnectivityReport( + in.readParcelable(null), + in.readLong(), + in.readParcelable(null), + in.readParcelable(null), + in.readParcelable(null)); + } + + public ConnectivityReport[] newArray(int size) { + return new ConnectivityReport[size]; + } + }; + } + + /** Class that includes information for a suspected data stall on a specific Network */ + public static final class DataStallReport implements Parcelable { + /** + * Indicates that the Data Stall was detected using DNS events. + */ + public static final int DETECTION_METHOD_DNS_EVENTS = 1; + + /** + * Indicates that the Data Stall was detected using TCP metrics. + */ + public static final int DETECTION_METHOD_TCP_METRICS = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"DETECTION_METHOD_"}, + value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS}) + public @interface DetectionMethod {} + + /** + * This key represents the period in milliseconds over which other included TCP metrics + * were measured. + * + *

This key will be included if the data stall detection method is + * {@link #DETECTION_METHOD_TCP_METRICS}. + * + *

This value is an int. + */ + public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = + "tcpMetricsCollectionPeriodMillis"; + + /** + * This key represents the fail rate of TCP packets when the suspected data stall was + * detected. + * + *

This key will be included if the data stall detection method is + * {@link #DETECTION_METHOD_TCP_METRICS}. + * + *

This value is an int percentage between 0 and 100. + */ + public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate"; + + /** + * This key represents the consecutive number of DNS timeouts that have occurred. + * + *

The consecutive count will be reset any time a DNS response is received. + * + *

This key will be included if the data stall detection method is + * {@link #DETECTION_METHOD_DNS_EVENTS}. + * + *

This value is an int. + */ + public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts"; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(prefix = {"KEY_"}, value = { + KEY_TCP_PACKET_FAIL_RATE, + KEY_DNS_CONSECUTIVE_TIMEOUTS + }) + public @interface DataStallReportBundleKeys {} + + /** The Network for which this DataStallReport applied */ + @NonNull private final Network mNetwork; + + /** + * The timestamp for the report. The timestamp is taken from {@link + * System#currentTimeMillis}. + */ + private long mReportTimestamp; + + /** A bitmask of the detection methods used to identify the suspected data stall */ + @DetectionMethod private final int mDetectionMethod; + + /** LinkProperties available on the Network at the reported timestamp */ + @NonNull private final LinkProperties mLinkProperties; + + /** NetworkCapabilities available on the Network at the reported timestamp */ + @NonNull private final NetworkCapabilities mNetworkCapabilities; + + /** PersistableBundle that may contain additional information on the suspected data stall */ + @NonNull private final PersistableBundle mStallDetails; + + /** + * Constructor for DataStallReport. + * + *

Apps should obtain instances through {@link + * ConnectivityDiagnosticsCallback#onDataStallSuspected} instead of instantiating their own + * instances (unless for testing purposes). + * + * @param network The Network for which this DataStallReport applies + * @param reportTimestamp The timestamp for the report + * @param detectionMethod The detection method used to identify this data stall + * @param linkProperties The LinkProperties available on network at reportTimestamp + * @param networkCapabilities The NetworkCapabilities available on network at + * reportTimestamp + * @param stallDetails A PersistableBundle that may contain additional info about the report + */ + public DataStallReport( + @NonNull Network network, + long reportTimestamp, + @DetectionMethod int detectionMethod, + @NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, + @NonNull PersistableBundle stallDetails) { + mNetwork = network; + mReportTimestamp = reportTimestamp; + mDetectionMethod = detectionMethod; + mLinkProperties = new LinkProperties(linkProperties); + mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); + mStallDetails = stallDetails; + } + + /** + * Returns the Network for this DataStallReport. + * + * @return The Network for which this DataStallReport applied + */ + @NonNull + public Network getNetwork() { + return mNetwork; + } + + /** + * Returns the epoch timestamp (milliseconds) for when this report was taken. + * + * @return The timestamp for the report. Taken from {@link System#currentTimeMillis}. + */ + public long getReportTimestamp() { + return mReportTimestamp; + } + + /** + * Returns the bitmask of detection methods used to identify this suspected data stall. + * + * @return The bitmask of detection methods used to identify the suspected data stall + */ + public int getDetectionMethod() { + return mDetectionMethod; + } + + /** + * Returns the LinkProperties available when this report was taken. + * + * @return LinkProperties available on the Network at the reported timestamp + */ + @NonNull + public LinkProperties getLinkProperties() { + return new LinkProperties(mLinkProperties); + } + + /** + * Returns the NetworkCapabilities when this report was taken. + * + * @return NetworkCapabilities available on the Network at the reported timestamp + */ + @NonNull + public NetworkCapabilities getNetworkCapabilities() { + return new NetworkCapabilities(mNetworkCapabilities); + } + + /** + * Returns a PersistableBundle with additional info for this report. + * + *

Gets a bundle with details about the suspected data stall including information + * specific to the monitoring method that detected the data stall. + * + * @return PersistableBundle that may contain additional information on the suspected data + * stall + */ + @NonNull + public PersistableBundle getStallDetails() { + return new PersistableBundle(mStallDetails); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (!(o instanceof DataStallReport)) return false; + final DataStallReport that = (DataStallReport) o; + + // PersistableBundle is optimized to avoid unparcelling data unless fields are + // referenced. Because of this, use {@link ConnectivityDiagnosticsManager#equals} over + // {@link PersistableBundle#kindofEquals}. + return mReportTimestamp == that.mReportTimestamp + && mDetectionMethod == that.mDetectionMethod + && mNetwork.equals(that.mNetwork) + && mLinkProperties.equals(that.mLinkProperties) + && mNetworkCapabilities.equals(that.mNetworkCapabilities) + && persistableBundleEquals(mStallDetails, that.mStallDetails); + } + + @Override + public int hashCode() { + return Objects.hash( + mNetwork, + mReportTimestamp, + mDetectionMethod, + mLinkProperties, + mNetworkCapabilities, + mStallDetails); + } + + /** {@inheritDoc} */ + @Override + public int describeContents() { + return 0; + } + + /** {@inheritDoc} */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mNetwork, flags); + dest.writeLong(mReportTimestamp); + dest.writeInt(mDetectionMethod); + dest.writeParcelable(mLinkProperties, flags); + dest.writeParcelable(mNetworkCapabilities, flags); + dest.writeParcelable(mStallDetails, flags); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator CREATOR = + new Creator() { + public DataStallReport createFromParcel(Parcel in) { + return new DataStallReport( + in.readParcelable(null), + in.readLong(), + in.readInt(), + in.readParcelable(null), + in.readParcelable(null), + in.readParcelable(null)); + } + + public DataStallReport[] newArray(int size) { + return new DataStallReport[size]; + } + }; + } + + /** @hide */ + @VisibleForTesting + public static class ConnectivityDiagnosticsBinder + extends IConnectivityDiagnosticsCallback.Stub { + @NonNull private final ConnectivityDiagnosticsCallback mCb; + @NonNull private final Executor mExecutor; + + /** @hide */ + @VisibleForTesting + public ConnectivityDiagnosticsBinder( + @NonNull ConnectivityDiagnosticsCallback cb, @NonNull Executor executor) { + this.mCb = cb; + this.mExecutor = executor; + } + + /** @hide */ + @VisibleForTesting + public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mCb.onConnectivityReportAvailable(report); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** @hide */ + @VisibleForTesting + public void onDataStallSuspected(@NonNull DataStallReport report) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mCb.onDataStallSuspected(report); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + /** @hide */ + @VisibleForTesting + public void onNetworkConnectivityReported( + @NonNull Network network, boolean hasConnectivity) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mCb.onNetworkConnectivityReported(network, hasConnectivity); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + + /** + * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about + * network connectivity events. Must be extended by applications wanting notifications. + */ + public abstract static class ConnectivityDiagnosticsCallback { + /** + * Called when the platform completes a data connectivity check. This will also be invoked + * immediately upon registration for each network matching the request with the latest + * report, if a report has already been generated for that network. + * + *

The Network specified in the ConnectivityReport may not be active any more when this + * method is invoked. + * + * @param report The ConnectivityReport containing information about a connectivity check + */ + public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {} + + /** + * Called when the platform suspects a data stall on some Network. + * + *

The Network specified in the DataStallReport may not be active any more when this + * method is invoked. + * + * @param report The DataStallReport containing information about the suspected data stall + */ + public void onDataStallSuspected(@NonNull DataStallReport report) {} + + /** + * Called when any app reports connectivity to the System. + * + * @param network The Network for which connectivity has been reported + * @param hasConnectivity The connectivity reported to the System + */ + public void onNetworkConnectivityReported( + @NonNull Network network, boolean hasConnectivity) {} + } + + /** + * Registers a ConnectivityDiagnosticsCallback with the System. + * + *

Only apps that offer network connectivity to the user should be registering callbacks. + * These are the only apps whose callbacks will be invoked by the system. Apps considered to + * meet these conditions include: + * + *

    + *
  • Carrier apps with active subscriptions + *
  • Active VPNs + *
  • WiFi Suggesters + *
+ * + *

Callbacks registered by apps not meeting the above criteria will not be invoked. + * + *

If a registering app loses its relevant permissions, any callbacks it registered will + * silently stop receiving callbacks. + * + *

Each register() call MUST use a ConnectivityDiagnosticsCallback instance that is + * not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with + * multiple NetworkRequests, an IllegalArgumentException will be thrown. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * callbacks in {@link ConnectivityManager}. Registering a callback with this method will count + * toward this limit. If this limit is exceeded, an exception will be thrown. To avoid hitting + * this issue and to conserve resources, make sure to unregister the callbacks with + * {@link #unregisterConnectivityDiagnosticsCallback}. + * + * @param request The NetworkRequest that will be used to match with Networks for which + * callbacks will be fired + * @param e The Executor to be used for running the callback method invocations + * @param callback The ConnectivityDiagnosticsCallback that the caller wants registered with the + * System + * @throws IllegalArgumentException if the same callback instance is registered with multiple + * NetworkRequests + * @throws RuntimeException if the app already has too many callbacks registered. + */ + public void registerConnectivityDiagnosticsCallback( + @NonNull NetworkRequest request, + @NonNull Executor e, + @NonNull ConnectivityDiagnosticsCallback callback) { + final ConnectivityDiagnosticsBinder binder = new ConnectivityDiagnosticsBinder(callback, e); + if (sCallbacks.putIfAbsent(callback, binder) != null) { + throw new IllegalArgumentException("Callback is currently registered"); + } + + try { + mService.registerConnectivityDiagnosticsCallback( + binder, request, mContext.getOpPackageName()); + } catch (RemoteException exception) { + exception.rethrowFromSystemServer(); + } + } + + /** + * Unregisters a ConnectivityDiagnosticsCallback with the System. + * + *

If the given callback is not currently registered with the System, this operation will be + * a no-op. + * + * @param callback The ConnectivityDiagnosticsCallback to be unregistered from the System. + */ + public void unregisterConnectivityDiagnosticsCallback( + @NonNull ConnectivityDiagnosticsCallback callback) { + // unconditionally removing from sCallbacks prevents race conditions here, since remove() is + // atomic. + final ConnectivityDiagnosticsBinder binder = sCallbacks.remove(callback); + if (binder == null) return; + + try { + mService.unregisterConnectivityDiagnosticsCallback(binder); + } catch (RemoteException exception) { + exception.rethrowFromSystemServer(); + } + } +} diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java new file mode 100644 index 0000000000..7f07bba668 --- /dev/null +++ b/framework/src/android/net/ConnectivityManager.java @@ -0,0 +1,5058 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.IpSecManager.INVALID_RESOURCE_ID; +import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; +import static android.net.NetworkRequest.Type.LISTEN; +import static android.net.NetworkRequest.Type.REQUEST; +import static android.net.NetworkRequest.Type.TRACK_DEFAULT; +import static android.net.QosCallback.QosCallbackRegistrationException; + +import android.annotation.CallbackExecutor; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; +import android.annotation.SystemService; +import android.app.PendingIntent; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.content.Intent; +import android.net.IpSecManager.UdpEncapsulationSocket; +import android.net.SocketKeepalive.Callback; +import android.net.TetheringManager.StartTetheringCallback; +import android.net.TetheringManager.TetheringEventCallback; +import android.net.TetheringManager.TetheringRequest; +import android.os.Binder; +import android.os.Build; +import android.os.Build.VERSION_CODES; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.INetworkActivityListener; +import android.os.INetworkManagementService; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; +import android.os.Process; +import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.provider.Settings; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Range; +import android.util.SparseIntArray; + +import com.android.connectivity.aidl.INetworkAgent; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; +import com.android.internal.util.Protocol; + +import libcore.net.event.NetworkEventDispatcher; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; + +/** + * Class that answers queries about the state of network connectivity. It also + * notifies applications when network connectivity changes. + *

+ * The primary responsibilities of this class are to: + *

    + *
  1. Monitor network connections (Wi-Fi, GPRS, UMTS, etc.)
  2. + *
  3. Send broadcast intents when network connectivity changes
  4. + *
  5. Attempt to "fail over" to another network when connectivity to a network + * is lost
  6. + *
  7. Provide an API that allows applications to query the coarse-grained or fine-grained + * state of the available networks
  8. + *
  9. Provide an API that allows applications to request and select networks for their data + * traffic
  10. + *
+ */ +@SystemService(Context.CONNECTIVITY_SERVICE) +public class ConnectivityManager { + private static final String TAG = "ConnectivityManager"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + /** + * A change in network connectivity has occurred. A default connection has either + * been established or lost. The NetworkInfo for the affected network is + * sent as an extra; it should be consulted to see what kind of + * connectivity event occurred. + *

+ * Apps targeting Android 7.0 (API level 24) and higher do not receive this + * broadcast if they declare the broadcast receiver in their manifest. Apps + * will still receive broadcasts if they register their + * {@link android.content.BroadcastReceiver} with + * {@link android.content.Context#registerReceiver Context.registerReceiver()} + * and that context is still valid. + *

+ * If this is a connection that was the result of failing over from a + * disconnected network, then the FAILOVER_CONNECTION boolean extra is + * set to true. + *

+ * For a loss of connectivity, if the connectivity manager is attempting + * to connect (or has already connected) to another network, the + * NetworkInfo for the new network is also passed as an extra. This lets + * any receivers of the broadcast know that they should not necessarily + * tell the user that no data traffic will be possible. Instead, the + * receiver should expect another broadcast soon, indicating either that + * the failover attempt succeeded (and so there is still overall data + * connectivity), or that the failover attempt failed, meaning that all + * connectivity has been lost. + *

+ * For a disconnect event, the boolean extra EXTRA_NO_CONNECTIVITY + * is set to {@code true} if there are no connected networks at all. + * + * @deprecated apps should use the more versatile {@link #requestNetwork}, + * {@link #registerNetworkCallback} or {@link #registerDefaultNetworkCallback} + * functions instead for faster and more detailed updates about the network + * changes they care about. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @Deprecated + public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + + /** + * The device has connected to a network that has presented a captive + * portal, which is blocking Internet connectivity. The user was presented + * with a notification that network sign in is required, + * and the user invoked the notification's action indicating they + * desire to sign in to the network. Apps handling this activity should + * facilitate signing in to the network. This action includes a + * {@link Network} typed extra called {@link #EXTRA_NETWORK} that represents + * the network presenting the captive portal; all communication with the + * captive portal must be done using this {@code Network} object. + *

+ * This activity includes a {@link CaptivePortal} extra named + * {@link #EXTRA_CAPTIVE_PORTAL} that can be used to indicate different + * outcomes of the captive portal sign in to the system: + *

    + *
  • When the app handling this action believes the user has signed in to + * the network and the captive portal has been dismissed, the app should + * call {@link CaptivePortal#reportCaptivePortalDismissed} so the system can + * reevaluate the network. If reevaluation finds the network no longer + * subject to a captive portal, the network may become the default active + * data network.
  • + *
  • When the app handling this action believes the user explicitly wants + * to ignore the captive portal and the network, the app should call + * {@link CaptivePortal#ignoreNetwork}.
  • + *
+ */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL"; + + /** + * The lookup key for a {@link NetworkInfo} object. Retrieve with + * {@link android.content.Intent#getParcelableExtra(String)}. + * + * @deprecated The {@link NetworkInfo} object is deprecated, as many of its properties + * can't accurately represent modern network characteristics. + * Please obtain information about networks from the {@link NetworkCapabilities} + * or {@link LinkProperties} objects instead. + */ + @Deprecated + public static final String EXTRA_NETWORK_INFO = "networkInfo"; + + /** + * Network type which triggered a {@link #CONNECTIVITY_ACTION} broadcast. + * + * @see android.content.Intent#getIntExtra(String, int) + * @deprecated The network type is not rich enough to represent the characteristics + * of modern networks. Please use {@link NetworkCapabilities} instead, + * in particular the transports. + */ + @Deprecated + public static final String EXTRA_NETWORK_TYPE = "networkType"; + + /** + * The lookup key for a boolean that indicates whether a connect event + * is for a network to which the connectivity manager was failing over + * following a disconnect on another network. + * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. + * + * @deprecated See {@link NetworkInfo}. + */ + @Deprecated + public static final String EXTRA_IS_FAILOVER = "isFailover"; + /** + * The lookup key for a {@link NetworkInfo} object. This is supplied when + * there is another network that it may be possible to connect to. Retrieve with + * {@link android.content.Intent#getParcelableExtra(String)}. + * + * @deprecated See {@link NetworkInfo}. + */ + @Deprecated + public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork"; + /** + * The lookup key for a boolean that indicates whether there is a + * complete lack of connectivity, i.e., no network is available. + * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. + */ + public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity"; + /** + * The lookup key for a string that indicates why an attempt to connect + * to a network failed. The string has no particular structure. It is + * intended to be used in notifications presented to users. Retrieve + * it with {@link android.content.Intent#getStringExtra(String)}. + */ + public static final String EXTRA_REASON = "reason"; + /** + * The lookup key for a string that provides optionally supplied + * extra information about the network state. The information + * may be passed up from the lower networking layers, and its + * meaning may be specific to a particular network type. Retrieve + * it with {@link android.content.Intent#getStringExtra(String)}. + * + * @deprecated See {@link NetworkInfo#getExtraInfo()}. + */ + @Deprecated + public static final String EXTRA_EXTRA_INFO = "extraInfo"; + /** + * The lookup key for an int that provides information about + * our connection to the internet at large. 0 indicates no connection, + * 100 indicates a great connection. Retrieve it with + * {@link android.content.Intent#getIntExtra(String, int)}. + * {@hide} + */ + public static final String EXTRA_INET_CONDITION = "inetCondition"; + /** + * The lookup key for a {@link CaptivePortal} object included with the + * {@link #ACTION_CAPTIVE_PORTAL_SIGN_IN} intent. The {@code CaptivePortal} + * object can be used to either indicate to the system that the captive + * portal has been dismissed or that the user does not want to pursue + * signing in to captive portal. Retrieve it with + * {@link android.content.Intent#getParcelableExtra(String)}. + */ + public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; + + /** + * Key for passing a URL to the captive portal login activity. + */ + public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; + + /** + * Key for passing a {@link android.net.captiveportal.CaptivePortalProbeSpec} to the captive + * portal login activity. + * {@hide} + */ + @SystemApi + public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = + "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; + + /** + * Key for passing a user agent string to the captive portal login activity. + * {@hide} + */ + @SystemApi + public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = + "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + + /** + * Broadcast action to indicate the change of data activity status + * (idle or active) on a network in a recent period. + * The network becomes active when data transmission is started, or + * idle if there is no data transmission for a period of time. + * {@hide} + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_DATA_ACTIVITY_CHANGE = + "android.net.conn.DATA_ACTIVITY_CHANGE"; + /** + * The lookup key for an enum that indicates the network device type on which this data activity + * change happens. + * {@hide} + */ + public static final String EXTRA_DEVICE_TYPE = "deviceType"; + /** + * The lookup key for a boolean that indicates the device is active or not. {@code true} means + * it is actively sending or receiving data and {@code false} means it is idle. + * {@hide} + */ + public static final String EXTRA_IS_ACTIVE = "isActive"; + /** + * The lookup key for a long that contains the timestamp (nanos) of the radio state change. + * {@hide} + */ + public static final String EXTRA_REALTIME_NS = "tsNanos"; + + /** + * Broadcast Action: The setting for background data usage has changed + * values. Use {@link #getBackgroundDataSetting()} to get the current value. + *

+ * If an application uses the network in the background, it should listen + * for this broadcast and stop using the background data if the value is + * {@code false}. + *

+ * + * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, availability + * of background data depends on several combined factors, and + * this broadcast is no longer sent. Instead, when background + * data is unavailable, {@link #getActiveNetworkInfo()} will now + * appear disconnected. During first boot after a platform + * upgrade, this broadcast will be sent once if + * {@link #getBackgroundDataSetting()} was {@code false} before + * the upgrade. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @Deprecated + public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = + "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; + + /** + * Broadcast Action: The network connection may not be good + * uses {@code ConnectivityManager.EXTRA_INET_CONDITION} and + * {@code ConnectivityManager.EXTRA_NETWORK_INFO} to specify + * the network and it's condition. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage + public static final String INET_CONDITION_ACTION = + "android.net.conn.INET_CONDITION_ACTION"; + + /** + * Broadcast Action: A tetherable connection has come or gone. + * Uses {@code ConnectivityManager.EXTRA_AVAILABLE_TETHER}, + * {@code ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY}, + * {@code ConnectivityManager.EXTRA_ACTIVE_TETHER}, and + * {@code ConnectivityManager.EXTRA_ERRORED_TETHER} to indicate + * the current state of tethering. Each include a list of + * interface names in that state (may be empty). + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final String ACTION_TETHER_STATE_CHANGED = + TetheringManager.ACTION_TETHER_STATE_CHANGED; + + /** + * @hide + * gives a String[] listing all the interfaces configured for + * tethering and currently available for tethering. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final String EXTRA_AVAILABLE_TETHER = TetheringManager.EXTRA_AVAILABLE_TETHER; + + /** + * @hide + * gives a String[] listing all the interfaces currently in local-only + * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding) + */ + public static final String EXTRA_ACTIVE_LOCAL_ONLY = TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY; + + /** + * @hide + * gives a String[] listing all the interfaces currently tethered + * (ie, has DHCPv4 support and packets potentially forwarded/NATed) + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final String EXTRA_ACTIVE_TETHER = TetheringManager.EXTRA_ACTIVE_TETHER; + + /** + * @hide + * gives a String[] listing all the interfaces we tried to tether and + * failed. Use {@link #getLastTetherError} to find the error code + * for any interfaces listed here. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final String EXTRA_ERRORED_TETHER = TetheringManager.EXTRA_ERRORED_TETHER; + + /** + * Broadcast Action: The captive portal tracker has finished its test. + * Sent only while running Setup Wizard, in lieu of showing a user + * notification. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_CAPTIVE_PORTAL_TEST_COMPLETED = + "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED"; + /** + * The lookup key for a boolean that indicates whether a captive portal was detected. + * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}. + * @hide + */ + public static final String EXTRA_IS_CAPTIVE_PORTAL = "captivePortal"; + + /** + * Action used to display a dialog that asks the user whether to connect to a network that is + * not validated. This intent is used to start the dialog in settings via startActivity. + * + * @hide + */ + public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED"; + + /** + * Action used to display a dialog that asks the user whether to avoid a network that is no + * longer validated. This intent is used to start the dialog in settings via startActivity. + * + * @hide + */ + public static final String ACTION_PROMPT_LOST_VALIDATION = + "android.net.conn.PROMPT_LOST_VALIDATION"; + + /** + * Action used to display a dialog that asks the user whether to stay connected to a network + * that has not validated. This intent is used to start the dialog in settings via + * startActivity. + * + * @hide + */ + public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = + "android.net.conn.PROMPT_PARTIAL_CONNECTIVITY"; + + /** + * Invalid tethering type. + * @see #startTethering(int, boolean, OnStartTetheringCallback) + * @hide + */ + public static final int TETHERING_INVALID = TetheringManager.TETHERING_INVALID; + + /** + * Wifi tethering type. + * @see #startTethering(int, boolean, OnStartTetheringCallback) + * @hide + */ + @SystemApi + public static final int TETHERING_WIFI = TetheringManager.TETHERING_WIFI; + + /** + * USB tethering type. + * @see #startTethering(int, boolean, OnStartTetheringCallback) + * @hide + */ + @SystemApi + public static final int TETHERING_USB = TetheringManager.TETHERING_USB; + + /** + * Bluetooth tethering type. + * @see #startTethering(int, boolean, OnStartTetheringCallback) + * @hide + */ + @SystemApi + public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH; + + /** + * Wifi P2p tethering type. + * Wifi P2p tethering is set through events automatically, and don't + * need to start from #startTethering(int, boolean, OnStartTetheringCallback). + * @hide + */ + public static final int TETHERING_WIFI_P2P = TetheringManager.TETHERING_WIFI_P2P; + + /** + * Extra used for communicating with the TetherService. Includes the type of tethering to + * enable if any. + * @hide + */ + public static final String EXTRA_ADD_TETHER_TYPE = TetheringConstants.EXTRA_ADD_TETHER_TYPE; + + /** + * Extra used for communicating with the TetherService. Includes the type of tethering for + * which to cancel provisioning. + * @hide + */ + public static final String EXTRA_REM_TETHER_TYPE = TetheringConstants.EXTRA_REM_TETHER_TYPE; + + /** + * Extra used for communicating with the TetherService. True to schedule a recheck of tether + * provisioning. + * @hide + */ + public static final String EXTRA_SET_ALARM = TetheringConstants.EXTRA_SET_ALARM; + + /** + * Tells the TetherService to run a provision check now. + * @hide + */ + public static final String EXTRA_RUN_PROVISION = TetheringConstants.EXTRA_RUN_PROVISION; + + /** + * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver} + * which will receive provisioning results. Can be left empty. + * @hide + */ + public static final String EXTRA_PROVISION_CALLBACK = + TetheringConstants.EXTRA_PROVISION_CALLBACK; + + /** + * The absence of a connection type. + * @hide + */ + @SystemApi + public static final int TYPE_NONE = -1; + + /** + * A Mobile data connection. Devices may support more than one. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an + * appropriate network. {@see NetworkCapabilities} for supported transports. + */ + @Deprecated + public static final int TYPE_MOBILE = 0; + + /** + * A WIFI data connection. Devices may support more than one. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an + * appropriate network. {@see NetworkCapabilities} for supported transports. + */ + @Deprecated + public static final int TYPE_WIFI = 1; + + /** + * An MMS-specific Mobile data connection. This network type may use the + * same network interface as {@link #TYPE_MOBILE} or it may use a different + * one. This is used by applications needing to talk to the carrier's + * Multimedia Messaging Service servers. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability. + */ + @Deprecated + public static final int TYPE_MOBILE_MMS = 2; + + /** + * A SUPL-specific Mobile data connection. This network type may use the + * same network interface as {@link #TYPE_MOBILE} or it may use a different + * one. This is used by applications needing to talk to the carrier's + * Secure User Plane Location servers for help locating the device. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability. + */ + @Deprecated + public static final int TYPE_MOBILE_SUPL = 3; + + /** + * A DUN-specific Mobile data connection. This network type may use the + * same network interface as {@link #TYPE_MOBILE} or it may use a different + * one. This is sometimes by the system when setting up an upstream connection + * for tethering so that the carrier is aware of DUN traffic. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_DUN} capability. + */ + @Deprecated + public static final int TYPE_MOBILE_DUN = 4; + + /** + * A High Priority Mobile data connection. This network type uses the + * same network interface as {@link #TYPE_MOBILE} but the routing setup + * is different. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an + * appropriate network. {@see NetworkCapabilities} for supported transports. + */ + @Deprecated + public static final int TYPE_MOBILE_HIPRI = 5; + + /** + * A WiMAX data connection. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an + * appropriate network. {@see NetworkCapabilities} for supported transports. + */ + @Deprecated + public static final int TYPE_WIMAX = 6; + + /** + * A Bluetooth data connection. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an + * appropriate network. {@see NetworkCapabilities} for supported transports. + */ + @Deprecated + public static final int TYPE_BLUETOOTH = 7; + + /** + * Fake data connection. This should not be used on shipping devices. + * @deprecated This is not used any more. + */ + @Deprecated + public static final int TYPE_DUMMY = 8; + + /** + * An Ethernet data connection. + * + * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an + * appropriate network. {@see NetworkCapabilities} for supported transports. + */ + @Deprecated + public static final int TYPE_ETHERNET = 9; + + /** + * Over the air Administration. + * @deprecated Use {@link NetworkCapabilities} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + public static final int TYPE_MOBILE_FOTA = 10; + + /** + * IP Multimedia Subsystem. + * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IMS} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage + public static final int TYPE_MOBILE_IMS = 11; + + /** + * Carrier Branded Services. + * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_CBS} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + public static final int TYPE_MOBILE_CBS = 12; + + /** + * A Wi-Fi p2p connection. Only requesting processes will have access to + * the peers connected. + * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_WIFI_P2P} instead. + * {@hide} + */ + @Deprecated + @SystemApi + public static final int TYPE_WIFI_P2P = 13; + + /** + * The network to use for initially attaching to the network + * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IA} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage + public static final int TYPE_MOBILE_IA = 14; + + /** + * Emergency PDN connection for emergency services. This + * may include IMS and MMS in emergency situations. + * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_EIMS} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + public static final int TYPE_MOBILE_EMERGENCY = 15; + + /** + * The network that uses proxy to achieve connectivity. + * @deprecated Use {@link NetworkCapabilities} instead. + * {@hide} + */ + @Deprecated + @SystemApi + public static final int TYPE_PROXY = 16; + + /** + * A virtual network using one or more native bearers. + * It may or may not be providing security services. + * @deprecated Applications should use {@link NetworkCapabilities#TRANSPORT_VPN} instead. + */ + @Deprecated + public static final int TYPE_VPN = 17; + + /** + * A network that is exclusively meant to be used for testing + * + * @deprecated Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. + + /** + * @deprecated Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "TYPE_" }, value = { + TYPE_NONE, + TYPE_MOBILE, + TYPE_WIFI, + TYPE_MOBILE_MMS, + TYPE_MOBILE_SUPL, + TYPE_MOBILE_DUN, + TYPE_MOBILE_HIPRI, + TYPE_WIMAX, + TYPE_BLUETOOTH, + TYPE_DUMMY, + TYPE_ETHERNET, + TYPE_MOBILE_FOTA, + TYPE_MOBILE_IMS, + TYPE_MOBILE_CBS, + TYPE_WIFI_P2P, + TYPE_MOBILE_IA, + TYPE_MOBILE_EMERGENCY, + TYPE_PROXY, + TYPE_VPN, + TYPE_TEST + }) + public @interface LegacyNetworkType {} + + // Deprecated constants for return values of startUsingNetworkFeature. They used to live + // in com.android.internal.telephony.PhoneConstants until they were made inaccessible. + private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0; + private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED = 1; + private static final int DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED = 3; + + /** {@hide} */ + public static final int MAX_RADIO_TYPE = TYPE_TEST; + + /** {@hide} */ + public static final int MAX_NETWORK_TYPE = TYPE_TEST; + + private static final int MIN_NETWORK_TYPE = TYPE_MOBILE; + + /** + * If you want to set the default network preference,you can directly + * change the networkAttributes array in framework's config.xml. + * + * @deprecated Since we support so many more networks now, the single + * network default network preference can't really express + * the hierarchy. Instead, the default is defined by the + * networkAttributes in config.xml. You can determine + * the current value by calling {@link #getNetworkPreference()} + * from an App. + */ + @Deprecated + public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI; + + /** + * @hide + */ + public static final int REQUEST_ID_UNSET = 0; + + /** + * Static unique request used as a tombstone for NetworkCallbacks that have been unregistered. + * This allows to distinguish when unregistering NetworkCallbacks those that were never + * registered from those that were already unregistered. + * @hide + */ + private static final NetworkRequest ALREADY_UNREGISTERED = + new NetworkRequest.Builder().clearCapabilities().build(); + + /** + * A NetID indicating no Network is selected. + * Keep in sync with bionic/libc/dns/include/resolv_netid.h + * @hide + */ + public static final int NETID_UNSET = 0; + + /** + * Private DNS Mode values. + * + * The "private_dns_mode" global setting stores a String value which is + * expected to be one of the following. + */ + + /** + * @hide + */ + public static final String PRIVATE_DNS_MODE_OFF = "off"; + /** + * @hide + */ + public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; + /** + * @hide + */ + public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; + /** + * The default Private DNS mode. + * + * This may change from release to release or may become dependent upon + * the capabilities of the underlying platform. + * + * @hide + */ + public static final String PRIVATE_DNS_DEFAULT_MODE_FALLBACK = PRIVATE_DNS_MODE_OPPORTUNISTIC; + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + private final IConnectivityManager mService; + /** + * A kludge to facilitate static access where a Context pointer isn't available, like in the + * case of the static set/getProcessDefaultNetwork methods and from the Network class. + * TODO: Remove this after deprecating the static methods in favor of non-static methods or + * methods that take a Context argument. + */ + private static ConnectivityManager sInstance; + + private final Context mContext; + + private INetworkManagementService mNMService; + private INetworkPolicyManager mNPManager; + private final TetheringManager mTetheringManager; + + /** + * Tests if a given integer represents a valid network type. + * @param networkType the type to be tested + * @return a boolean. {@code true} if the type is valid, else {@code false} + * @deprecated All APIs accepting a network type are deprecated. There should be no need to + * validate a network type. + */ + @Deprecated + public static boolean isNetworkTypeValid(int networkType) { + return MIN_NETWORK_TYPE <= networkType && networkType <= MAX_NETWORK_TYPE; + } + + /** + * Returns a non-localized string representing a given network type. + * ONLY used for debugging output. + * @param type the type needing naming + * @return a String for the given type, or a string version of the type ("87") + * if no name is known. + * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static String getNetworkTypeName(int type) { + switch (type) { + case TYPE_NONE: + return "NONE"; + case TYPE_MOBILE: + return "MOBILE"; + case TYPE_WIFI: + return "WIFI"; + case TYPE_MOBILE_MMS: + return "MOBILE_MMS"; + case TYPE_MOBILE_SUPL: + return "MOBILE_SUPL"; + case TYPE_MOBILE_DUN: + return "MOBILE_DUN"; + case TYPE_MOBILE_HIPRI: + return "MOBILE_HIPRI"; + case TYPE_WIMAX: + return "WIMAX"; + case TYPE_BLUETOOTH: + return "BLUETOOTH"; + case TYPE_DUMMY: + return "DUMMY"; + case TYPE_ETHERNET: + return "ETHERNET"; + case TYPE_MOBILE_FOTA: + return "MOBILE_FOTA"; + case TYPE_MOBILE_IMS: + return "MOBILE_IMS"; + case TYPE_MOBILE_CBS: + return "MOBILE_CBS"; + case TYPE_WIFI_P2P: + return "WIFI_P2P"; + case TYPE_MOBILE_IA: + return "MOBILE_IA"; + case TYPE_MOBILE_EMERGENCY: + return "MOBILE_EMERGENCY"; + case TYPE_PROXY: + return "PROXY"; + case TYPE_VPN: + return "VPN"; + default: + return Integer.toString(type); + } + } + + /** + * @hide + * TODO: Expose for SystemServer when becomes a module. + */ + public void systemReady() { + try { + mService.systemReady(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Checks if a given type uses the cellular data connection. + * This should be replaced in the future by a network property. + * @param networkType the type to check + * @return a boolean - {@code true} if uses cellular network, else {@code false} + * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. + * {@hide} + */ + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + public static boolean isNetworkTypeMobile(int networkType) { + switch (networkType) { + case TYPE_MOBILE: + case TYPE_MOBILE_MMS: + case TYPE_MOBILE_SUPL: + case TYPE_MOBILE_DUN: + case TYPE_MOBILE_HIPRI: + case TYPE_MOBILE_FOTA: + case TYPE_MOBILE_IMS: + case TYPE_MOBILE_CBS: + case TYPE_MOBILE_IA: + case TYPE_MOBILE_EMERGENCY: + return true; + default: + return false; + } + } + + /** + * Checks if the given network type is backed by a Wi-Fi radio. + * + * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + public static boolean isNetworkTypeWifi(int networkType) { + switch (networkType) { + case TYPE_WIFI: + case TYPE_WIFI_P2P: + return true; + default: + return false; + } + } + + /** + * Specifies the preferred network type. When the device has more + * than one type available the preferred network type will be used. + * + * @param preference the network type to prefer over all others. It is + * unspecified what happens to the old preferred network in the + * overall ordering. + * @deprecated Functionality has been removed as it no longer makes sense, + * with many more than two networks - we'd need an array to express + * preference. Instead we use dynamic network properties of + * the networks to describe their precedence. + */ + @Deprecated + public void setNetworkPreference(int preference) { + } + + /** + * Retrieves the current preferred network type. + * + * @return an integer representing the preferred network type + * + * @deprecated Functionality has been removed as it no longer makes sense, + * with many more than two networks - we'd need an array to express + * preference. Instead we use dynamic network properties of + * the networks to describe their precedence. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public int getNetworkPreference() { + return TYPE_NONE; + } + + /** + * Returns details about the currently active default data network. When + * connected, this network is the default route for outgoing connections. + * You should always check {@link NetworkInfo#isConnected()} before initiating + * network traffic. This may return {@code null} when there is no default + * network. + * Note that if the default network is a VPN, this method will return the + * NetworkInfo for one of its underlying networks instead, or null if the + * VPN agent did not specify any. Apps interested in learning about VPNs + * should use {@link #getNetworkInfo(android.net.Network)} instead. + * + * @return a {@link NetworkInfo} object for the current default network + * or {@code null} if no default network is currently active + * @deprecated See {@link NetworkInfo}. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @Nullable + public NetworkInfo getActiveNetworkInfo() { + try { + return mService.getActiveNetworkInfo(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns a {@link Network} object corresponding to the currently active + * default data network. In the event that the current active default data + * network disconnects, the returned {@code Network} object will no longer + * be usable. This will return {@code null} when there is no default + * network. + * + * @return a {@link Network} object for the current default network or + * {@code null} if no default network is currently active + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @Nullable + public Network getActiveNetwork() { + try { + return mService.getActiveNetwork(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns a {@link Network} object corresponding to the currently active + * default data network for a specific UID. In the event that the default data + * network disconnects, the returned {@code Network} object will no longer + * be usable. This will return {@code null} when there is no default + * network for the UID. + * + * @return a {@link Network} object for the current default network for the + * given UID or {@code null} if no default network is currently active + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @Nullable + public Network getActiveNetworkForUid(int uid) { + return getActiveNetworkForUid(uid, false); + } + + /** {@hide} */ + public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { + try { + return mService.getActiveNetworkForUid(uid, ignoreBlocked); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Checks if a VPN app supports always-on mode. + * + * In order to support the always-on feature, an app has to + *

    + *
  • target {@link VERSION_CODES#N API 24} or above, and + *
  • not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} + * meta-data field. + *
+ * + * @param userId The identifier of the user for whom the VPN app is installed. + * @param vpnPackage The canonical package name of the VPN app. + * @return {@code true} if and only if the VPN app exists and supports always-on mode. + * @hide + */ + public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { + try { + return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Configures an always-on VPN connection through a specific application. + * This connection is automatically granted and persisted after a reboot. + * + *

The designated package should declare a {@link VpnService} in its + * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, + * otherwise the call will fail. + * + * @param userId The identifier of the user to set an always-on VPN for. + * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} + * to remove an existing always-on VPN configuration. + * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or + * {@code false} otherwise. + * @param lockdownAllowlist The list of packages that are allowed to access network directly + * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so + * this method must be called when a package that should be allowed is installed or + * uninstalled. + * @return {@code true} if the package is set as always-on VPN controller; + * {@code false} otherwise. + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, + boolean lockdownEnabled, @Nullable List lockdownAllowlist) { + try { + return mService.setAlwaysOnVpnPackage( + userId, vpnPackage, lockdownEnabled, lockdownAllowlist); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the package name of the currently set always-on VPN application. + * If there is no always-on VPN set, or the VPN is provided by the system instead + * of by an app, {@code null} will be returned. + * + * @return Package name of VPN controller responsible for always-on VPN, + * or {@code null} if none is set. + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public String getAlwaysOnVpnPackageForUser(int userId) { + try { + return mService.getAlwaysOnVpnPackage(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @return whether always-on VPN is in lockdown mode. + * + * @hide + **/ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public boolean isVpnLockdownEnabled(int userId) { + try { + return mService.isVpnLockdownEnabled(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + } + + /** + * @return the list of packages that are allowed to access network when always-on VPN is in + * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. + * + * @hide + **/ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public List getVpnLockdownWhitelist(int userId) { + try { + return mService.getVpnLockdownWhitelist(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Adds or removes a requirement for given UID ranges to use the VPN. + * + * If set to {@code true}, informs the system that the UIDs in the specified ranges must not + * have any connectivity except if a VPN is connected and applies to the UIDs, or if the UIDs + * otherwise have permission to bypass the VPN (e.g., because they have the + * {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS} permission, or when + * using a socket protected by a method such as {@link VpnService#protect(DatagramSocket)}. If + * set to {@code false}, a previously-added restriction is removed. + *

+ * Each of the UID ranges specified by this method is added and removed as is, and no processing + * is performed on the ranges to de-duplicate, merge, split, or intersect them. In order to + * remove a previously-added range, the exact range must be removed as is. + *

+ * The changes are applied asynchronously and may not have been applied by the time the method + * returns. Apps will be notified about any changes that apply to them via + * {@link NetworkCallback#onBlockedStatusChanged} callbacks called after the changes take + * effect. + *

+ * This method should be called only by the VPN code. + * + * @param ranges the UID ranges to restrict + * @param requireVpn whether the specified UID ranges must use a VPN + * + * TODO: expose as @SystemApi. + * @hide + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void setRequireVpnForUids(boolean requireVpn, + @NonNull Collection> ranges) { + Objects.requireNonNull(ranges); + // The Range class is not parcelable. Convert to UidRange, which is what is used internally. + // This method is not necessarily expected to be used outside the system server, so + // parceling may not be necessary, but it could be used out-of-process, e.g., by the network + // stack process, or by tests. + UidRange[] rangesArray = new UidRange[ranges.size()]; + int index = 0; + for (Range range : ranges) { + rangesArray[index++] = new UidRange(range.getLower(), range.getUpper()); + } + try { + mService.setRequireVpnForUids(requireVpn, rangesArray); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns details about the currently active default data network + * for a given uid. This is for internal use only to avoid spying + * other apps. + * + * @return a {@link NetworkInfo} object for the current default network + * for the given uid or {@code null} if no default network is + * available for the specified uid. + * + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public NetworkInfo getActiveNetworkInfoForUid(int uid) { + return getActiveNetworkInfoForUid(uid, false); + } + + /** {@hide} */ + public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { + try { + return mService.getActiveNetworkInfoForUid(uid, ignoreBlocked); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns connection status information about a particular + * network type. + * + * @param networkType integer specifying which networkType in + * which you're interested. + * @return a {@link NetworkInfo} object for the requested + * network type or {@code null} if the type is not + * supported by the device. If {@code networkType} is + * TYPE_VPN and a VPN is active for the calling app, + * then this method will try to return one of the + * underlying networks for the VPN or null if the + * VPN agent didn't specify any. + * + * @deprecated This method does not support multiple connected networks + * of the same type. Use {@link #getAllNetworks} and + * {@link #getNetworkInfo(android.net.Network)} instead. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @Nullable + public NetworkInfo getNetworkInfo(int networkType) { + try { + return mService.getNetworkInfo(networkType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns connection status information about a particular + * Network. + * + * @param network {@link Network} specifying which network + * in which you're interested. + * @return a {@link NetworkInfo} object for the requested + * network or {@code null} if the {@code Network} + * is not valid. + * @deprecated See {@link NetworkInfo}. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @Nullable + public NetworkInfo getNetworkInfo(@Nullable Network network) { + return getNetworkInfoForUid(network, Process.myUid(), false); + } + + /** {@hide} */ + public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { + try { + return mService.getNetworkInfoForUid(network, uid, ignoreBlocked); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns connection status information about all network + * types supported by the device. + * + * @return an array of {@link NetworkInfo} objects. Check each + * {@link NetworkInfo#getType} for which type each applies. + * + * @deprecated This method does not support multiple connected networks + * of the same type. Use {@link #getAllNetworks} and + * {@link #getNetworkInfo(android.net.Network)} instead. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @NonNull + public NetworkInfo[] getAllNetworkInfo() { + try { + return mService.getAllNetworkInfo(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the {@link Network} object currently serving a given type, or + * null if the given type is not connected. + * + * @hide + * @deprecated This method does not support multiple connected networks + * of the same type. Use {@link #getAllNetworks} and + * {@link #getNetworkInfo(android.net.Network)} instead. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + public Network getNetworkForType(int networkType) { + try { + return mService.getNetworkForType(networkType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns an array of all {@link Network} currently tracked by the + * framework. + * + * @return an array of {@link Network} objects. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @NonNull + public Network[] getAllNetworks() { + try { + return mService.getAllNetworks(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns an array of {@link android.net.NetworkCapabilities} objects, representing + * the Networks that applications run by the given user will use by default. + * @hide + */ + @UnsupportedAppUsage + public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { + try { + return mService.getDefaultNetworkCapabilitiesForUser( + userId, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the IP information for the current default network. + * + * @return a {@link LinkProperties} object describing the IP info + * for the current default network, or {@code null} if there + * is no current default network. + * + * {@hide} + * @deprecated please use {@link #getLinkProperties(Network)} on the return + * value of {@link #getActiveNetwork()} instead. In particular, + * this method will return non-null LinkProperties even if the + * app is blocked by policy from using this network. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 109783091) + public LinkProperties getActiveLinkProperties() { + try { + return mService.getActiveLinkProperties(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the IP information for a given network type. + * + * @param networkType the network type of interest. + * @return a {@link LinkProperties} object describing the IP info + * for the given networkType, or {@code null} if there is + * no current default network. + * + * {@hide} + * @deprecated This method does not support multiple connected networks + * of the same type. Use {@link #getAllNetworks}, + * {@link #getNetworkInfo(android.net.Network)}, and + * {@link #getLinkProperties(android.net.Network)} instead. + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + public LinkProperties getLinkProperties(int networkType) { + try { + return mService.getLinkPropertiesForType(networkType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the {@link LinkProperties} for the given {@link Network}. This + * will return {@code null} if the network is unknown. + * + * @param network The {@link Network} object identifying the network in question. + * @return The {@link LinkProperties} for the network, or {@code null}. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @Nullable + public LinkProperties getLinkProperties(@Nullable Network network) { + try { + return mService.getLinkProperties(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This + * will return {@code null} if the network is unknown. + * + * @param network The {@link Network} object identifying the network in question. + * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @Nullable + public NetworkCapabilities getNetworkCapabilities(@Nullable Network network) { + try { + return mService.getNetworkCapabilities(network, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets a URL that can be used for resolving whether a captive portal is present. + * 1. This URL should respond with a 204 response to a GET request to indicate no captive + * portal is present. + * 2. This URL must be HTTP as redirect responses are used to find captive portal + * sign-in pages. Captive portals cannot respond to HTTPS requests with redirects. + * + * The system network validation may be using different strategies to detect captive portals, + * so this method does not necessarily return a URL used by the system. It only returns a URL + * that may be relevant for other components trying to detect captive portals. + * + * @hide + * @deprecated This API returns URL which is not guaranteed to be one of the URLs used by the + * system. + */ + @Deprecated + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public String getCaptivePortalServerUrl() { + try { + return mService.getCaptivePortalServerUrl(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Tells the underlying networking system that the caller wants to + * begin using the named feature. The interpretation of {@code feature} + * is completely up to each networking implementation. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + * @param networkType specifies which network the request pertains to + * @param feature the name of the feature to be used + * @return an integer value representing the outcome of the request. + * The interpretation of this value is specific to each networking + * implementation+feature combination, except that the value {@code -1} + * always indicates failure. + * + * @deprecated Deprecated in favor of the cleaner + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} API. + * In {@link VERSION_CODES#M}, and above, this method is unsupported and will + * throw {@code UnsupportedOperationException} if called. + * @removed + */ + @Deprecated + public int startUsingNetworkFeature(int networkType, String feature) { + checkLegacyRoutingApiAccess(); + NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); + if (netCap == null) { + Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " + + feature); + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; + } + + NetworkRequest request = null; + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.get(netCap); + if (l != null) { + Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest); + renewRequestLocked(l); + if (l.currentNetwork != null) { + return DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE; + } else { + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; + } + } + + request = requestNetworkForFeatureLocked(netCap); + } + if (request != null) { + Log.d(TAG, "starting startUsingNetworkFeature for request " + request); + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_STARTED; + } else { + Log.d(TAG, " request Failed"); + return DEPRECATED_PHONE_CONSTANT_APN_REQUEST_FAILED; + } + } + + /** + * Tells the underlying networking system that the caller is finished + * using the named feature. The interpretation of {@code feature} + * is completely up to each networking implementation. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + * @param networkType specifies which network the request pertains to + * @param feature the name of the feature that is no longer needed + * @return an integer value representing the outcome of the request. + * The interpretation of this value is specific to each networking + * implementation+feature combination, except that the value {@code -1} + * always indicates failure. + * + * @deprecated Deprecated in favor of the cleaner + * {@link #unregisterNetworkCallback(NetworkCallback)} API. + * In {@link VERSION_CODES#M}, and above, this method is unsupported and will + * throw {@code UnsupportedOperationException} if called. + * @removed + */ + @Deprecated + public int stopUsingNetworkFeature(int networkType, String feature) { + checkLegacyRoutingApiAccess(); + NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); + if (netCap == null) { + Log.d(TAG, "Can't satisfy stopUsingNetworkFeature for " + networkType + ", " + + feature); + return -1; + } + + if (removeRequestForFeature(netCap)) { + Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature); + } + return 1; + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) { + if (networkType == TYPE_MOBILE) { + switch (feature) { + case "enableCBS": + return networkCapabilitiesForType(TYPE_MOBILE_CBS); + case "enableDUN": + case "enableDUNAlways": + return networkCapabilitiesForType(TYPE_MOBILE_DUN); + case "enableFOTA": + return networkCapabilitiesForType(TYPE_MOBILE_FOTA); + case "enableHIPRI": + return networkCapabilitiesForType(TYPE_MOBILE_HIPRI); + case "enableIMS": + return networkCapabilitiesForType(TYPE_MOBILE_IMS); + case "enableMMS": + return networkCapabilitiesForType(TYPE_MOBILE_MMS); + case "enableSUPL": + return networkCapabilitiesForType(TYPE_MOBILE_SUPL); + default: + return null; + } + } else if (networkType == TYPE_WIFI && "p2p".equals(feature)) { + return networkCapabilitiesForType(TYPE_WIFI_P2P); + } + return null; + } + + private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) { + if (netCap == null) return TYPE_NONE; + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { + return TYPE_MOBILE_CBS; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { + return TYPE_MOBILE_IMS; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { + return TYPE_MOBILE_FOTA; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { + return TYPE_MOBILE_DUN; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { + return TYPE_MOBILE_SUPL; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { + return TYPE_MOBILE_MMS; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + return TYPE_MOBILE_HIPRI; + } + if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) { + return TYPE_WIFI_P2P; + } + return TYPE_NONE; + } + + private static class LegacyRequest { + NetworkCapabilities networkCapabilities; + NetworkRequest networkRequest; + int expireSequenceNumber; + Network currentNetwork; + int delay = -1; + + private void clearDnsBinding() { + if (currentNetwork != null) { + currentNetwork = null; + setProcessDefaultNetworkForHostResolution(null); + } + } + + NetworkCallback networkCallback = new NetworkCallback() { + @Override + public void onAvailable(Network network) { + currentNetwork = network; + Log.d(TAG, "startUsingNetworkFeature got Network:" + network); + setProcessDefaultNetworkForHostResolution(network); + } + @Override + public void onLost(Network network) { + if (network.equals(currentNetwork)) clearDnsBinding(); + Log.d(TAG, "startUsingNetworkFeature lost Network:" + network); + } + }; + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private static final HashMap sLegacyRequests = + new HashMap<>(); + + private NetworkRequest findRequestForFeature(NetworkCapabilities netCap) { + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.get(netCap); + if (l != null) return l.networkRequest; + } + return null; + } + + private void renewRequestLocked(LegacyRequest l) { + l.expireSequenceNumber++; + Log.d(TAG, "renewing request to seqNum " + l.expireSequenceNumber); + sendExpireMsgForFeature(l.networkCapabilities, l.expireSequenceNumber, l.delay); + } + + private void expireRequest(NetworkCapabilities netCap, int sequenceNum) { + int ourSeqNum = -1; + synchronized (sLegacyRequests) { + LegacyRequest l = sLegacyRequests.get(netCap); + if (l == null) return; + ourSeqNum = l.expireSequenceNumber; + if (l.expireSequenceNumber == sequenceNum) removeRequestForFeature(netCap); + } + Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum); + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) { + int delay = -1; + int type = legacyTypeForNetworkCapabilities(netCap); + try { + delay = mService.getRestoreDefaultNetworkDelay(type); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + LegacyRequest l = new LegacyRequest(); + l.networkCapabilities = netCap; + l.delay = delay; + l.expireSequenceNumber = 0; + l.networkRequest = sendRequestForNetwork( + netCap, l.networkCallback, 0, REQUEST, type, getDefaultHandler()); + if (l.networkRequest == null) return null; + sLegacyRequests.put(netCap, l); + sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay); + return l.networkRequest; + } + + private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) { + if (delay >= 0) { + Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay); + CallbackHandler handler = getDefaultHandler(); + Message msg = handler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap); + handler.sendMessageDelayed(msg, delay); + } + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private boolean removeRequestForFeature(NetworkCapabilities netCap) { + final LegacyRequest l; + synchronized (sLegacyRequests) { + l = sLegacyRequests.remove(netCap); + } + if (l == null) return false; + unregisterNetworkCallback(l.networkCallback); + l.clearDnsBinding(); + return true; + } + + private static final SparseIntArray sLegacyTypeToTransport = new SparseIntArray(); + static { + sLegacyTypeToTransport.put(TYPE_MOBILE, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_CBS, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_DUN, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_FOTA, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_HIPRI, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_IMS, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_MMS, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_MOBILE_SUPL, NetworkCapabilities.TRANSPORT_CELLULAR); + sLegacyTypeToTransport.put(TYPE_WIFI, NetworkCapabilities.TRANSPORT_WIFI); + sLegacyTypeToTransport.put(TYPE_WIFI_P2P, NetworkCapabilities.TRANSPORT_WIFI); + sLegacyTypeToTransport.put(TYPE_BLUETOOTH, NetworkCapabilities.TRANSPORT_BLUETOOTH); + sLegacyTypeToTransport.put(TYPE_ETHERNET, NetworkCapabilities.TRANSPORT_ETHERNET); + } + + private static final SparseIntArray sLegacyTypeToCapability = new SparseIntArray(); + static { + sLegacyTypeToCapability.put(TYPE_MOBILE_CBS, NetworkCapabilities.NET_CAPABILITY_CBS); + sLegacyTypeToCapability.put(TYPE_MOBILE_DUN, NetworkCapabilities.NET_CAPABILITY_DUN); + sLegacyTypeToCapability.put(TYPE_MOBILE_FOTA, NetworkCapabilities.NET_CAPABILITY_FOTA); + sLegacyTypeToCapability.put(TYPE_MOBILE_IMS, NetworkCapabilities.NET_CAPABILITY_IMS); + sLegacyTypeToCapability.put(TYPE_MOBILE_MMS, NetworkCapabilities.NET_CAPABILITY_MMS); + sLegacyTypeToCapability.put(TYPE_MOBILE_SUPL, NetworkCapabilities.NET_CAPABILITY_SUPL); + sLegacyTypeToCapability.put(TYPE_WIFI_P2P, NetworkCapabilities.NET_CAPABILITY_WIFI_P2P); + } + + /** + * Given a legacy type (TYPE_WIFI, ...) returns a NetworkCapabilities + * instance suitable for registering a request or callback. Throws an + * IllegalArgumentException if no mapping from the legacy type to + * NetworkCapabilities is known. + * + * @deprecated Types are deprecated. Use {@link NetworkCallback} or {@link NetworkRequest} + * to find the network instead. + * @hide + */ + public static NetworkCapabilities networkCapabilitiesForType(int type) { + final NetworkCapabilities nc = new NetworkCapabilities(); + + // Map from type to transports. + final int NOT_FOUND = -1; + final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND); + Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type); + nc.addTransportType(transport); + + // Map from type to capabilities. + nc.addCapability(sLegacyTypeToCapability.get( + type, NetworkCapabilities.NET_CAPABILITY_INTERNET)); + nc.maybeMarkCapabilitiesRestricted(); + return nc; + } + + /** @hide */ + public static class PacketKeepaliveCallback { + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public PacketKeepaliveCallback() { + } + /** The requested keepalive was successfully started. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void onStarted() {} + /** The keepalive was successfully stopped. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void onStopped() {} + /** An error occurred. */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void onError(int error) {} + } + + /** + * Allows applications to request that the system periodically send specific packets on their + * behalf, using hardware offload to save battery power. + * + * To request that the system send keepalives, call one of the methods that return a + * {@link ConnectivityManager.PacketKeepalive} object, such as {@link #startNattKeepalive}, + * passing in a non-null callback. If the callback is successfully started, the callback's + * {@code onStarted} method will be called. If an error occurs, {@code onError} will be called, + * specifying one of the {@code ERROR_*} constants in this class. + * + * To stop an existing keepalive, call {@link PacketKeepalive#stop}. The system will call + * {@link PacketKeepaliveCallback#onStopped} if the operation was successful or + * {@link PacketKeepaliveCallback#onError} if an error occurred. + * + * @deprecated Use {@link SocketKeepalive} instead. + * + * @hide + */ + public class PacketKeepalive { + + private static final String TAG = "PacketKeepalive"; + + /** @hide */ + public static final int SUCCESS = 0; + + /** @hide */ + public static final int NO_KEEPALIVE = -1; + + /** @hide */ + public static final int BINDER_DIED = -10; + + /** The specified {@code Network} is not connected. */ + public static final int ERROR_INVALID_NETWORK = -20; + /** The specified IP addresses are invalid. For example, the specified source IP address is + * not configured on the specified {@code Network}. */ + public static final int ERROR_INVALID_IP_ADDRESS = -21; + /** The requested port is invalid. */ + public static final int ERROR_INVALID_PORT = -22; + /** The packet length is invalid (e.g., too long). */ + public static final int ERROR_INVALID_LENGTH = -23; + /** The packet transmission interval is invalid (e.g., too short). */ + public static final int ERROR_INVALID_INTERVAL = -24; + + /** The hardware does not support this request. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = -30; + /** The hardware returned an error. */ + public static final int ERROR_HARDWARE_ERROR = -31; + + /** The NAT-T destination port for IPsec */ + public static final int NATT_PORT = 4500; + + /** The minimum interval in seconds between keepalive packet transmissions */ + public static final int MIN_INTERVAL = 10; + + private final Network mNetwork; + private final ISocketKeepaliveCallback mCallback; + private final ExecutorService mExecutor; + + private volatile Integer mSlot; + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void stop() { + try { + mExecutor.execute(() -> { + try { + if (mSlot != null) { + mService.stopKeepalive(mNetwork, mSlot); + } + } catch (RemoteException e) { + Log.e(TAG, "Error stopping packet keepalive: ", e); + throw e.rethrowFromSystemServer(); + } + }); + } catch (RejectedExecutionException e) { + // The internal executor has already stopped due to previous event. + } + } + + private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { + Preconditions.checkNotNull(network, "network cannot be null"); + Preconditions.checkNotNull(callback, "callback cannot be null"); + mNetwork = network; + mExecutor = Executors.newSingleThreadExecutor(); + mCallback = new ISocketKeepaliveCallback.Stub() { + @Override + public void onStarted(int slot) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mSlot = slot; + callback.onStarted(); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void onStopped() { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mSlot = null; + callback.onStopped(); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + mExecutor.shutdown(); + } + + @Override + public void onError(int error) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mSlot = null; + callback.onError(error); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + mExecutor.shutdown(); + } + + @Override + public void onDataReceived() { + // PacketKeepalive is only used for Nat-T keepalive and as such does not invoke + // this callback when data is received. + } + }; + } + } + + /** + * Starts an IPsec NAT-T keepalive packet with the specified parameters. + * + * @deprecated Use {@link #createSocketKeepalive} instead. + * + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public PacketKeepalive startNattKeepalive( + Network network, int intervalSeconds, PacketKeepaliveCallback callback, + InetAddress srcAddr, int srcPort, InetAddress dstAddr) { + final PacketKeepalive k = new PacketKeepalive(network, callback); + try { + mService.startNattKeepalive(network, intervalSeconds, k.mCallback, + srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress()); + } catch (RemoteException e) { + Log.e(TAG, "Error starting packet keepalive: ", e); + throw e.rethrowFromSystemServer(); + } + return k; + } + + // Construct an invalid fd. + private ParcelFileDescriptor createInvalidFd() { + final int invalidFd = -1; + return ParcelFileDescriptor.adoptFd(invalidFd); + } + + /** + * Request that keepalives be started on a IPsec NAT-T socket. + * + * @param network The {@link Network} the socket is on. + * @param socket The socket that needs to be kept alive. + * @param source The source address of the {@link UdpEncapsulationSocket}. + * @param destination The destination address of the {@link UdpEncapsulationSocket}. + * @param executor The executor on which callback will be invoked. The provided {@link Executor} + * must run callback sequentially, otherwise the order of callbacks cannot be + * guaranteed. + * @param callback A {@link SocketKeepalive.Callback}. Used for notifications about keepalive + * changes. Must be extended by applications that use this API. + * + * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the + * given socket. + **/ + public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network, + @NonNull UdpEncapsulationSocket socket, + @NonNull InetAddress source, + @NonNull InetAddress destination, + @NonNull @CallbackExecutor Executor executor, + @NonNull Callback callback) { + ParcelFileDescriptor dup; + try { + // Dup is needed here as the pfd inside the socket is owned by the IpSecService, + // which cannot be obtained by the app process. + dup = ParcelFileDescriptor.dup(socket.getFileDescriptor()); + } catch (IOException ignored) { + // Construct an invalid fd, so that if the user later calls start(), it will fail with + // ERROR_INVALID_SOCKET. + dup = createInvalidFd(); + } + return new NattSocketKeepalive(mService, network, dup, socket.getResourceId(), source, + destination, executor, callback); + } + + /** + * Request that keepalives be started on a IPsec NAT-T socket file descriptor. Directly called + * by system apps which don't use IpSecService to create {@link UdpEncapsulationSocket}. + * + * @param network The {@link Network} the socket is on. + * @param pfd The {@link ParcelFileDescriptor} that needs to be kept alive. The provided + * {@link ParcelFileDescriptor} must be bound to a port and the keepalives will be sent + * from that port. + * @param source The source address of the {@link UdpEncapsulationSocket}. + * @param destination The destination address of the {@link UdpEncapsulationSocket}. The + * keepalive packets will always be sent to port 4500 of the given {@code destination}. + * @param executor The executor on which callback will be invoked. The provided {@link Executor} + * must run callback sequentially, otherwise the order of callbacks cannot be + * guaranteed. + * @param callback A {@link SocketKeepalive.Callback}. Used for notifications about keepalive + * changes. Must be extended by applications that use this API. + * + * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the + * given socket. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) + public @NonNull SocketKeepalive createNattKeepalive(@NonNull Network network, + @NonNull ParcelFileDescriptor pfd, + @NonNull InetAddress source, + @NonNull InetAddress destination, + @NonNull @CallbackExecutor Executor executor, + @NonNull Callback callback) { + ParcelFileDescriptor dup; + try { + // TODO: Consider remove unnecessary dup. + dup = pfd.dup(); + } catch (IOException ignored) { + // Construct an invalid fd, so that if the user later calls start(), it will fail with + // ERROR_INVALID_SOCKET. + dup = createInvalidFd(); + } + return new NattSocketKeepalive(mService, network, dup, + INVALID_RESOURCE_ID /* Unused */, source, destination, executor, callback); + } + + /** + * Request that keepalives be started on a TCP socket. + * The socket must be established. + * + * @param network The {@link Network} the socket is on. + * @param socket The socket that needs to be kept alive. + * @param executor The executor on which callback will be invoked. This implementation assumes + * the provided {@link Executor} runs the callbacks in sequence with no + * concurrency. Failing this, no guarantee of correctness can be made. It is + * the responsibility of the caller to ensure the executor provides this + * guarantee. A simple way of creating such an executor is with the standard + * tool {@code Executors.newSingleThreadExecutor}. + * @param callback A {@link SocketKeepalive.Callback}. Used for notifications about keepalive + * changes. Must be extended by applications that use this API. + * + * @return A {@link SocketKeepalive} object that can be used to control the keepalive on the + * given socket. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) + public @NonNull SocketKeepalive createSocketKeepalive(@NonNull Network network, + @NonNull Socket socket, + @NonNull Executor executor, + @NonNull Callback callback) { + ParcelFileDescriptor dup; + try { + dup = ParcelFileDescriptor.fromSocket(socket); + } catch (UncheckedIOException ignored) { + // Construct an invalid fd, so that if the user later calls start(), it will fail with + // ERROR_INVALID_SOCKET. + dup = createInvalidFd(); + } + return new TcpSocketKeepalive(mService, network, dup, executor, callback); + } + + /** + * Ensure that a network route exists to deliver traffic to the specified + * host via the specified network interface. An attempt to add a route that + * already exists is ignored, but treated as successful. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + * @param networkType the type of the network over which traffic to the specified + * host is to be routed + * @param hostAddress the IP address of the host to which the route is desired + * @return {@code true} on success, {@code false} on failure + * + * @deprecated Deprecated in favor of the + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, + * {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} API. + * In {@link VERSION_CODES#M}, and above, this method is unsupported and will + * throw {@code UnsupportedOperationException} if called. + * @removed + */ + @Deprecated + public boolean requestRouteToHost(int networkType, int hostAddress) { + return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress)); + } + + /** + * Ensure that a network route exists to deliver traffic to the specified + * host via the specified network interface. An attempt to add a route that + * already exists is ignored, but treated as successful. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + * @param networkType the type of the network over which traffic to the specified + * host is to be routed + * @param hostAddress the IP address of the host to which the route is desired + * @return {@code true} on success, {@code false} on failure + * @hide + * @deprecated Deprecated in favor of the {@link #requestNetwork} and + * {@link #bindProcessToNetwork} API. + */ + @Deprecated + @UnsupportedAppUsage + public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) { + checkLegacyRoutingApiAccess(); + try { + return mService.requestRouteToHostAddress(networkType, hostAddress.getAddress(), + mContext.getOpPackageName(), getAttributionTag()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @return the context's attribution tag + */ + // TODO: Remove method and replace with direct call once R code is pushed to AOSP + private @Nullable String getAttributionTag() { + return null; + } + + /** + * Returns the value of the setting for background data usage. If false, + * applications should not use the network if the application is not in the + * foreground. Developers should respect this setting, and check the value + * of this before performing any background data operations. + *

+ * All applications that have background services that use the network + * should listen to {@link #ACTION_BACKGROUND_DATA_SETTING_CHANGED}. + *

+ * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, availability of + * background data depends on several combined factors, and this method will + * always return {@code true}. Instead, when background data is unavailable, + * {@link #getActiveNetworkInfo()} will now appear disconnected. + * + * @return Whether background data usage is allowed. + */ + @Deprecated + public boolean getBackgroundDataSetting() { + // assume that background data is allowed; final authority is + // NetworkInfo which may be blocked. + return true; + } + + /** + * Sets the value of the setting for background data usage. + * + * @param allowBackgroundData Whether an application should use data while + * it is in the background. + * + * @attr ref android.Manifest.permission#CHANGE_BACKGROUND_DATA_SETTING + * @see #getBackgroundDataSetting() + * @hide + */ + @Deprecated + @UnsupportedAppUsage + public void setBackgroundDataSetting(boolean allowBackgroundData) { + // ignored + } + + /** + * @hide + * @deprecated Talk to TelephonyManager directly + */ + @Deprecated + @UnsupportedAppUsage + public boolean getMobileDataEnabled() { + TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); + if (tm != null) { + int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + Log.d("ConnectivityManager", "getMobileDataEnabled()+ subId=" + subId); + boolean retVal = tm.createForSubscriptionId(subId).isDataEnabled(); + Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId + + " retVal=" + retVal); + return retVal; + } + Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false"); + return false; + } + + /** + * Callback for use with {@link ConnectivityManager#addDefaultNetworkActiveListener} + * to find out when the system default network has gone in to a high power state. + */ + public interface OnNetworkActiveListener { + /** + * Called on the main thread of the process to report that the current data network + * has become active, and it is now a good time to perform any pending network + * operations. Note that this listener only tells you when the network becomes + * active; if at any other time you want to know whether it is active (and thus okay + * to initiate network traffic), you can retrieve its instantaneous state with + * {@link ConnectivityManager#isDefaultNetworkActive}. + */ + void onNetworkActive(); + } + + private INetworkManagementService getNetworkManagementService() { + synchronized (this) { + if (mNMService != null) { + return mNMService; + } + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + mNMService = INetworkManagementService.Stub.asInterface(b); + return mNMService; + } + } + + private final ArrayMap + mNetworkActivityListeners = new ArrayMap<>(); + + /** + * Start listening to reports when the system's default data network is active, meaning it is + * a good time to perform network traffic. Use {@link #isDefaultNetworkActive()} + * to determine the current state of the system's default network after registering the + * listener. + *

+ * If the process default network has been set with + * {@link ConnectivityManager#bindProcessToNetwork} this function will not + * reflect the process's default, but the system default. + * + * @param l The listener to be told when the network is active. + */ + public void addDefaultNetworkActiveListener(final OnNetworkActiveListener l) { + INetworkActivityListener rl = new INetworkActivityListener.Stub() { + @Override + public void onNetworkActive() throws RemoteException { + l.onNetworkActive(); + } + }; + + try { + getNetworkManagementService().registerNetworkActivityListener(rl); + mNetworkActivityListeners.put(l, rl); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Remove network active listener previously registered with + * {@link #addDefaultNetworkActiveListener}. + * + * @param l Previously registered listener. + */ + public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) { + INetworkActivityListener rl = mNetworkActivityListeners.get(l); + Preconditions.checkArgument(rl != null, "Listener was not registered."); + try { + getNetworkManagementService().unregisterNetworkActivityListener(rl); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return whether the data network is currently active. An active network means that + * it is currently in a high power state for performing data transmission. On some + * types of networks, it may be expensive to move and stay in such a state, so it is + * more power efficient to batch network traffic together when the radio is already in + * this state. This method tells you whether right now is currently a good time to + * initiate network traffic, as the network is already active. + */ + public boolean isDefaultNetworkActive() { + try { + return getNetworkManagementService().isNetworkActive(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * {@hide} + */ + public ConnectivityManager(Context context, IConnectivityManager service) { + mContext = Preconditions.checkNotNull(context, "missing context"); + mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); + sInstance = this; + } + + /** {@hide} */ + @UnsupportedAppUsage + public static ConnectivityManager from(Context context) { + return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + } + + /** @hide */ + public NetworkRequest getDefaultRequest() { + try { + // This is not racy as the default request is final in ConnectivityService. + return mService.getDefaultRequest(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /* TODO: These permissions checks don't belong in client-side code. Move them to + * services.jar, possibly in com.android.server.net. */ + + /** {@hide} */ + public static final void enforceChangePermission(Context context, + String callingPkg, String callingAttributionTag) { + int uid = Binder.getCallingUid(); + checkAndNoteChangeNetworkStateOperation(context, uid, callingPkg, + callingAttributionTag, true /* throwException */); + } + + /** + * Check if the package is a allowed to change the network state. This also accounts that such + * an access happened. + * + * @return {@code true} iff the package is allowed to change the network state. + */ + // TODO: Remove method and replace with direct call once R code is pushed to AOSP + private static boolean checkAndNoteChangeNetworkStateOperation(@NonNull Context context, + int uid, @NonNull String callingPackage, @Nullable String callingAttributionTag, + boolean throwException) { + return Settings.checkAndNoteChangeNetworkStateOperation(context, uid, callingPackage, + throwException); + } + + /** + * Check if the package is a allowed to write settings. This also accounts that such an access + * happened. + * + * @return {@code true} iff the package is allowed to write settings. + */ + // TODO: Remove method and replace with direct call once R code is pushed to AOSP + private static boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid, + @NonNull String callingPackage, @Nullable String callingAttributionTag, + boolean throwException) { + return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage, + throwException); + } + + /** + * @deprecated - use getSystemService. This is a kludge to support static access in certain + * situations where a Context pointer is unavailable. + * @hide + */ + @Deprecated + static ConnectivityManager getInstanceOrNull() { + return sInstance; + } + + /** + * @deprecated - use getSystemService. This is a kludge to support static access in certain + * situations where a Context pointer is unavailable. + * @hide + */ + @Deprecated + @UnsupportedAppUsage + private static ConnectivityManager getInstance() { + if (getInstanceOrNull() == null) { + throw new IllegalStateException("No ConnectivityManager yet constructed"); + } + return getInstanceOrNull(); + } + + /** + * Get the set of tetherable, available interfaces. This list is limited by + * device configuration and current interface existence. + * + * @return an array of 0 or more Strings of tetherable interface names. + * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + @Deprecated + public String[] getTetherableIfaces() { + return mTetheringManager.getTetherableIfaces(); + } + + /** + * Get the set of tethered interfaces. + * + * @return an array of 0 or more String of currently tethered interface names. + * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + @Deprecated + public String[] getTetheredIfaces() { + return mTetheringManager.getTetheredIfaces(); + } + + /** + * Get the set of interface names which attempted to tether but + * failed. Re-attempting to tether may cause them to reset to the Tethered + * state. Alternatively, causing the interface to be destroyed and recreated + * may cause them to reset to the available state. + * {@link ConnectivityManager#getLastTetherError} can be used to get more + * information on the cause of the errors. + * + * @return an array of 0 or more String indicating the interface names + * which failed to tether. + * + * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + @Deprecated + public String[] getTetheringErroredIfaces() { + return mTetheringManager.getTetheringErroredIfaces(); + } + + /** + * Get the set of tethered dhcp ranges. + * + * @deprecated This method is not supported. + * TODO: remove this function when all of clients are removed. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @Deprecated + public String[] getTetheredDhcpRanges() { + throw new UnsupportedOperationException("getTetheredDhcpRanges is not supported"); + } + + /** + * Attempt to tether the named interface. This will setup a dhcp server + * on the interface, forward and NAT IP packets and forward DNS requests + * to the best active upstream network interface. Note that if no upstream + * IP network interface is available, dhcp will still run and traffic will be + * allowed between the tethered devices and this device, though upstream net + * access will of course fail until an upstream network interface becomes + * active. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + *

WARNING: New clients should not use this function. The only usages should be in PanService + * and WifiStateMachine which need direct access. All other clients should use + * {@link #startTethering} and {@link #stopTethering} which encapsulate proper provisioning + * logic.

+ * + * @param iface the interface name to tether. + * @return error a {@code TETHER_ERROR} value indicating success or failure type + * @deprecated Use {@link TetheringManager#startTethering} instead + * + * {@hide} + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Deprecated + public int tether(String iface) { + return mTetheringManager.tether(iface); + } + + /** + * Stop tethering the named interface. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + *

WARNING: New clients should not use this function. The only usages should be in PanService + * and WifiStateMachine which need direct access. All other clients should use + * {@link #startTethering} and {@link #stopTethering} which encapsulate proper provisioning + * logic.

+ * + * @param iface the interface name to untether. + * @return error a {@code TETHER_ERROR} value indicating success or failure type + * + * {@hide} + */ + @UnsupportedAppUsage + @Deprecated + public int untether(String iface) { + return mTetheringManager.untether(iface); + } + + /** + * Check if the device allows for tethering. It may be disabled via + * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or + * due to device configuration. + * + *

If this app does not have permission to use this API, it will always + * return false rather than throw an exception.

+ * + *

If the device has a hotspot provisioning app, the caller is required to hold the + * {@link android.Manifest.permission.TETHER_PRIVILEGED} permission.

+ * + *

Otherwise, this method requires the caller to hold the ability to modify system + * settings as determined by {@link android.provider.Settings.System#canWrite}.

+ * + * @return a boolean - {@code true} indicating Tethering is supported. + * + * @deprecated Use {@link TetheringEventCallback#onTetheringSupported(boolean)} instead. + * {@hide} + */ + @SystemApi + @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED, + android.Manifest.permission.WRITE_SETTINGS}) + public boolean isTetheringSupported() { + return mTetheringManager.isTetheringSupported(); + } + + /** + * Callback for use with {@link #startTethering} to find out whether tethering succeeded. + * + * @deprecated Use {@link TetheringManager.StartTetheringCallback} instead. + * @hide + */ + @SystemApi + @Deprecated + public static abstract class OnStartTetheringCallback { + /** + * Called when tethering has been successfully started. + */ + public void onTetheringStarted() {} + + /** + * Called when starting tethering failed. + */ + public void onTetheringFailed() {} + } + + /** + * Convenient overload for + * {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null + * handler to run on the current thread's {@link Looper}. + * + * @deprecated Use {@link TetheringManager#startTethering} instead. + * @hide + */ + @SystemApi + @Deprecated + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void startTethering(int type, boolean showProvisioningUi, + final OnStartTetheringCallback callback) { + startTethering(type, showProvisioningUi, callback, null); + } + + /** + * Runs tether provisioning for the given type if needed and then starts tethering if + * the check succeeds. If no carrier provisioning is required for tethering, tethering is + * enabled immediately. If provisioning fails, tethering will not be enabled. It also + * schedules tether provisioning re-checks if appropriate. + * + * @param type The type of tethering to start. Must be one of + * {@link ConnectivityManager.TETHERING_WIFI}, + * {@link ConnectivityManager.TETHERING_USB}, or + * {@link ConnectivityManager.TETHERING_BLUETOOTH}. + * @param showProvisioningUi a boolean indicating to show the provisioning app UI if there + * is one. This should be true the first time this function is called and also any time + * the user can see this UI. It gives users information from their carrier about the + * check failing and how they can sign up for tethering if possible. + * @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller + * of the result of trying to tether. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * + * @deprecated Use {@link TetheringManager#startTethering} instead. + * @hide + */ + @SystemApi + @Deprecated + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void startTethering(int type, boolean showProvisioningUi, + final OnStartTetheringCallback callback, Handler handler) { + Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); + + final Executor executor = new Executor() { + @Override + public void execute(Runnable command) { + if (handler == null) { + command.run(); + } else { + handler.post(command); + } + } + }; + + final StartTetheringCallback tetheringCallback = new StartTetheringCallback() { + @Override + public void onTetheringStarted() { + callback.onTetheringStarted(); + } + + @Override + public void onTetheringFailed(final int error) { + callback.onTetheringFailed(); + } + }; + + final TetheringRequest request = new TetheringRequest.Builder(type) + .setShouldShowEntitlementUi(showProvisioningUi).build(); + + mTetheringManager.startTethering(request, executor, tetheringCallback); + } + + /** + * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if + * applicable. + * + * @param type The type of tethering to stop. Must be one of + * {@link ConnectivityManager.TETHERING_WIFI}, + * {@link ConnectivityManager.TETHERING_USB}, or + * {@link ConnectivityManager.TETHERING_BLUETOOTH}. + * + * @deprecated Use {@link TetheringManager#stopTethering} instead. + * @hide + */ + @SystemApi + @Deprecated + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void stopTethering(int type) { + mTetheringManager.stopTethering(type); + } + + /** + * Callback for use with {@link registerTetheringEventCallback} to find out tethering + * upstream status. + * + * @deprecated Use {@link TetheringManager#OnTetheringEventCallback} instead. + * @hide + */ + @SystemApi + @Deprecated + public abstract static class OnTetheringEventCallback { + + /** + * Called when tethering upstream changed. This can be called multiple times and can be + * called any time. + * + * @param network the {@link Network} of tethering upstream. Null means tethering doesn't + * have any upstream. + */ + public void onUpstreamChanged(@Nullable Network network) {} + } + + @GuardedBy("mTetheringEventCallbacks") + private final ArrayMap + mTetheringEventCallbacks = new ArrayMap<>(); + + /** + * Start listening to tethering change events. Any new added callback will receive the last + * tethering status right away. If callback is registered when tethering has no upstream or + * disabled, {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called + * with a null argument. The same callback object cannot be registered twice. + * + * @param executor the executor on which callback will be invoked. + * @param callback the callback to be called when tethering has change events. + * + * @deprecated Use {@link TetheringManager#registerTetheringEventCallback} instead. + * @hide + */ + @SystemApi + @Deprecated + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void registerTetheringEventCallback( + @NonNull @CallbackExecutor Executor executor, + @NonNull final OnTetheringEventCallback callback) { + Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); + + final TetheringEventCallback tetherCallback = + new TetheringEventCallback() { + @Override + public void onUpstreamChanged(@Nullable Network network) { + callback.onUpstreamChanged(network); + } + }; + + synchronized (mTetheringEventCallbacks) { + mTetheringEventCallbacks.put(callback, tetherCallback); + mTetheringManager.registerTetheringEventCallback(executor, tetherCallback); + } + } + + /** + * Remove tethering event callback previously registered with + * {@link #registerTetheringEventCallback}. + * + * @param callback previously registered callback. + * + * @deprecated Use {@link TetheringManager#unregisterTetheringEventCallback} instead. + * @hide + */ + @SystemApi + @Deprecated + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void unregisterTetheringEventCallback( + @NonNull final OnTetheringEventCallback callback) { + Objects.requireNonNull(callback, "The callback must be non-null"); + synchronized (mTetheringEventCallbacks) { + final TetheringEventCallback tetherCallback = + mTetheringEventCallbacks.remove(callback); + mTetheringManager.unregisterTetheringEventCallback(tetherCallback); + } + } + + + /** + * Get the list of regular expressions that define any tetherable + * USB network interfaces. If USB tethering is not supported by the + * device, this list should be empty. + * + * @return an array of 0 or more regular expression Strings defining + * what interfaces are considered tetherable usb interfaces. + * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + @Deprecated + public String[] getTetherableUsbRegexs() { + return mTetheringManager.getTetherableUsbRegexs(); + } + + /** + * Get the list of regular expressions that define any tetherable + * Wifi network interfaces. If Wifi tethering is not supported by the + * device, this list should be empty. + * + * @return an array of 0 or more regular expression Strings defining + * what interfaces are considered tetherable wifi interfaces. + * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + @Deprecated + public String[] getTetherableWifiRegexs() { + return mTetheringManager.getTetherableWifiRegexs(); + } + + /** + * Get the list of regular expressions that define any tetherable + * Bluetooth network interfaces. If Bluetooth tethering is not supported by the + * device, this list should be empty. + * + * @return an array of 0 or more regular expression Strings defining + * what interfaces are considered tetherable bluetooth interfaces. + * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged( + *TetheringManager.TetheringInterfaceRegexps)} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage + @Deprecated + public String[] getTetherableBluetoothRegexs() { + return mTetheringManager.getTetherableBluetoothRegexs(); + } + + /** + * Attempt to both alter the mode of USB and Tethering of USB. A + * utility method to deal with some of the complexity of USB - will + * attempt to switch to Rndis and subsequently tether the resulting + * interface on {@code true} or turn off tethering and switch off + * Rndis on {@code false}. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + * @param enable a boolean - {@code true} to enable tethering + * @return error a {@code TETHER_ERROR} value indicating success or failure type + * @deprecated Use {@link TetheringManager#startTethering} instead + * + * {@hide} + */ + @UnsupportedAppUsage + @Deprecated + public int setUsbTethering(boolean enable) { + return mTetheringManager.setUsbTethering(enable); + } + + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_NO_ERROR}. + * {@hide} + */ + @SystemApi + @Deprecated + public static final int TETHER_ERROR_NO_ERROR = TetheringManager.TETHER_ERROR_NO_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNKNOWN_IFACE = + TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_SERVICE_UNAVAIL}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_SERVICE_UNAVAIL = + TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNSUPPORTED}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNSUPPORTED = TetheringManager.TETHER_ERROR_UNSUPPORTED; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNAVAIL_IFACE}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNAVAIL_IFACE = + TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_INTERNAL_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_MASTER_ERROR = + TetheringManager.TETHER_ERROR_INTERNAL_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_TETHER_IFACE_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_TETHER_IFACE_ERROR = + TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNTETHER_IFACE_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = + TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_FORWARDING_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_ENABLE_NAT_ERROR = + TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_FORWARDING_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_DISABLE_NAT_ERROR = + TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_IFACE_CFG_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_IFACE_CFG_ERROR = + TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISIONING_FAILED}. + * {@hide} + */ + @SystemApi + @Deprecated + public static final int TETHER_ERROR_PROVISION_FAILED = + TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_DHCPSERVER_ERROR = + TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENTITLEMENT_UNKNOWN}. + * {@hide} + */ + @SystemApi + @Deprecated + public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = + TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; + + /** + * Get a more detailed error code after a Tethering or Untethering + * request asynchronously failed. + * + * @param iface The name of the interface of interest + * @return error The error code of the last error tethering or untethering the named + * interface + * + * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead. + * {@hide} + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Deprecated + public int getLastTetherError(String iface) { + int error = mTetheringManager.getLastTetherError(iface); + if (error == TetheringManager.TETHER_ERROR_UNKNOWN_TYPE) { + // TETHER_ERROR_UNKNOWN_TYPE was introduced with TetheringManager and has never been + // returned by ConnectivityManager. Convert it to the legacy TETHER_ERROR_UNKNOWN_IFACE + // instead. + error = TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; + } + return error; + } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + TETHER_ERROR_NO_ERROR, + TETHER_ERROR_PROVISION_FAILED, + TETHER_ERROR_ENTITLEMENT_UNKONWN, + }) + public @interface EntitlementResultCode { + } + + /** + * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether + * entitlement succeeded. + * + * @deprecated Use {@link TetheringManager#OnTetheringEntitlementResultListener} instead. + * @hide + */ + @SystemApi + @Deprecated + public interface OnTetheringEntitlementResultListener { + /** + * Called to notify entitlement result. + * + * @param resultCode an int value of entitlement result. It may be one of + * {@link #TETHER_ERROR_NO_ERROR}, + * {@link #TETHER_ERROR_PROVISION_FAILED}, or + * {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}. + */ + void onTetheringEntitlementResult(@EntitlementResultCode int resultCode); + } + + /** + * Get the last value of the entitlement check on this downstream. If the cached value is + * {@link #TETHER_ERROR_NO_ERROR} or showEntitlementUi argument is false, it just return the + * cached value. Otherwise, a UI-based entitlement check would be performed. It is not + * guaranteed that the UI-based entitlement check will complete in any specific time period + * and may in fact never complete. Any successful entitlement check the platform performs for + * any reason will update the cached value. + * + * @param type the downstream type of tethering. Must be one of + * {@link #TETHERING_WIFI}, + * {@link #TETHERING_USB}, or + * {@link #TETHERING_BLUETOOTH}. + * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check. + * @param executor the executor on which callback will be invoked. + * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to + * notify the caller of the result of entitlement check. The listener may be called zero + * or one time. + * @deprecated Use {@link TetheringManager#requestLatestTetheringEntitlementResult} instead. + * {@hide} + */ + @SystemApi + @Deprecated + @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, + @NonNull @CallbackExecutor Executor executor, + @NonNull final OnTetheringEntitlementResultListener listener) { + Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null."); + ResultReceiver wrappedListener = new ResultReceiver(null) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + Binder.withCleanCallingIdentity(() -> + executor.execute(() -> { + listener.onTetheringEntitlementResult(resultCode); + })); + } + }; + + mTetheringManager.requestLatestTetheringEntitlementResult(type, wrappedListener, + showEntitlementUi); + } + + /** + * Report network connectivity status. This is currently used only + * to alter status bar UI. + *

This method requires the caller to hold the permission + * {@link android.Manifest.permission#STATUS_BAR}. + * + * @param networkType The type of network you want to report on + * @param percentage The quality of the connection 0 is bad, 100 is good + * @deprecated Types are deprecated. Use {@link #reportNetworkConnectivity} instead. + * {@hide} + */ + public void reportInetCondition(int networkType, int percentage) { + printStackTrace(); + try { + mService.reportInetCondition(networkType, percentage); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Report a problem network to the framework. This provides a hint to the system + * that there might be connectivity problems on this network and may cause + * the framework to re-evaluate network connectivity and/or switch to another + * network. + * + * @param network The {@link Network} the application was attempting to use + * or {@code null} to indicate the current default network. + * @deprecated Use {@link #reportNetworkConnectivity} which allows reporting both + * working and non-working connectivity. + */ + @Deprecated + public void reportBadNetwork(@Nullable Network network) { + printStackTrace(); + try { + // One of these will be ignored because it matches system's current state. + // The other will trigger the necessary reevaluation. + mService.reportNetworkConnectivity(network, true); + mService.reportNetworkConnectivity(network, false); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Report to the framework whether a network has working connectivity. + * This provides a hint to the system that a particular network is providing + * working connectivity or not. In response the framework may re-evaluate + * the network's connectivity and might take further action thereafter. + * + * @param network The {@link Network} the application was attempting to use + * or {@code null} to indicate the current default network. + * @param hasConnectivity {@code true} if the application was able to successfully access the + * Internet using {@code network} or {@code false} if not. + */ + public void reportNetworkConnectivity(@Nullable Network network, boolean hasConnectivity) { + printStackTrace(); + try { + mService.reportNetworkConnectivity(network, hasConnectivity); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set a network-independent global http proxy. This is not normally what you want + * for typical HTTP proxies - they are general network dependent. However if you're + * doing something unusual like general internal filtering this may be useful. On + * a private network where the proxy is not accessible, you may break HTTP using this. + * + * @param p A {@link ProxyInfo} object defining the new global + * HTTP proxy. A {@code null} value will clear the global HTTP proxy. + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void setGlobalProxy(ProxyInfo p) { + try { + mService.setGlobalProxy(p); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve any network-independent global HTTP proxy. + * + * @return {@link ProxyInfo} for the current global HTTP proxy or {@code null} + * if no global HTTP proxy is set. + * @hide + */ + public ProxyInfo getGlobalProxy() { + try { + return mService.getGlobalProxy(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve the global HTTP proxy, or if no global HTTP proxy is set, a + * network-specific HTTP proxy. If {@code network} is null, the + * network-specific proxy returned is the proxy of the default active + * network. + * + * @return {@link ProxyInfo} for the current global HTTP proxy, or if no + * global HTTP proxy is set, {@code ProxyInfo} for {@code network}, + * or when {@code network} is {@code null}, + * the {@code ProxyInfo} for the default active network. Returns + * {@code null} when no proxy applies or the caller doesn't have + * permission to use {@code network}. + * @hide + */ + public ProxyInfo getProxyForNetwork(Network network) { + try { + return mService.getProxyForNetwork(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the current default HTTP proxy settings. If a global proxy is set it will be returned, + * otherwise if this process is bound to a {@link Network} using + * {@link #bindProcessToNetwork} then that {@code Network}'s proxy is returned, otherwise + * the default network's proxy is returned. + * + * @return the {@link ProxyInfo} for the current HTTP proxy, or {@code null} if no + * HTTP proxy is active. + */ + @Nullable + public ProxyInfo getDefaultProxy() { + return getProxyForNetwork(getBoundNetworkForProcess()); + } + + /** + * Returns true if the hardware supports the given network type + * else it returns false. This doesn't indicate we have coverage + * or are authorized onto a network, just whether or not the + * hardware supports it. For example a GSM phone without a SIM + * should still return {@code true} for mobile data, but a wifi only + * tablet would return {@code false}. + * + * @param networkType The network type we'd like to check + * @return {@code true} if supported, else {@code false} + * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) + public boolean isNetworkSupported(int networkType) { + try { + return mService.isNetworkSupported(networkType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns if the currently active data network is metered. A network is + * classified as metered when the user is sensitive to heavy data usage on + * that connection due to monetary costs, data limitations or + * battery/performance issues. You should check this before doing large + * data transfers, and warn the user or delay the operation until another + * network is available. + * + * @return {@code true} if large transfers should be avoided, otherwise + * {@code false}. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public boolean isActiveNetworkMetered() { + try { + return mService.isActiveNetworkMetered(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * If the LockdownVpn mechanism is enabled, updates the vpn + * with a reload of its profile. + * + * @return a boolean with {@code} indicating success + * + *

This method can only be called by the system UID + * {@hide} + */ + public boolean updateLockdownVpn() { + try { + return mService.updateLockdownVpn(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set sign in error notification to visible or invisible + * + * @hide + * @deprecated Doesn't properly deal with multiple connected networks of the same type. + */ + @Deprecated + public void setProvisioningNotificationVisible(boolean visible, int networkType, + String action) { + try { + mService.setProvisioningNotificationVisible(visible, networkType, action); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set the value for enabling/disabling airplane mode + * + * @param enable whether to enable airplane mode or not + * + * @hide + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_AIRPLANE_MODE, + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK}) + @SystemApi + public void setAirplaneMode(boolean enable) { + try { + mService.setAirplaneMode(enable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** {@hide} - returns the factory serial number */ + @UnsupportedAppUsage + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public int registerNetworkFactory(Messenger messenger, String name) { + try { + return mService.registerNetworkFactory(messenger, name); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** {@hide} */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public void unregisterNetworkFactory(Messenger messenger) { + try { + mService.unregisterNetworkFactory(messenger); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Registers the specified {@link NetworkProvider}. + * Each listener must only be registered once. The listener can be unregistered with + * {@link #unregisterNetworkProvider}. + * + * @param provider the provider to register + * @return the ID of the provider. This ID must be used by the provider when registering + * {@link android.net.NetworkAgent}s. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public int registerNetworkProvider(@NonNull NetworkProvider provider) { + if (provider.getProviderId() != NetworkProvider.ID_NONE) { + throw new IllegalStateException("NetworkProviders can only be registered once"); + } + + try { + int providerId = mService.registerNetworkProvider(provider.getMessenger(), + provider.getName()); + provider.setProviderId(providerId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return provider.getProviderId(); + } + + /** + * Unregisters the specified NetworkProvider. + * + * @param provider the provider to unregister + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public void unregisterNetworkProvider(@NonNull NetworkProvider provider) { + try { + mService.unregisterNetworkProvider(provider.getMessenger()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + provider.setProviderId(NetworkProvider.ID_NONE); + } + + + /** @hide exposed via the NetworkProvider class. */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) { + try { + mService.declareNetworkRequestUnfulfillable(request); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + // TODO : remove this method. It is a stopgap measure to help sheperding a number + // of dependent changes that would conflict throughout the automerger graph. Having this + // temporarily helps with the process of going through with all these dependent changes across + // the entire tree. + /** + * @hide + * Register a NetworkAgent with ConnectivityService. + * @return Network corresponding to NetworkAgent. + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, + NetworkCapabilities nc, int score, NetworkAgentConfig config) { + return registerNetworkAgent(na, ni, lp, nc, score, config, NetworkProvider.ID_NONE); + } + + /** + * @hide + * Register a NetworkAgent with ConnectivityService. + * @return Network corresponding to NetworkAgent. + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) + public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, + NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { + try { + return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Base class for {@code NetworkRequest} callbacks. Used for notifications about network + * changes. Should be extended by applications wanting notifications. + * + * A {@code NetworkCallback} is registered by calling + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, + * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)}, + * or {@link #registerDefaultNetworkCallback(NetworkCallback)}. A {@code NetworkCallback} is + * unregistered by calling {@link #unregisterNetworkCallback(NetworkCallback)}. + * A {@code NetworkCallback} should be registered at most once at any time. + * A {@code NetworkCallback} that has been unregistered can be registered again. + */ + public static class NetworkCallback { + /** + * Called when the framework connects to a new network to evaluate whether it satisfies this + * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable} + * callback. There is no guarantee that this new network will satisfy any requests, or that + * the network will stay connected for longer than the time necessary to evaluate it. + *

+ * Most applications should not act on this callback, and should instead use + * {@link #onAvailable}. This callback is intended for use by applications that can assist + * the framework in properly evaluating the network — for example, an application that + * can automatically log in to a captive portal without user intervention. + * + * @param network The {@link Network} of the network that is being evaluated. + * + * @hide + */ + public void onPreCheck(@NonNull Network network) {} + + /** + * Called when the framework connects and has declared a new network ready for use. + * This callback may be called more than once if the {@link Network} that is + * satisfying the request changes. + * + * @param network The {@link Network} of the satisfying network. + * @param networkCapabilities The {@link NetworkCapabilities} of the satisfying network. + * @param linkProperties The {@link LinkProperties} of the satisfying network. + * @param blocked Whether access to the {@link Network} is blocked due to system policy. + * @hide + */ + public void onAvailable(@NonNull Network network, + @NonNull NetworkCapabilities networkCapabilities, + @NonNull LinkProperties linkProperties, boolean blocked) { + // Internally only this method is called when a new network is available, and + // it calls the callback in the same way and order that older versions used + // to call so as not to change the behavior. + onAvailable(network); + if (!networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) { + onNetworkSuspended(network); + } + onCapabilitiesChanged(network, networkCapabilities); + onLinkPropertiesChanged(network, linkProperties); + onBlockedStatusChanged(network, blocked); + } + + /** + * Called when the framework connects and has declared a new network ready for use. + * + *

For callbacks registered with {@link #registerNetworkCallback}, multiple networks may + * be available at the same time, and onAvailable will be called for each of these as they + * appear. + * + *

For callbacks registered with {@link #requestNetwork} and + * {@link #registerDefaultNetworkCallback}, this means the network passed as an argument + * is the new best network for this request and is now tracked by this callback ; this + * callback will no longer receive method calls about other networks that may have been + * passed to this method previously. The previously-best network may have disconnected, or + * it may still be around and the newly-best network may simply be better. + * + *

Starting with {@link android.os.Build.VERSION_CODES#O}, this will always immediately + * be followed by a call to {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} + * then by a call to {@link #onLinkPropertiesChanged(Network, LinkProperties)}, and a call + * to {@link #onBlockedStatusChanged(Network, boolean)}. + * + *

Do NOT call {@link #getNetworkCapabilities(Network)} or + * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in + * this callback as this is prone to race conditions (there is no guarantee the objects + * returned by these methods will be current). Instead, wait for a call to + * {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} and + * {@link #onLinkPropertiesChanged(Network, LinkProperties)} whose arguments are guaranteed + * to be well-ordered with respect to other callbacks. + * + * @param network The {@link Network} of the satisfying network. + */ + public void onAvailable(@NonNull Network network) {} + + /** + * Called when the network is about to be lost, typically because there are no outstanding + * requests left for it. This may be paired with a {@link NetworkCallback#onAvailable} call + * with the new replacement network for graceful handover. This method is not guaranteed + * to be called before {@link NetworkCallback#onLost} is called, for example in case a + * network is suddenly disconnected. + * + *

Do NOT call {@link #getNetworkCapabilities(Network)} or + * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in + * this callback as this is prone to race conditions ; calling these methods while in a + * callback may return an outdated or even a null object. + * + * @param network The {@link Network} that is about to be lost. + * @param maxMsToLive The time in milliseconds the system intends to keep the network + * connected for graceful handover; note that the network may still + * suffer a hard loss at any time. + */ + public void onLosing(@NonNull Network network, int maxMsToLive) {} + + /** + * Called when a network disconnects or otherwise no longer satisfies this request or + * callback. + * + *

If the callback was registered with requestNetwork() or + * registerDefaultNetworkCallback(), it will only be invoked against the last network + * returned by onAvailable() when that network is lost and no other network satisfies + * the criteria of the request. + * + *

If the callback was registered with registerNetworkCallback() it will be called for + * each network which no longer satisfies the criteria of the callback. + * + *

Do NOT call {@link #getNetworkCapabilities(Network)} or + * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in + * this callback as this is prone to race conditions ; calling these methods while in a + * callback may return an outdated or even a null object. + * + * @param network The {@link Network} lost. + */ + public void onLost(@NonNull Network network) {} + + /** + * Called if no network is found within the timeout time specified in + * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the + * requested network request cannot be fulfilled (whether or not a timeout was + * specified). When this callback is invoked the associated + * {@link NetworkRequest} will have already been removed and released, as if + * {@link #unregisterNetworkCallback(NetworkCallback)} had been called. + */ + public void onUnavailable() {} + + /** + * Called when the network corresponding to this request changes capabilities but still + * satisfies the requested criteria. + * + *

Starting with {@link android.os.Build.VERSION_CODES#O} this method is guaranteed + * to be called immediately after {@link #onAvailable}. + * + *

Do NOT call {@link #getLinkProperties(Network)} or other synchronous + * ConnectivityManager methods in this callback as this is prone to race conditions : + * calling these methods while in a callback may return an outdated or even a null object. + * + * @param network The {@link Network} whose capabilities have changed. + * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this + * network. + */ + public void onCapabilitiesChanged(@NonNull Network network, + @NonNull NetworkCapabilities networkCapabilities) {} + + /** + * Called when the network corresponding to this request changes {@link LinkProperties}. + * + *

Starting with {@link android.os.Build.VERSION_CODES#O} this method is guaranteed + * to be called immediately after {@link #onAvailable}. + * + *

Do NOT call {@link #getNetworkCapabilities(Network)} or other synchronous + * ConnectivityManager methods in this callback as this is prone to race conditions : + * calling these methods while in a callback may return an outdated or even a null object. + * + * @param network The {@link Network} whose link properties have changed. + * @param linkProperties The new {@link LinkProperties} for this network. + */ + public void onLinkPropertiesChanged(@NonNull Network network, + @NonNull LinkProperties linkProperties) {} + + /** + * Called when the network the framework connected to for this request suspends data + * transmission temporarily. + * + *

This generally means that while the TCP connections are still live temporarily + * network data fails to transfer. To give a specific example, this is used on cellular + * networks to mask temporary outages when driving through a tunnel, etc. In general this + * means read operations on sockets on this network will block once the buffers are + * drained, and write operations will block once the buffers are full. + * + *

Do NOT call {@link #getNetworkCapabilities(Network)} or + * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in + * this callback as this is prone to race conditions (there is no guarantee the objects + * returned by these methods will be current). + * + * @hide + */ + public void onNetworkSuspended(@NonNull Network network) {} + + /** + * Called when the network the framework connected to for this request + * returns from a {@link NetworkInfo.State#SUSPENDED} state. This should always be + * preceded by a matching {@link NetworkCallback#onNetworkSuspended} call. + + *

Do NOT call {@link #getNetworkCapabilities(Network)} or + * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in + * this callback as this is prone to race conditions : calling these methods while in a + * callback may return an outdated or even a null object. + * + * @hide + */ + public void onNetworkResumed(@NonNull Network network) {} + + /** + * Called when access to the specified network is blocked or unblocked. + * + *

Do NOT call {@link #getNetworkCapabilities(Network)} or + * {@link #getLinkProperties(Network)} or other synchronous ConnectivityManager methods in + * this callback as this is prone to race conditions : calling these methods while in a + * callback may return an outdated or even a null object. + * + * @param network The {@link Network} whose blocked status has changed. + * @param blocked The blocked status of this {@link Network}. + */ + public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {} + + private NetworkRequest networkRequest; + } + + /** + * Constant error codes used by ConnectivityService to communicate about failures and errors + * across a Binder boundary. + * @hide + */ + public interface Errors { + int TOO_MANY_REQUESTS = 1; + } + + /** @hide */ + public static class TooManyRequestsException extends RuntimeException {} + + private static RuntimeException convertServiceException(ServiceSpecificException e) { + switch (e.errorCode) { + case Errors.TOO_MANY_REQUESTS: + return new TooManyRequestsException(); + default: + Log.w(TAG, "Unknown service error code " + e.errorCode); + return new RuntimeException(e); + } + } + + private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; + /** @hide */ + public static final int CALLBACK_PRECHECK = BASE + 1; + /** @hide */ + public static final int CALLBACK_AVAILABLE = BASE + 2; + /** @hide arg1 = TTL */ + public static final int CALLBACK_LOSING = BASE + 3; + /** @hide */ + public static final int CALLBACK_LOST = BASE + 4; + /** @hide */ + public static final int CALLBACK_UNAVAIL = BASE + 5; + /** @hide */ + public static final int CALLBACK_CAP_CHANGED = BASE + 6; + /** @hide */ + public static final int CALLBACK_IP_CHANGED = BASE + 7; + /** @hide obj = NetworkCapabilities, arg1 = seq number */ + private static final int EXPIRE_LEGACY_REQUEST = BASE + 8; + /** @hide */ + public static final int CALLBACK_SUSPENDED = BASE + 9; + /** @hide */ + public static final int CALLBACK_RESUMED = BASE + 10; + /** @hide */ + public static final int CALLBACK_BLK_CHANGED = BASE + 11; + + /** @hide */ + public static String getCallbackName(int whichCallback) { + switch (whichCallback) { + case CALLBACK_PRECHECK: return "CALLBACK_PRECHECK"; + case CALLBACK_AVAILABLE: return "CALLBACK_AVAILABLE"; + case CALLBACK_LOSING: return "CALLBACK_LOSING"; + case CALLBACK_LOST: return "CALLBACK_LOST"; + case CALLBACK_UNAVAIL: return "CALLBACK_UNAVAIL"; + case CALLBACK_CAP_CHANGED: return "CALLBACK_CAP_CHANGED"; + case CALLBACK_IP_CHANGED: return "CALLBACK_IP_CHANGED"; + case EXPIRE_LEGACY_REQUEST: return "EXPIRE_LEGACY_REQUEST"; + case CALLBACK_SUSPENDED: return "CALLBACK_SUSPENDED"; + case CALLBACK_RESUMED: return "CALLBACK_RESUMED"; + case CALLBACK_BLK_CHANGED: return "CALLBACK_BLK_CHANGED"; + default: + return Integer.toString(whichCallback); + } + } + + private class CallbackHandler extends Handler { + private static final String TAG = "ConnectivityManager.CallbackHandler"; + private static final boolean DBG = false; + + CallbackHandler(Looper looper) { + super(looper); + } + + CallbackHandler(Handler handler) { + this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper()); + } + + @Override + public void handleMessage(Message message) { + if (message.what == EXPIRE_LEGACY_REQUEST) { + expireRequest((NetworkCapabilities) message.obj, message.arg1); + return; + } + + final NetworkRequest request = getObject(message, NetworkRequest.class); + final Network network = getObject(message, Network.class); + final NetworkCallback callback; + synchronized (sCallbacks) { + callback = sCallbacks.get(request); + if (callback == null) { + Log.w(TAG, + "callback not found for " + getCallbackName(message.what) + " message"); + return; + } + if (message.what == CALLBACK_UNAVAIL) { + sCallbacks.remove(request); + callback.networkRequest = ALREADY_UNREGISTERED; + } + } + if (DBG) { + Log.d(TAG, getCallbackName(message.what) + " for network " + network); + } + + switch (message.what) { + case CALLBACK_PRECHECK: { + callback.onPreCheck(network); + break; + } + case CALLBACK_AVAILABLE: { + NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); + LinkProperties lp = getObject(message, LinkProperties.class); + callback.onAvailable(network, cap, lp, message.arg1 != 0); + break; + } + case CALLBACK_LOSING: { + callback.onLosing(network, message.arg1); + break; + } + case CALLBACK_LOST: { + callback.onLost(network); + break; + } + case CALLBACK_UNAVAIL: { + callback.onUnavailable(); + break; + } + case CALLBACK_CAP_CHANGED: { + NetworkCapabilities cap = getObject(message, NetworkCapabilities.class); + callback.onCapabilitiesChanged(network, cap); + break; + } + case CALLBACK_IP_CHANGED: { + LinkProperties lp = getObject(message, LinkProperties.class); + callback.onLinkPropertiesChanged(network, lp); + break; + } + case CALLBACK_SUSPENDED: { + callback.onNetworkSuspended(network); + break; + } + case CALLBACK_RESUMED: { + callback.onNetworkResumed(network); + break; + } + case CALLBACK_BLK_CHANGED: { + boolean blocked = message.arg1 != 0; + callback.onBlockedStatusChanged(network, blocked); + } + } + } + + private T getObject(Message msg, Class c) { + return (T) msg.getData().getParcelable(c.getSimpleName()); + } + } + + private CallbackHandler getDefaultHandler() { + synchronized (sCallbacks) { + if (sCallbackHandler == null) { + sCallbackHandler = new CallbackHandler(ConnectivityThread.getInstanceLooper()); + } + return sCallbackHandler; + } + } + + private static final HashMap sCallbacks = new HashMap<>(); + private static CallbackHandler sCallbackHandler; + + private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback, + int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { + printStackTrace(); + checkCallbackNotNull(callback); + Preconditions.checkArgument( + reqType == TRACK_DEFAULT || need != null, "null NetworkCapabilities"); + final NetworkRequest request; + final String callingPackageName = mContext.getOpPackageName(); + try { + synchronized(sCallbacks) { + if (callback.networkRequest != null + && callback.networkRequest != ALREADY_UNREGISTERED) { + // TODO: throw exception instead and enforce 1:1 mapping of callbacks + // and requests (http://b/20701525). + Log.e(TAG, "NetworkCallback was already registered"); + } + Messenger messenger = new Messenger(handler); + Binder binder = new Binder(); + if (reqType == LISTEN) { + request = mService.listenForNetwork( + need, messenger, binder, callingPackageName); + } else { + request = mService.requestNetwork( + need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType, + callingPackageName, getAttributionTag()); + } + if (request != null) { + sCallbacks.put(request, callback); + } + callback.networkRequest = request; + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw convertServiceException(e); + } + return request; + } + + /** + * Helper function to request a network with a particular legacy type. + * + * This API is only for use in internal system code that requests networks with legacy type and + * relies on CONNECTIVITY_ACTION broadcasts instead of NetworkCallbacks. New caller should use + * {@link #requestNetwork(NetworkRequest, NetworkCallback, Handler)} instead. + * + * @param request {@link NetworkRequest} describing this request. + * @param timeoutMs The time in milliseconds to attempt looking for a suitable network + * before {@link NetworkCallback#onUnavailable()} is called. The timeout must + * be a positive value (i.e. >0). + * @param legacyType to specify the network type(#TYPE_*). + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * + * @hide + */ + @SystemApi + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + public void requestNetwork(@NonNull NetworkRequest request, + int timeoutMs, int legacyType, @NonNull Handler handler, + @NonNull NetworkCallback networkCallback) { + if (legacyType == TYPE_NONE) { + throw new IllegalArgumentException("TYPE_NONE is meaningless legacy type"); + } + CallbackHandler cbHandler = new CallbackHandler(handler); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler); + } + + /** + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * + *

This method will attempt to find the best network that matches the passed + * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the + * criteria. The platform will evaluate which network is the best at its own discretion. + * Throughput, latency, cost per byte, policy, user preference and other considerations + * may be factored in the decision of what is considered the best network. + * + *

As long as this request is outstanding, the platform will try to maintain the best network + * matching this request, while always attempting to match the request to a better network if + * possible. If a better match is found, the platform will switch this request to the now-best + * network and inform the app of the newly best network by invoking + * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform + * will not try to maintain any other network than the best one currently matching the request: + * a network not matching any network request may be disconnected at any time. + * + *

For example, an application could use this method to obtain a connected cellular network + * even if the device currently has a data connection over Ethernet. This may cause the cellular + * radio to consume additional power. Or, an application could inform the system that it wants + * a network supporting sending MMSes and have the system let it know about the currently best + * MMS-supporting network through the provided {@link NetworkCallback}. + * + *

The status of the request can be followed by listening to the various callbacks described + * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be + * used to direct traffic to the network (although accessing some networks may be subject to + * holding specific permissions). Callers will learn about the specific characteristics of the + * network through + * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and + * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the + * provided {@link NetworkCallback} will only be invoked due to changes in the best network + * matching the request at any given time; therefore when a better network matching the request + * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called + * with the new network after which no further updates are given about the previously-best + * network, unless it becomes the best again at some later time. All callbacks are invoked + * in order on the same thread, which by default is a thread created by the framework running + * in the app. + * {@see #requestNetwork(NetworkRequest, NetworkCallback, Handler)} to change where the + * callbacks are invoked. + * + *

This{@link NetworkRequest} will live until released via + * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at + * which point the system may let go of the network at any time. + * + *

A version of this method which takes a timeout is + * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)}, that an app can use to only + * wait for a limited amount of time for the network to become unavailable. + * + *

It is presently unsupported to request a network with mutable + * {@link NetworkCapabilities} such as + * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or + * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL} + * as these {@code NetworkCapabilities} represent states that a particular + * network may never attain, and whether a network will attain these states + * is unknown prior to bringing up the network so the framework does not + * know how to go about satisfying a request with these capabilities. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #registerNetworkCallback} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * The callback is invoked on the default internal Handler. + * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. + * @throws SecurityException if missing the appropriate permissions. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + public void requestNetwork(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback) { + requestNetwork(request, networkCallback, getDefaultHandler()); + } + + /** + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * + * This method behaves identically to {@link #requestNetwork(NetworkRequest, NetworkCallback)} + * but runs all the callbacks on the passed Handler. + * + *

This method has the same permission requirements as + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, + * and throws the same exceptions in the same conditions. + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + */ + public void requestNetwork(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { + CallbackHandler cbHandler = new CallbackHandler(handler); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler); + } + + /** + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * by a timeout. + * + * This function behaves identically to the non-timed-out version + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, but if a suitable network + * is not found within the given time (in milliseconds) the + * {@link NetworkCallback#onUnavailable()} callback is called. The request can still be + * released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)} but does + * not have to be released if timed-out (it is automatically released). Unregistering a + * request that timed out is not an error. + * + *

Do not use this method to poll for the existence of specific networks (e.g. with a small + * timeout) - {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} is provided + * for that purpose. Calling this method will attempt to bring up the requested network. + * + *

This method has the same permission requirements as + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, + * and throws the same exceptions in the same conditions. + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * @param timeoutMs The time in milliseconds to attempt looking for a suitable network + * before {@link NetworkCallback#onUnavailable()} is called. The timeout must + * be a positive value (i.e. >0). + */ + public void requestNetwork(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback, int timeoutMs) { + checkTimeout(timeoutMs); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, TYPE_NONE, + getDefaultHandler()); + } + + /** + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * by a timeout. + * + * This method behaves identically to + * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} but runs all the callbacks + * on the passed Handler. + * + *

This method has the same permission requirements as + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, + * and throws the same exceptions in the same conditions. + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @param timeoutMs The time in milliseconds to attempt looking for a suitable network + * before {@link NetworkCallback#onUnavailable} is called. + */ + public void requestNetwork(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) { + checkTimeout(timeoutMs); + CallbackHandler cbHandler = new CallbackHandler(handler); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, TYPE_NONE, cbHandler); + } + + /** + * The lookup key for a {@link Network} object included with the intent after + * successfully finding a network for the applications request. Retrieve it with + * {@link android.content.Intent#getParcelableExtra(String)}. + *

+ * Note that if you intend to invoke {@link Network#openConnection(java.net.URL)} + * then you must get a ConnectivityManager instance before doing so. + */ + public static final String EXTRA_NETWORK = "android.net.extra.NETWORK"; + + /** + * The lookup key for a {@link NetworkRequest} object included with the intent after + * successfully finding a network for the applications request. Retrieve it with + * {@link android.content.Intent#getParcelableExtra(String)}. + */ + public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST"; + + + /** + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * + * This function behaves identically to the version that takes a NetworkCallback, but instead + * of {@link NetworkCallback} a {@link PendingIntent} is used. This means + * the request may outlive the calling application and get called back when a suitable + * network is found. + *

+ * The operation is an Intent broadcast that goes to a broadcast receiver that + * you registered with {@link Context#registerReceiver} or through the + * <receiver> tag in an AndroidManifest.xml file + *

+ * The operation Intent is delivered with two extras, a {@link Network} typed + * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest} + * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing + * the original requests parameters. It is important to create a new, + * {@link NetworkCallback} based request before completing the processing of the + * Intent to reserve the network or it will be released shortly after the Intent + * is processed. + *

+ * If there is already a request for this Intent registered (with the equality of + * two Intents defined by {@link Intent#filterEquals}), then it will be removed and + * replaced by this one, effectively releasing the previous {@link NetworkRequest}. + *

+ * The request may be released normally by calling + * {@link #releaseNetworkRequest(android.app.PendingIntent)}. + *

It is presently unsupported to request a network with either + * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or + * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL} + * as these {@code NetworkCapabilities} represent states that a particular + * network may never attain, and whether a network will attain these states + * is unknown prior to bringing up the network so the framework does not + * know how to go about satisfying a request with these capabilities. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #registerNetworkCallback} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with {@link #unregisterNetworkCallback(PendingIntent)} + * or {@link #releaseNetworkRequest(PendingIntent)}. + * + *

This method requires the caller to hold either the + * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission + * or the ability to modify system settings as determined by + * {@link android.provider.Settings.System#canWrite}.

+ * + * @param request {@link NetworkRequest} describing this request. + * @param operation Action to perform when the network is available (corresponds + * to the {@link NetworkCallback#onAvailable} call. Typically + * comes from {@link PendingIntent#getBroadcast}. Cannot be null. + * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. + * @throws SecurityException if missing the appropriate permissions. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + public void requestNetwork(@NonNull NetworkRequest request, + @NonNull PendingIntent operation) { + printStackTrace(); + checkPendingIntentNotNull(operation); + try { + mService.pendingRequestForNetwork( + request.networkCapabilities, operation, mContext.getOpPackageName(), + getAttributionTag()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw convertServiceException(e); + } + } + + /** + * Removes a request made via {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)} + *

+ * This method has the same behavior as + * {@link #unregisterNetworkCallback(android.app.PendingIntent)} with respect to + * releasing network resources and disconnecting. + * + * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the + * PendingIntent passed to + * {@link #requestNetwork(NetworkRequest, android.app.PendingIntent)} with the + * corresponding NetworkRequest you'd like to remove. Cannot be null. + */ + public void releaseNetworkRequest(@NonNull PendingIntent operation) { + printStackTrace(); + checkPendingIntentNotNull(operation); + try { + mService.releasePendingNetworkRequest(operation); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private static void checkPendingIntentNotNull(PendingIntent intent) { + Preconditions.checkNotNull(intent, "PendingIntent cannot be null."); + } + + private static void checkCallbackNotNull(NetworkCallback callback) { + Preconditions.checkNotNull(callback, "null NetworkCallback"); + } + + private static void checkTimeout(int timeoutMs) { + Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive."); + } + + /** + * Registers to receive notifications about all networks which satisfy the given + * {@link NetworkRequest}. The callbacks will continue to be called until + * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is + * called. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} that the system will call as suitable + * networks change state. + * The callback is invoked on the default internal Handler. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void registerNetworkCallback(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback) { + registerNetworkCallback(request, networkCallback, getDefaultHandler()); + } + + /** + * Registers to receive notifications about all networks which satisfy the given + * {@link NetworkRequest}. The callbacks will continue to be called until + * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is + * called. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} that the system will call as suitable + * networks change state. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void registerNetworkCallback(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { + CallbackHandler cbHandler = new CallbackHandler(handler); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, 0, LISTEN, TYPE_NONE, cbHandler); + } + + /** + * Registers a PendingIntent to be sent when a network is available which satisfies the given + * {@link NetworkRequest}. + * + * This function behaves identically to the version that takes a NetworkCallback, but instead + * of {@link NetworkCallback} a {@link PendingIntent} is used. This means + * the request may outlive the calling application and get called back when a suitable + * network is found. + *

+ * The operation is an Intent broadcast that goes to a broadcast receiver that + * you registered with {@link Context#registerReceiver} or through the + * <receiver> tag in an AndroidManifest.xml file + *

+ * The operation Intent is delivered with two extras, a {@link Network} typed + * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest} + * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing + * the original requests parameters. + *

+ * If there is already a request for this Intent registered (with the equality of + * two Intents defined by {@link Intent#filterEquals}), then it will be removed and + * replaced by this one, effectively releasing the previous {@link NetworkRequest}. + *

+ * The request may be released normally by calling + * {@link #unregisterNetworkCallback(android.app.PendingIntent)}. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with {@link #unregisterNetworkCallback(PendingIntent)} + * or {@link #releaseNetworkRequest(PendingIntent)}. + * + * @param request {@link NetworkRequest} describing this request. + * @param operation Action to perform when the network is available (corresponds + * to the {@link NetworkCallback#onAvailable} call. Typically + * comes from {@link PendingIntent#getBroadcast}. Cannot be null. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void registerNetworkCallback(@NonNull NetworkRequest request, + @NonNull PendingIntent operation) { + printStackTrace(); + checkPendingIntentNotNull(operation); + try { + mService.pendingListenForNetwork( + request.networkCapabilities, operation, mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + throw convertServiceException(e); + } + } + + /** + * Registers to receive notifications about changes in the system default network. The callbacks + * will continue to be called until either the application exits or + * {@link #unregisterNetworkCallback(NetworkCallback)} is called. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param networkCallback The {@link NetworkCallback} that the system will call as the + * system default network changes. + * The callback is invoked on the default internal Handler. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback) { + registerDefaultNetworkCallback(networkCallback, getDefaultHandler()); + } + + /** + * Registers to receive notifications about changes in the system default network. The callbacks + * will continue to be called until either the application exits or + * {@link #unregisterNetworkCallback(NetworkCallback)} is called. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param networkCallback The {@link NetworkCallback} that the system will call as the + * system default network changes. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, + @NonNull Handler handler) { + // This works because if the NetworkCapabilities are null, + // ConnectivityService takes them from the default request. + // + // Since the capabilities are exactly the same as the default request's + // capabilities, this request is guaranteed, at all times, to be + // satisfied by the same network, if any, that satisfies the default + // request, i.e., the system default network. + CallbackHandler cbHandler = new CallbackHandler(handler); + sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, + TRACK_DEFAULT, TYPE_NONE, cbHandler); + } + + /** + * Requests bandwidth update for a given {@link Network} and returns whether the update request + * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying + * network connection for updated bandwidth information. The caller will be notified via + * {@link ConnectivityManager.NetworkCallback} if there is an update. Notice that this + * method assumes that the caller has previously called + * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} to listen for network + * changes. + * + * @param network {@link Network} specifying which network you're interested. + * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. + */ + public boolean requestBandwidthUpdate(@NonNull Network network) { + try { + return mService.requestBandwidthUpdate(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregisters a {@code NetworkCallback} and possibly releases networks originating from + * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and + * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} calls. + * If the given {@code NetworkCallback} had previously been used with + * {@code #requestNetwork}, any networks that had been connected to only to satisfy that request + * will be disconnected. + * + * Notifications that would have triggered that {@code NetworkCallback} will immediately stop + * triggering it as soon as this call returns. + * + * @param networkCallback The {@link NetworkCallback} used when making the request. + */ + public void unregisterNetworkCallback(@NonNull NetworkCallback networkCallback) { + printStackTrace(); + checkCallbackNotNull(networkCallback); + final List reqs = new ArrayList<>(); + // Find all requests associated to this callback and stop callback triggers immediately. + // Callback is reusable immediately. http://b/20701525, http://b/35921499. + synchronized (sCallbacks) { + Preconditions.checkArgument(networkCallback.networkRequest != null, + "NetworkCallback was not registered"); + if (networkCallback.networkRequest == ALREADY_UNREGISTERED) { + Log.d(TAG, "NetworkCallback was already unregistered"); + return; + } + for (Map.Entry e : sCallbacks.entrySet()) { + if (e.getValue() == networkCallback) { + reqs.add(e.getKey()); + } + } + // TODO: throw exception if callback was registered more than once (http://b/20701525). + for (NetworkRequest r : reqs) { + try { + mService.releaseNetworkRequest(r); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + // Only remove mapping if rpc was successful. + sCallbacks.remove(r); + } + networkCallback.networkRequest = ALREADY_UNREGISTERED; + } + } + + /** + * Unregisters a callback previously registered via + * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. + * + * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the + * PendingIntent passed to + * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. + * Cannot be null. + */ + public void unregisterNetworkCallback(@NonNull PendingIntent operation) { + releaseNetworkRequest(operation); + } + + /** + * Informs the system whether it should switch to {@code network} regardless of whether it is + * validated or not. If {@code accept} is true, and the network was explicitly selected by the + * user (e.g., by selecting a Wi-Fi network in the Settings app), then the network will become + * the system default network regardless of any other network that's currently connected. If + * {@code always} is true, then the choice is remembered, so that the next time the user + * connects to this network, the system will switch to it. + * + * @param network The network to accept. + * @param accept Whether to accept the network even if unvalidated. + * @param always Whether to remember this choice in the future. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { + try { + mService.setAcceptUnvalidated(network, accept, always); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Informs the system whether it should consider the network as validated even if it only has + * partial connectivity. If {@code accept} is true, then the network will be considered as + * validated even if connectivity is only partial. If {@code always} is true, then the choice + * is remembered, so that the next time the user connects to this network, the system will + * switch to it. + * + * @param network The network to accept. + * @param accept Whether to consider the network as validated even if it has partial + * connectivity. + * @param always Whether to remember this choice in the future. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) { + try { + mService.setAcceptPartialConnectivity(network, accept, always); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is + * only meaningful if the system is configured not to penalize such networks, e.g., if the + * {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code + * NETWORK_AVOID_BAD_WIFI setting is unset}. + * + * @param network The network to accept. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void setAvoidUnvalidated(Network network) { + try { + mService.setAvoidUnvalidated(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Requests that the system open the captive portal app on the specified network. + * + * @param network The network to log into. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void startCaptivePortalApp(Network network) { + try { + mService.startCaptivePortalApp(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Requests that the system open the captive portal app with the specified extras. + * + *

This endpoint is exclusively for use by the NetworkStack and is protected by the + * corresponding permission. + * @param network Network on which the captive portal was detected. + * @param appExtras Extras to include in the app start intent. + * @hide + */ + @SystemApi + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + public void startCaptivePortalApp(@NonNull Network network, @NonNull Bundle appExtras) { + try { + mService.startCaptivePortalAppInternal(network, appExtras); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Determine whether the device is configured to avoid bad wifi. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public boolean shouldAvoidBadWifi() { + try { + return mService.shouldAvoidBadWifi(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * It is acceptable to briefly use multipath data to provide seamless connectivity for + * time-sensitive user-facing operations when the system default network is temporarily + * unresponsive. The amount of data should be limited (less than one megabyte for every call to + * this method), and the operation should be infrequent to ensure that data usage is limited. + * + * An example of such an operation might be a time-sensitive foreground activity, such as a + * voice command, that the user is performing while walking out of range of a Wi-Fi network. + */ + public static final int MULTIPATH_PREFERENCE_HANDOVER = 1 << 0; + + /** + * It is acceptable to use small amounts of multipath data on an ongoing basis to provide + * a backup channel for traffic that is primarily going over another network. + * + * An example might be maintaining backup connections to peers or servers for the purpose of + * fast fallback if the default network is temporarily unresponsive or disconnects. The traffic + * on backup paths should be negligible compared to the traffic on the main path. + */ + public static final int MULTIPATH_PREFERENCE_RELIABILITY = 1 << 1; + + /** + * It is acceptable to use metered data to improve network latency and performance. + */ + public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 1 << 2; + + /** + * Return value to use for unmetered networks. On such networks we currently set all the flags + * to true. + * @hide + */ + public static final int MULTIPATH_PREFERENCE_UNMETERED = + MULTIPATH_PREFERENCE_HANDOVER | + MULTIPATH_PREFERENCE_RELIABILITY | + MULTIPATH_PREFERENCE_PERFORMANCE; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = { + MULTIPATH_PREFERENCE_HANDOVER, + MULTIPATH_PREFERENCE_RELIABILITY, + MULTIPATH_PREFERENCE_PERFORMANCE, + }) + public @interface MultipathPreference { + } + + /** + * Provides a hint to the calling application on whether it is desirable to use the + * multinetwork APIs (e.g., {@link Network#openConnection}, {@link Network#bindSocket}, etc.) + * for multipath data transfer on this network when it is not the system default network. + * Applications desiring to use multipath network protocols should call this method before + * each such operation. + * + * @param network The network on which the application desires to use multipath data. + * If {@code null}, this method will return the a preference that will generally + * apply to metered networks. + * @return a bitwise OR of zero or more of the {@code MULTIPATH_PREFERENCE_*} constants. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public @MultipathPreference int getMultipathPreference(@Nullable Network network) { + try { + return mService.getMultipathPreference(network); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Resets all connectivity manager settings back to factory defaults. + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void factoryReset() { + try { + mService.factoryReset(); + mTetheringManager.stopAllTethering(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Binds the current process to {@code network}. All Sockets created in the future + * (and not explicitly bound via a bound SocketFactory from + * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to + * {@code network}. All host name resolutions will be limited to {@code network} as well. + * Note that if {@code network} ever disconnects, all Sockets created in this way will cease to + * work and all host name resolutions will fail. This is by design so an application doesn't + * accidentally use Sockets it thinks are still bound to a particular {@link Network}. + * To clear binding pass {@code null} for {@code network}. Using individually bound + * Sockets created by Network.getSocketFactory().createSocket() and + * performing network-specific host name resolutions via + * {@link Network#getAllByName Network.getAllByName} is preferred to calling + * {@code bindProcessToNetwork}. + * + * @param network The {@link Network} to bind the current process to, or {@code null} to clear + * the current binding. + * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. + */ + public boolean bindProcessToNetwork(@Nullable Network network) { + // Forcing callers to call through non-static function ensures ConnectivityManager + // instantiated. + return setProcessDefaultNetwork(network); + } + + /** + * Binds the current process to {@code network}. All Sockets created in the future + * (and not explicitly bound via a bound SocketFactory from + * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to + * {@code network}. All host name resolutions will be limited to {@code network} as well. + * Note that if {@code network} ever disconnects, all Sockets created in this way will cease to + * work and all host name resolutions will fail. This is by design so an application doesn't + * accidentally use Sockets it thinks are still bound to a particular {@link Network}. + * To clear binding pass {@code null} for {@code network}. Using individually bound + * Sockets created by Network.getSocketFactory().createSocket() and + * performing network-specific host name resolutions via + * {@link Network#getAllByName Network.getAllByName} is preferred to calling + * {@code setProcessDefaultNetwork}. + * + * @param network The {@link Network} to bind the current process to, or {@code null} to clear + * the current binding. + * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. + * @deprecated This function can throw {@link IllegalStateException}. Use + * {@link #bindProcessToNetwork} instead. {@code bindProcessToNetwork} + * is a direct replacement. + */ + @Deprecated + public static boolean setProcessDefaultNetwork(@Nullable Network network) { + int netId = (network == null) ? NETID_UNSET : network.netId; + boolean isSameNetId = (netId == NetworkUtils.getBoundNetworkForProcess()); + + if (netId != NETID_UNSET) { + netId = network.getNetIdForResolv(); + } + + if (!NetworkUtils.bindProcessToNetwork(netId)) { + return false; + } + + if (!isSameNetId) { + // Set HTTP proxy system properties to match network. + // TODO: Deprecate this static method and replace it with a non-static version. + try { + Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy()); + } catch (SecurityException e) { + // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy. + Log.e(TAG, "Can't set proxy properties", e); + } + // Must flush DNS cache as new network may have different DNS resolutions. + InetAddress.clearDnsCache(); + // Must flush socket pool as idle sockets will be bound to previous network and may + // cause subsequent fetches to be performed on old network. + NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); + } + + return true; + } + + /** + * Returns the {@link Network} currently bound to this process via + * {@link #bindProcessToNetwork}, or {@code null} if no {@link Network} is explicitly bound. + * + * @return {@code Network} to which this process is bound, or {@code null}. + */ + @Nullable + public Network getBoundNetworkForProcess() { + // Forcing callers to call thru non-static function ensures ConnectivityManager + // instantiated. + return getProcessDefaultNetwork(); + } + + /** + * Returns the {@link Network} currently bound to this process via + * {@link #bindProcessToNetwork}, or {@code null} if no {@link Network} is explicitly bound. + * + * @return {@code Network} to which this process is bound, or {@code null}. + * @deprecated Using this function can lead to other functions throwing + * {@link IllegalStateException}. Use {@link #getBoundNetworkForProcess} instead. + * {@code getBoundNetworkForProcess} is a direct replacement. + */ + @Deprecated + @Nullable + public static Network getProcessDefaultNetwork() { + int netId = NetworkUtils.getBoundNetworkForProcess(); + if (netId == NETID_UNSET) return null; + return new Network(netId); + } + + private void unsupportedStartingFrom(int version) { + if (Process.myUid() == Process.SYSTEM_UID) { + // The getApplicationInfo() call we make below is not supported in system context. Let + // the call through here, and rely on the fact that ConnectivityService will refuse to + // allow the system to use these APIs anyway. + return; + } + + if (mContext.getApplicationInfo().targetSdkVersion >= version) { + throw new UnsupportedOperationException( + "This method is not supported in target SDK version " + version + " and above"); + } + } + + // Checks whether the calling app can use the legacy routing API (startUsingNetworkFeature, + // stopUsingNetworkFeature, requestRouteToHost), and if not throw UnsupportedOperationException. + // TODO: convert the existing system users (Tethering, GnssLocationProvider) to the new APIs and + // remove these exemptions. Note that this check is not secure, and apps can still access these + // functions by accessing ConnectivityService directly. However, it should be clear that doing + // so is unsupported and may break in the future. http://b/22728205 + private void checkLegacyRoutingApiAccess() { + unsupportedStartingFrom(VERSION_CODES.M); + } + + /** + * Binds host resolutions performed by this process to {@code network}. + * {@link #bindProcessToNetwork} takes precedence over this setting. + * + * @param network The {@link Network} to bind host resolutions from the current process to, or + * {@code null} to clear the current binding. + * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid. + * @hide + * @deprecated This is strictly for legacy usage to support {@link #startUsingNetworkFeature}. + */ + @Deprecated + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static boolean setProcessDefaultNetworkForHostResolution(Network network) { + return NetworkUtils.bindProcessToNetworkForHostResolution( + (network == null) ? NETID_UNSET : network.getNetIdForResolv()); + } + + /** + * Device is not restricting metered network activity while application is running on + * background. + */ + public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; + + /** + * Device is restricting metered network activity while application is running on background, + * but application is allowed to bypass it. + *

+ * In this state, application should take action to mitigate metered network access. + * For example, a music streaming application should switch to a low-bandwidth bitrate. + */ + public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; + + /** + * Device is restricting metered network activity while application is running on background. + *

+ * In this state, application should not try to use the network while running on background, + * because it would be denied. + */ + public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; + + /** + * A change in the background metered network activity restriction has occurred. + *

+ * Applications should call {@link #getRestrictBackgroundStatus()} to check if the restriction + * applies to them. + *

+ * This is only sent to registered receivers, not manifest receivers. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = + "android.net.conn.RESTRICT_BACKGROUND_CHANGED"; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = false, value = { + RESTRICT_BACKGROUND_STATUS_DISABLED, + RESTRICT_BACKGROUND_STATUS_WHITELISTED, + RESTRICT_BACKGROUND_STATUS_ENABLED, + }) + public @interface RestrictBackgroundStatus { + } + + private INetworkPolicyManager getNetworkPolicyManager() { + synchronized (this) { + if (mNPManager != null) { + return mNPManager; + } + mNPManager = INetworkPolicyManager.Stub.asInterface(ServiceManager + .getService(Context.NETWORK_POLICY_SERVICE)); + return mNPManager; + } + } + + /** + * Determines if the calling application is subject to metered network restrictions while + * running on background. + * + * @return {@link #RESTRICT_BACKGROUND_STATUS_DISABLED}, + * {@link #RESTRICT_BACKGROUND_STATUS_ENABLED}, + * or {@link #RESTRICT_BACKGROUND_STATUS_WHITELISTED} + */ + public @RestrictBackgroundStatus int getRestrictBackgroundStatus() { + try { + return getNetworkPolicyManager().getRestrictBackgroundByCaller(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * The network watchlist is a list of domains and IP addresses that are associated with + * potentially harmful apps. This method returns the SHA-256 of the watchlist config file + * currently used by the system for validation purposes. + * + * @return Hash of network watchlist config file. Null if config does not exist. + */ + @Nullable + public byte[] getNetworkWatchlistConfigHash() { + try { + return mService.getNetworkWatchlistConfigHash(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to get watchlist config hash"); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the {@code uid} of the owner of a network connection. + * + * @param protocol The protocol of the connection. Only {@code IPPROTO_TCP} and {@code + * IPPROTO_UDP} currently supported. + * @param local The local {@link InetSocketAddress} of a connection. + * @param remote The remote {@link InetSocketAddress} of a connection. + * @return {@code uid} if the connection is found and the app has permission to observe it + * (e.g., if it is associated with the calling VPN app's VpnService tunnel) or {@link + * android.os.Process#INVALID_UID} if the connection is not found. + * @throws {@link SecurityException} if the caller is not the active VpnService for the current + * user. + * @throws {@link IllegalArgumentException} if an unsupported protocol is requested. + */ + public int getConnectionOwnerUid( + int protocol, @NonNull InetSocketAddress local, @NonNull InetSocketAddress remote) { + ConnectionInfo connectionInfo = new ConnectionInfo(protocol, local, remote); + try { + return mService.getConnectionOwnerUid(connectionInfo); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private void printStackTrace() { + if (DEBUG) { + final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); + final StringBuffer sb = new StringBuffer(); + for (int i = 3; i < callStack.length; i++) { + final String stackTrace = callStack[i].toString(); + if (stackTrace == null || stackTrace.contains("android.os")) { + break; + } + sb.append(" [").append(stackTrace).append("]"); + } + Log.d(TAG, "StackLog:" + sb.toString()); + } + } + + /** + * Simulates a Data Stall for the specified Network. + * + *

This method should only be used for tests. + * + *

The caller must be the owner of the specified Network. + * + * @param detectionMethod The detection method used to identify the Data Stall. + * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds. + * @param network The Network for which a Data Stall is being simluated. + * @param extras The PersistableBundle of extras included in the Data Stall notification. + * @throws SecurityException if the caller is not the owner of the given network. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS, + android.Manifest.permission.NETWORK_STACK}) + public void simulateDataStall(int detectionMethod, long timestampMillis, + @NonNull Network network, @NonNull PersistableBundle extras) { + try { + mService.simulateDataStall(detectionMethod, timestampMillis, network, extras); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + private void setOemNetworkPreference(@NonNull OemNetworkPreferences preference) { + Log.d(TAG, "setOemNetworkPreference called with preference: " + + preference.toString()); + } + + @NonNull + private final List mQosCallbackConnections = new ArrayList<>(); + + /** + * Registers a {@link QosSocketInfo} with an associated {@link QosCallback}. The callback will + * receive available QoS events related to the {@link Network} and local ip + port + * specified within socketInfo. + *

+ * The same {@link QosCallback} must be unregistered before being registered a second time, + * otherwise {@link QosCallbackRegistrationException} is thrown. + *

+ * This API does not, in itself, require any permission if called with a network that is not + * restricted. However, the underlying implementation currently only supports the IMS network, + * which is always restricted. That means non-preinstalled callers can't possibly find this API + * useful, because they'd never be called back on networks that they would have access to. + * + * @throws SecurityException if {@link QosSocketInfo#getNetwork()} is restricted and the app is + * missing CONNECTIVITY_USE_RESTRICTED_NETWORKS permission. + * @throws QosCallback.QosCallbackRegistrationException if qosCallback is already registered. + * @throws RuntimeException if the app already has too many callbacks registered. + * + * Exceptions after the time of registration is passed through + * {@link QosCallback#onError(QosCallbackException)}. see: {@link QosCallbackException}. + * + * @param socketInfo the socket information used to match QoS events + * @param callback receives qos events that satisfy socketInfo + * @param executor The executor on which the callback will be invoked. The provided + * {@link Executor} must run callback sequentially, otherwise the order of + * callbacks cannot be guaranteed. + * + * @hide + */ + @SystemApi + public void registerQosCallback(@NonNull final QosSocketInfo socketInfo, + @NonNull final QosCallback callback, + @CallbackExecutor @NonNull final Executor executor) { + Objects.requireNonNull(socketInfo, "socketInfo must be non-null"); + Objects.requireNonNull(callback, "callback must be non-null"); + Objects.requireNonNull(executor, "executor must be non-null"); + + try { + synchronized (mQosCallbackConnections) { + if (getQosCallbackConnection(callback) == null) { + final QosCallbackConnection connection = + new QosCallbackConnection(this, callback, executor); + mQosCallbackConnections.add(connection); + mService.registerQosSocketCallback(socketInfo, connection); + } else { + Log.e(TAG, "registerQosCallback: Callback already registered"); + throw new QosCallbackRegistrationException(); + } + } + } catch (final RemoteException e) { + Log.e(TAG, "registerQosCallback: Error while registering ", e); + + // The same unregister method method is called for consistency even though nothing + // will be sent to the ConnectivityService since the callback was never successfully + // registered. + unregisterQosCallback(callback); + e.rethrowFromSystemServer(); + } catch (final ServiceSpecificException e) { + Log.e(TAG, "registerQosCallback: Error while registering ", e); + unregisterQosCallback(callback); + throw convertServiceException(e); + } + } + + /** + * Unregisters the given {@link QosCallback}. The {@link QosCallback} will no longer receive + * events once unregistered and can be registered a second time. + *

+ * If the {@link QosCallback} does not have an active registration, it is a no-op. + * + * @param callback the callback being unregistered + * + * @hide + */ + @SystemApi + public void unregisterQosCallback(@NonNull final QosCallback callback) { + Objects.requireNonNull(callback, "The callback must be non-null"); + try { + synchronized (mQosCallbackConnections) { + final QosCallbackConnection connection = getQosCallbackConnection(callback); + if (connection != null) { + connection.stopReceivingMessages(); + mService.unregisterQosCallback(connection); + mQosCallbackConnections.remove(connection); + } else { + Log.d(TAG, "unregisterQosCallback: Callback not registered"); + } + } + } catch (final RemoteException e) { + Log.e(TAG, "unregisterQosCallback: Error while unregistering ", e); + e.rethrowFromSystemServer(); + } + } + + /** + * Gets the connection related to the callback. + * + * @param callback the callback to look up + * @return the related connection + */ + @Nullable + private QosCallbackConnection getQosCallbackConnection(final QosCallback callback) { + for (final QosCallbackConnection connection : mQosCallbackConnections) { + // Checking by reference here is intentional + if (connection.getCallback() == callback) { + return connection; + } + } + return null; + } + + /** + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, but + * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can + * be used to request that the system provide a network without causing the network to be + * in the foreground. + * + *

This method will attempt to find the best network that matches the passed + * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the + * criteria. The platform will evaluate which network is the best at its own discretion. + * Throughput, latency, cost per byte, policy, user preference and other considerations + * may be factored in the decision of what is considered the best network. + * + *

As long as this request is outstanding, the platform will try to maintain the best network + * matching this request, while always attempting to match the request to a better network if + * possible. If a better match is found, the platform will switch this request to the now-best + * network and inform the app of the newly best network by invoking + * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform + * will not try to maintain any other network than the best one currently matching the request: + * a network not matching any network request may be disconnected at any time. + * + *

For example, an application could use this method to obtain a connected cellular network + * even if the device currently has a data connection over Ethernet. This may cause the cellular + * radio to consume additional power. Or, an application could inform the system that it wants + * a network supporting sending MMSes and have the system let it know about the currently best + * MMS-supporting network through the provided {@link NetworkCallback}. + * + *

The status of the request can be followed by listening to the various callbacks described + * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be + * used to direct traffic to the network (although accessing some networks may be subject to + * holding specific permissions). Callers will learn about the specific characteristics of the + * network through + * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and + * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the + * provided {@link NetworkCallback} will only be invoked due to changes in the best network + * matching the request at any given time; therefore when a better network matching the request + * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called + * with the new network after which no further updates are given about the previously-best + * network, unless it becomes the best again at some later time. All callbacks are invoked + * in order on the same thread, which by default is a thread created by the framework running + * in the app. + * + *

This{@link NetworkRequest} will live until released via + * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at + * which point the system may let go of the network at any time. + * + *

It is presently unsupported to request a network with mutable + * {@link NetworkCapabilities} such as + * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or + * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL} + * as these {@code NetworkCapabilities} represent states that a particular + * network may never attain, and whether a network will attain these states + * is unknown prior to bringing up the network so the framework does not + * know how to go about satisfying a request with these capabilities. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #registerNetworkCallback} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param request {@link NetworkRequest} describing this request. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * If null, the callback is invoked on the default internal Handler. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. + * @throws SecurityException if missing the appropriate permissions. + * @throws RuntimeException if the app already has too many callbacks registered. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @SuppressLint("ExecutorRegistration") + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) + public void requestBackgroundNetwork(@NonNull NetworkRequest request, + @Nullable Handler handler, @NonNull NetworkCallback networkCallback) { + final NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST, + TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler)); + } +} diff --git a/framework/src/android/net/ConnectivityMetricsEvent.aidl b/framework/src/android/net/ConnectivityMetricsEvent.aidl new file mode 100644 index 0000000000..1c541dc4c8 --- /dev/null +++ b/framework/src/android/net/ConnectivityMetricsEvent.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** {@hide} */ +parcelable ConnectivityMetricsEvent; diff --git a/framework/src/android/net/ConnectivityThread.java b/framework/src/android/net/ConnectivityThread.java new file mode 100644 index 0000000000..0b218e738b --- /dev/null +++ b/framework/src/android/net/ConnectivityThread.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.HandlerThread; +import android.os.Looper; + +/** + * Shared singleton connectivity thread for the system. This is a thread for + * connectivity operations such as AsyncChannel connections to system services. + * Various connectivity manager objects can use this singleton as a common + * resource for their handlers instead of creating separate threads of their own. + * @hide + */ +public final class ConnectivityThread extends HandlerThread { + + // A class implementing the lazy holder idiom: the unique static instance + // of ConnectivityThread is instantiated in a thread-safe way (guaranteed by + // the language specs) the first time that Singleton is referenced in get() + // or getInstanceLooper(). + private static class Singleton { + private static final ConnectivityThread INSTANCE = createInstance(); + } + + private ConnectivityThread() { + super("ConnectivityThread"); + } + + private static ConnectivityThread createInstance() { + ConnectivityThread t = new ConnectivityThread(); + t.start(); + return t; + } + + public static ConnectivityThread get() { + return Singleton.INSTANCE; + } + + public static Looper getInstanceLooper() { + return Singleton.INSTANCE.getLooper(); + } +} diff --git a/framework/src/android/net/DhcpInfo.aidl b/framework/src/android/net/DhcpInfo.aidl new file mode 100644 index 0000000000..29cd21fe76 --- /dev/null +++ b/framework/src/android/net/DhcpInfo.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2008, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable DhcpInfo; diff --git a/framework/src/android/net/DhcpInfo.java b/framework/src/android/net/DhcpInfo.java new file mode 100644 index 0000000000..912df67a0b --- /dev/null +++ b/framework/src/android/net/DhcpInfo.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A simple object for retrieving the results of a DHCP request. + */ +public class DhcpInfo implements Parcelable { + public int ipAddress; + public int gateway; + public int netmask; + public int dns1; + public int dns2; + public int serverAddress; + + public int leaseDuration; + + public DhcpInfo() { + super(); + } + + /** copy constructor {@hide} */ + public DhcpInfo(DhcpInfo source) { + if (source != null) { + ipAddress = source.ipAddress; + gateway = source.gateway; + netmask = source.netmask; + dns1 = source.dns1; + dns2 = source.dns2; + serverAddress = source.serverAddress; + leaseDuration = source.leaseDuration; + } + } + + public String toString() { + StringBuffer str = new StringBuffer(); + + str.append("ipaddr "); putAddress(str, ipAddress); + str.append(" gateway "); putAddress(str, gateway); + str.append(" netmask "); putAddress(str, netmask); + str.append(" dns1 "); putAddress(str, dns1); + str.append(" dns2 "); putAddress(str, dns2); + str.append(" DHCP server "); putAddress(str, serverAddress); + str.append(" lease ").append(leaseDuration).append(" seconds"); + + return str.toString(); + } + + private static void putAddress(StringBuffer buf, int addr) { + buf.append(NetworkUtils.intToInetAddress(addr).getHostAddress()); + } + + /** Implement the Parcelable interface */ + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(ipAddress); + dest.writeInt(gateway); + dest.writeInt(netmask); + dest.writeInt(dns1); + dest.writeInt(dns2); + dest.writeInt(serverAddress); + dest.writeInt(leaseDuration); + } + + /** Implement the Parcelable interface */ + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public DhcpInfo createFromParcel(Parcel in) { + DhcpInfo info = new DhcpInfo(); + info.ipAddress = in.readInt(); + info.gateway = in.readInt(); + info.netmask = in.readInt(); + info.dns1 = in.readInt(); + info.dns2 = in.readInt(); + info.serverAddress = in.readInt(); + info.leaseDuration = in.readInt(); + return info; + } + + public DhcpInfo[] newArray(int size) { + return new DhcpInfo[size]; + } + }; +} diff --git a/framework/src/android/net/DnsResolver.java b/framework/src/android/net/DnsResolver.java new file mode 100644 index 0000000000..3f7660f570 --- /dev/null +++ b/framework/src/android/net/DnsResolver.java @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.net.NetworkUtils.getDnsNetwork; +import static android.net.NetworkUtils.resNetworkCancel; +import static android.net.NetworkUtils.resNetworkQuery; +import static android.net.NetworkUtils.resNetworkResult; +import static android.net.NetworkUtils.resNetworkSend; +import static android.net.util.DnsUtils.haveIpv4; +import static android.net.util.DnsUtils.haveIpv6; +import static android.net.util.DnsUtils.rfc6724Sort; +import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR; +import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; +import static android.system.OsConstants.ENONET; + +import android.annotation.CallbackExecutor; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.CancellationSignal; +import android.os.Looper; +import android.os.MessageQueue; +import android.system.ErrnoException; +import android.util.Log; + +import com.android.net.module.util.DnsPacket; + +import java.io.FileDescriptor; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +/** + * Dns resolver class for asynchronous dns querying + * + * Note that if a client sends a query with more than 1 record in the question section but + * the remote dns server does not support this, it may not respond at all, leading to a timeout. + * + */ +public final class DnsResolver { + private static final String TAG = "DnsResolver"; + private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR; + private static final int MAXPACKET = 8 * 1024; + private static final int SLEEP_TIME_MS = 2; + + @IntDef(prefix = { "CLASS_" }, value = { + CLASS_IN + }) + @Retention(RetentionPolicy.SOURCE) + @interface QueryClass {} + public static final int CLASS_IN = 1; + + @IntDef(prefix = { "TYPE_" }, value = { + TYPE_A, + TYPE_AAAA + }) + @Retention(RetentionPolicy.SOURCE) + @interface QueryType {} + public static final int TYPE_A = 1; + public static final int TYPE_AAAA = 28; + + @IntDef(prefix = { "FLAG_" }, value = { + FLAG_EMPTY, + FLAG_NO_RETRY, + FLAG_NO_CACHE_STORE, + FLAG_NO_CACHE_LOOKUP + }) + @Retention(RetentionPolicy.SOURCE) + @interface QueryFlag {} + public static final int FLAG_EMPTY = 0; + public static final int FLAG_NO_RETRY = 1 << 0; + public static final int FLAG_NO_CACHE_STORE = 1 << 1; + public static final int FLAG_NO_CACHE_LOOKUP = 1 << 2; + + @IntDef(prefix = { "ERROR_" }, value = { + ERROR_PARSE, + ERROR_SYSTEM + }) + @Retention(RetentionPolicy.SOURCE) + @interface DnsError {} + /** + * Indicates that there was an error parsing the response the query. + * The cause of this error is available via getCause() and is a {@link ParseException}. + */ + public static final int ERROR_PARSE = 0; + /** + * Indicates that there was an error sending the query. + * The cause of this error is available via getCause() and is an ErrnoException. + */ + public static final int ERROR_SYSTEM = 1; + + private static final int NETID_UNSET = 0; + + private static final DnsResolver sInstance = new DnsResolver(); + + /** + * Get instance for DnsResolver + */ + public static @NonNull DnsResolver getInstance() { + return sInstance; + } + + private DnsResolver() {} + + /** + * Base interface for answer callbacks + * + * @param The type of the answer + */ + public interface Callback { + /** + * Success response to + * {@link android.net.DnsResolver#query query()} or + * {@link android.net.DnsResolver#rawQuery rawQuery()}. + * + * Invoked when the answer to a query was successfully parsed. + * + * @param answer answer to the query. + * @param rcode The response code in the DNS response. + * + * {@see android.net.DnsResolver#query query()} + */ + void onAnswer(@NonNull T answer, int rcode); + /** + * Error response to + * {@link android.net.DnsResolver#query query()} or + * {@link android.net.DnsResolver#rawQuery rawQuery()}. + * + * Invoked when there is no valid answer to + * {@link android.net.DnsResolver#query query()} + * {@link android.net.DnsResolver#rawQuery rawQuery()}. + * + * @param error a {@link DnsException} object with additional + * detail regarding the failure + */ + void onError(@NonNull DnsException error); + } + + /** + * Class to represent DNS error + */ + public static class DnsException extends Exception { + /** + * DNS error code as one of the ERROR_* constants + */ + @DnsError public final int code; + + DnsException(@DnsError int code, @Nullable Throwable cause) { + super(cause); + this.code = code; + } + } + + /** + * Send a raw DNS query. + * The answer will be provided asynchronously through the provided {@link Callback}. + * + * @param network {@link Network} specifying which network to query on. + * {@code null} for query on default network. + * @param query blob message to query + * @param flags flags as a combination of the FLAGS_* constants + * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. + * @param callback a {@link Callback} which will be called to notify the caller + * of the result of dns query. + */ + public void rawQuery(@Nullable Network network, @NonNull byte[] query, @QueryFlag int flags, + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull Callback callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + final Object lock = new Object(); + final FileDescriptor queryfd; + try { + queryfd = resNetworkSend((network != null) + ? network.getNetIdForResolv() : NETID_UNSET, query, query.length, flags); + } catch (ErrnoException e) { + executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); + return; + } + + synchronized (lock) { + registerFDListener(executor, queryfd, callback, cancellationSignal, lock); + if (cancellationSignal == null) return; + addCancellationSignal(cancellationSignal, queryfd, lock); + } + } + + /** + * Send a DNS query with the specified name, class and query type. + * The answer will be provided asynchronously through the provided {@link Callback}. + * + * @param network {@link Network} specifying which network to query on. + * {@code null} for query on default network. + * @param domain domain name to query + * @param nsClass dns class as one of the CLASS_* constants + * @param nsType dns resource record (RR) type as one of the TYPE_* constants + * @param flags flags as a combination of the FLAGS_* constants + * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. + * @param callback a {@link Callback} which will be called to notify the caller + * of the result of dns query. + */ + public void rawQuery(@Nullable Network network, @NonNull String domain, + @QueryClass int nsClass, @QueryType int nsType, @QueryFlag int flags, + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull Callback callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + final Object lock = new Object(); + final FileDescriptor queryfd; + try { + queryfd = resNetworkQuery((network != null) + ? network.getNetIdForResolv() : NETID_UNSET, domain, nsClass, nsType, flags); + } catch (ErrnoException e) { + executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); + return; + } + synchronized (lock) { + registerFDListener(executor, queryfd, callback, cancellationSignal, lock); + if (cancellationSignal == null) return; + addCancellationSignal(cancellationSignal, queryfd, lock); + } + } + + private class InetAddressAnswerAccumulator implements Callback { + private final List mAllAnswers; + private final Network mNetwork; + private int mRcode; + private DnsException mDnsException; + private final Callback> mUserCallback; + private final int mTargetAnswerCount; + private int mReceivedAnswerCount = 0; + + InetAddressAnswerAccumulator(@NonNull Network network, int size, + @NonNull Callback> callback) { + mNetwork = network; + mTargetAnswerCount = size; + mAllAnswers = new ArrayList<>(); + mUserCallback = callback; + } + + private boolean maybeReportError() { + if (mRcode != 0) { + mUserCallback.onAnswer(mAllAnswers, mRcode); + return true; + } + if (mDnsException != null) { + mUserCallback.onError(mDnsException); + return true; + } + return false; + } + + private void maybeReportAnswer() { + if (++mReceivedAnswerCount != mTargetAnswerCount) return; + if (mAllAnswers.isEmpty() && maybeReportError()) return; + mUserCallback.onAnswer(rfc6724Sort(mNetwork, mAllAnswers), mRcode); + } + + @Override + public void onAnswer(@NonNull byte[] answer, int rcode) { + // If at least one query succeeded, return an rcode of 0. + // Otherwise, arbitrarily return the first rcode received. + if (mReceivedAnswerCount == 0 || rcode == 0) { + mRcode = rcode; + } + try { + mAllAnswers.addAll(new DnsAddressAnswer(answer).getAddresses()); + } catch (DnsPacket.ParseException e) { + // Convert the com.android.net.module.util.DnsPacket.ParseException to an + // android.net.ParseException. This is the type that was used in Q and is implied + // by the public documentation of ERROR_PARSE. + // + // DnsPacket cannot throw android.net.ParseException directly because it's @hide. + ParseException pe = new ParseException(e.reason, e.getCause()); + pe.setStackTrace(e.getStackTrace()); + mDnsException = new DnsException(ERROR_PARSE, pe); + } + maybeReportAnswer(); + } + + @Override + public void onError(@NonNull DnsException error) { + mDnsException = error; + maybeReportAnswer(); + } + } + + /** + * Send a DNS query with the specified name on a network with both IPv4 and IPv6, + * get back a set of InetAddresses with rfc6724 sorting style asynchronously. + * + * This method will examine the connection ability on given network, and query IPv4 + * and IPv6 if connection is available. + * + * If at least one query succeeded with valid answer, rcode will be 0 + * + * The answer will be provided asynchronously through the provided {@link Callback}. + * + * @param network {@link Network} specifying which network to query on. + * {@code null} for query on default network. + * @param domain domain name to query + * @param flags flags as a combination of the FLAGS_* constants + * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. + * @param callback a {@link Callback} which will be called to notify the + * caller of the result of dns query. + */ + public void query(@Nullable Network network, @NonNull String domain, @QueryFlag int flags, + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull Callback> callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + final Object lock = new Object(); + final Network queryNetwork; + try { + queryNetwork = (network != null) ? network : getDnsNetwork(); + } catch (ErrnoException e) { + executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); + return; + } + final boolean queryIpv6 = haveIpv6(queryNetwork); + final boolean queryIpv4 = haveIpv4(queryNetwork); + + // This can only happen if queryIpv4 and queryIpv6 are both false. + // This almost certainly means that queryNetwork does not exist or no longer exists. + if (!queryIpv6 && !queryIpv4) { + executor.execute(() -> callback.onError( + new DnsException(ERROR_SYSTEM, new ErrnoException("resNetworkQuery", ENONET)))); + return; + } + + final FileDescriptor v4fd; + final FileDescriptor v6fd; + + int queryCount = 0; + + if (queryIpv6) { + try { + v6fd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, + TYPE_AAAA, flags); + } catch (ErrnoException e) { + executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); + return; + } + queryCount++; + } else v6fd = null; + + // Avoiding gateways drop packets if queries are sent too close together + try { + Thread.sleep(SLEEP_TIME_MS); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + + if (queryIpv4) { + try { + v4fd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, TYPE_A, + flags); + } catch (ErrnoException e) { + if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid. + executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); + return; + } + queryCount++; + } else v4fd = null; + + final InetAddressAnswerAccumulator accumulator = + new InetAddressAnswerAccumulator(queryNetwork, queryCount, callback); + + synchronized (lock) { + if (queryIpv6) { + registerFDListener(executor, v6fd, accumulator, cancellationSignal, lock); + } + if (queryIpv4) { + registerFDListener(executor, v4fd, accumulator, cancellationSignal, lock); + } + if (cancellationSignal == null) return; + cancellationSignal.setOnCancelListener(() -> { + synchronized (lock) { + if (queryIpv4) cancelQuery(v4fd); + if (queryIpv6) cancelQuery(v6fd); + } + }); + } + } + + /** + * Send a DNS query with the specified name and query type, get back a set of + * InetAddresses with rfc6724 sorting style asynchronously. + * + * The answer will be provided asynchronously through the provided {@link Callback}. + * + * @param network {@link Network} specifying which network to query on. + * {@code null} for query on default network. + * @param domain domain name to query + * @param nsType dns resource record (RR) type as one of the TYPE_* constants + * @param flags flags as a combination of the FLAGS_* constants + * @param executor The {@link Executor} that the callback should be executed on. + * @param cancellationSignal used by the caller to signal if the query should be + * cancelled. May be {@code null}. + * @param callback a {@link Callback} which will be called to notify the caller + * of the result of dns query. + */ + public void query(@Nullable Network network, @NonNull String domain, + @QueryType int nsType, @QueryFlag int flags, + @NonNull @CallbackExecutor Executor executor, + @Nullable CancellationSignal cancellationSignal, + @NonNull Callback> callback) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + final Object lock = new Object(); + final FileDescriptor queryfd; + final Network queryNetwork; + try { + queryNetwork = (network != null) ? network : getDnsNetwork(); + queryfd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, nsType, + flags); + } catch (ErrnoException e) { + executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e))); + return; + } + final InetAddressAnswerAccumulator accumulator = + new InetAddressAnswerAccumulator(queryNetwork, 1, callback); + synchronized (lock) { + registerFDListener(executor, queryfd, accumulator, cancellationSignal, lock); + if (cancellationSignal == null) return; + addCancellationSignal(cancellationSignal, queryfd, lock); + } + } + + /** + * Class to retrieve DNS response + * + * @hide + */ + public static final class DnsResponse { + public final @NonNull byte[] answerbuf; + public final int rcode; + public DnsResponse(@NonNull byte[] answerbuf, int rcode) { + this.answerbuf = answerbuf; + this.rcode = rcode; + } + } + + private void registerFDListener(@NonNull Executor executor, + @NonNull FileDescriptor queryfd, @NonNull Callback answerCallback, + @Nullable CancellationSignal cancellationSignal, @NonNull Object lock) { + final MessageQueue mainThreadMessageQueue = Looper.getMainLooper().getQueue(); + mainThreadMessageQueue.addOnFileDescriptorEventListener( + queryfd, + FD_EVENTS, + (fd, events) -> { + // b/134310704 + // Unregister fd event listener before resNetworkResult is called to prevent + // race condition caused by fd reused. + // For example when querying v4 and v6, it's possible that the first query ends + // and the fd is closed before the second request starts, which might return + // the same fd for the second request. By that time, the looper must have + // unregistered the fd, otherwise another event listener can't be registered. + mainThreadMessageQueue.removeOnFileDescriptorEventListener(fd); + + executor.execute(() -> { + DnsResponse resp = null; + ErrnoException exception = null; + synchronized (lock) { + if (cancellationSignal != null && cancellationSignal.isCanceled()) { + return; + } + try { + resp = resNetworkResult(fd); // Closes fd, marks it invalid. + } catch (ErrnoException e) { + Log.e(TAG, "resNetworkResult:" + e.toString()); + exception = e; + } + } + if (exception != null) { + answerCallback.onError(new DnsException(ERROR_SYSTEM, exception)); + return; + } + answerCallback.onAnswer(resp.answerbuf, resp.rcode); + }); + + // The file descriptor has already been unregistered, so it does not really + // matter what is returned here. In spirit 0 (meaning "unregister this FD") + // is still the closest to what the looper needs to do. When returning 0, + // Looper knows to ignore the fd if it has already been unregistered. + return 0; + }); + } + + private void cancelQuery(@NonNull FileDescriptor queryfd) { + if (!queryfd.valid()) return; + Looper.getMainLooper().getQueue().removeOnFileDescriptorEventListener(queryfd); + resNetworkCancel(queryfd); // Closes fd, marks it invalid. + } + + private void addCancellationSignal(@NonNull CancellationSignal cancellationSignal, + @NonNull FileDescriptor queryfd, @NonNull Object lock) { + cancellationSignal.setOnCancelListener(() -> { + synchronized (lock) { + cancelQuery(queryfd); + } + }); + } + + private static class DnsAddressAnswer extends DnsPacket { + private static final String TAG = "DnsResolver.DnsAddressAnswer"; + private static final boolean DBG = false; + + private final int mQueryType; + + DnsAddressAnswer(@NonNull byte[] data) throws ParseException { + super(data); + if ((mHeader.flags & (1 << 15)) == 0) { + throw new ParseException("Not an answer packet"); + } + if (mHeader.getRecordCount(QDSECTION) == 0) { + throw new ParseException("No question found"); + } + // Expect only one question in question section. + mQueryType = mRecords[QDSECTION].get(0).nsType; + } + + public @NonNull List getAddresses() { + final List results = new ArrayList(); + if (mHeader.getRecordCount(ANSECTION) == 0) return results; + + for (final DnsRecord ansSec : mRecords[ANSECTION]) { + // Only support A and AAAA, also ignore answers if query type != answer type. + int nsType = ansSec.nsType; + if (nsType != mQueryType || (nsType != TYPE_A && nsType != TYPE_AAAA)) { + continue; + } + try { + results.add(InetAddress.getByAddress(ansSec.getRR())); + } catch (UnknownHostException e) { + if (DBG) { + Log.w(TAG, "rr to address fail"); + } + } + } + return results; + } + } + +} diff --git a/framework/src/android/net/ICaptivePortal.aidl b/framework/src/android/net/ICaptivePortal.aidl new file mode 100644 index 0000000000..fe21905c70 --- /dev/null +++ b/framework/src/android/net/ICaptivePortal.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * Interface to inform NetworkMonitor of decisions of app handling captive portal. + * @hide + */ +oneway interface ICaptivePortal { + void appRequest(int request); + void appResponse(int response); + void logEvent(int eventId, String packageName); +} diff --git a/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl b/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl new file mode 100644 index 0000000000..82b64a9280 --- /dev/null +++ b/framework/src/android/net/IConnectivityDiagnosticsCallback.aidl @@ -0,0 +1,28 @@ +/** + * + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.ConnectivityDiagnosticsManager; +import android.net.Network; + +/** @hide */ +oneway interface IConnectivityDiagnosticsCallback { + void onConnectivityReportAvailable(in ConnectivityDiagnosticsManager.ConnectivityReport report); + void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report); + void onNetworkConnectivityReported(in Network n, boolean hasConnectivity); +} \ No newline at end of file diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl new file mode 100644 index 0000000000..1b4d2e4139 --- /dev/null +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -0,0 +1,246 @@ +/** + * Copyright (c) 2008, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.app.PendingIntent; +import android.net.ConnectionInfo; +import android.net.ConnectivityDiagnosticsManager; +import android.net.IConnectivityDiagnosticsCallback; +import android.net.IQosCallback; +import android.net.ISocketKeepaliveCallback; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkAgentConfig; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; +import android.net.NetworkRequest; +import android.net.NetworkState; +import android.net.ProxyInfo; +import android.net.UidRange; +import android.net.QosSocketInfo; +import android.os.Bundle; +import android.os.IBinder; +import android.os.INetworkActivityListener; +import android.os.Messenger; +import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; +import android.os.ResultReceiver; + +import com.android.connectivity.aidl.INetworkAgent; +import com.android.internal.net.LegacyVpnInfo; +import com.android.internal.net.VpnConfig; +import com.android.internal.net.VpnProfile; + +/** + * Interface that answers queries about, and allows changing, the + * state of network connectivity. + */ +/** {@hide} */ +interface IConnectivityManager +{ + Network getActiveNetwork(); + Network getActiveNetworkForUid(int uid, boolean ignoreBlocked); + @UnsupportedAppUsage + NetworkInfo getActiveNetworkInfo(); + NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked); + @UnsupportedAppUsage(maxTargetSdk = 28) + NetworkInfo getNetworkInfo(int networkType); + NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked); + @UnsupportedAppUsage + NetworkInfo[] getAllNetworkInfo(); + Network getNetworkForType(int networkType); + Network[] getAllNetworks(); + NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser( + int userId, String callingPackageName); + + boolean isNetworkSupported(int networkType); + + @UnsupportedAppUsage + LinkProperties getActiveLinkProperties(); + LinkProperties getLinkPropertiesForType(int networkType); + LinkProperties getLinkProperties(in Network network); + + NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName); + + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) + NetworkState[] getAllNetworkState(); + + boolean isActiveNetworkMetered(); + + boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, + String callingPackageName, String callingAttributionTag); + + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getLastTetherError} as alternative") + int getLastTetherError(String iface); + + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetherableIfaces} as alternative") + String[] getTetherableIfaces(); + + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetheredIfaces} as alternative") + String[] getTetheredIfaces(); + + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetheringErroredIfaces} " + + "as Alternative") + String[] getTetheringErroredIfaces(); + + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetherableUsbRegexs} as alternative") + String[] getTetherableUsbRegexs(); + + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetherableWifiRegexs} as alternative") + String[] getTetherableWifiRegexs(); + + @UnsupportedAppUsage(maxTargetSdk = 28) + void reportInetCondition(int networkType, int percentage); + + void reportNetworkConnectivity(in Network network, boolean hasConnectivity); + + ProxyInfo getGlobalProxy(); + + void setGlobalProxy(in ProxyInfo p); + + ProxyInfo getProxyForNetwork(in Network nework); + + boolean prepareVpn(String oldPackage, String newPackage, int userId); + + void setVpnPackageAuthorization(String packageName, int userId, int vpnType); + + ParcelFileDescriptor establishVpn(in VpnConfig config); + + boolean provisionVpnProfile(in VpnProfile profile, String packageName); + + void deleteVpnProfile(String packageName); + + void startVpnProfile(String packageName); + + void stopVpnProfile(String packageName); + + VpnConfig getVpnConfig(int userId); + + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) + void startLegacyVpn(in VpnProfile profile); + + LegacyVpnInfo getLegacyVpnInfo(int userId); + + boolean updateLockdownVpn(); + boolean isAlwaysOnVpnPackageSupported(int userId, String packageName); + boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown, + in List lockdownWhitelist); + String getAlwaysOnVpnPackage(int userId); + boolean isVpnLockdownEnabled(int userId); + List getVpnLockdownWhitelist(int userId); + void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges); + + void setProvisioningNotificationVisible(boolean visible, int networkType, in String action); + + void setAirplaneMode(boolean enable); + + boolean requestBandwidthUpdate(in Network network); + + int registerNetworkFactory(in Messenger messenger, in String name); + void unregisterNetworkFactory(in Messenger messenger); + + int registerNetworkProvider(in Messenger messenger, in String name); + void unregisterNetworkProvider(in Messenger messenger); + + void declareNetworkRequestUnfulfillable(in NetworkRequest request); + + Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp, + in NetworkCapabilities nc, int score, in NetworkAgentConfig config, + in int factorySerialNumber); + + NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, + in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, + String callingPackageName, String callingAttributionTag); + + NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, + in PendingIntent operation, String callingPackageName, String callingAttributionTag); + + void releasePendingNetworkRequest(in PendingIntent operation); + + NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, + in Messenger messenger, in IBinder binder, String callingPackageName); + + void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, + in PendingIntent operation, String callingPackageName); + + void releaseNetworkRequest(in NetworkRequest networkRequest); + + void setAcceptUnvalidated(in Network network, boolean accept, boolean always); + void setAcceptPartialConnectivity(in Network network, boolean accept, boolean always); + void setAvoidUnvalidated(in Network network); + void startCaptivePortalApp(in Network network); + void startCaptivePortalAppInternal(in Network network, in Bundle appExtras); + + boolean shouldAvoidBadWifi(); + int getMultipathPreference(in Network Network); + + NetworkRequest getDefaultRequest(); + + int getRestoreDefaultNetworkDelay(int networkType); + + boolean addVpnAddress(String address, int prefixLength); + boolean removeVpnAddress(String address, int prefixLength); + boolean setUnderlyingNetworksForVpn(in Network[] networks); + + void factoryReset(); + + void startNattKeepalive(in Network network, int intervalSeconds, + in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr); + + void startNattKeepaliveWithFd(in Network network, in ParcelFileDescriptor pfd, int resourceId, + int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr, + String dstAddr); + + void startTcpKeepalive(in Network network, in ParcelFileDescriptor pfd, int intervalSeconds, + in ISocketKeepaliveCallback cb); + + void stopKeepalive(in Network network, int slot); + + String getCaptivePortalServerUrl(); + + byte[] getNetworkWatchlistConfigHash(); + + int getConnectionOwnerUid(in ConnectionInfo connectionInfo); + boolean isCallerCurrentAlwaysOnVpnApp(); + boolean isCallerCurrentAlwaysOnVpnLockdownApp(); + + void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, + in NetworkRequest request, String callingPackageName); + void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); + + IBinder startOrGetTestNetworkService(); + + void simulateDataStall(int detectionMethod, long timestampMillis, in Network network, + in PersistableBundle extras); + + void systemReady(); + + void registerNetworkActivityListener(in INetworkActivityListener l); + + void unregisterNetworkActivityListener(in INetworkActivityListener l); + + boolean isDefaultNetworkActive(); + + void registerQosSocketCallback(in QosSocketInfo socketInfo, in IQosCallback callback); + void unregisterQosCallback(in IQosCallback callback); +} diff --git a/framework/src/android/net/ISocketKeepaliveCallback.aidl b/framework/src/android/net/ISocketKeepaliveCallback.aidl new file mode 100644 index 0000000000..020fbcacbf --- /dev/null +++ b/framework/src/android/net/ISocketKeepaliveCallback.aidl @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2019, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * Callback to provide status changes of keepalive offload. + * + * @hide + */ +oneway interface ISocketKeepaliveCallback +{ + /** The keepalive was successfully started. */ + void onStarted(int slot); + /** The keepalive was successfully stopped. */ + void onStopped(); + /** The keepalive was stopped because of an error. */ + void onError(int error); + /** The keepalive on a TCP socket was stopped because the socket received data. */ + void onDataReceived(); +} diff --git a/framework/src/android/net/ITestNetworkManager.aidl b/framework/src/android/net/ITestNetworkManager.aidl new file mode 100644 index 0000000000..2a863adde5 --- /dev/null +++ b/framework/src/android/net/ITestNetworkManager.aidl @@ -0,0 +1,39 @@ +/** + * 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. + */ + +package android.net; + +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.TestNetworkInterface; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; + +/** + * Interface that allows for creation and management of test-only networks. + * + * @hide + */ +interface ITestNetworkManager +{ + TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs); + TestNetworkInterface createTapInterface(); + + void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered, + in int[] administratorUids, in IBinder binder); + + void teardownTestNetwork(int netId); +} diff --git a/framework/src/android/net/InetAddresses.java b/framework/src/android/net/InetAddresses.java new file mode 100644 index 0000000000..01b795e456 --- /dev/null +++ b/framework/src/android/net/InetAddresses.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package android.net; + +import android.annotation.NonNull; + +import libcore.net.InetAddressUtils; + +import java.net.InetAddress; + +/** + * Utility methods for {@link InetAddress} implementations. + */ +public class InetAddresses { + + private InetAddresses() {} + + /** + * Checks to see if the {@code address} is a numeric address (such as {@code "192.0.2.1"} or + * {@code "2001:db8::1:2"}). + * + *

A numeric address is either an IPv4 address containing exactly 4 decimal numbers or an + * IPv6 numeric address. IPv4 addresses that consist of either hexadecimal or octal digits or + * do not have exactly 4 numbers are not treated as numeric. + * + *

This method will never do a DNS lookup. + * + * @param address the address to parse. + * @return true if the supplied address is numeric, false otherwise. + */ + public static boolean isNumericAddress(@NonNull String address) { + return InetAddressUtils.isNumericAddress(address); + } + + /** + * Returns an InetAddress corresponding to the given numeric address (such + * as {@code "192.168.0.1"} or {@code "2001:4860:800d::68"}). + * + *

See {@link #isNumericAddress(String)} (String)} for a definition as to what constitutes a + * numeric address. + * + *

This method will never do a DNS lookup. + * + * @param address the address to parse, must be numeric. + * @return an {@link InetAddress} instance corresponding to the address. + * @throws IllegalArgumentException if {@code address} is not a numeric address. + */ + public static @NonNull InetAddress parseNumericAddress(@NonNull String address) { + return InetAddressUtils.parseNumericAddress(address); + } +} diff --git a/framework/src/android/net/InterfaceConfiguration.aidl b/framework/src/android/net/InterfaceConfiguration.aidl new file mode 100644 index 0000000000..8aa5e34528 --- /dev/null +++ b/framework/src/android/net/InterfaceConfiguration.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2008, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable InterfaceConfiguration; diff --git a/framework/src/android/net/InvalidPacketException.java b/framework/src/android/net/InvalidPacketException.java new file mode 100644 index 0000000000..1873d778c0 --- /dev/null +++ b/framework/src/android/net/InvalidPacketException.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.SystemApi; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Thrown when a packet is invalid. + * @hide + */ +@SystemApi +public final class InvalidPacketException extends Exception { + private final int mError; + + // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. + /** Invalid IP address. */ + public static final int ERROR_INVALID_IP_ADDRESS = -21; + + // Must match SocketKeepalive#ERROR_INVALID_PORT. + /** Invalid port number. */ + public static final int ERROR_INVALID_PORT = -22; + + // Must match SocketKeepalive#ERROR_INVALID_LENGTH. + /** Invalid packet length. */ + public static final int ERROR_INVALID_LENGTH = -23; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "ERROR_" }, value = { + ERROR_INVALID_IP_ADDRESS, + ERROR_INVALID_PORT, + ERROR_INVALID_LENGTH + }) + public @interface ErrorCode {} + + /** + * This packet is invalid. + * See the error code for details. + */ + public InvalidPacketException(@ErrorCode final int error) { + this.mError = error; + } + + /** Get error code. */ + public int getError() { + return mError; + } +} diff --git a/framework/src/android/net/IpConfiguration.aidl b/framework/src/android/net/IpConfiguration.aidl new file mode 100644 index 0000000000..7a30f0e79c --- /dev/null +++ b/framework/src/android/net/IpConfiguration.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable IpConfiguration; diff --git a/framework/src/android/net/IpConfiguration.java b/framework/src/android/net/IpConfiguration.java new file mode 100644 index 0000000000..0b205642b3 --- /dev/null +++ b/framework/src/android/net/IpConfiguration.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * A class representing a configured network. + * @hide + */ +@SystemApi +public final class IpConfiguration implements Parcelable { + private static final String TAG = "IpConfiguration"; + + // This enum has been used by apps through reflection for many releases. + // Therefore they can't just be removed. Duplicating these constants to + // give an alternate SystemApi is a worse option than exposing them. + @SuppressLint("Enum") + public enum IpAssignment { + /* Use statically configured IP settings. Configuration can be accessed + * with staticIpConfiguration */ + STATIC, + /* Use dynamically configured IP settings */ + DHCP, + /* no IP details are assigned, this is used to indicate + * that any existing IP settings should be retained */ + UNASSIGNED + } + + /** @hide */ + public IpAssignment ipAssignment; + + /** @hide */ + public StaticIpConfiguration staticIpConfiguration; + + // This enum has been used by apps through reflection for many releases. + // Therefore they can't just be removed. Duplicating these constants to + // give an alternate SystemApi is a worse option than exposing them. + @SuppressLint("Enum") + public enum ProxySettings { + /* No proxy is to be used. Any existing proxy settings + * should be cleared. */ + NONE, + /* Use statically configured proxy. Configuration can be accessed + * with httpProxy. */ + STATIC, + /* no proxy details are assigned, this is used to indicate + * that any existing proxy settings should be retained */ + UNASSIGNED, + /* Use a Pac based proxy. + */ + PAC + } + + /** @hide */ + public ProxySettings proxySettings; + + /** @hide */ + @UnsupportedAppUsage + public ProxyInfo httpProxy; + + private void init(IpAssignment ipAssignment, + ProxySettings proxySettings, + StaticIpConfiguration staticIpConfiguration, + ProxyInfo httpProxy) { + this.ipAssignment = ipAssignment; + this.proxySettings = proxySettings; + this.staticIpConfiguration = (staticIpConfiguration == null) ? + null : new StaticIpConfiguration(staticIpConfiguration); + this.httpProxy = (httpProxy == null) ? + null : new ProxyInfo(httpProxy); + } + + public IpConfiguration() { + init(IpAssignment.UNASSIGNED, ProxySettings.UNASSIGNED, null, null); + } + + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public IpConfiguration(IpAssignment ipAssignment, + ProxySettings proxySettings, + StaticIpConfiguration staticIpConfiguration, + ProxyInfo httpProxy) { + init(ipAssignment, proxySettings, staticIpConfiguration, httpProxy); + } + + public IpConfiguration(@NonNull IpConfiguration source) { + this(); + if (source != null) { + init(source.ipAssignment, source.proxySettings, + source.staticIpConfiguration, source.httpProxy); + } + } + + public @NonNull IpAssignment getIpAssignment() { + return ipAssignment; + } + + public void setIpAssignment(@NonNull IpAssignment ipAssignment) { + this.ipAssignment = ipAssignment; + } + + public @Nullable StaticIpConfiguration getStaticIpConfiguration() { + return staticIpConfiguration; + } + + public void setStaticIpConfiguration(@Nullable StaticIpConfiguration staticIpConfiguration) { + this.staticIpConfiguration = staticIpConfiguration; + } + + public @NonNull ProxySettings getProxySettings() { + return proxySettings; + } + + public void setProxySettings(@NonNull ProxySettings proxySettings) { + this.proxySettings = proxySettings; + } + + public @Nullable ProxyInfo getHttpProxy() { + return httpProxy; + } + + public void setHttpProxy(@Nullable ProxyInfo httpProxy) { + this.httpProxy = httpProxy; + } + + @Override + public String toString() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("IP assignment: " + ipAssignment.toString()); + sbuf.append("\n"); + if (staticIpConfiguration != null) { + sbuf.append("Static configuration: " + staticIpConfiguration.toString()); + sbuf.append("\n"); + } + sbuf.append("Proxy settings: " + proxySettings.toString()); + sbuf.append("\n"); + if (httpProxy != null) { + sbuf.append("HTTP proxy: " + httpProxy.toString()); + sbuf.append("\n"); + } + + return sbuf.toString(); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + + if (!(o instanceof IpConfiguration)) { + return false; + } + + IpConfiguration other = (IpConfiguration) o; + return this.ipAssignment == other.ipAssignment && + this.proxySettings == other.proxySettings && + Objects.equals(this.staticIpConfiguration, other.staticIpConfiguration) && + Objects.equals(this.httpProxy, other.httpProxy); + } + + @Override + public int hashCode() { + return 13 + (staticIpConfiguration != null ? staticIpConfiguration.hashCode() : 0) + + 17 * ipAssignment.ordinal() + + 47 * proxySettings.ordinal() + + 83 * httpProxy.hashCode(); + } + + /** Implement the Parcelable interface */ + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface */ + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(ipAssignment.name()); + dest.writeString(proxySettings.name()); + dest.writeParcelable(staticIpConfiguration, flags); + dest.writeParcelable(httpProxy, flags); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator CREATOR = + new Creator() { + public IpConfiguration createFromParcel(Parcel in) { + IpConfiguration config = new IpConfiguration(); + config.ipAssignment = IpAssignment.valueOf(in.readString()); + config.proxySettings = ProxySettings.valueOf(in.readString()); + config.staticIpConfiguration = in.readParcelable(null); + config.httpProxy = in.readParcelable(null); + return config; + } + + public IpConfiguration[] newArray(int size) { + return new IpConfiguration[size]; + } + }; +} diff --git a/framework/src/android/net/IpPrefix.aidl b/framework/src/android/net/IpPrefix.aidl new file mode 100644 index 0000000000..0d70f2a1ed --- /dev/null +++ b/framework/src/android/net/IpPrefix.aidl @@ -0,0 +1,22 @@ +/** + * + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +// @JavaOnlyStableParcelable only affects the parcelable when built as stable aidl (aidl_interface +// build rule). IpPrefix is also used in cpp but only as non-stable aidl. +@JavaOnlyStableParcelable parcelable IpPrefix cpp_header "binder/IpPrefix.h"; diff --git a/framework/src/android/net/IpPrefix.java b/framework/src/android/net/IpPrefix.java new file mode 100644 index 0000000000..e7c801475c --- /dev/null +++ b/framework/src/android/net/IpPrefix.java @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Pair; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Comparator; + +/** + * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a + * power of two boundary (also known as an "IP subnet"). A prefix is specified by two pieces of + * information: + * + *

    + *
  • A starting IP address (IPv4 or IPv6). This is the first IP address of the prefix. + *
  • A prefix length. This specifies the length of the prefix by specifing the number of bits + * in the IP address, starting from the most significant bit in network byte order, that + * are constant for all addresses in the prefix. + *
+ * + * For example, the prefix 192.0.2.0/24 covers the 256 IPv4 addresses from + * 192.0.2.0 to 192.0.2.255, inclusive, and the prefix + * 2001:db8:1:2 covers the 2^64 IPv6 addresses from 2001:db8:1:2:: to + * 2001:db8:1:2:ffff:ffff:ffff:ffff, inclusive. + * + * Objects of this class are immutable. + */ +public final class IpPrefix implements Parcelable { + private final byte[] address; // network byte order + private final int prefixLength; + + private void checkAndMaskAddressAndPrefixLength() { + if (address.length != 4 && address.length != 16) { + throw new IllegalArgumentException( + "IpPrefix has " + address.length + " bytes which is neither 4 nor 16"); + } + NetworkUtils.maskRawAddress(address, prefixLength); + } + + /** + * Constructs a new {@code IpPrefix} from a byte array containing an IPv4 or IPv6 address in + * network byte order and a prefix length. Silently truncates the address to the prefix length, + * so for example {@code 192.0.2.1/24} is silently converted to {@code 192.0.2.0/24}. + * + * @param address the IP address. Must be non-null and exactly 4 or 16 bytes long. + * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * + * @hide + */ + public IpPrefix(@NonNull byte[] address, @IntRange(from = 0, to = 128) int prefixLength) { + this.address = address.clone(); + this.prefixLength = prefixLength; + checkAndMaskAddressAndPrefixLength(); + } + + /** + * Constructs a new {@code IpPrefix} from an IPv4 or IPv6 address and a prefix length. Silently + * truncates the address to the prefix length, so for example {@code 192.0.2.1/24} is silently + * converted to {@code 192.0.2.0/24}. + * + * @param address the IP address. Must be non-null. + * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * @hide + */ + @SystemApi + public IpPrefix(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength) { + // We don't reuse the (byte[], int) constructor because it calls clone() on the byte array, + // which is unnecessary because getAddress() already returns a clone. + this.address = address.getAddress(); + this.prefixLength = prefixLength; + checkAndMaskAddressAndPrefixLength(); + } + + /** + * Constructs a new IpPrefix from a string such as "192.0.2.1/24" or "2001:db8::1/64". + * Silently truncates the address to the prefix length, so for example {@code 192.0.2.1/24} + * is silently converted to {@code 192.0.2.0/24}. + * + * @param prefix the prefix to parse + * + * @hide + */ + @SystemApi + public IpPrefix(@NonNull String prefix) { + // We don't reuse the (InetAddress, int) constructor because "error: call to this must be + // first statement in constructor". We could factor out setting the member variables to an + // init() method, but if we did, then we'd have to make the members non-final, or "error: + // cannot assign a value to final variable address". So we just duplicate the code here. + Pair ipAndMask = NetworkUtils.parseIpAndMask(prefix); + this.address = ipAndMask.first.getAddress(); + this.prefixLength = ipAndMask.second; + checkAndMaskAddressAndPrefixLength(); + } + + /** + * Compares this {@code IpPrefix} object against the specified object in {@code obj}. Two + * objects are equal if they have the same startAddress and prefixLength. + * + * @param obj the object to be tested for equality. + * @return {@code true} if both objects are equal, {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IpPrefix)) { + return false; + } + IpPrefix that = (IpPrefix) obj; + return Arrays.equals(this.address, that.address) && this.prefixLength == that.prefixLength; + } + + /** + * Gets the hashcode of the represented IP prefix. + * + * @return the appropriate hashcode value. + */ + @Override + public int hashCode() { + return Arrays.hashCode(address) + 11 * prefixLength; + } + + /** + * Returns a copy of the first IP address in the prefix. Modifying the returned object does not + * change this object's contents. + * + * @return the address in the form of a byte array. + */ + public @NonNull InetAddress getAddress() { + try { + return InetAddress.getByAddress(address); + } catch (UnknownHostException e) { + // Cannot happen. InetAddress.getByAddress can only throw an exception if the byte + // array is the wrong length, but we check that in the constructor. + throw new IllegalArgumentException("Address is invalid"); + } + } + + /** + * Returns a copy of the IP address bytes in network order (the highest order byte is the zeroth + * element). Modifying the returned array does not change this object's contents. + * + * @return the address in the form of a byte array. + */ + public @NonNull byte[] getRawAddress() { + return address.clone(); + } + + /** + * Returns the prefix length of this {@code IpPrefix}. + * + * @return the prefix length. + */ + @IntRange(from = 0, to = 128) + public int getPrefixLength() { + return prefixLength; + } + + /** + * Determines whether the prefix contains the specified address. + * + * @param address An {@link InetAddress} to test. + * @return {@code true} if the prefix covers the given address. {@code false} otherwise. + */ + public boolean contains(@NonNull InetAddress address) { + byte[] addrBytes = address.getAddress(); + if (addrBytes == null || addrBytes.length != this.address.length) { + return false; + } + NetworkUtils.maskRawAddress(addrBytes, prefixLength); + return Arrays.equals(this.address, addrBytes); + } + + /** + * Returns whether the specified prefix is entirely contained in this prefix. + * + * Note this is mathematical inclusion, so a prefix is always contained within itself. + * @param otherPrefix the prefix to test + * @hide + */ + public boolean containsPrefix(@NonNull IpPrefix otherPrefix) { + if (otherPrefix.getPrefixLength() < prefixLength) return false; + final byte[] otherAddress = otherPrefix.getRawAddress(); + NetworkUtils.maskRawAddress(otherAddress, prefixLength); + return Arrays.equals(otherAddress, address); + } + + /** + * @hide + */ + public boolean isIPv6() { + return getAddress() instanceof Inet6Address; + } + + /** + * @hide + */ + public boolean isIPv4() { + return getAddress() instanceof Inet4Address; + } + + /** + * Returns a string representation of this {@code IpPrefix}. + * + * @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}. + */ + public String toString() { + try { + return InetAddress.getByAddress(address).getHostAddress() + "/" + prefixLength; + } catch(UnknownHostException e) { + // Cosmic rays? + throw new IllegalStateException("IpPrefix with invalid address! Shouldn't happen.", e); + } + } + + /** + * Implement the Parcelable interface. + */ + public int describeContents() { + return 0; + } + + /** + * Implement the Parcelable interface. + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(address); + dest.writeInt(prefixLength); + } + + /** + * Returns a comparator ordering IpPrefixes by length, shorter to longer. + * Contents of the address will break ties. + * @hide + */ + public static Comparator lengthComparator() { + return new Comparator() { + @Override + public int compare(IpPrefix prefix1, IpPrefix prefix2) { + if (prefix1.isIPv4()) { + if (prefix2.isIPv6()) return -1; + } else { + if (prefix2.isIPv4()) return 1; + } + final int p1len = prefix1.getPrefixLength(); + final int p2len = prefix2.getPrefixLength(); + if (p1len < p2len) return -1; + if (p2len < p1len) return 1; + final byte[] a1 = prefix1.address; + final byte[] a2 = prefix2.address; + final int len = a1.length < a2.length ? a1.length : a2.length; + for (int i = 0; i < len; ++i) { + if (a1[i] < a2[i]) return -1; + if (a1[i] > a2[i]) return 1; + } + if (a2.length < len) return 1; + if (a1.length < len) return -1; + return 0; + } + }; + } + + /** + * Implement the Parcelable interface. + */ + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public IpPrefix createFromParcel(Parcel in) { + byte[] address = in.createByteArray(); + int prefixLength = in.readInt(); + return new IpPrefix(address, prefixLength); + } + + public IpPrefix[] newArray(int size) { + return new IpPrefix[size]; + } + }; +} diff --git a/framework/src/android/net/KeepalivePacketData.aidl b/framework/src/android/net/KeepalivePacketData.aidl new file mode 100644 index 0000000000..d456b53fd1 --- /dev/null +++ b/framework/src/android/net/KeepalivePacketData.aidl @@ -0,0 +1,19 @@ +/* + * 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. + */ + +package android.net; + +parcelable KeepalivePacketData; diff --git a/framework/src/android/net/KeepalivePacketData.java b/framework/src/android/net/KeepalivePacketData.java new file mode 100644 index 0000000000..5877f1f4e2 --- /dev/null +++ b/framework/src/android/net/KeepalivePacketData.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; +import static android.net.InvalidPacketException.ERROR_INVALID_PORT; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.util.Log; + +import com.android.net.module.util.IpUtils; + +import java.net.InetAddress; + +/** + * Represents the actual packets that are sent by the + * {@link android.net.SocketKeepalive} API. + * @hide + */ +@SystemApi +public class KeepalivePacketData { + private static final String TAG = "KeepalivePacketData"; + + /** Source IP address */ + @NonNull + private final InetAddress mSrcAddress; + + /** Destination IP address */ + @NonNull + private final InetAddress mDstAddress; + + /** Source port */ + private final int mSrcPort; + + /** Destination port */ + private final int mDstPort; + + /** Packet data. A raw byte string of packet data, not including the link-layer header. */ + private final byte[] mPacket; + + // Note: If you add new fields, please modify the parcelling code in the child classes. + + + // This should only be constructed via static factory methods, such as + // nattKeepalivePacket. + /** + * A holding class for data necessary to build a keepalive packet. + */ + protected KeepalivePacketData(@NonNull InetAddress srcAddress, + @IntRange(from = 0, to = 65535) int srcPort, @NonNull InetAddress dstAddress, + @IntRange(from = 0, to = 65535) int dstPort, + @NonNull byte[] data) throws InvalidPacketException { + this.mSrcAddress = srcAddress; + this.mDstAddress = dstAddress; + this.mSrcPort = srcPort; + this.mDstPort = dstPort; + this.mPacket = data; + + // Check we have two IP addresses of the same family. + if (srcAddress == null || dstAddress == null || !srcAddress.getClass().getName() + .equals(dstAddress.getClass().getName())) { + Log.e(TAG, "Invalid or mismatched InetAddresses in KeepalivePacketData"); + throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); + } + + // Check the ports. + if (!IpUtils.isValidUdpOrTcpPort(srcPort) || !IpUtils.isValidUdpOrTcpPort(dstPort)) { + Log.e(TAG, "Invalid ports in KeepalivePacketData"); + throw new InvalidPacketException(ERROR_INVALID_PORT); + } + } + + /** Get source IP address. */ + @NonNull + public InetAddress getSrcAddress() { + return mSrcAddress; + } + + /** Get destination IP address. */ + @NonNull + public InetAddress getDstAddress() { + return mDstAddress; + } + + /** Get source port number. */ + public int getSrcPort() { + return mSrcPort; + } + + /** Get destination port number. */ + public int getDstPort() { + return mDstPort; + } + + /** + * Returns a byte array of the given packet data. + */ + @NonNull + public byte[] getPacket() { + return mPacket.clone(); + } + +} diff --git a/framework/src/android/net/LinkAddress.aidl b/framework/src/android/net/LinkAddress.aidl new file mode 100644 index 0000000000..9c804db08d --- /dev/null +++ b/framework/src/android/net/LinkAddress.aidl @@ -0,0 +1,21 @@ +/** + * + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +@JavaOnlyStableParcelable parcelable LinkAddress; + diff --git a/framework/src/android/net/LinkAddress.java b/framework/src/android/net/LinkAddress.java new file mode 100644 index 0000000000..44d25a1ab0 --- /dev/null +++ b/framework/src/android/net/LinkAddress.java @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.system.OsConstants.IFA_F_DADFAILED; +import static android.system.OsConstants.IFA_F_DEPRECATED; +import static android.system.OsConstants.IFA_F_OPTIMISTIC; +import static android.system.OsConstants.IFA_F_PERMANENT; +import static android.system.OsConstants.IFA_F_TENTATIVE; +import static android.system.OsConstants.RT_SCOPE_HOST; +import static android.system.OsConstants.RT_SCOPE_LINK; +import static android.system.OsConstants.RT_SCOPE_SITE; +import static android.system.OsConstants.RT_SCOPE_UNIVERSE; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.util.Pair; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +/** + * Identifies an IP address on a network link. + * + * A {@code LinkAddress} consists of: + *
    + *
  • An IP address and prefix length (e.g., {@code 2001:db8::1/64} or {@code 192.0.2.1/24}). + * The address must be unicast, as multicast addresses cannot be assigned to interfaces. + *
  • Address flags: A bitmask of {@code OsConstants.IFA_F_*} values representing properties + * of the address (e.g., {@code android.system.OsConstants.IFA_F_OPTIMISTIC}). + *
  • Address scope: One of the {@code OsConstants.IFA_F_*} values; defines the scope in which + * the address is unique (e.g., + * {@code android.system.OsConstants.RT_SCOPE_LINK} or + * {@code android.system.OsConstants.RT_SCOPE_UNIVERSE}). + *
+ */ +public class LinkAddress implements Parcelable { + + /** + * Indicates the deprecation or expiration time is unknown + * @hide + */ + @SystemApi + public static final long LIFETIME_UNKNOWN = -1; + + /** + * Indicates this address is permanent. + * @hide + */ + @SystemApi + public static final long LIFETIME_PERMANENT = Long.MAX_VALUE; + + /** + * IPv4 or IPv6 address. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + private InetAddress address; + + /** + * Prefix length. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + private int prefixLength; + + /** + * Address flags. A bitmask of {@code IFA_F_*} values. Note that {@link #getFlags()} may not + * return these exact values. For example, it may set or clear the {@code IFA_F_DEPRECATED} + * flag depending on the current preferred lifetime. + */ + private int flags; + + /** + * Address scope. One of the RT_SCOPE_* constants. + */ + private int scope; + + /** + * The time, as reported by {@link SystemClock#elapsedRealtime}, when this LinkAddress will be + * or was deprecated. At the time existing connections can still use this address until it + * expires, but new connections should use the new address. {@link #LIFETIME_UNKNOWN} indicates + * this information is not available. {@link #LIFETIME_PERMANENT} indicates this + * {@link LinkAddress} will never be deprecated. + */ + private long deprecationTime; + + /** + * The time, as reported by {@link SystemClock#elapsedRealtime}, when this {@link LinkAddress} + * will expire and be removed from the interface. {@link #LIFETIME_UNKNOWN} indicates this + * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} + * will never expire. + */ + private long expirationTime; + + /** + * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and + * RFC 6724 section 3.2. + * @hide + */ + private static int scopeForUnicastAddress(InetAddress addr) { + if (addr.isAnyLocalAddress()) { + return RT_SCOPE_HOST; + } + + if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { + return RT_SCOPE_LINK; + } + + // isSiteLocalAddress() returns true for private IPv4 addresses, but RFC 6724 section 3.2 + // says that they are assigned global scope. + if (!(addr instanceof Inet4Address) && addr.isSiteLocalAddress()) { + return RT_SCOPE_SITE; + } + + return RT_SCOPE_UNIVERSE; + } + + /** + * Utility function to check if |address| is a Unique Local IPv6 Unicast Address + * (a.k.a. "ULA"; RFC 4193). + * + * Per RFC 4193 section 8, fc00::/7 identifies these addresses. + */ + private boolean isIpv6ULA() { + if (isIpv6()) { + byte[] bytes = address.getAddress(); + return ((bytes[0] & (byte)0xfe) == (byte)0xfc); + } + return false; + } + + /** + * @return true if the address is IPv6. + * @hide + */ + @SystemApi + public boolean isIpv6() { + return address instanceof Inet6Address; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return true if the address is IPv6. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean isIPv6() { + return isIpv6(); + } + + /** + * @return true if the address is IPv4 or is a mapped IPv4 address. + * @hide + */ + @SystemApi + public boolean isIpv4() { + return address instanceof Inet4Address; + } + + /** + * Utility function for the constructors. + */ + private void init(InetAddress address, int prefixLength, int flags, int scope, + long deprecationTime, long expirationTime) { + if (address == null || + address.isMulticastAddress() || + prefixLength < 0 || + (address instanceof Inet4Address && prefixLength > 32) || + (prefixLength > 128)) { + throw new IllegalArgumentException("Bad LinkAddress params " + address + + "/" + prefixLength); + } + + // deprecation time and expiration time must be both provided, or neither. + if ((deprecationTime == LIFETIME_UNKNOWN) != (expirationTime == LIFETIME_UNKNOWN)) { + throw new IllegalArgumentException( + "Must not specify only one of deprecation time and expiration time"); + } + + // deprecation time needs to be a positive value. + if (deprecationTime != LIFETIME_UNKNOWN && deprecationTime < 0) { + throw new IllegalArgumentException("invalid deprecation time " + deprecationTime); + } + + // expiration time needs to be a positive value. + if (expirationTime != LIFETIME_UNKNOWN && expirationTime < 0) { + throw new IllegalArgumentException("invalid expiration time " + expirationTime); + } + + // expiration time can't be earlier than deprecation time + if (deprecationTime != LIFETIME_UNKNOWN && expirationTime != LIFETIME_UNKNOWN + && expirationTime < deprecationTime) { + throw new IllegalArgumentException("expiration earlier than deprecation (" + + deprecationTime + ", " + expirationTime + ")"); + } + + this.address = address; + this.prefixLength = prefixLength; + this.flags = flags; + this.scope = scope; + this.deprecationTime = deprecationTime; + this.expirationTime = expirationTime; + } + + /** + * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with + * the specified flags and scope. Flags and scope are not checked for validity. + * + * @param address The IP address. + * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. + * @param scope An integer defining the scope in which the address is unique (e.g., + * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). + * @hide + */ + @SystemApi + public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength, + int flags, int scope) { + init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); + } + + /** + * Constructs a new {@code LinkAddress} from an {@code InetAddress}, prefix length, with + * the specified flags, scope, deprecation time, and expiration time. Flags and scope are not + * checked for validity. The value of the {@code IFA_F_DEPRECATED} and {@code IFA_F_PERMANENT} + * flag will be adjusted based on the passed-in lifetimes. + * + * @param address The IP address. + * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. + * @param scope An integer defining the scope in which the address is unique (e.g., + * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). + * @param deprecationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when + * this {@link LinkAddress} will be or was deprecated. At the time + * existing connections can still use this address until it expires, but + * new connections should use the new address. {@link #LIFETIME_UNKNOWN} + * indicates this information is not available. + * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will + * never be deprecated. + * @param expirationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when this + * {@link LinkAddress} will expire and be removed from the interface. + * {@link #LIFETIME_UNKNOWN} indicates this information is not available. + * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will + * never expire. + * @hide + */ + @SystemApi + public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength, + int flags, int scope, long deprecationTime, long expirationTime) { + init(address, prefixLength, flags, scope, deprecationTime, expirationTime); + } + + /** + * Constructs a new {@code LinkAddress} from an {@code InetAddress} and a prefix length. + * The flags are set to zero and the scope is determined from the address. + * @param address The IP address. + * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * @hide + */ + @SystemApi + public LinkAddress(@NonNull InetAddress address, + @IntRange(from = 0, to = 128) int prefixLength) { + this(address, prefixLength, 0, 0); + this.scope = scopeForUnicastAddress(address); + } + + /** + * Constructs a new {@code LinkAddress} from an {@code InterfaceAddress}. + * The flags are set to zero and the scope is determined from the address. + * @param interfaceAddress The interface address. + * @hide + */ + public LinkAddress(@NonNull InterfaceAddress interfaceAddress) { + this(interfaceAddress.getAddress(), + interfaceAddress.getNetworkPrefixLength()); + } + + /** + * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or + * "2001:db8::1/64". The flags are set to zero and the scope is determined from the address. + * @param address The string to parse. + * @hide + */ + @SystemApi + public LinkAddress(@NonNull String address) { + this(address, 0, 0); + this.scope = scopeForUnicastAddress(this.address); + } + + /** + * Constructs a new {@code LinkAddress} from a string such as "192.0.2.5/24" or + * "2001:db8::1/64", with the specified flags and scope. + * @param address The string to parse. + * @param flags The address flags. + * @param scope The address scope. + * @hide + */ + @SystemApi + public LinkAddress(@NonNull String address, int flags, int scope) { + // This may throw an IllegalArgumentException; catching it is the caller's responsibility. + // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24". + Pair ipAndMask = NetworkUtils.parseIpAndMask(address); + init(ipAndMask.first, ipAndMask.second, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); + } + + /** + * Returns a string representation of this address, such as "192.0.2.1/24" or "2001:db8::1/64". + * The string representation does not contain the flags and scope, just the address and prefix + * length. + */ + @Override + public String toString() { + return address.getHostAddress() + "/" + prefixLength; + } + + /** + * Compares this {@code LinkAddress} instance against {@code obj}. Two addresses are equal if + * their address, prefix length, flags and scope are equal. Thus, for example, two addresses + * that have the same address and prefix length are not equal if one of them is deprecated and + * the other is not. + * + * @param obj the object to be tested for equality. + * @return {@code true} if both objects are equal, {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LinkAddress)) { + return false; + } + LinkAddress linkAddress = (LinkAddress) obj; + return this.address.equals(linkAddress.address) + && this.prefixLength == linkAddress.prefixLength + && this.flags == linkAddress.flags + && this.scope == linkAddress.scope + && this.deprecationTime == linkAddress.deprecationTime + && this.expirationTime == linkAddress.expirationTime; + } + + /** + * Returns a hashcode for this address. + */ + @Override + public int hashCode() { + return Objects.hash(address, prefixLength, flags, scope, deprecationTime, expirationTime); + } + + /** + * Determines whether this {@code LinkAddress} and the provided {@code LinkAddress} + * represent the same address. Two {@code LinkAddresses} represent the same address + * if they have the same IP address and prefix length, even if their properties are + * different. + * + * @param other the {@code LinkAddress} to compare to. + * @return {@code true} if both objects have the same address and prefix length, {@code false} + * otherwise. + * @hide + */ + @SystemApi + public boolean isSameAddressAs(@Nullable LinkAddress other) { + if (other == null) { + return false; + } + return address.equals(other.address) && prefixLength == other.prefixLength; + } + + /** + * Returns the {@link InetAddress} of this {@code LinkAddress}. + */ + public InetAddress getAddress() { + return address; + } + + /** + * Returns the prefix length of this {@code LinkAddress}. + */ + @IntRange(from = 0, to = 128) + public int getPrefixLength() { + return prefixLength; + } + + /** + * Returns the prefix length of this {@code LinkAddress}. + * TODO: Delete all callers and remove in favour of getPrefixLength(). + * @hide + */ + @UnsupportedAppUsage + @IntRange(from = 0, to = 128) + public int getNetworkPrefixLength() { + return getPrefixLength(); + } + + /** + * Returns the flags of this {@code LinkAddress}. + */ + public int getFlags() { + int flags = this.flags; + if (deprecationTime != LIFETIME_UNKNOWN) { + if (SystemClock.elapsedRealtime() >= deprecationTime) { + flags |= IFA_F_DEPRECATED; + } else { + // If deprecation time is in the future, or permanent. + flags &= ~IFA_F_DEPRECATED; + } + } + + if (expirationTime == LIFETIME_PERMANENT) { + flags |= IFA_F_PERMANENT; + } else if (expirationTime != LIFETIME_UNKNOWN) { + // If we know this address expired or will expire in the future, then this address + // should not be permanent. + flags &= ~IFA_F_PERMANENT; + } + + // Do no touch the original flags. Return the adjusted flags here. + return flags; + } + + /** + * Returns the scope of this {@code LinkAddress}. + */ + public int getScope() { + return scope; + } + + /** + * Get the deprecation time, as reported by {@link SystemClock#elapsedRealtime}, when this + * {@link LinkAddress} will be or was deprecated. At the time existing connections can still use + * this address until it expires, but new connections should use the new address. + * + * @return The deprecation time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this + * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} + * will never be deprecated. + * + * @hide + */ + @SystemApi + public long getDeprecationTime() { + return deprecationTime; + } + + /** + * Get the expiration time, as reported by {@link SystemClock#elapsedRealtime}, when this + * {@link LinkAddress} will expire and be removed from the interface. + * + * @return The expiration time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this + * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} + * will never expire. + * + * @hide + */ + @SystemApi + public long getExpirationTime() { + return expirationTime; + } + + /** + * Returns true if this {@code LinkAddress} is global scope and preferred (i.e., not currently + * deprecated). + * + * @hide + */ + @SystemApi + public boolean isGlobalPreferred() { + /** + * Note that addresses flagged as IFA_F_OPTIMISTIC are + * simultaneously flagged as IFA_F_TENTATIVE (when the tentative + * state has cleared either DAD has succeeded or failed, and both + * flags are cleared regardless). + */ + int flags = getFlags(); + return (scope == RT_SCOPE_UNIVERSE + && !isIpv6ULA() + && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L + && ((flags & IFA_F_TENTATIVE) == 0L || (flags & IFA_F_OPTIMISTIC) != 0L)); + } + + /** + * Implement the Parcelable interface. + */ + public int describeContents() { + return 0; + } + + /** + * Implement the Parcelable interface. + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(address.getAddress()); + dest.writeInt(prefixLength); + dest.writeInt(this.flags); + dest.writeInt(scope); + dest.writeLong(deprecationTime); + dest.writeLong(expirationTime); + } + + /** + * Implement the Parcelable interface. + */ + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public LinkAddress createFromParcel(Parcel in) { + InetAddress address = null; + try { + address = InetAddress.getByAddress(in.createByteArray()); + } catch (UnknownHostException e) { + // Nothing we can do here. When we call the constructor, we'll throw an + // IllegalArgumentException, because a LinkAddress can't have a null + // InetAddress. + } + int prefixLength = in.readInt(); + int flags = in.readInt(); + int scope = in.readInt(); + long deprecationTime = in.readLong(); + long expirationTime = in.readLong(); + return new LinkAddress(address, prefixLength, flags, scope, deprecationTime, + expirationTime); + } + + public LinkAddress[] newArray(int size) { + return new LinkAddress[size]; + } + }; +} diff --git a/framework/src/android/net/LinkProperties.aidl b/framework/src/android/net/LinkProperties.aidl new file mode 100644 index 0000000000..a8b3c7b039 --- /dev/null +++ b/framework/src/android/net/LinkProperties.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright (C) 2010 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +@JavaOnlyStableParcelable parcelable LinkProperties; diff --git a/framework/src/android/net/LinkProperties.java b/framework/src/android/net/LinkProperties.java new file mode 100644 index 0000000000..486e2d74dd --- /dev/null +++ b/framework/src/android/net/LinkProperties.java @@ -0,0 +1,1823 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.net.module.util.LinkPropertiesUtils; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Hashtable; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * Describes the properties of a network link. + * + * A link represents a connection to a network. + * It may have multiple addresses and multiple gateways, + * multiple dns servers but only one http proxy and one + * network interface. + * + * Note that this is just a holder of data. Modifying it + * does not affect live networks. + * + */ +public final class LinkProperties implements Parcelable { + // The interface described by the network link. + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + private String mIfaceName; + private final ArrayList mLinkAddresses = new ArrayList<>(); + private final ArrayList mDnses = new ArrayList<>(); + // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service. + private final ArrayList mPcscfs = new ArrayList(); + private final ArrayList mValidatedPrivateDnses = new ArrayList<>(); + private boolean mUsePrivateDns; + private String mPrivateDnsServerName; + private String mDomains; + private ArrayList mRoutes = new ArrayList<>(); + private Inet4Address mDhcpServerAddress; + private ProxyInfo mHttpProxy; + private int mMtu; + // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max" + private String mTcpBufferSizes; + private IpPrefix mNat64Prefix; + private boolean mWakeOnLanSupported; + private Uri mCaptivePortalApiUrl; + private CaptivePortalData mCaptivePortalData; + + /** + * Indicates whether parceling should preserve fields that are set based on permissions of + * the process receiving the {@link LinkProperties}. + */ + private final transient boolean mParcelSensitiveFields; + + private static final int MIN_MTU = 68; + + private static final int MIN_MTU_V6 = 1280; + + private static final int MAX_MTU = 10000; + + private static final int INET6_ADDR_LENGTH = 16; + + // Stores the properties of links that are "stacked" above this link. + // Indexed by interface name to allow modification and to prevent duplicates being added. + private Hashtable mStackedLinks = new Hashtable<>(); + + /** + * @hide + */ + @UnsupportedAppUsage(implicitMember = + "values()[Landroid/net/LinkProperties$ProvisioningChange;") + public enum ProvisioningChange { + @UnsupportedAppUsage + STILL_NOT_PROVISIONED, + @UnsupportedAppUsage + LOST_PROVISIONING, + @UnsupportedAppUsage + GAINED_PROVISIONING, + @UnsupportedAppUsage + STILL_PROVISIONED, + } + + /** + * Compare the provisioning states of two LinkProperties instances. + * + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static ProvisioningChange compareProvisioning( + LinkProperties before, LinkProperties after) { + if (before.isProvisioned() && after.isProvisioned()) { + // On dual-stack networks, DHCPv4 renewals can occasionally fail. + // When this happens, IPv6-reachable services continue to function + // normally but IPv4-only services (naturally) fail. + // + // When an application using an IPv4-only service reports a bad + // network condition to the framework, attempts to re-validate + // the network succeed (since we support IPv6-only networks) and + // nothing is changed. + // + // For users, this is confusing and unexpected behaviour, and is + // not necessarily easy to diagnose. Therefore, we treat changing + // from a dual-stack network to an IPv6-only network equivalent to + // a total loss of provisioning. + // + // For one such example of this, see b/18867306. + // + // Additionally, losing IPv6 provisioning can result in TCP + // connections getting stuck until timeouts fire and other + // baffling failures. Therefore, loss of either IPv4 or IPv6 on a + // previously dual-stack network is deemed a lost of provisioning. + if ((before.isIpv4Provisioned() && !after.isIpv4Provisioned()) + || (before.isIpv6Provisioned() && !after.isIpv6Provisioned())) { + return ProvisioningChange.LOST_PROVISIONING; + } + return ProvisioningChange.STILL_PROVISIONED; + } else if (before.isProvisioned() && !after.isProvisioned()) { + return ProvisioningChange.LOST_PROVISIONING; + } else if (!before.isProvisioned() && after.isProvisioned()) { + return ProvisioningChange.GAINED_PROVISIONING; + } else { // !before.isProvisioned() && !after.isProvisioned() + return ProvisioningChange.STILL_NOT_PROVISIONED; + } + } + + /** + * Constructs a new {@code LinkProperties} with default values. + */ + public LinkProperties() { + mParcelSensitiveFields = false; + } + + /** + * @hide + */ + @SystemApi + public LinkProperties(@Nullable LinkProperties source) { + this(source, false /* parcelSensitiveFields */); + } + + /** + * Create a copy of a {@link LinkProperties} that may preserve fields that were set + * based on the permissions of the process that originally received it. + * + *

By default {@link LinkProperties} does not preserve such fields during parceling, as + * they should not be shared outside of the process that receives them without appropriate + * checks. + * @param parcelSensitiveFields Whether the sensitive fields should be kept when parceling + * @hide + */ + @SystemApi + public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) { + mParcelSensitiveFields = parcelSensitiveFields; + if (source == null) return; + mIfaceName = source.mIfaceName; + mLinkAddresses.addAll(source.mLinkAddresses); + mDnses.addAll(source.mDnses); + mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses); + mUsePrivateDns = source.mUsePrivateDns; + mPrivateDnsServerName = source.mPrivateDnsServerName; + mPcscfs.addAll(source.mPcscfs); + mDomains = source.mDomains; + mRoutes.addAll(source.mRoutes); + mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy); + for (LinkProperties l: source.mStackedLinks.values()) { + addStackedLink(l); + } + setMtu(source.mMtu); + setDhcpServerAddress(source.getDhcpServerAddress()); + mTcpBufferSizes = source.mTcpBufferSizes; + mNat64Prefix = source.mNat64Prefix; + mWakeOnLanSupported = source.mWakeOnLanSupported; + mCaptivePortalApiUrl = source.mCaptivePortalApiUrl; + mCaptivePortalData = source.mCaptivePortalData; + } + + /** + * Sets the interface name for this link. All {@link RouteInfo} already set for this + * will have their interface changed to match this new value. + * + * @param iface The name of the network interface used for this link. + */ + public void setInterfaceName(@Nullable String iface) { + mIfaceName = iface; + ArrayList newRoutes = new ArrayList<>(mRoutes.size()); + for (RouteInfo route : mRoutes) { + newRoutes.add(routeWithInterface(route)); + } + mRoutes = newRoutes; + } + + /** + * Gets the interface name for this link. May be {@code null} if not set. + * + * @return The interface name set for this link or {@code null}. + */ + public @Nullable String getInterfaceName() { + return mIfaceName; + } + + /** + * @hide + */ + @SystemApi + public @NonNull List getAllInterfaceNames() { + List interfaceNames = new ArrayList<>(mStackedLinks.size() + 1); + if (mIfaceName != null) interfaceNames.add(mIfaceName); + for (LinkProperties stacked: mStackedLinks.values()) { + interfaceNames.addAll(stacked.getAllInterfaceNames()); + } + return interfaceNames; + } + + /** + * Returns all the addresses on this link. We often think of a link having a single address, + * however, particularly with Ipv6 several addresses are typical. Note that the + * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include + * prefix lengths for each address. This is a simplified utility alternative to + * {@link LinkProperties#getLinkAddresses}. + * + * @return An unmodifiable {@link List} of {@link InetAddress} for this link. + * @hide + */ + @SystemApi + public @NonNull List getAddresses() { + final List addresses = new ArrayList<>(); + for (LinkAddress linkAddress : mLinkAddresses) { + addresses.add(linkAddress.getAddress()); + } + return Collections.unmodifiableList(addresses); + } + + /** + * Returns all the addresses on this link and all the links stacked above it. + * @hide + */ + @UnsupportedAppUsage + public @NonNull List getAllAddresses() { + List addresses = new ArrayList<>(); + for (LinkAddress linkAddress : mLinkAddresses) { + addresses.add(linkAddress.getAddress()); + } + for (LinkProperties stacked: mStackedLinks.values()) { + addresses.addAll(stacked.getAllAddresses()); + } + return addresses; + } + + private int findLinkAddressIndex(LinkAddress address) { + for (int i = 0; i < mLinkAddresses.size(); i++) { + if (mLinkAddresses.get(i).isSameAddressAs(address)) { + return i; + } + } + return -1; + } + + /** + * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the + * same address/prefix does not already exist. If it does exist it is replaced. + * @param address The {@code LinkAddress} to add. + * @return true if {@code address} was added or updated, false otherwise. + * @hide + */ + @SystemApi + public boolean addLinkAddress(@NonNull LinkAddress address) { + if (address == null) { + return false; + } + int i = findLinkAddressIndex(address); + if (i < 0) { + // Address was not present. Add it. + mLinkAddresses.add(address); + return true; + } else if (mLinkAddresses.get(i).equals(address)) { + // Address was present and has same properties. Do nothing. + return false; + } else { + // Address was present and has different properties. Update it. + mLinkAddresses.set(i, address); + return true; + } + } + + /** + * Removes a {@link LinkAddress} from this {@code LinkProperties}. Specifically, matches + * and {@link LinkAddress} with the same address and prefix. + * + * @param toRemove A {@link LinkAddress} specifying the address to remove. + * @return true if the address was removed, false if it did not exist. + * @hide + */ + @SystemApi + public boolean removeLinkAddress(@NonNull LinkAddress toRemove) { + int i = findLinkAddressIndex(toRemove); + if (i >= 0) { + mLinkAddresses.remove(i); + return true; + } + return false; + } + + /** + * Returns all the {@link LinkAddress} on this link. Typically a link will have + * one IPv4 address and one or more IPv6 addresses. + * + * @return An unmodifiable {@link List} of {@link LinkAddress} for this link. + */ + public @NonNull List getLinkAddresses() { + return Collections.unmodifiableList(mLinkAddresses); + } + + /** + * Returns all the addresses on this link and all the links stacked above it. + * @hide + */ + @SystemApi + public @NonNull List getAllLinkAddresses() { + List addresses = new ArrayList<>(mLinkAddresses); + for (LinkProperties stacked: mStackedLinks.values()) { + addresses.addAll(stacked.getAllLinkAddresses()); + } + return addresses; + } + + /** + * Replaces the {@link LinkAddress} in this {@code LinkProperties} with + * the given {@link Collection} of {@link LinkAddress}. + * + * @param addresses The {@link Collection} of {@link LinkAddress} to set in this + * object. + */ + public void setLinkAddresses(@NonNull Collection addresses) { + mLinkAddresses.clear(); + for (LinkAddress address: addresses) { + addLinkAddress(address); + } + } + + /** + * Adds the given {@link InetAddress} to the list of DNS servers, if not present. + * + * @param dnsServer The {@link InetAddress} to add to the list of DNS servers. + * @return true if the DNS server was added, false if it was already present. + * @hide + */ + @SystemApi + public boolean addDnsServer(@NonNull InetAddress dnsServer) { + if (dnsServer != null && !mDnses.contains(dnsServer)) { + mDnses.add(dnsServer); + return true; + } + return false; + } + + /** + * Removes the given {@link InetAddress} from the list of DNS servers. + * + * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers. + * @return true if the DNS server was removed, false if it did not exist. + * @hide + */ + @SystemApi + public boolean removeDnsServer(@NonNull InetAddress dnsServer) { + return mDnses.remove(dnsServer); + } + + /** + * Replaces the DNS servers in this {@code LinkProperties} with + * the given {@link Collection} of {@link InetAddress} objects. + * + * @param dnsServers The {@link Collection} of DNS servers to set in this object. + */ + public void setDnsServers(@NonNull Collection dnsServers) { + mDnses.clear(); + for (InetAddress dnsServer: dnsServers) { + addDnsServer(dnsServer); + } + } + + /** + * Returns all the {@link InetAddress} for DNS servers on this link. + * + * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on + * this link. + */ + public @NonNull List getDnsServers() { + return Collections.unmodifiableList(mDnses); + } + + /** + * Set whether private DNS is currently in use on this network. + * + * @param usePrivateDns The private DNS state. + * @hide + */ + @SystemApi + public void setUsePrivateDns(boolean usePrivateDns) { + mUsePrivateDns = usePrivateDns; + } + + /** + * Returns whether private DNS is currently in use on this network. When + * private DNS is in use, applications must not send unencrypted DNS + * queries as doing so could reveal private user information. Furthermore, + * if private DNS is in use and {@link #getPrivateDnsServerName} is not + * {@code null}, DNS queries must be sent to the specified DNS server. + * + * @return {@code true} if private DNS is in use, {@code false} otherwise. + */ + public boolean isPrivateDnsActive() { + return mUsePrivateDns; + } + + /** + * Set the name of the private DNS server to which private DNS queries + * should be sent when in strict mode. This value should be {@code null} + * when private DNS is off or in opportunistic mode. + * + * @param privateDnsServerName The private DNS server name. + * @hide + */ + @SystemApi + public void setPrivateDnsServerName(@Nullable String privateDnsServerName) { + mPrivateDnsServerName = privateDnsServerName; + } + + /** + * Set DHCP server address. + * + * @param serverAddress the server address to set. + */ + public void setDhcpServerAddress(@Nullable Inet4Address serverAddress) { + mDhcpServerAddress = serverAddress; + } + + /** + * Get DHCP server address + * + * @return The current DHCP server address. + */ + public @Nullable Inet4Address getDhcpServerAddress() { + return mDhcpServerAddress; + } + + /** + * Returns the private DNS server name that is in use. If not {@code null}, + * private DNS is in strict mode. In this mode, applications should ensure + * that all DNS queries are encrypted and sent to this hostname and that + * queries are only sent if the hostname's certificate is valid. If + * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private + * DNS is in opportunistic mode, and applications should ensure that DNS + * queries are encrypted and sent to a DNS server returned by + * {@link #getDnsServers}. System DNS will handle each of these cases + * correctly, but applications implementing their own DNS lookups must make + * sure to follow these requirements. + * + * @return The private DNS server name. + */ + public @Nullable String getPrivateDnsServerName() { + return mPrivateDnsServerName; + } + + /** + * Adds the given {@link InetAddress} to the list of validated private DNS servers, + * if not present. This is distinct from the server name in that these are actually + * resolved addresses. + * + * @param dnsServer The {@link InetAddress} to add to the list of validated private DNS servers. + * @return true if the DNS server was added, false if it was already present. + * @hide + */ + public boolean addValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) { + if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) { + mValidatedPrivateDnses.add(dnsServer); + return true; + } + return false; + } + + /** + * Removes the given {@link InetAddress} from the list of validated private DNS servers. + * + * @param dnsServer The {@link InetAddress} to remove from the list of validated private DNS + * servers. + * @return true if the DNS server was removed, false if it did not exist. + * @hide + */ + public boolean removeValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) { + return mValidatedPrivateDnses.remove(dnsServer); + } + + /** + * Replaces the validated private DNS servers in this {@code LinkProperties} with + * the given {@link Collection} of {@link InetAddress} objects. + * + * @param dnsServers The {@link Collection} of validated private DNS servers to set in this + * object. + * @hide + */ + @SystemApi + public void setValidatedPrivateDnsServers(@NonNull Collection dnsServers) { + mValidatedPrivateDnses.clear(); + for (InetAddress dnsServer: dnsServers) { + addValidatedPrivateDnsServer(dnsServer); + } + } + + /** + * Returns all the {@link InetAddress} for validated private DNS servers on this link. + * These are resolved from the private DNS server name. + * + * @return An unmodifiable {@link List} of {@link InetAddress} for validated private + * DNS servers on this link. + * @hide + */ + @SystemApi + public @NonNull List getValidatedPrivateDnsServers() { + return Collections.unmodifiableList(mValidatedPrivateDnses); + } + + /** + * Adds the given {@link InetAddress} to the list of PCSCF servers, if not present. + * + * @param pcscfServer The {@link InetAddress} to add to the list of PCSCF servers. + * @return true if the PCSCF server was added, false otherwise. + * @hide + */ + @SystemApi + public boolean addPcscfServer(@NonNull InetAddress pcscfServer) { + if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) { + mPcscfs.add(pcscfServer); + return true; + } + return false; + } + + /** + * Removes the given {@link InetAddress} from the list of PCSCF servers. + * + * @param pcscfServer The {@link InetAddress} to remove from the list of PCSCF servers. + * @return true if the PCSCF server was removed, false otherwise. + * @hide + */ + public boolean removePcscfServer(@NonNull InetAddress pcscfServer) { + return mPcscfs.remove(pcscfServer); + } + + /** + * Replaces the PCSCF servers in this {@code LinkProperties} with + * the given {@link Collection} of {@link InetAddress} objects. + * + * @param pcscfServers The {@link Collection} of PCSCF servers to set in this object. + * @hide + */ + @SystemApi + public void setPcscfServers(@NonNull Collection pcscfServers) { + mPcscfs.clear(); + for (InetAddress pcscfServer: pcscfServers) { + addPcscfServer(pcscfServer); + } + } + + /** + * Returns all the {@link InetAddress} for PCSCF servers on this link. + * + * @return An unmodifiable {@link List} of {@link InetAddress} for PCSCF servers on + * this link. + * @hide + */ + @SystemApi + public @NonNull List getPcscfServers() { + return Collections.unmodifiableList(mPcscfs); + } + + /** + * Sets the DNS domain search path used on this link. + * + * @param domains A {@link String} listing in priority order the comma separated + * domains to search when resolving host names on this link. + */ + public void setDomains(@Nullable String domains) { + mDomains = domains; + } + + /** + * Get the DNS domains search path set for this link. May be {@code null} if not set. + * + * @return A {@link String} containing the comma separated domains to search when resolving host + * names on this link or {@code null}. + */ + public @Nullable String getDomains() { + return mDomains; + } + + /** + * Sets the Maximum Transmission Unit size to use on this link. This should not be used + * unless the system default (1500) is incorrect. Values less than 68 or greater than + * 10000 will be ignored. + * + * @param mtu The MTU to use for this link. + */ + public void setMtu(int mtu) { + mMtu = mtu; + } + + /** + * Gets any non-default MTU size set for this link. Note that if the default is being used + * this will return 0. + * + * @return The mtu value set for this link. + */ + public int getMtu() { + return mMtu; + } + + /** + * Sets the tcp buffers sizes to be used when this link is the system default. + * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max". + * + * @param tcpBufferSizes The tcp buffers sizes to use. + * + * @hide + */ + @SystemApi + public void setTcpBufferSizes(@Nullable String tcpBufferSizes) { + mTcpBufferSizes = tcpBufferSizes; + } + + /** + * Gets the tcp buffer sizes. May be {@code null} if not set. + * + * @return the tcp buffer sizes to use when this link is the system default or {@code null}. + * + * @hide + */ + @SystemApi + public @Nullable String getTcpBufferSizes() { + return mTcpBufferSizes; + } + + private RouteInfo routeWithInterface(RouteInfo route) { + return new RouteInfo( + route.getDestination(), + route.getGateway(), + mIfaceName, + route.getType(), + route.getMtu()); + } + + private int findRouteIndexByRouteKey(RouteInfo route) { + for (int i = 0; i < mRoutes.size(); i++) { + if (mRoutes.get(i).getRouteKey().equals(route.getRouteKey())) { + return i; + } + } + return -1; + } + + /** + * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo} + * with the same {@link RouteInfo.RouteKey} with different properties + * (e.g., different MTU), it will be updated. If the {@link RouteInfo} had an + * interface name set and that differs from the interface set for this + * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. + * The proper course is to add either un-named or properly named {@link RouteInfo}. + * + * @param route A {@link RouteInfo} to add to this object. + * @return {@code true} was added or updated, false otherwise. + */ + public boolean addRoute(@NonNull RouteInfo route) { + String routeIface = route.getInterface(); + if (routeIface != null && !routeIface.equals(mIfaceName)) { + throw new IllegalArgumentException( + "Route added with non-matching interface: " + routeIface + + " vs. " + mIfaceName); + } + route = routeWithInterface(route); + + int i = findRouteIndexByRouteKey(route); + if (i == -1) { + // Route was not present. Add it. + mRoutes.add(route); + return true; + } else if (mRoutes.get(i).equals(route)) { + // Route was present and has same properties. Do nothing. + return false; + } else { + // Route was present and has different properties. Update it. + mRoutes.set(i, route); + return true; + } + } + + /** + * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must + * specify an interface and the interface must match the interface of this + * {@code LinkProperties}, or it will not be removed. + * + * @param route A {@link RouteInfo} specifying the route to remove. + * @return {@code true} if the route was removed, {@code false} if it was not present. + * + * @hide + */ + @SystemApi + public boolean removeRoute(@NonNull RouteInfo route) { + return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route); + } + + /** + * Returns all the {@link RouteInfo} set on this link. + * + * @return An unmodifiable {@link List} of {@link RouteInfo} for this link. + */ + public @NonNull List getRoutes() { + return Collections.unmodifiableList(mRoutes); + } + + /** + * Make sure this LinkProperties instance contains routes that cover the local subnet + * of its link addresses. Add any route that is missing. + * @hide + */ + public void ensureDirectlyConnectedRoutes() { + for (LinkAddress addr : mLinkAddresses) { + addRoute(new RouteInfo(addr, null, mIfaceName)); + } + } + + /** + * Returns all the routes on this link and all the links stacked above it. + * @hide + */ + @SystemApi + public @NonNull List getAllRoutes() { + List routes = new ArrayList<>(mRoutes); + for (LinkProperties stacked: mStackedLinks.values()) { + routes.addAll(stacked.getAllRoutes()); + } + return routes; + } + + /** + * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none. + * Note that Http Proxies are only a hint - the system recommends their use, but it does + * not enforce it and applications may ignore them. + * + * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link. + */ + public void setHttpProxy(@Nullable ProxyInfo proxy) { + mHttpProxy = proxy; + } + + /** + * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link. + * + * @return The {@link ProxyInfo} set on this link or {@code null}. + */ + public @Nullable ProxyInfo getHttpProxy() { + return mHttpProxy; + } + + /** + * Returns the NAT64 prefix in use on this link, if any. + * + * @return the NAT64 prefix or {@code null}. + */ + public @Nullable IpPrefix getNat64Prefix() { + return mNat64Prefix; + } + + /** + * Sets the NAT64 prefix in use on this link. + * + * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the + * 128-bit IPv6 address) are supported or {@code null} for no prefix. + * + * @param prefix the NAT64 prefix. + */ + public void setNat64Prefix(@Nullable IpPrefix prefix) { + if (prefix != null && prefix.getPrefixLength() != 96) { + throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix); + } + mNat64Prefix = prefix; // IpPrefix objects are immutable. + } + + /** + * Adds a stacked link. + * + * If there is already a stacked link with the same interface name as link, + * that link is replaced with link. Otherwise, link is added to the list + * of stacked links. + * + * @param link The link to add. + * @return true if the link was stacked, false otherwise. + * @hide + */ + @UnsupportedAppUsage + public boolean addStackedLink(@NonNull LinkProperties link) { + if (link.getInterfaceName() != null) { + mStackedLinks.put(link.getInterfaceName(), link); + return true; + } + return false; + } + + /** + * Removes a stacked link. + * + * If there is a stacked link with the given interface name, it is + * removed. Otherwise, nothing changes. + * + * @param iface The interface name of the link to remove. + * @return true if the link was removed, false otherwise. + * @hide + */ + public boolean removeStackedLink(@NonNull String iface) { + LinkProperties removed = mStackedLinks.remove(iface); + return removed != null; + } + + /** + * Returns all the links stacked on top of this link. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public @NonNull List getStackedLinks() { + if (mStackedLinks.isEmpty()) { + return Collections.emptyList(); + } + final List stacked = new ArrayList<>(); + for (LinkProperties link : mStackedLinks.values()) { + stacked.add(new LinkProperties(link)); + } + return Collections.unmodifiableList(stacked); + } + + /** + * Clears this object to its initial state. + */ + public void clear() { + if (mParcelSensitiveFields) { + throw new UnsupportedOperationException( + "Cannot clear LinkProperties when parcelSensitiveFields is set"); + } + + mIfaceName = null; + mLinkAddresses.clear(); + mDnses.clear(); + mUsePrivateDns = false; + mPrivateDnsServerName = null; + mPcscfs.clear(); + mDomains = null; + mRoutes.clear(); + mHttpProxy = null; + mStackedLinks.clear(); + mMtu = 0; + mDhcpServerAddress = null; + mTcpBufferSizes = null; + mNat64Prefix = null; + mWakeOnLanSupported = false; + mCaptivePortalApiUrl = null; + mCaptivePortalData = null; + } + + /** + * Implement the Parcelable interface + */ + public int describeContents() { + return 0; + } + + @Override + public String toString() { + // Space as a separator, so no need for spaces at start/end of the individual fragments. + final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}"); + + if (mIfaceName != null) { + resultJoiner.add("InterfaceName:"); + resultJoiner.add(mIfaceName); + } + + resultJoiner.add("LinkAddresses: ["); + if (!mLinkAddresses.isEmpty()) { + resultJoiner.add(TextUtils.join(",", mLinkAddresses)); + } + resultJoiner.add("]"); + + resultJoiner.add("DnsAddresses: ["); + if (!mDnses.isEmpty()) { + resultJoiner.add(TextUtils.join(",", mDnses)); + } + resultJoiner.add("]"); + + if (mUsePrivateDns) { + resultJoiner.add("UsePrivateDns: true"); + } + + if (mPrivateDnsServerName != null) { + resultJoiner.add("PrivateDnsServerName:"); + resultJoiner.add(mPrivateDnsServerName); + } + + if (!mPcscfs.isEmpty()) { + resultJoiner.add("PcscfAddresses: ["); + resultJoiner.add(TextUtils.join(",", mPcscfs)); + resultJoiner.add("]"); + } + + if (!mValidatedPrivateDnses.isEmpty()) { + final StringJoiner validatedPrivateDnsesJoiner = + new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]"); + for (final InetAddress addr : mValidatedPrivateDnses) { + validatedPrivateDnsesJoiner.add(addr.getHostAddress()); + } + resultJoiner.add(validatedPrivateDnsesJoiner.toString()); + } + + resultJoiner.add("Domains:"); + resultJoiner.add(mDomains); + + resultJoiner.add("MTU:"); + resultJoiner.add(Integer.toString(mMtu)); + + if (mWakeOnLanSupported) { + resultJoiner.add("WakeOnLanSupported: true"); + } + + if (mDhcpServerAddress != null) { + resultJoiner.add("ServerAddress:"); + resultJoiner.add(mDhcpServerAddress.toString()); + } + + if (mCaptivePortalApiUrl != null) { + resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl); + } + + if (mCaptivePortalData != null) { + resultJoiner.add("CaptivePortalData: " + mCaptivePortalData); + } + + if (mTcpBufferSizes != null) { + resultJoiner.add("TcpBufferSizes:"); + resultJoiner.add(mTcpBufferSizes); + } + + resultJoiner.add("Routes: ["); + if (!mRoutes.isEmpty()) { + resultJoiner.add(TextUtils.join(",", mRoutes)); + } + resultJoiner.add("]"); + + if (mHttpProxy != null) { + resultJoiner.add("HttpProxy:"); + resultJoiner.add(mHttpProxy.toString()); + } + + if (mNat64Prefix != null) { + resultJoiner.add("Nat64Prefix:"); + resultJoiner.add(mNat64Prefix.toString()); + } + + final Collection stackedLinksValues = mStackedLinks.values(); + if (!stackedLinksValues.isEmpty()) { + final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]"); + for (final LinkProperties lp : stackedLinksValues) { + stackedLinksJoiner.add("[ " + lp + " ]"); + } + resultJoiner.add(stackedLinksJoiner.toString()); + } + + return resultJoiner.toString(); + } + + /** + * Returns true if this link has an IPv4 address. + * + * @return {@code true} if there is an IPv4 address, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean hasIpv4Address() { + for (LinkAddress address : mLinkAddresses) { + if (address.getAddress() instanceof Inet4Address) { + return true; + } + } + return false; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv4 address, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv4Address() { + return hasIpv4Address(); + } + + /** + * Returns true if this link or any of its stacked interfaces has an IPv4 address. + * + * @return {@code true} if there is an IPv4 address, {@code false} otherwise. + */ + private boolean hasIpv4AddressOnInterface(String iface) { + // mIfaceName can be null. + return (Objects.equals(iface, mIfaceName) && hasIpv4Address()) + || (iface != null && mStackedLinks.containsKey(iface) + && mStackedLinks.get(iface).hasIpv4Address()); + } + + /** + * Returns true if this link has a global preferred IPv6 address. + * + * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean hasGlobalIpv6Address() { + for (LinkAddress address : mLinkAddresses) { + if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) { + return true; + } + } + return false; + } + + /** + * Returns true if this link has an IPv4 unreachable default route. + * + * @return {@code true} if there is an IPv4 unreachable default route, {@code false} otherwise. + * @hide + */ + public boolean hasIpv4UnreachableDefaultRoute() { + for (RouteInfo r : mRoutes) { + if (r.isIPv4UnreachableDefault()) { + return true; + } + } + return false; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasGlobalIPv6Address() { + return hasGlobalIpv6Address(); + } + + /** + * Returns true if this link has an IPv4 default route. + * + * @return {@code true} if there is an IPv4 default route, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean hasIpv4DefaultRoute() { + for (RouteInfo r : mRoutes) { + if (r.isIPv4Default()) { + return true; + } + } + return false; + } + + /** + * Returns true if this link has an IPv6 unreachable default route. + * + * @return {@code true} if there is an IPv6 unreachable default route, {@code false} otherwise. + * @hide + */ + public boolean hasIpv6UnreachableDefaultRoute() { + for (RouteInfo r : mRoutes) { + if (r.isIPv6UnreachableDefault()) { + return true; + } + } + return false; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv4 default route, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv4DefaultRoute() { + return hasIpv4DefaultRoute(); + } + + /** + * Returns true if this link has an IPv6 default route. + * + * @return {@code true} if there is an IPv6 default route, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean hasIpv6DefaultRoute() { + for (RouteInfo r : mRoutes) { + if (r.isIPv6Default()) { + return true; + } + } + return false; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv6 default route, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv6DefaultRoute() { + return hasIpv6DefaultRoute(); + } + + /** + * Returns true if this link has an IPv4 DNS server. + * + * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean hasIpv4DnsServer() { + for (InetAddress ia : mDnses) { + if (ia instanceof Inet4Address) { + return true; + } + } + return false; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv4DnsServer() { + return hasIpv4DnsServer(); + } + + /** + * Returns true if this link has an IPv6 DNS server. + * + * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean hasIpv6DnsServer() { + for (InetAddress ia : mDnses) { + if (ia instanceof Inet6Address) { + return true; + } + } + return false; + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean hasIPv6DnsServer() { + return hasIpv6DnsServer(); + } + + /** + * Returns true if this link has an IPv4 PCSCF server. + * + * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise. + * @hide + */ + public boolean hasIpv4PcscfServer() { + for (InetAddress ia : mPcscfs) { + if (ia instanceof Inet4Address) { + return true; + } + } + return false; + } + + /** + * Returns true if this link has an IPv6 PCSCF server. + * + * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise. + * @hide + */ + public boolean hasIpv6PcscfServer() { + for (InetAddress ia : mPcscfs) { + if (ia instanceof Inet6Address) { + return true; + } + } + return false; + } + + /** + * Returns true if this link is provisioned for global IPv4 connectivity. + * This requires an IP address, default route, and DNS server. + * + * @return {@code true} if the link is provisioned, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean isIpv4Provisioned() { + return (hasIpv4Address() + && hasIpv4DefaultRoute() + && hasIpv4DnsServer()); + } + + /** + * Returns true if this link is provisioned for global IPv6 connectivity. + * This requires an IP address, default route, and DNS server. + * + * @return {@code true} if the link is provisioned, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean isIpv6Provisioned() { + return (hasGlobalIpv6Address() + && hasIpv6DefaultRoute() + && hasIpv6DnsServer()); + } + + /** + * For backward compatibility. + * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely + * just yet. + * @return {@code true} if the link is provisioned, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + public boolean isIPv6Provisioned() { + return isIpv6Provisioned(); + } + + + /** + * Returns true if this link is provisioned for global connectivity, + * for at least one Internet Protocol family. + * + * @return {@code true} if the link is provisioned, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean isProvisioned() { + return (isIpv4Provisioned() || isIpv6Provisioned()); + } + + /** + * Evaluate whether the {@link InetAddress} is considered reachable. + * + * @return {@code true} if the given {@link InetAddress} is considered reachable, + * {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean isReachable(@NonNull InetAddress ip) { + final List allRoutes = getAllRoutes(); + // If we don't have a route to this IP address, it's not reachable. + final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip); + if (bestRoute == null) { + return false; + } + + // TODO: better source address evaluation for destination addresses. + + if (ip instanceof Inet4Address) { + // For IPv4, it suffices for now to simply have any address. + return hasIpv4AddressOnInterface(bestRoute.getInterface()); + } else if (ip instanceof Inet6Address) { + if (ip.isLinkLocalAddress()) { + // For now, just make sure link-local destinations have + // scopedIds set, since transmits will generally fail otherwise. + // TODO: verify it matches the ifindex of one of the interfaces. + return (((Inet6Address)ip).getScopeId() != 0); + } else { + // For non-link-local destinations check that either the best route + // is directly connected or that some global preferred address exists. + // TODO: reconsider all cases (disconnected ULA networks, ...). + return (!bestRoute.hasGateway() || hasGlobalIpv6Address()); + } + } + + return false; + } + + /** + * Compares this {@code LinkProperties} interface name against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage + public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) { + return LinkPropertiesUtils.isIdenticalInterfaceName(target, this); + } + + /** + * Compares this {@code LinkProperties} DHCP server address against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalDhcpServerAddress(@NonNull LinkProperties target) { + return Objects.equals(mDhcpServerAddress, target.mDhcpServerAddress); + } + + /** + * Compares this {@code LinkProperties} interface addresses against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage + public boolean isIdenticalAddresses(@NonNull LinkProperties target) { + return LinkPropertiesUtils.isIdenticalAddresses(target, this); + } + + /** + * Compares this {@code LinkProperties} DNS addresses against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage + public boolean isIdenticalDnses(@NonNull LinkProperties target) { + return LinkPropertiesUtils.isIdenticalDnses(target, this); + } + + /** + * Compares this {@code LinkProperties} private DNS settings against the + * target. + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalPrivateDns(@NonNull LinkProperties target) { + return (isPrivateDnsActive() == target.isPrivateDnsActive() + && TextUtils.equals(getPrivateDnsServerName(), + target.getPrivateDnsServerName())); + } + + /** + * Compares this {@code LinkProperties} validated private DNS addresses against + * the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalValidatedPrivateDnses(@NonNull LinkProperties target) { + Collection targetDnses = target.getValidatedPrivateDnsServers(); + return (mValidatedPrivateDnses.size() == targetDnses.size()) + ? mValidatedPrivateDnses.containsAll(targetDnses) : false; + } + + /** + * Compares this {@code LinkProperties} PCSCF addresses against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalPcscfs(@NonNull LinkProperties target) { + Collection targetPcscfs = target.getPcscfServers(); + return (mPcscfs.size() == targetPcscfs.size()) ? + mPcscfs.containsAll(targetPcscfs) : false; + } + + /** + * Compares this {@code LinkProperties} Routes against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage + public boolean isIdenticalRoutes(@NonNull LinkProperties target) { + return LinkPropertiesUtils.isIdenticalRoutes(target, this); + } + + /** + * Compares this {@code LinkProperties} HttpProxy against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) { + return LinkPropertiesUtils.isIdenticalHttpProxy(target, this); + } + + /** + * Compares this {@code LinkProperties} stacked links against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public boolean isIdenticalStackedLinks(@NonNull LinkProperties target) { + if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) { + return false; + } + for (LinkProperties stacked : mStackedLinks.values()) { + // Hashtable values can never be null. + String iface = stacked.getInterfaceName(); + if (!stacked.equals(target.mStackedLinks.get(iface))) { + return false; + } + } + return true; + } + + /** + * Compares this {@code LinkProperties} MTU against the target + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalMtu(@NonNull LinkProperties target) { + return getMtu() == target.getMtu(); + } + + /** + * Compares this {@code LinkProperties} Tcp buffer sizes against the target. + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalTcpBufferSizes(@NonNull LinkProperties target) { + return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes); + } + + /** + * Compares this {@code LinkProperties} NAT64 prefix against the target. + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalNat64Prefix(@NonNull LinkProperties target) { + return Objects.equals(mNat64Prefix, target.mNat64Prefix); + } + + /** + * Compares this {@code LinkProperties} WakeOnLan supported against the target. + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalWakeOnLan(LinkProperties target) { + return isWakeOnLanSupported() == target.isWakeOnLanSupported(); + } + + /** + * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target. + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) { + return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl); + } + + /** + * Compares this {@code LinkProperties}'s CaptivePortalData against the target. + * + * @param target LinkProperties to compare. + * @return {@code true} if both are identical, {@code false} otherwise. + * @hide + */ + public boolean isIdenticalCaptivePortalData(LinkProperties target) { + return Objects.equals(mCaptivePortalData, target.mCaptivePortalData); + } + + /** + * Set whether the network interface supports WakeOnLAN + * + * @param supported WakeOnLAN supported value + * + * @hide + */ + public void setWakeOnLanSupported(boolean supported) { + mWakeOnLanSupported = supported; + } + + /** + * Returns whether the network interface supports WakeOnLAN + * + * @return {@code true} if interface supports WakeOnLAN, {@code false} otherwise. + */ + public boolean isWakeOnLanSupported() { + return mWakeOnLanSupported; + } + + /** + * Set the URL of the captive portal API endpoint to get more information about the network. + * @hide + */ + @SystemApi + public void setCaptivePortalApiUrl(@Nullable Uri url) { + mCaptivePortalApiUrl = url; + } + + /** + * Get the URL of the captive portal API endpoint to get more information about the network. + * + *

This is null unless the application has + * {@link android.Manifest.permission.NETWORK_SETTINGS} or + * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided + * the URL. + * @hide + */ + @SystemApi + @Nullable + public Uri getCaptivePortalApiUrl() { + return mCaptivePortalApiUrl; + } + + /** + * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis). + * @hide + */ + @SystemApi + public void setCaptivePortalData(@Nullable CaptivePortalData data) { + mCaptivePortalData = data; + } + + /** + * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis). + * + *

This is null unless the application has + * {@link android.Manifest.permission.NETWORK_SETTINGS} or + * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions. + * @hide + */ + @SystemApi + @Nullable + public CaptivePortalData getCaptivePortalData() { + return mCaptivePortalData; + } + + /** + * Compares this {@code LinkProperties} instance against the target + * LinkProperties in {@code obj}. Two LinkPropertieses are equal if + * all their fields are equal in values. + * + * For collection fields, such as mDnses, containsAll() is used to check + * if two collections contains the same elements, independent of order. + * There are two thoughts regarding containsAll() + * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal. + * 2. Worst case performance is O(n^2). + * + * @param obj the object to be tested for equality. + * @return {@code true} if both objects are equal, {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + + if (!(obj instanceof LinkProperties)) return false; + + LinkProperties target = (LinkProperties) obj; + /* + * This method does not check that stacked interfaces are equal, because + * stacked interfaces are not so much a property of the link as a + * description of connections between links. + */ + return isIdenticalInterfaceName(target) + && isIdenticalAddresses(target) + && isIdenticalDhcpServerAddress(target) + && isIdenticalDnses(target) + && isIdenticalPrivateDns(target) + && isIdenticalValidatedPrivateDnses(target) + && isIdenticalPcscfs(target) + && isIdenticalRoutes(target) + && isIdenticalHttpProxy(target) + && isIdenticalStackedLinks(target) + && isIdenticalMtu(target) + && isIdenticalTcpBufferSizes(target) + && isIdenticalNat64Prefix(target) + && isIdenticalWakeOnLan(target) + && isIdenticalCaptivePortalApiUrl(target) + && isIdenticalCaptivePortalData(target); + } + + /** + * Generate hashcode based on significant fields + * + * Equal objects must produce the same hash code, while unequal objects + * may have the same hash codes. + */ + @Override + public int hashCode() { + return ((null == mIfaceName) ? 0 : mIfaceName.hashCode() + + mLinkAddresses.size() * 31 + + mDnses.size() * 37 + + mValidatedPrivateDnses.size() * 61 + + ((null == mDomains) ? 0 : mDomains.hashCode()) + + mRoutes.size() * 41 + + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()) + + mStackedLinks.hashCode() * 47) + + mMtu * 51 + + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode()) + + (mUsePrivateDns ? 57 : 0) + + ((null == mDhcpServerAddress) ? 0 : mDhcpServerAddress.hashCode()) + + mPcscfs.size() * 67 + + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode()) + + Objects.hash(mNat64Prefix) + + (mWakeOnLanSupported ? 71 : 0) + + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData); + } + + /** + * Implement the Parcelable interface. + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(getInterfaceName()); + dest.writeInt(mLinkAddresses.size()); + for (LinkAddress linkAddress : mLinkAddresses) { + dest.writeParcelable(linkAddress, flags); + } + + writeAddresses(dest, mDnses); + writeAddresses(dest, mValidatedPrivateDnses); + dest.writeBoolean(mUsePrivateDns); + dest.writeString(mPrivateDnsServerName); + writeAddresses(dest, mPcscfs); + dest.writeString(mDomains); + writeAddress(dest, mDhcpServerAddress); + dest.writeInt(mMtu); + dest.writeString(mTcpBufferSizes); + dest.writeInt(mRoutes.size()); + for (RouteInfo route : mRoutes) { + dest.writeParcelable(route, flags); + } + + if (mHttpProxy != null) { + dest.writeByte((byte)1); + dest.writeParcelable(mHttpProxy, flags); + } else { + dest.writeByte((byte)0); + } + dest.writeParcelable(mNat64Prefix, 0); + + ArrayList stackedLinks = new ArrayList<>(mStackedLinks.values()); + dest.writeList(stackedLinks); + + dest.writeBoolean(mWakeOnLanSupported); + dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0); + dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0); + } + + private static void writeAddresses(@NonNull Parcel dest, @NonNull List list) { + dest.writeInt(list.size()); + for (InetAddress d : list) { + writeAddress(dest, d); + } + } + + private static void writeAddress(@NonNull Parcel dest, @Nullable InetAddress addr) { + byte[] addressBytes = (addr == null ? null : addr.getAddress()); + dest.writeByteArray(addressBytes); + if (addr instanceof Inet6Address) { + final Inet6Address v6Addr = (Inet6Address) addr; + final boolean hasScopeId = v6Addr.getScopeId() != 0; + dest.writeBoolean(hasScopeId); + if (hasScopeId) dest.writeInt(v6Addr.getScopeId()); + } + } + + @Nullable + private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException { + final byte[] addr = p.createByteArray(); + if (addr == null) return null; + + if (addr.length == INET6_ADDR_LENGTH) { + final boolean hasScopeId = p.readBoolean(); + final int scopeId = hasScopeId ? p.readInt() : 0; + return Inet6Address.getByAddress(null /* host */, addr, scopeId); + } + + return InetAddress.getByAddress(addr); + } + + /** + * Implement the Parcelable interface. + */ + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public LinkProperties createFromParcel(Parcel in) { + LinkProperties netProp = new LinkProperties(); + + String iface = in.readString(); + if (iface != null) { + netProp.setInterfaceName(iface); + } + int addressCount = in.readInt(); + for (int i = 0; i < addressCount; i++) { + netProp.addLinkAddress(in.readParcelable(null)); + } + addressCount = in.readInt(); + for (int i = 0; i < addressCount; i++) { + try { + netProp.addDnsServer(readAddress(in)); + } catch (UnknownHostException e) { } + } + addressCount = in.readInt(); + for (int i = 0; i < addressCount; i++) { + try { + netProp.addValidatedPrivateDnsServer(readAddress(in)); + } catch (UnknownHostException e) { } + } + netProp.setUsePrivateDns(in.readBoolean()); + netProp.setPrivateDnsServerName(in.readString()); + addressCount = in.readInt(); + for (int i = 0; i < addressCount; i++) { + try { + netProp.addPcscfServer(readAddress(in)); + } catch (UnknownHostException e) { } + } + netProp.setDomains(in.readString()); + try { + netProp.setDhcpServerAddress((Inet4Address) InetAddress + .getByAddress(in.createByteArray())); + } catch (UnknownHostException e) { } + netProp.setMtu(in.readInt()); + netProp.setTcpBufferSizes(in.readString()); + addressCount = in.readInt(); + for (int i = 0; i < addressCount; i++) { + netProp.addRoute(in.readParcelable(null)); + } + if (in.readByte() == 1) { + netProp.setHttpProxy(in.readParcelable(null)); + } + netProp.setNat64Prefix(in.readParcelable(null)); + ArrayList stackedLinks = new ArrayList(); + in.readList(stackedLinks, LinkProperties.class.getClassLoader()); + for (LinkProperties stackedLink: stackedLinks) { + netProp.addStackedLink(stackedLink); + } + netProp.setWakeOnLanSupported(in.readBoolean()); + + netProp.setCaptivePortalApiUrl(in.readParcelable(null)); + netProp.setCaptivePortalData(in.readParcelable(null)); + return netProp; + } + + public LinkProperties[] newArray(int size) { + return new LinkProperties[size]; + } + }; + + /** + * Check the valid MTU range based on IPv4 or IPv6. + * @hide + */ + public static boolean isValidMtu(int mtu, boolean ipv6) { + if (ipv6) { + return mtu >= MIN_MTU_V6 && mtu <= MAX_MTU; + } else { + return mtu >= MIN_MTU && mtu <= MAX_MTU; + } + } +} diff --git a/framework/src/android/net/MacAddress.aidl b/framework/src/android/net/MacAddress.aidl new file mode 100644 index 0000000000..48a18a7ac8 --- /dev/null +++ b/framework/src/android/net/MacAddress.aidl @@ -0,0 +1,20 @@ +/** + * + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +@JavaOnlyStableParcelable parcelable MacAddress; diff --git a/framework/src/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java new file mode 100644 index 0000000000..c7116b41e8 --- /dev/null +++ b/framework/src/android/net/MacAddress.java @@ -0,0 +1,400 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.compat.annotation.UnsupportedAppUsage; +import android.net.wifi.WifiInfo; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; +import com.android.net.module.util.MacAddressUtils; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.Inet6Address; +import java.net.UnknownHostException; +import java.security.SecureRandom; +import java.util.Arrays; + +/** + * Representation of a MAC address. + * + * This class only supports 48 bits long addresses and does not support 64 bits long addresses. + * Instances of this class are immutable. This class provides implementations of hashCode() + * and equals() that make it suitable for use as keys in standard implementations of + * {@link java.util.Map}. + */ +public final class MacAddress implements Parcelable { + + private static final int ETHER_ADDR_LEN = 6; + private static final byte[] ETHER_ADDR_BROADCAST = addr(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + + /** + * The MacAddress representing the unique broadcast MAC address. + */ + public static final MacAddress BROADCAST_ADDRESS = MacAddress.fromBytes(ETHER_ADDR_BROADCAST); + + /** + * The MacAddress zero MAC address. + * + *

Not publicly exposed or treated specially since the OUI 00:00:00 is registered. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final MacAddress ALL_ZEROS_ADDRESS = new MacAddress(0); + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "TYPE_" }, value = { + TYPE_UNKNOWN, + TYPE_UNICAST, + TYPE_MULTICAST, + TYPE_BROADCAST, + }) + public @interface MacAddressType { } + + /** @hide Indicates a MAC address of unknown type. */ + public static final int TYPE_UNKNOWN = 0; + /** Indicates a MAC address is a unicast address. */ + public static final int TYPE_UNICAST = 1; + /** Indicates a MAC address is a multicast address. */ + public static final int TYPE_MULTICAST = 2; + /** Indicates a MAC address is the broadcast address. */ + public static final int TYPE_BROADCAST = 3; + + private static final long VALID_LONG_MASK = (1L << 48) - 1; + private static final long LOCALLY_ASSIGNED_MASK = MacAddress.fromString("2:0:0:0:0:0").mAddr; + private static final long MULTICAST_MASK = MacAddress.fromString("1:0:0:0:0:0").mAddr; + private static final long OUI_MASK = MacAddress.fromString("ff:ff:ff:0:0:0").mAddr; + private static final long NIC_MASK = MacAddress.fromString("0:0:0:ff:ff:ff").mAddr; + private static final MacAddress BASE_GOOGLE_MAC = MacAddress.fromString("da:a1:19:0:0:0"); + /** Default wifi MAC address used for a special purpose **/ + private static final MacAddress DEFAULT_MAC_ADDRESS = + MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); + + // Internal representation of the MAC address as a single 8 byte long. + // The encoding scheme sets the two most significant bytes to 0. The 6 bytes of the + // MAC address are encoded in the 6 least significant bytes of the long, where the first + // byte of the array is mapped to the 3rd highest logical byte of the long, the second + // byte of the array is mapped to the 4th highest logical byte of the long, and so on. + private final long mAddr; + + private MacAddress(long addr) { + mAddr = (VALID_LONG_MASK & addr); + } + + /** + * Returns the type of this address. + * + * @return the int constant representing the MAC address type of this MacAddress. + */ + public @MacAddressType int getAddressType() { + if (equals(BROADCAST_ADDRESS)) { + return TYPE_BROADCAST; + } + if ((mAddr & MULTICAST_MASK) != 0) { + return TYPE_MULTICAST; + } + return TYPE_UNICAST; + } + + /** + * @return true if this MacAddress is a locally assigned address. + */ + public boolean isLocallyAssigned() { + return (mAddr & LOCALLY_ASSIGNED_MASK) != 0; + } + + /** + * Convert this MacAddress to a byte array. + * + * The returned array is in network order. For example, if this MacAddress is 1:2:3:4:5:6, + * the returned array is [1, 2, 3, 4, 5, 6]. + * + * @return a byte array representation of this MacAddress. + */ + public @NonNull byte[] toByteArray() { + return byteAddrFromLongAddr(mAddr); + } + + /** + * Returns a human-readable representation of this MacAddress. + * The exact format is implementation-dependent and should not be assumed to have any + * particular format. + */ + @Override + public @NonNull String toString() { + return stringAddrFromLongAddr(mAddr); + } + + /** + * @return a String representation of the OUI part of this MacAddress made of 3 hexadecimal + * numbers in [0,ff] joined by ':' characters. + */ + public @NonNull String toOuiString() { + return String.format( + "%02x:%02x:%02x", (mAddr >> 40) & 0xff, (mAddr >> 32) & 0xff, (mAddr >> 24) & 0xff); + } + + @Override + public int hashCode() { + return (int) ((mAddr >> 32) ^ mAddr); + } + + @Override + public boolean equals(Object o) { + return (o instanceof MacAddress) && ((MacAddress) o).mAddr == mAddr; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeLong(mAddr); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public MacAddress createFromParcel(Parcel in) { + return new MacAddress(in.readLong()); + } + + public MacAddress[] newArray(int size) { + return new MacAddress[size]; + } + }; + + /** + * Returns true if the given byte array is an valid MAC address. + * A valid byte array representation for a MacAddress is a non-null array of length 6. + * + * @param addr a byte array. + * @return true if the given byte array is not null and has the length of a MAC address. + * + * @hide + */ + public static boolean isMacAddress(byte[] addr) { + return MacAddressUtils.isMacAddress(addr); + } + + /** + * Returns the MAC address type of the MAC address represented by the given byte array, + * or null if the given byte array does not represent a MAC address. + * A valid byte array representation for a MacAddress is a non-null array of length 6. + * + * @param addr a byte array representing a MAC address. + * @return the int constant representing the MAC address type of the MAC address represented + * by the given byte array, or type UNKNOWN if the byte array is not a valid MAC address. + * + * @hide + */ + public static int macAddressType(byte[] addr) { + if (!isMacAddress(addr)) { + return TYPE_UNKNOWN; + } + return MacAddress.fromBytes(addr).getAddressType(); + } + + /** + * Converts a String representation of a MAC address to a byte array representation. + * A valid String representation for a MacAddress is a series of 6 values in the + * range [0,ff] printed in hexadecimal and joined by ':' characters. + * + * @param addr a String representation of a MAC address. + * @return the byte representation of the MAC address. + * @throws IllegalArgumentException if the given String is not a valid representation. + * + * @hide + */ + public static @NonNull byte[] byteAddrFromStringAddr(String addr) { + Preconditions.checkNotNull(addr); + String[] parts = addr.split(":"); + if (parts.length != ETHER_ADDR_LEN) { + throw new IllegalArgumentException(addr + " was not a valid MAC address"); + } + byte[] bytes = new byte[ETHER_ADDR_LEN]; + for (int i = 0; i < ETHER_ADDR_LEN; i++) { + int x = Integer.valueOf(parts[i], 16); + if (x < 0 || 0xff < x) { + throw new IllegalArgumentException(addr + "was not a valid MAC address"); + } + bytes[i] = (byte) x; + } + return bytes; + } + + /** + * Converts a byte array representation of a MAC address to a String representation made + * of 6 hexadecimal numbers in [0,ff] joined by ':' characters. + * A valid byte array representation for a MacAddress is a non-null array of length 6. + * + * @param addr a byte array representation of a MAC address. + * @return the String representation of the MAC address. + * @throws IllegalArgumentException if the given byte array is not a valid representation. + * + * @hide + */ + public static @NonNull String stringAddrFromByteAddr(byte[] addr) { + if (!isMacAddress(addr)) { + return null; + } + return String.format("%02x:%02x:%02x:%02x:%02x:%02x", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + } + + private static byte[] byteAddrFromLongAddr(long addr) { + return MacAddressUtils.byteAddrFromLongAddr(addr); + } + + private static long longAddrFromByteAddr(byte[] addr) { + return MacAddressUtils.longAddrFromByteAddr(addr); + } + + // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) + // that avoids the allocation of an intermediary byte[]. + private static long longAddrFromStringAddr(String addr) { + Preconditions.checkNotNull(addr); + String[] parts = addr.split(":"); + if (parts.length != ETHER_ADDR_LEN) { + throw new IllegalArgumentException(addr + " was not a valid MAC address"); + } + long longAddr = 0; + for (int i = 0; i < parts.length; i++) { + int x = Integer.valueOf(parts[i], 16); + if (x < 0 || 0xff < x) { + throw new IllegalArgumentException(addr + "was not a valid MAC address"); + } + longAddr = x + (longAddr << 8); + } + return longAddr; + } + + // Internal conversion function equivalent to stringAddrFromByteAddr(byteAddrFromLongAddr(addr)) + // that avoids the allocation of an intermediary byte[]. + private static @NonNull String stringAddrFromLongAddr(long addr) { + return String.format("%02x:%02x:%02x:%02x:%02x:%02x", + (addr >> 40) & 0xff, + (addr >> 32) & 0xff, + (addr >> 24) & 0xff, + (addr >> 16) & 0xff, + (addr >> 8) & 0xff, + addr & 0xff); + } + + /** + * Creates a MacAddress from the given String representation. A valid String representation + * for a MacAddress is a series of 6 values in the range [0,ff] printed in hexadecimal + * and joined by ':' characters. + * + * @param addr a String representation of a MAC address. + * @return the MacAddress corresponding to the given String representation. + * @throws IllegalArgumentException if the given String is not a valid representation. + */ + public static @NonNull MacAddress fromString(@NonNull String addr) { + return new MacAddress(longAddrFromStringAddr(addr)); + } + + /** + * Creates a MacAddress from the given byte array representation. + * A valid byte array representation for a MacAddress is a non-null array of length 6. + * + * @param addr a byte array representation of a MAC address. + * @return the MacAddress corresponding to the given byte array representation. + * @throws IllegalArgumentException if the given byte array is not a valid representation. + */ + public static @NonNull MacAddress fromBytes(@NonNull byte[] addr) { + return new MacAddress(longAddrFromByteAddr(addr)); + } + + /** + * Returns a generated MAC address whose 24 least significant bits constituting the + * NIC part of the address are randomly selected and has Google OUI base. + * + * The locally assigned bit is always set to 1. The multicast bit is always set to 0. + * + * @return a random locally assigned, unicast MacAddress with Google OUI. + * + * @hide + */ + public static @NonNull MacAddress createRandomUnicastAddressWithGoogleBase() { + return MacAddressUtils.createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom()); + } + + // Convenience function for working around the lack of byte literals. + private static byte[] addr(int... in) { + if (in.length != ETHER_ADDR_LEN) { + throw new IllegalArgumentException(Arrays.toString(in) + + " was not an array with length equal to " + ETHER_ADDR_LEN); + } + byte[] out = new byte[ETHER_ADDR_LEN]; + for (int i = 0; i < ETHER_ADDR_LEN; i++) { + out[i] = (byte) in[i]; + } + return out; + } + + /** + * Checks if this MAC Address matches the provided range. + * + * @param baseAddress MacAddress representing the base address to compare with. + * @param mask MacAddress representing the mask to use during comparison. + * @return true if this MAC Address matches the given range. + * + */ + public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) { + Preconditions.checkNotNull(baseAddress); + Preconditions.checkNotNull(mask); + return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr); + } + + /** + * Create a link-local Inet6Address from the MAC address. The EUI-48 MAC address is converted + * to an EUI-64 MAC address per RFC 4291. The resulting EUI-64 is used to construct a link-local + * IPv6 address per RFC 4862. + * + * @return A link-local Inet6Address constructed from the MAC address. + */ + public @Nullable Inet6Address getLinkLocalIpv6FromEui48Mac() { + byte[] macEui48Bytes = toByteArray(); + byte[] addr = new byte[16]; + + addr[0] = (byte) 0xfe; + addr[1] = (byte) 0x80; + addr[8] = (byte) (macEui48Bytes[0] ^ (byte) 0x02); // flip the link-local bit + addr[9] = macEui48Bytes[1]; + addr[10] = macEui48Bytes[2]; + addr[11] = (byte) 0xff; + addr[12] = (byte) 0xfe; + addr[13] = macEui48Bytes[3]; + addr[14] = macEui48Bytes[4]; + addr[15] = macEui48Bytes[5]; + + try { + return Inet6Address.getByAddress(null, addr, 0); + } catch (UnknownHostException e) { + return null; + } + } +} diff --git a/framework/src/android/net/NattKeepalivePacketData.java b/framework/src/android/net/NattKeepalivePacketData.java new file mode 100644 index 0000000000..c4f8fc281f --- /dev/null +++ b/framework/src/android/net/NattKeepalivePacketData.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; +import static android.net.InvalidPacketException.ERROR_INVALID_PORT; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.system.OsConstants; + +import com.android.net.module.util.IpUtils; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Objects; + +/** @hide */ +@SystemApi +public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable { + private static final int IPV4_HEADER_LENGTH = 20; + private static final int UDP_HEADER_LENGTH = 8; + + // This should only be constructed via static factory methods, such as + // nattKeepalivePacket + public NattKeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort, + @NonNull InetAddress dstAddress, int dstPort, @NonNull byte[] data) throws + InvalidPacketException { + super(srcAddress, srcPort, dstAddress, dstPort, data); + } + + /** + * Factory method to create Nat-T keepalive packet structure. + * @hide + */ + public static NattKeepalivePacketData nattKeepalivePacket( + InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort) + throws InvalidPacketException { + + if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) { + throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); + } + + if (dstPort != NattSocketKeepalive.NATT_PORT) { + throw new InvalidPacketException(ERROR_INVALID_PORT); + } + + int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; + ByteBuffer buf = ByteBuffer.allocate(length); + buf.order(ByteOrder.BIG_ENDIAN); + buf.putShort((short) 0x4500); // IP version and TOS + buf.putShort((short) length); + buf.putInt(0); // ID, flags, offset + buf.put((byte) 64); // TTL + buf.put((byte) OsConstants.IPPROTO_UDP); + int ipChecksumOffset = buf.position(); + buf.putShort((short) 0); // IP checksum + buf.put(srcAddress.getAddress()); + buf.put(dstAddress.getAddress()); + buf.putShort((short) srcPort); + buf.putShort((short) dstPort); + buf.putShort((short) (length - 20)); // UDP length + int udpChecksumOffset = buf.position(); + buf.putShort((short) 0); // UDP checksum + buf.put((byte) 0xff); // NAT-T keepalive + buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); + buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); + + return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); + } + + /** Parcelable Implementation */ + public int describeContents() { + return 0; + } + + /** Write to parcel */ + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); + } + + /** Parcelable Creator */ + public static final @NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public NattKeepalivePacketData createFromParcel(Parcel in) { + final InetAddress srcAddress = + InetAddresses.parseNumericAddress(in.readString()); + final InetAddress dstAddress = + InetAddresses.parseNumericAddress(in.readString()); + final int srcPort = in.readInt(); + final int dstPort = in.readInt(); + try { + return NattKeepalivePacketData.nattKeepalivePacket(srcAddress, srcPort, + dstAddress, dstPort); + } catch (InvalidPacketException e) { + throw new IllegalArgumentException( + "Invalid NAT-T keepalive data: " + e.getError()); + } + } + + public NattKeepalivePacketData[] newArray(int size) { + return new NattKeepalivePacketData[size]; + } + }; + + @Override + public boolean equals(@Nullable final Object o) { + if (!(o instanceof NattKeepalivePacketData)) return false; + final NattKeepalivePacketData other = (NattKeepalivePacketData) o; + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort(); + } + + @Override + public int hashCode() { + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort()); + } +} diff --git a/framework/src/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java new file mode 100644 index 0000000000..a15d165e65 --- /dev/null +++ b/framework/src/android/net/NattSocketKeepalive.java @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package android.net; + +import android.annotation.NonNull; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import java.net.InetAddress; +import java.util.concurrent.Executor; + +/** @hide */ +public final class NattSocketKeepalive extends SocketKeepalive { + /** The NAT-T destination port for IPsec */ + public static final int NATT_PORT = 4500; + + @NonNull private final InetAddress mSource; + @NonNull private final InetAddress mDestination; + private final int mResourceId; + + NattSocketKeepalive(@NonNull IConnectivityManager service, + @NonNull Network network, + @NonNull ParcelFileDescriptor pfd, + int resourceId, + @NonNull InetAddress source, + @NonNull InetAddress destination, + @NonNull Executor executor, + @NonNull Callback callback) { + super(service, network, pfd, executor, callback); + mSource = source; + mDestination = destination; + mResourceId = resourceId; + } + + @Override + void startImpl(int intervalSec) { + mExecutor.execute(() -> { + try { + mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId, + intervalSec, mCallback, + mSource.getHostAddress(), mDestination.getHostAddress()); + } catch (RemoteException e) { + Log.e(TAG, "Error starting socket keepalive: ", e); + throw e.rethrowFromSystemServer(); + } + }); + } + + @Override + void stopImpl() { + mExecutor.execute(() -> { + try { + if (mSlot != null) { + mService.stopKeepalive(mNetwork, mSlot); + } + } catch (RemoteException e) { + Log.e(TAG, "Error stopping socket keepalive: ", e); + throw e.rethrowFromSystemServer(); + } + }); + } +} diff --git a/framework/src/android/net/Network.aidl b/framework/src/android/net/Network.aidl new file mode 100644 index 0000000000..05622025bf --- /dev/null +++ b/framework/src/android/net/Network.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright (C) 2014 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +@JavaOnlyStableParcelable parcelable Network; diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java new file mode 100644 index 0000000000..b07bd68a0f --- /dev/null +++ b/framework/src/android/net/Network.java @@ -0,0 +1,535 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; +import android.util.proto.ProtoOutputStream; + +import com.android.internal.annotations.GuardedBy; +import com.android.okhttp.internalandroidapi.Dns; +import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory; + +import libcore.io.IoUtils; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.URL; +import java.net.URLConnection; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import javax.net.SocketFactory; + +/** + * Identifies a {@code Network}. This is supplied to applications via + * {@link ConnectivityManager.NetworkCallback} in response to the active + * {@link ConnectivityManager#requestNetwork} or passive + * {@link ConnectivityManager#registerNetworkCallback} calls. + * It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis + * through a targeted {@link SocketFactory} or process-wide via + * {@link ConnectivityManager#bindProcessToNetwork}. + */ +public class Network implements Parcelable { + + /** + * The unique id of the network. + * @hide + */ + @UnsupportedAppUsage + public final int netId; + + // Objects used to perform per-network operations such as getSocketFactory + // and openConnection, and a lock to protect access to them. + private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; + // mUrlConnectionFactory is initialized lazily when it is first needed. + @GuardedBy("mLock") + private HttpURLConnectionFactory mUrlConnectionFactory; + private final Object mLock = new Object(); + + // Default connection pool values. These are evaluated at startup, just + // like the OkHttp code. Also like the OkHttp code, we will throw parse + // exceptions at class loading time if the properties are set but are not + // valid integers. + private static final boolean httpKeepAlive = + Boolean.parseBoolean(System.getProperty("http.keepAlive", "true")); + private static final int httpMaxConnections = + httpKeepAlive ? Integer.parseInt(System.getProperty("http.maxConnections", "5")) : 0; + private static final long httpKeepAliveDurationMs = + Long.parseLong(System.getProperty("http.keepAliveDuration", "300000")); // 5 minutes. + // Value used to obfuscate network handle longs. + // The HANDLE_MAGIC value MUST be kept in sync with the corresponding + // value in the native/android/net.c NDK implementation. + private static final long HANDLE_MAGIC = 0xcafed00dL; + private static final int HANDLE_MAGIC_SIZE = 32; + + // A boolean to control how getAllByName()/getByName() behaves in the face + // of Private DNS. + // + // When true, these calls will request that DNS resolution bypass any + // Private DNS that might otherwise apply. Use of this feature is restricted + // and permission checks are made by netd (attempts to bypass Private DNS + // without appropriate permission are silently turned into vanilla DNS + // requests). This only affects DNS queries made using this network object. + // + // It it not parceled to receivers because (a) it can be set or cleared at + // anytime and (b) receivers should be explicit about attempts to bypass + // Private DNS so that the intent of the code is easily determined and + // code search audits are possible. + private final transient boolean mPrivateDnsBypass; + + /** + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public Network(int netId) { + this(netId, false); + } + + /** + * @hide + */ + public Network(int netId, boolean privateDnsBypass) { + this.netId = netId; + this.mPrivateDnsBypass = privateDnsBypass; + } + + /** + * @hide + */ + @SystemApi + public Network(@NonNull Network that) { + this(that.netId, that.mPrivateDnsBypass); + } + + /** + * Operates the same as {@code InetAddress.getAllByName} except that host + * resolution is done on this network. + * + * @param host the hostname or literal IP string to be resolved. + * @return the array of addresses associated with the specified host. + * @throws UnknownHostException if the address lookup fails. + */ + public InetAddress[] getAllByName(String host) throws UnknownHostException { + return InetAddress.getAllByNameOnNet(host, getNetIdForResolv()); + } + + /** + * Operates the same as {@code InetAddress.getByName} except that host + * resolution is done on this network. + * + * @param host the hostname to be resolved to an address or {@code null}. + * @return the {@code InetAddress} instance representing the host. + * @throws UnknownHostException + * if the address lookup fails. + */ + public InetAddress getByName(String host) throws UnknownHostException { + return InetAddress.getByNameOnNet(host, getNetIdForResolv()); + } + + /** + * Obtain a Network object for which Private DNS is to be bypassed when attempting + * to use {@link #getAllByName(String)}/{@link #getByName(String)} methods on the given + * instance for hostname resolution. + * + * @hide + */ + @SystemApi + public @NonNull Network getPrivateDnsBypassingCopy() { + return new Network(netId, true); + } + + /** + * Get the unique id of the network. + * + * @hide + */ + @SystemApi + public int getNetId() { + return netId; + } + + /** + * Returns a netid marked with the Private DNS bypass flag. + * + * This flag must be kept in sync with the NETID_USE_LOCAL_NAMESERVERS flag + * in system/netd/include/NetdClient.h. + * + * @hide + */ + public int getNetIdForResolv() { + return mPrivateDnsBypass + ? (int) (0x80000000L | (long) netId) // Non-portable DNS resolution flag. + : netId; + } + + /** + * A {@code SocketFactory} that produces {@code Socket}'s bound to this network. + */ + private class NetworkBoundSocketFactory extends SocketFactory { + private Socket connectToHost(String host, int port, SocketAddress localAddress) + throws IOException { + // Lookup addresses only on this Network. + InetAddress[] hostAddresses = getAllByName(host); + // Try all addresses. + for (int i = 0; i < hostAddresses.length; i++) { + try { + Socket socket = createSocket(); + boolean failed = true; + try { + if (localAddress != null) socket.bind(localAddress); + socket.connect(new InetSocketAddress(hostAddresses[i], port)); + failed = false; + return socket; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } + } catch (IOException e) { + if (i == (hostAddresses.length - 1)) throw e; + } + } + throw new UnknownHostException(host); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) + throws IOException { + return connectToHost(host, port, new InetSocketAddress(localHost, localPort)); + } + + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, + int localPort) throws IOException { + Socket socket = createSocket(); + boolean failed = true; + try { + socket.bind(new InetSocketAddress(localAddress, localPort)); + socket.connect(new InetSocketAddress(address, port)); + failed = false; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } + return socket; + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + Socket socket = createSocket(); + boolean failed = true; + try { + socket.connect(new InetSocketAddress(host, port)); + failed = false; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } + return socket; + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + return connectToHost(host, port, null); + } + + @Override + public Socket createSocket() throws IOException { + Socket socket = new Socket(); + boolean failed = true; + try { + bindSocket(socket); + failed = false; + } finally { + if (failed) IoUtils.closeQuietly(socket); + } + return socket; + } + } + + /** + * Returns a {@link SocketFactory} bound to this network. Any {@link Socket} created by + * this factory will have its traffic sent over this {@code Network}. Note that if this + * {@code Network} ever disconnects, this factory and any {@link Socket} it produced in the + * past or future will cease to work. + * + * @return a {@link SocketFactory} which produces {@link Socket} instances bound to this + * {@code Network}. + */ + public SocketFactory getSocketFactory() { + if (mNetworkBoundSocketFactory == null) { + synchronized (mLock) { + if (mNetworkBoundSocketFactory == null) { + mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(); + } + } + } + return mNetworkBoundSocketFactory; + } + + private static HttpURLConnectionFactory createUrlConnectionFactory(Dns dnsLookup) { + // Set configuration on the HttpURLConnectionFactory that will be good for all + // connections created by this Network. Configuration that might vary is left + // until openConnection() and passed as arguments. + HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory(); + urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup + // A private connection pool just for this Network. + urlConnectionFactory.setNewConnectionPool(httpMaxConnections, + httpKeepAliveDurationMs, TimeUnit.MILLISECONDS); + return urlConnectionFactory; + } + + /** + * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent + * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}. + * + * @return a {@code URLConnection} to the resource referred to by this URL. + * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS. + * @throws IOException if an error occurs while opening the connection. + * @see java.net.URL#openConnection() + */ + public URLConnection openConnection(URL url) throws IOException { + final ConnectivityManager cm = ConnectivityManager.getInstanceOrNull(); + if (cm == null) { + throw new IOException("No ConnectivityManager yet constructed, please construct one"); + } + // TODO: Should this be optimized to avoid fetching the global proxy for every request? + final ProxyInfo proxyInfo = cm.getProxyForNetwork(this); + final java.net.Proxy proxy; + if (proxyInfo != null) { + proxy = proxyInfo.makeProxy(); + } else { + proxy = java.net.Proxy.NO_PROXY; + } + return openConnection(url, proxy); + } + + /** + * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent + * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}. + * + * @param proxy the proxy through which the connection will be established. + * @return a {@code URLConnection} to the resource referred to by this URL. + * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS. + * @throws IllegalArgumentException if the argument proxy is null. + * @throws IOException if an error occurs while opening the connection. + * @see java.net.URL#openConnection() + */ + public URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException { + if (proxy == null) throw new IllegalArgumentException("proxy is null"); + // TODO: This creates a connection pool and host resolver for + // every Network object, instead of one for every NetId. This is + // suboptimal, because an app could potentially have more than one + // Network object for the same NetId, causing increased memory footprint + // and performance penalties due to lack of connection reuse (connection + // setup time, congestion window growth time, etc.). + // + // Instead, investigate only having one connection pool and host resolver + // for every NetId, perhaps by using a static HashMap of NetIds to + // connection pools and host resolvers. The tricky part is deciding when + // to remove a map entry; a WeakHashMap shouldn't be used because whether + // a Network is referenced doesn't correlate with whether a new Network + // will be instantiated in the near future with the same NetID. A good + // solution would involve purging empty (or when all connections are timed + // out) ConnectionPools. + final HttpURLConnectionFactory urlConnectionFactory; + synchronized (mLock) { + if (mUrlConnectionFactory == null) { + Dns dnsLookup = hostname -> Arrays.asList(getAllByName(hostname)); + mUrlConnectionFactory = createUrlConnectionFactory(dnsLookup); + } + urlConnectionFactory = mUrlConnectionFactory; + } + SocketFactory socketFactory = getSocketFactory(); + return urlConnectionFactory.openConnection(url, socketFactory, proxy); + } + + /** + * Binds the specified {@link DatagramSocket} to this {@code Network}. All data traffic on the + * socket will be sent on this {@code Network}, irrespective of any process-wide network binding + * set by {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be + * connected. + */ + public void bindSocket(DatagramSocket socket) throws IOException { + // Query a property of the underlying socket to ensure that the socket's file descriptor + // exists, is available to bind to a network and is not closed. + socket.getReuseAddress(); + final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket); + bindSocket(pfd.getFileDescriptor()); + // ParcelFileDescriptor.fromSocket() creates a dup of the original fd. The original and the + // dup share the underlying socket in the kernel. The socket is never truly closed until the + // last fd pointing to the socket being closed. So close the dup one after binding the + // socket to control the lifetime of the dup fd. + pfd.close(); + } + + /** + * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket + * will be sent on this {@code Network}, irrespective of any process-wide network binding set by + * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected. + */ + public void bindSocket(Socket socket) throws IOException { + // Query a property of the underlying socket to ensure that the socket's file descriptor + // exists, is available to bind to a network and is not closed. + socket.getReuseAddress(); + final ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); + bindSocket(pfd.getFileDescriptor()); + // ParcelFileDescriptor.fromSocket() creates a dup of the original fd. The original and the + // dup share the underlying socket in the kernel. The socket is never truly closed until the + // last fd pointing to the socket being closed. So close the dup one after binding the + // socket to control the lifetime of the dup fd. + pfd.close(); + } + + /** + * Binds the specified {@link FileDescriptor} to this {@code Network}. All data traffic on the + * socket represented by this file descriptor will be sent on this {@code Network}, + * irrespective of any process-wide network binding set by + * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected. + */ + public void bindSocket(FileDescriptor fd) throws IOException { + try { + final SocketAddress peer = Os.getpeername(fd); + final InetAddress inetPeer = ((InetSocketAddress) peer).getAddress(); + if (!inetPeer.isAnyLocalAddress()) { + // Apparently, the kernel doesn't update a connected UDP socket's + // routing upon mark changes. + throw new SocketException("Socket is connected"); + } + } catch (ErrnoException e) { + // getpeername() failed. + if (e.errno != OsConstants.ENOTCONN) { + throw e.rethrowAsSocketException(); + } + } catch (ClassCastException e) { + // Wasn't an InetSocketAddress. + throw new SocketException("Only AF_INET/AF_INET6 sockets supported"); + } + + final int err = NetworkUtils.bindSocketToNetwork(fd, netId); + if (err != 0) { + // bindSocketToNetwork returns negative errno. + throw new ErrnoException("Binding socket to network " + netId, -err) + .rethrowAsSocketException(); + } + } + + /** + * Returns a {@link Network} object given a handle returned from {@link #getNetworkHandle}. + * + * @param networkHandle a handle returned from {@link #getNetworkHandle}. + * @return A {@link Network} object derived from {@code networkHandle}. + */ + public static Network fromNetworkHandle(long networkHandle) { + if (networkHandle == 0) { + throw new IllegalArgumentException( + "Network.fromNetworkHandle refusing to instantiate NETID_UNSET Network."); + } + if ((networkHandle & ((1L << HANDLE_MAGIC_SIZE) - 1)) != HANDLE_MAGIC + || networkHandle < 0) { + throw new IllegalArgumentException( + "Value passed to fromNetworkHandle() is not a network handle."); + } + return new Network((int) (networkHandle >> HANDLE_MAGIC_SIZE)); + } + + /** + * Returns a handle representing this {@code Network}, for use with the NDK API. + */ + public long getNetworkHandle() { + // The network handle is explicitly not the same as the netId. + // + // The netId is an implementation detail which might be changed in the + // future, or which alone (i.e. in the absence of some additional + // context) might not be sufficient to fully identify a Network. + // + // As such, the intention is to prevent accidental misuse of the API + // that might result if a developer assumed that handles and netIds + // were identical and passing a netId to a call expecting a handle + // "just worked". Such accidental misuse, if widely deployed, might + // prevent future changes to the semantics of the netId field or + // inhibit the expansion of state required for Network objects. + // + // This extra layer of indirection might be seen as paranoia, and might + // never end up being necessary, but the added complexity is trivial. + // At some future date it may be desirable to realign the handle with + // Multiple Provisioning Domains API recommendations, as made by the + // IETF mif working group. + if (netId == 0) { + return 0L; // make this zero condition obvious for debugging + } + return (((long) netId) << HANDLE_MAGIC_SIZE) | HANDLE_MAGIC; + } + + // implement the Parcelable interface + public int describeContents() { + return 0; + } + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(netId); + } + + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public Network createFromParcel(Parcel in) { + int netId = in.readInt(); + + return new Network(netId); + } + + public Network[] newArray(int size) { + return new Network[size]; + } + }; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Network)) return false; + Network other = (Network)obj; + return this.netId == other.netId; + } + + @Override + public int hashCode() { + return netId * 11; + } + + @Override + public String toString() { + return Integer.toString(netId); + } + + /** @hide */ + public void dumpDebug(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(NetworkProto.NET_ID, netId); + proto.end(token); + } +} diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java new file mode 100644 index 0000000000..d22d82d1f4 --- /dev/null +++ b/framework/src/android/net/NetworkAgent.java @@ -0,0 +1,1185 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.os.Build; +import android.os.Bundle; +import android.os.ConditionVariable; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.telephony.data.EpsBearerQosSessionAttributes; +import android.util.Log; + +import com.android.connectivity.aidl.INetworkAgent; +import com.android.connectivity.aidl.INetworkAgentRegistry; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Protocol; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * A utility class for handling for communicating between bearer-specific + * code and ConnectivityService. + * + * An agent manages the life cycle of a network. A network starts its + * life cycle when {@link register} is called on NetworkAgent. The network + * is then connecting. When full L3 connectivity has been established, + * the agent should call {@link markConnected} to inform the system that + * this network is ready to use. When the network disconnects its life + * ends and the agent should call {@link unregister}, at which point the + * system will clean up and free resources. + * Any reconnection becomes a new logical network, so after a network + * is disconnected the agent cannot be used any more. Network providers + * should create a new NetworkAgent instance to handle new connections. + * + * A bearer may have more than one NetworkAgent if it can simultaneously + * support separate networks (IMS / Internet / MMS Apns on cellular, or + * perhaps connections with different SSID or P2P for Wi-Fi). + * + * This class supports methods to start and stop sending keepalive packets. + * Keepalive packets are typically sent at periodic intervals over a network + * with NAT when there is no other traffic to avoid the network forcefully + * closing the connection. NetworkAgents that manage technologies that + * have hardware support for keepalive should implement the related + * methods to save battery life. NetworkAgent that cannot get support + * without waking up the CPU should not, as this would be prohibitive in + * terms of battery - these agents should simply not override the related + * methods, which results in the implementation returning + * {@link SocketKeepalive.ERROR_UNSUPPORTED} as appropriate. + * + * Keepalive packets need to be sent at relatively frequent intervals + * (a few seconds to a few minutes). As the contents of keepalive packets + * depend on the current network status, hardware needs to be configured + * to send them and has a limited amount of memory to do so. The HAL + * formalizes this as slots that an implementation can configure to send + * the correct packets. Devices typically have a small number of slots + * per radio technology, and the specific number of slots for each + * technology is specified in configuration files. + * {@see SocketKeepalive} for details. + * + * @hide + */ +@SystemApi +public abstract class NetworkAgent { + /** + * The {@link Network} corresponding to this object. + */ + @Nullable + private volatile Network mNetwork; + + @Nullable + private volatile INetworkAgentRegistry mRegistry; + + private interface RegistryAction { + void execute(@NonNull INetworkAgentRegistry registry) throws RemoteException; + } + + private final Handler mHandler; + private final String LOG_TAG; + private static final boolean DBG = true; + private static final boolean VDBG = false; + private final ArrayList mPreConnectedQueue = new ArrayList<>(); + private volatile long mLastBwRefreshTime = 0; + private static final long BW_REFRESH_MIN_WIN_MS = 500; + private boolean mBandwidthUpdateScheduled = false; + private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); + @NonNull + private NetworkInfo mNetworkInfo; + @NonNull + private final Object mRegisterLock = new Object(); + + /** + * The ID of the {@link NetworkProvider} that created this object, or + * {@link NetworkProvider#ID_NONE} if unknown. + * @hide + */ + public final int providerId; + + private static final int BASE = Protocol.BASE_NETWORK_AGENT; + + /** + * Sent by ConnectivityService to the NetworkAgent to inform it of + * suspected connectivity problems on its network. The NetworkAgent + * should take steps to verify and correct connectivity. + * @hide + */ + public static final int CMD_SUSPECT_BAD = BASE; + + /** + * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to + * ConnectivityService to pass the current NetworkInfo (connection state). + * Sent when the NetworkInfo changes, mainly due to change of state. + * obj = NetworkInfo + * @hide + */ + public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1; + + /** + * Sent by the NetworkAgent to ConnectivityService to pass the current + * NetworkCapabilties. + * obj = NetworkCapabilities + * @hide + */ + public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2; + + /** + * Sent by the NetworkAgent to ConnectivityService to pass the current + * NetworkProperties. + * obj = NetworkProperties + * @hide + */ + public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; + + /** + * Centralize the place where base network score, and network score scaling, will be + * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE + * @hide + */ + public static final int WIFI_BASE_SCORE = 60; + + /** + * Sent by the NetworkAgent to ConnectivityService to pass the current + * network score. + * arg1 = network score int + * @hide + */ + public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; + + /** + * Sent by the NetworkAgent to ConnectivityService to pass the current + * list of underlying networks. + * obj = array of Network objects + * @hide + */ + public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5; + + /** + * Sent by ConnectivityService to the NetworkAgent to inform the agent of the + * networks status - whether we could use the network or could not, due to + * either a bad network configuration (no internet link) or captive portal. + * + * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK} + * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String} + * representing URL that Internet probe was redirect to, if it was redirected, + * or mapping to {@code null} otherwise. + * @hide + */ + public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7; + + + /** + * Network validation suceeded. + * Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}. + */ + public static final int VALIDATION_STATUS_VALID = 1; + + /** + * Network validation was attempted and failed. This may be received more than once as + * subsequent validation attempts are made. + */ + public static final int VALIDATION_STATUS_NOT_VALID = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "VALIDATION_STATUS_" }, value = { + VALIDATION_STATUS_VALID, + VALIDATION_STATUS_NOT_VALID + }) + public @interface ValidationStatus {} + + // TODO: remove. + /** @hide */ + public static final int VALID_NETWORK = 1; + /** @hide */ + public static final int INVALID_NETWORK = 2; + + /** + * The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}. + * @hide + */ + public static final String REDIRECT_URL_KEY = "redirect URL"; + + /** + * Sent by the NetworkAgent to ConnectivityService to indicate this network was + * explicitly selected. This should be sent before the NetworkInfo is marked + * CONNECTED so it can be given special treatment at that time. + * + * obj = boolean indicating whether to use this network even if unvalidated + * @hide + */ + public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8; + + /** + * Sent by ConnectivityService to the NetworkAgent to inform the agent of + * whether the network should in the future be used even if not validated. + * This decision is made by the user, but it is the network transport's + * responsibility to remember it. + * + * arg1 = 1 if true, 0 if false + * @hide + */ + public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9; + + /** + * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull + * the underlying network connection for updated bandwidth information. + * @hide + */ + public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10; + + /** + * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent + * periodically on the given interval. + * + * arg1 = the hardware slot number of the keepalive to start + * arg2 = interval in seconds + * obj = KeepalivePacketData object describing the data to be sent + * + * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + * @hide + */ + public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11; + + /** + * Requests that the specified keepalive packet be stopped. + * + * arg1 = hardware slot number of the keepalive to stop. + * + * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + * @hide + */ + public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12; + + /** + * Sent by the NetworkAgent to ConnectivityService to provide status on a socket keepalive + * request. This may either be the reply to a CMD_START_SOCKET_KEEPALIVE, or an asynchronous + * error notification. + * + * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive}, + * so that the app's {@link SocketKeepalive.Callback} methods can be called. + * + * arg1 = hardware slot number of the keepalive + * arg2 = error code + * @hide + */ + public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13; + + /** + * Sent by ConnectivityService to inform this network transport of signal strength thresholds + * that when crossed should trigger a system wakeup and a NetworkCapabilities update. + * + * obj = int[] describing signal strength thresholds. + * @hide + */ + public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14; + + /** + * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid + * automatically reconnecting to this network (e.g. via autojoin). Happens + * when user selects "No" option on the "Stay connected?" dialog box. + * @hide + */ + public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15; + + /** + * Sent by the KeepaliveTracker to NetworkAgent to add a packet filter. + * + * For TCP keepalive offloads, keepalive packets are sent by the firmware. However, because the + * remote site will send ACK packets in response to the keepalive packets, the firmware also + * needs to be configured to properly filter the ACKs to prevent the system from waking up. + * This does not happen with UDP, so this message is TCP-specific. + * arg1 = hardware slot number of the keepalive to filter for. + * obj = the keepalive packet to send repeatedly. + * @hide + */ + public static final int CMD_ADD_KEEPALIVE_PACKET_FILTER = BASE + 16; + + /** + * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See + * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}. + * arg1 = hardware slot number of the keepalive packet filter to remove. + * @hide + */ + public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; + + /** + * Sent by ConnectivityService to the NetworkAgent to complete the bidirectional connection. + * obj = INetworkAgentRegistry + */ + private static final int EVENT_AGENT_CONNECTED = BASE + 18; + + /** + * Sent by ConnectivityService to the NetworkAgent to inform the agent that it was disconnected. + */ + private static final int EVENT_AGENT_DISCONNECTED = BASE + 19; + + /** + * Sent by QosCallbackTracker to {@link NetworkAgent} to register a new filter with + * callback. + * + * arg1 = QoS agent callback ID + * obj = {@link QosFilter} + * @hide + */ + public static final int CMD_REGISTER_QOS_CALLBACK = BASE + 20; + + /** + * Sent by QosCallbackTracker to {@link NetworkAgent} to unregister a callback. + * + * arg1 = QoS agent callback ID + * @hide + */ + public static final int CMD_UNREGISTER_QOS_CALLBACK = BASE + 21; + + private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { + // The subtype can be changed with (TODO) setLegacySubtype, but it starts + // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description. + final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, ""); + ni.setIsAvailable(true); + ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */, + config.getLegacyExtraInfo()); + return ni; + } + + /** + * Create a new network agent. + * @param context a {@link Context} to get system services from. + * @param looper the {@link Looper} on which to invoke the callbacks. + * @param logTag the tag for logs + * @param nc the initial {@link NetworkCapabilities} of this network. Update with + * sendNetworkCapabilities. + * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties. + * @param score the initial score of this network. Update with sendNetworkScore. + * @param config an immutable {@link NetworkAgentConfig} for this agent. + * @param provider the {@link NetworkProvider} managing this agent. + */ + public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + this(looper, context, logTag, nc, lp, score, config, + provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), + getLegacyNetworkInfo(config)); + } + + private static class InitialConfiguration { + public final Context context; + public final NetworkCapabilities capabilities; + public final LinkProperties properties; + public final int score; + public final NetworkAgentConfig config; + public final NetworkInfo info; + InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, + @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, + @NonNull NetworkInfo info) { + this.context = context; + this.capabilities = capabilities; + this.properties = properties; + this.score = score; + this.config = config; + this.info = info; + } + } + private volatile InitialConfiguration mInitialConfiguration; + + private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) { + mHandler = new NetworkAgentHandler(looper); + LOG_TAG = logTag; + mNetworkInfo = new NetworkInfo(ni); + this.providerId = providerId; + if (ni == null || nc == null || lp == null) { + throw new IllegalArgumentException(); + } + + mInitialConfiguration = new InitialConfiguration(context, + new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true), + new LinkProperties(lp), score, config, ni); + } + + private class NetworkAgentHandler extends Handler { + NetworkAgentHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case EVENT_AGENT_CONNECTED: { + if (mRegistry != null) { + log("Received new connection while already connected!"); + } else { + if (VDBG) log("NetworkAgent fully connected"); + synchronized (mPreConnectedQueue) { + final INetworkAgentRegistry registry = (INetworkAgentRegistry) msg.obj; + mRegistry = registry; + for (RegistryAction a : mPreConnectedQueue) { + try { + a.execute(registry); + } catch (RemoteException e) { + Log.wtf(LOG_TAG, "Communication error with registry", e); + // Fall through + } + } + mPreConnectedQueue.clear(); + } + } + break; + } + case EVENT_AGENT_DISCONNECTED: { + if (DBG) log("NetworkAgent channel lost"); + // let the client know CS is done with us. + onNetworkUnwanted(); + synchronized (mPreConnectedQueue) { + mRegistry = null; + } + break; + } + case CMD_SUSPECT_BAD: { + log("Unhandled Message " + msg); + break; + } + case CMD_REQUEST_BANDWIDTH_UPDATE: { + long currentTimeMs = System.currentTimeMillis(); + if (VDBG) { + log("CMD_REQUEST_BANDWIDTH_UPDATE request received."); + } + if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) { + mBandwidthUpdateScheduled = false; + if (!mBandwidthUpdatePending.getAndSet(true)) { + onBandwidthUpdateRequested(); + } + } else { + // deliver the request at a later time rather than discard it completely. + if (!mBandwidthUpdateScheduled) { + long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS + - currentTimeMs + 1; + mBandwidthUpdateScheduled = sendEmptyMessageDelayed( + CMD_REQUEST_BANDWIDTH_UPDATE, waitTime); + } + } + break; + } + case CMD_REPORT_NETWORK_STATUS: { + String redirectUrl = ((Bundle) msg.obj).getString(REDIRECT_URL_KEY); + if (VDBG) { + log("CMD_REPORT_NETWORK_STATUS(" + + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + + redirectUrl); + } + Uri uri = null; + try { + if (null != redirectUrl) { + uri = Uri.parse(redirectUrl); + } + } catch (Exception e) { + Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e); + } + onValidationStatus(msg.arg1 /* status */, uri); + break; + } + case CMD_SAVE_ACCEPT_UNVALIDATED: { + onSaveAcceptUnvalidated(msg.arg1 != 0); + break; + } + case CMD_START_SOCKET_KEEPALIVE: { + onStartSocketKeepalive(msg.arg1 /* slot */, + Duration.ofSeconds(msg.arg2) /* interval */, + (KeepalivePacketData) msg.obj /* packet */); + break; + } + case CMD_STOP_SOCKET_KEEPALIVE: { + onStopSocketKeepalive(msg.arg1 /* slot */); + break; + } + + case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: { + onSignalStrengthThresholdsUpdated((int[]) msg.obj); + break; + } + case CMD_PREVENT_AUTOMATIC_RECONNECT: { + onAutomaticReconnectDisabled(); + break; + } + case CMD_ADD_KEEPALIVE_PACKET_FILTER: { + onAddKeepalivePacketFilter(msg.arg1 /* slot */, + (KeepalivePacketData) msg.obj /* packet */); + break; + } + case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: { + onRemoveKeepalivePacketFilter(msg.arg1 /* slot */); + break; + } + case CMD_REGISTER_QOS_CALLBACK: { + onQosCallbackRegistered( + msg.arg1 /* QoS callback id */, + (QosFilter) msg.obj /* QoS filter */); + break; + } + case CMD_UNREGISTER_QOS_CALLBACK: { + onQosCallbackUnregistered( + msg.arg1 /* QoS callback id */); + break; + } + } + } + } + + /** + * Register this network agent with ConnectivityService. + * + * This method can only be called once per network agent. + * + * @return the Network associated with this network agent (which can also be obtained later + * by calling getNetwork() on this agent). + * @throws IllegalStateException thrown by the system server if this network agent is + * already registered. + */ + @NonNull + public Network register() { + if (VDBG) log("Registering NetworkAgent"); + synchronized (mRegisterLock) { + if (mNetwork != null) { + throw new IllegalStateException("Agent already registered"); + } + final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context + .getSystemService(Context.CONNECTIVITY_SERVICE); + mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler), + new NetworkInfo(mInitialConfiguration.info), + mInitialConfiguration.properties, mInitialConfiguration.capabilities, + mInitialConfiguration.score, mInitialConfiguration.config, providerId); + mInitialConfiguration = null; // All this memory can now be GC'd + } + return mNetwork; + } + + private static class NetworkAgentBinder extends INetworkAgent.Stub { + private static final String LOG_TAG = NetworkAgentBinder.class.getSimpleName(); + + private final Handler mHandler; + + private NetworkAgentBinder(Handler handler) { + mHandler = handler; + } + + @Override + public void onRegistered(@NonNull INetworkAgentRegistry registry) { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED, registry)); + } + + @Override + public void onDisconnected() { + mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED)); + } + + @Override + public void onBandwidthUpdateRequested() { + mHandler.sendMessage(mHandler.obtainMessage(CMD_REQUEST_BANDWIDTH_UPDATE)); + } + + @Override + public void onValidationStatusChanged( + int validationStatus, @Nullable String captivePortalUrl) { + // TODO: consider using a parcelable as argument when the interface is structured + Bundle redirectUrlBundle = new Bundle(); + redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, captivePortalUrl); + mHandler.sendMessage(mHandler.obtainMessage(CMD_REPORT_NETWORK_STATUS, + validationStatus, 0, redirectUrlBundle)); + } + + @Override + public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_SAVE_ACCEPT_UNVALIDATED, + acceptUnvalidated ? 1 : 0, 0)); + } + + @Override + public void onStartNattSocketKeepalive(int slot, int intervalDurationMs, + @NonNull NattKeepalivePacketData packetData) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, + slot, intervalDurationMs, packetData)); + } + + @Override + public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs, + @NonNull TcpKeepalivePacketData packetData) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, + slot, intervalDurationMs, packetData)); + } + + @Override + public void onStopSocketKeepalive(int slot) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0)); + } + + @Override + public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { + mHandler.sendMessage(mHandler.obtainMessage( + CMD_SET_SIGNAL_STRENGTH_THRESHOLDS, thresholds)); + } + + @Override + public void onPreventAutomaticReconnect() { + mHandler.sendMessage(mHandler.obtainMessage(CMD_PREVENT_AUTOMATIC_RECONNECT)); + } + + @Override + public void onAddNattKeepalivePacketFilter(int slot, + @NonNull NattKeepalivePacketData packetData) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, + slot, 0, packetData)); + } + + @Override + public void onAddTcpKeepalivePacketFilter(int slot, + @NonNull TcpKeepalivePacketData packetData) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, + slot, 0, packetData)); + } + + @Override + public void onRemoveKeepalivePacketFilter(int slot) { + mHandler.sendMessage(mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, + slot, 0)); + } + + @Override + public void onQosFilterCallbackRegistered(final int qosCallbackId, + final QosFilterParcelable qosFilterParcelable) { + if (qosFilterParcelable.getQosFilter() != null) { + mHandler.sendMessage( + mHandler.obtainMessage(CMD_REGISTER_QOS_CALLBACK, qosCallbackId, 0, + qosFilterParcelable.getQosFilter())); + return; + } + + Log.wtf(LOG_TAG, "onQosFilterCallbackRegistered: qos filter is null."); + } + + @Override + public void onQosCallbackUnregistered(final int qosCallbackId) { + mHandler.sendMessage(mHandler.obtainMessage( + CMD_UNREGISTER_QOS_CALLBACK, qosCallbackId, 0, null)); + } + } + + /** + * Register this network agent with a testing harness. + * + * The returned Messenger sends messages to the Handler. This allows a test to send + * this object {@code CMD_*} messages as if they came from ConnectivityService, which + * is useful for testing the behavior. + * + * @hide + */ + public INetworkAgent registerForTest(final Network network) { + log("Registering NetworkAgent for test"); + synchronized (mRegisterLock) { + mNetwork = network; + mInitialConfiguration = null; + } + return new NetworkAgentBinder(mHandler); + } + + /** + * Waits for the handler to be idle. + * This is useful for testing, and has smaller scope than an accessor to mHandler. + * TODO : move the implementation in common library with the tests + * @hide + */ + @VisibleForTesting + public boolean waitForIdle(final long timeoutMs) { + final ConditionVariable cv = new ConditionVariable(false); + mHandler.post(cv::open); + return cv.block(timeoutMs); + } + + /** + * @return The Network associated with this agent, or null if it's not registered yet. + */ + @Nullable + public Network getNetwork() { + return mNetwork; + } + + private void queueOrSendMessage(@NonNull RegistryAction action) { + synchronized (mPreConnectedQueue) { + if (mRegistry != null) { + try { + action.execute(mRegistry); + } catch (RemoteException e) { + Log.wtf(LOG_TAG, "Error executing registry action", e); + // Fall through: the channel is asynchronous and does not report errors back + } + } else { + mPreConnectedQueue.add(action); + } + } + } + + /** + * Must be called by the agent when the network's {@link LinkProperties} change. + * @param linkProperties the new LinkProperties. + */ + public final void sendLinkProperties(@NonNull LinkProperties linkProperties) { + Objects.requireNonNull(linkProperties); + final LinkProperties lp = new LinkProperties(linkProperties); + queueOrSendMessage(reg -> reg.sendLinkProperties(lp)); + } + + /** + * Must be called by the agent when the network's underlying networks change. + * + *

{@code networks} is one of the following: + *

    + *
  • a non-empty array: an array of one or more {@link Network}s, in + * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) + * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear + * first in the array.
  • + *
  • an empty array: a zero-element array, meaning that the VPN has no + * underlying network connection, and thus, app traffic will not be sent or received.
  • + *
  • null: (default) signifies that the VPN uses whatever is the system's + * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} + * APIs mentioned above to send traffic over specific channels.
  • + *
+ * + * @param underlyingNetworks the new list of underlying networks. + * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])} + */ + public final void setUnderlyingNetworks(@Nullable List underlyingNetworks) { + final ArrayList underlyingArray = (underlyingNetworks != null) + ? new ArrayList<>(underlyingNetworks) : null; + queueOrSendMessage(reg -> reg.sendUnderlyingNetworks(underlyingArray)); + } + + /** + * Inform ConnectivityService that this agent has now connected. + * Call {@link #unregister} to disconnect. + */ + public void markConnected() { + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */, + mNetworkInfo.getExtraInfo()); + queueOrSendNetworkInfo(mNetworkInfo); + } + + /** + * Unregister this network agent. + * + * This signals the network has disconnected and ends its lifecycle. After this is called, + * the network is torn down and this agent can no longer be used. + */ + public void unregister() { + // When unregistering an agent nobody should use the extrainfo (or reason) any more. + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */, + null /* extraInfo */); + queueOrSendNetworkInfo(mNetworkInfo); + } + + /** + * Change the legacy subtype of this network agent. + * + * This is only for backward compatibility and should not be used by non-legacy network agents, + * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use + * this and others will be thrown an exception if they try. + * + * @deprecated this is for backward compatibility only. + * @param legacySubtype the legacy subtype. + * @hide + */ + @Deprecated + public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { + mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); + queueOrSendNetworkInfo(mNetworkInfo); + } + + /** + * Set the ExtraInfo of this network agent. + * + * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the + * broadcasts about the corresponding Network. + * This is only for backward compatibility and should not be used by non-legacy network agents, + * who will be thrown an exception if they try. The extra info should only be : + *
    + *
  • For cellular agents, the APN name.
  • + *
  • For ethernet agents, the interface name.
  • + *
+ * + * @deprecated this is for backward compatibility only. + * @param extraInfo the ExtraInfo. + * @hide + */ + @Deprecated + public void setLegacyExtraInfo(@Nullable final String extraInfo) { + mNetworkInfo.setExtraInfo(extraInfo); + queueOrSendNetworkInfo(mNetworkInfo); + } + + /** + * Must be called by the agent when it has a new NetworkInfo object. + * @hide TODO: expose something better. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + public final void sendNetworkInfo(NetworkInfo networkInfo) { + queueOrSendNetworkInfo(new NetworkInfo(networkInfo)); + } + + private void queueOrSendNetworkInfo(NetworkInfo networkInfo) { + queueOrSendMessage(reg -> reg.sendNetworkInfo(networkInfo)); + } + + /** + * Must be called by the agent when the network's {@link NetworkCapabilities} change. + * @param networkCapabilities the new NetworkCapabilities. + */ + public final void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { + Objects.requireNonNull(networkCapabilities); + mBandwidthUpdatePending.set(false); + mLastBwRefreshTime = System.currentTimeMillis(); + final NetworkCapabilities nc = + new NetworkCapabilities(networkCapabilities, + /* parcelLocationSensitiveFields */ true); + queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); + } + + /** + * Must be called by the agent to update the score of this network. + * + * @param score the new score, between 0 and 99. + */ + public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { + if (score < 0) { + throw new IllegalArgumentException("Score must be >= 0"); + } + queueOrSendMessage(reg -> reg.sendScore(score)); + } + + /** + * Must be called by the agent to indicate this network was manually selected by the user. + * This should be called before the NetworkInfo is marked CONNECTED so that this + * Network can be given special treatment at that time. If {@code acceptUnvalidated} is + * {@code true}, then the system will switch to this network. If it is {@code false} and the + * network cannot be validated, the system will ask the user whether to switch to this network. + * If the user confirms and selects "don't ask again", then the system will call + * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever + * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement + * {@link #saveAcceptUnvalidated} to respect the user's choice. + * @hide should move to NetworkAgentConfig. + */ + public void explicitlySelected(boolean acceptUnvalidated) { + explicitlySelected(true /* explicitlySelected */, acceptUnvalidated); + } + + /** + * Must be called by the agent to indicate whether the network was manually selected by the + * user. This should be called before the network becomes connected, so it can be given + * special treatment when it does. + * + * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true}, + * then the system will switch to this network. If {@code explicitlySelected} is {@code true} + * and {@code acceptUnvalidated} is {@code false}, and the network cannot be validated, the + * system will ask the user whether to switch to this network. If the user confirms and selects + * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the + * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected} + * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also + * implement {@link #saveAcceptUnvalidated} to respect the user's choice. + * + * If {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is + * {@code true}, the system will interpret this as the user having accepted partial connectivity + * on this network. Thus, the system will switch to the network and consider it validated even + * if it only provides partial connectivity, but the network is not otherwise treated specially. + * @hide should move to NetworkAgentConfig. + */ + public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { + queueOrSendMessage(reg -> reg.sendExplicitlySelected( + explicitlySelected, acceptUnvalidated)); + } + + /** + * Called when ConnectivityService has indicated they no longer want this network. + * The parent factory should (previously) have received indication of the change + * as well, either canceling NetworkRequests or altering their score such that this + * network won't be immediately requested again. + */ + public void onNetworkUnwanted() { + unwanted(); + } + /** @hide TODO delete once subclasses have moved to onNetworkUnwanted. */ + protected void unwanted() { + } + + /** + * Called when ConnectivityService request a bandwidth update. The parent factory + * shall try to overwrite this method and produce a bandwidth update if capable. + * @hide + */ + public void onBandwidthUpdateRequested() { + pollLceData(); + } + /** @hide TODO delete once subclasses have moved to onBandwidthUpdateRequested. */ + protected void pollLceData() { + } + + /** + * Called when the system determines the usefulness of this network. + * + * The system attempts to validate Internet connectivity on networks that provide the + * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} capability. + * + * Currently there are two possible values: + * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated, + * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated. + * + * This is guaranteed to be called again when the network status changes, but the system + * may also call this multiple times even if the status does not change. + * + * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. + * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal), + * this is the destination the probes are being redirected to, otherwise {@code null}. + */ + public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) { + networkStatus(status, null == redirectUri ? "" : redirectUri.toString()); + } + /** @hide TODO delete once subclasses have moved to onValidationStatus */ + protected void networkStatus(int status, String redirectUrl) { + } + + + /** + * Called when the user asks to remember the choice to use this network even if unvalidated. + * The transport is responsible for remembering the choice, and the next time the user connects + * to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}. + * This method will only be called if {@link #explicitlySelected} was called with + * {@code acceptUnvalidated} set to {@code false}. + * @param accept whether the user wants to use the network even if unvalidated. + */ + public void onSaveAcceptUnvalidated(boolean accept) { + saveAcceptUnvalidated(accept); + } + /** @hide TODO delete once subclasses have moved to onSaveAcceptUnvalidated */ + protected void saveAcceptUnvalidated(boolean accept) { + } + + /** + * Requests that the network hardware send the specified packet at the specified interval. + * + * @param slot the hardware slot on which to start the keepalive. + * @param interval the interval between packets, between 10 and 3600. Note that this API + * does not support sub-second precision and will round off the request. + * @param packet the packet to send. + */ + // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should + // not be exposed as constants because they may change in the future (API guideline 4.8) + // and should have getters if exposed at all. Getters can't be used in the annotation, + // so the values unfortunately need to be copied. + public void onStartSocketKeepalive(int slot, @NonNull Duration interval, + @NonNull KeepalivePacketData packet) { + final long intervalSeconds = interval.getSeconds(); + if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC + || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) { + throw new IllegalArgumentException("Interval needs to be comprised between " + + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC + + " but was " + intervalSeconds); + } + final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, + (int) intervalSeconds, packet); + startSocketKeepalive(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onStartSocketKeepalive */ + protected void startSocketKeepalive(Message msg) { + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); + } + + /** + * Requests that the network hardware stop a previously-started keepalive. + * + * @param slot the hardware slot on which to stop the keepalive. + */ + public void onStopSocketKeepalive(int slot) { + Message msg = mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0, null); + stopSocketKeepalive(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onStopSocketKeepalive */ + protected void stopSocketKeepalive(Message msg) { + onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); + } + + /** + * Must be called by the agent when a socket keepalive event occurs. + * + * @param slot the hardware slot on which the event occurred. + * @param event the event that occurred, as one of the SocketKeepalive.ERROR_* + * or SocketKeepalive.SUCCESS constants. + */ + public final void sendSocketKeepaliveEvent(int slot, + @SocketKeepalive.KeepaliveEvent int event) { + queueOrSendMessage(reg -> reg.sendSocketKeepaliveEvent(slot, event)); + } + /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */ + public void onSocketKeepaliveEvent(int slot, int reason) { + sendSocketKeepaliveEvent(slot, reason); + } + + /** + * Called by ConnectivityService to add specific packet filter to network hardware to block + * replies (e.g., TCP ACKs) matching the sent keepalive packets. Implementations that support + * this feature must override this method. + * + * @param slot the hardware slot on which the keepalive should be sent. + * @param packet the packet that is being sent. + */ + public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { + Message msg = mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0, packet); + addKeepalivePacketFilter(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onAddKeepalivePacketFilter */ + protected void addKeepalivePacketFilter(Message msg) { + } + + /** + * Called by ConnectivityService to remove a packet filter installed with + * {@link #addKeepalivePacketFilter(Message)}. Implementations that support this feature + * must override this method. + * + * @param slot the hardware slot on which the keepalive is being sent. + */ + public void onRemoveKeepalivePacketFilter(int slot) { + Message msg = mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, slot, 0, null); + removeKeepalivePacketFilter(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onRemoveKeepalivePacketFilter */ + protected void removeKeepalivePacketFilter(Message msg) { + } + + /** + * Called by ConnectivityService to inform this network agent of signal strength thresholds + * that when crossed should trigger a system wakeup and a NetworkCapabilities update. + * + * When the system updates the list of thresholds that should wake up the CPU for a + * given agent it will call this method on the agent. The agent that implement this + * should implement it in hardware so as to ensure the CPU will be woken up on breach. + * Agents are expected to react to a breach by sending an updated NetworkCapabilities + * object with the appropriate signal strength to sendNetworkCapabilities. + * + * The specific units are bearer-dependent. See details on the units and requests in + * {@link NetworkCapabilities.Builder#setSignalStrength}. + * + * @param thresholds the array of thresholds that should trigger wakeups. + */ + public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { + setSignalStrengthThresholds(thresholds); + } + /** @hide TODO delete once subclasses have moved to onSetSignalStrengthThresholds */ + protected void setSignalStrengthThresholds(int[] thresholds) { + } + + /** + * Called when the user asks to not stay connected to this network because it was found to not + * provide Internet access. Usually followed by call to {@code unwanted}. The transport is + * responsible for making sure the device does not automatically reconnect to the same network + * after the {@code unwanted} call. + */ + public void onAutomaticReconnectDisabled() { + preventAutomaticReconnect(); + } + /** @hide TODO delete once subclasses have moved to onAutomaticReconnectDisabled */ + protected void preventAutomaticReconnect() { + } + + /** + * Called when a qos callback is registered with a filter. + * @param qosCallbackId the id for the callback registered + * @param filter the filter being registered + */ + public void onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter) { + } + + /** + * Called when a qos callback is registered with a filter. + *

+ * Any QoS events that are sent with the same callback id after this method is called + * are a no-op. + * + * @param qosCallbackId the id for the callback being unregistered + */ + public void onQosCallbackUnregistered(final int qosCallbackId) { + } + + + /** + * Sends the attributes of Eps Bearer Qos Session back to the Application + * + * @param qosCallbackId the callback id that the session belongs to + * @param sessionId the unique session id across all Eps Bearer Qos Sessions + * @param attributes the attributes of the Eps Qos Session + */ + public final void sendQosSessionAvailable(final int qosCallbackId, final int sessionId, + @NonNull final EpsBearerQosSessionAttributes attributes) { + Objects.requireNonNull(attributes, "The attributes must be non-null"); + queueOrSendMessage(ra -> ra.sendEpsQosSessionAvailable(qosCallbackId, + new QosSession(sessionId, QosSession.TYPE_EPS_BEARER), + attributes)); + } + + /** + * Sends event that the Eps Qos Session was lost. + * + * @param qosCallbackId the callback id that the session belongs to + * @param sessionId the unique session id across all Eps Bearer Qos Sessions + */ + public final void sendQosSessionLost(final int qosCallbackId, final int sessionId) { + queueOrSendMessage(ra -> ra.sendQosSessionLost(qosCallbackId, + new QosSession(sessionId, QosSession.TYPE_EPS_BEARER))); + } + + /** + * Sends the exception type back to the application. + * + * The NetworkAgent should not send anymore messages with this id. + * + * @param qosCallbackId the callback id this exception belongs to + * @param exceptionType the type of exception + */ + public final void sendQosCallbackError(final int qosCallbackId, + @QosCallbackException.ExceptionType final int exceptionType) { + queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType)); + } + + + /** @hide */ + protected void log(final String s) { + Log.d(LOG_TAG, "NetworkAgent: " + s); + } +} diff --git a/framework/src/android/net/NetworkAgentConfig.aidl b/framework/src/android/net/NetworkAgentConfig.aidl new file mode 100644 index 0000000000..cb70bdd312 --- /dev/null +++ b/framework/src/android/net/NetworkAgentConfig.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable NetworkAgentConfig; diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java new file mode 100644 index 0000000000..664c2650ff --- /dev/null +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Allows a network transport to provide the system with policy and configuration information about + * a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered. + * + * @hide + */ +@SystemApi +public final class NetworkAgentConfig implements Parcelable { + + /** + * If the {@link Network} is a VPN, whether apps are allowed to bypass the + * VPN. This is set by a {@link VpnService} and used by + * {@link ConnectivityManager} when creating a VPN. + * + * @hide + */ + public boolean allowBypass; + + /** + * Set if the network was manually/explicitly connected to by the user either from settings + * or a 3rd party app. For example, turning on cell data is not explicit but tapping on a wifi + * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to + * connect to a particular access point is also explicit, though this may change in the future + * as we want apps to use the multinetwork apis. + * + * @hide + */ + public boolean explicitlySelected; + + /** + * @return whether this network was explicitly selected by the user. + */ + public boolean isExplicitlySelected() { + return explicitlySelected; + } + + /** + * Set if the user desires to use this network even if it is unvalidated. This field has meaning + * only if {@link explicitlySelected} is true. If it is, this field must also be set to the + * appropriate value based on previous user choice. + * + * TODO : rename this field to match its accessor + * @hide + */ + public boolean acceptUnvalidated; + + /** + * @return whether the system should accept this network even if it doesn't validate. + */ + public boolean isUnvalidatedConnectivityAcceptable() { + return acceptUnvalidated; + } + + /** + * Whether the user explicitly set that this network should be validated even if presence of + * only partial internet connectivity. + * + * TODO : rename this field to match its accessor + * @hide + */ + public boolean acceptPartialConnectivity; + + /** + * @return whether the system should validate this network even if it only offers partial + * Internet connectivity. + */ + public boolean isPartialConnectivityAcceptable() { + return acceptPartialConnectivity; + } + + /** + * Set to avoid surfacing the "Sign in to network" notification. + * if carrier receivers/apps are registered to handle the carrier-specific provisioning + * procedure, a carrier specific provisioning notification will be placed. + * only one notification should be displayed. This field is set based on + * which notification should be used for provisioning. + * + * @hide + */ + public boolean provisioningNotificationDisabled; + + /** + * + * @return whether the sign in to network notification is enabled by this configuration. + * @hide + */ + public boolean isProvisioningNotificationEnabled() { + return !provisioningNotificationDisabled; + } + + /** + * For mobile networks, this is the subscriber ID (such as IMSI). + * + * @hide + */ + public String subscriberId; + + /** + * @return the subscriber ID, or null if none. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @Nullable + public String getSubscriberId() { + return subscriberId; + } + + /** + * Set to skip 464xlat. This means the device will treat the network as IPv6-only and + * will not attempt to detect a NAT64 via RFC 7050 DNS lookups. + * + * @hide + */ + public boolean skip464xlat; + + /** + * @return whether NAT64 prefix detection is enabled. + * @hide + */ + public boolean isNat64DetectionEnabled() { + return !skip464xlat; + } + + /** + * The legacy type of this network agent, or TYPE_NONE if unset. + * @hide + */ + public int legacyType = ConnectivityManager.TYPE_NONE; + + /** + * @return the legacy type + */ + @ConnectivityManager.LegacyNetworkType + public int getLegacyType() { + return legacyType; + } + + /** + * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. + * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. + * + * This is not parceled, because it would not make sense. + * + * @hide + */ + public transient boolean hasShownBroken; + + /** + * The name of the legacy network type. It's a free-form string used in logging. + * @hide + */ + @NonNull + public String legacyTypeName = ""; + + /** + * @return the name of the legacy network type. It's a free-form string used in logging. + */ + @NonNull + public String getLegacyTypeName() { + return legacyTypeName; + } + + /** + * The legacy extra info of the agent. The extra info should only be : + *

    + *
  • For cellular agents, the APN name.
  • + *
  • For ethernet agents, the interface name.
  • + *
+ * @hide + */ + @NonNull + private String mLegacyExtraInfo = ""; + + /** + * The legacy extra info of the agent. + * @hide + */ + @NonNull + public String getLegacyExtraInfo() { + return mLegacyExtraInfo; + } + + /** @hide */ + public NetworkAgentConfig() { + } + + /** @hide */ + public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) { + if (nac != null) { + allowBypass = nac.allowBypass; + explicitlySelected = nac.explicitlySelected; + acceptUnvalidated = nac.acceptUnvalidated; + acceptPartialConnectivity = nac.acceptPartialConnectivity; + subscriberId = nac.subscriberId; + provisioningNotificationDisabled = nac.provisioningNotificationDisabled; + skip464xlat = nac.skip464xlat; + legacyType = nac.legacyType; + legacyTypeName = nac.legacyTypeName; + mLegacyExtraInfo = nac.mLegacyExtraInfo; + } + } + + /** + * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. + */ + public static final class Builder { + private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); + + /** + * Sets whether the network was explicitly selected by the user. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setExplicitlySelected(final boolean explicitlySelected) { + mConfig.explicitlySelected = explicitlySelected; + return this; + } + + /** + * Sets whether the system should validate this network even if it is found not to offer + * Internet connectivity. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setUnvalidatedConnectivityAcceptable( + final boolean unvalidatedConnectivityAcceptable) { + mConfig.acceptUnvalidated = unvalidatedConnectivityAcceptable; + return this; + } + + /** + * Sets whether the system should validate this network even if it is found to only offer + * partial Internet connectivity. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setPartialConnectivityAcceptable( + final boolean partialConnectivityAcceptable) { + mConfig.acceptPartialConnectivity = partialConnectivityAcceptable; + return this; + } + + /** + * Sets the subscriber ID for this network. + * + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + @SystemApi(client = MODULE_LIBRARIES) + public Builder setSubscriberId(@Nullable String subscriberId) { + mConfig.subscriberId = subscriberId; + return this; + } + + /** + * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power + * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64. + * + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + public Builder disableNat64Detection() { + mConfig.skip464xlat = true; + return this; + } + + /** + * Disables the "Sign in to network" notification. Used if the network transport will + * perform its own carrier-specific provisioning procedure. + * + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + public Builder disableProvisioningNotification() { + mConfig.provisioningNotificationDisabled = true; + return this; + } + + /** + * Sets the legacy type for this network. + * + * @param legacyType the type + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setLegacyType(int legacyType) { + mConfig.legacyType = legacyType; + return this; + } + + /** + * Sets the name of the legacy type of the agent. It's a free-form string used in logging. + * @param legacyTypeName the name + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setLegacyTypeName(@NonNull String legacyTypeName) { + mConfig.legacyTypeName = legacyTypeName; + return this; + } + + /** + * Sets the legacy extra info of the agent. + * @param legacyExtraInfo the legacy extra info. + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + public Builder setLegacyExtraInfo(@NonNull String legacyExtraInfo) { + mConfig.mLegacyExtraInfo = legacyExtraInfo; + return this; + } + + /** + * Returns the constructed {@link NetworkAgentConfig} object. + */ + @NonNull + public NetworkAgentConfig build() { + return mConfig; + } + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final NetworkAgentConfig that = (NetworkAgentConfig) o; + return allowBypass == that.allowBypass + && explicitlySelected == that.explicitlySelected + && acceptUnvalidated == that.acceptUnvalidated + && acceptPartialConnectivity == that.acceptPartialConnectivity + && provisioningNotificationDisabled == that.provisioningNotificationDisabled + && skip464xlat == that.skip464xlat + && legacyType == that.legacyType + && Objects.equals(subscriberId, that.subscriberId) + && Objects.equals(legacyTypeName, that.legacyTypeName) + && Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo); + } + + @Override + public int hashCode() { + return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, + acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, + skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo); + } + + @Override + public String toString() { + return "NetworkAgentConfig {" + + " allowBypass = " + allowBypass + + ", explicitlySelected = " + explicitlySelected + + ", acceptUnvalidated = " + acceptUnvalidated + + ", acceptPartialConnectivity = " + acceptPartialConnectivity + + ", provisioningNotificationDisabled = " + provisioningNotificationDisabled + + ", subscriberId = '" + subscriberId + '\'' + + ", skip464xlat = " + skip464xlat + + ", legacyType = " + legacyType + + ", hasShownBroken = " + hasShownBroken + + ", legacyTypeName = '" + legacyTypeName + '\'' + + ", legacyExtraInfo = '" + mLegacyExtraInfo + '\'' + + "}"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeInt(allowBypass ? 1 : 0); + out.writeInt(explicitlySelected ? 1 : 0); + out.writeInt(acceptUnvalidated ? 1 : 0); + out.writeInt(acceptPartialConnectivity ? 1 : 0); + out.writeString(subscriberId); + out.writeInt(provisioningNotificationDisabled ? 1 : 0); + out.writeInt(skip464xlat ? 1 : 0); + out.writeInt(legacyType); + out.writeString(legacyTypeName); + out.writeString(mLegacyExtraInfo); + } + + public static final @NonNull Creator CREATOR = + new Creator() { + @Override + public NetworkAgentConfig createFromParcel(Parcel in) { + NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); + networkAgentConfig.allowBypass = in.readInt() != 0; + networkAgentConfig.explicitlySelected = in.readInt() != 0; + networkAgentConfig.acceptUnvalidated = in.readInt() != 0; + networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0; + networkAgentConfig.subscriberId = in.readString(); + networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0; + networkAgentConfig.skip464xlat = in.readInt() != 0; + networkAgentConfig.legacyType = in.readInt(); + networkAgentConfig.legacyTypeName = in.readString(); + networkAgentConfig.mLegacyExtraInfo = in.readString(); + return networkAgentConfig; + } + + @Override + public NetworkAgentConfig[] newArray(int size) { + return new NetworkAgentConfig[size]; + } + }; +} diff --git a/framework/src/android/net/NetworkCapabilities.aidl b/framework/src/android/net/NetworkCapabilities.aidl new file mode 100644 index 0000000000..01d328605d --- /dev/null +++ b/framework/src/android/net/NetworkCapabilities.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright (C) 2014 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +@JavaOnlyStableParcelable parcelable NetworkCapabilities; + diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java new file mode 100644 index 0000000000..3843b9ab93 --- /dev/null +++ b/framework/src/android/net/NetworkCapabilities.java @@ -0,0 +1,2517 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.net.ConnectivityManager.NetworkCallback; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.Process; +import android.text.TextUtils; +import android.util.ArraySet; +import android.util.proto.ProtoOutputStream; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.BitUtils; +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; +import java.util.Objects; +import java.util.Set; +import java.util.StringJoiner; + +/** + * Representation of the capabilities of an active network. Instances are + * typically obtained through + * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} + * or {@link ConnectivityManager#getNetworkCapabilities(Network)}. + *

+ * This replaces the old {@link ConnectivityManager#TYPE_MOBILE} method of + * network selection. Rather than indicate a need for Wi-Fi because an + * application needs high bandwidth and risk obsolescence when a new, fast + * network appears (like LTE), the application should specify it needs high + * bandwidth. Similarly if an application needs an unmetered network for a bulk + * transfer it can specify that rather than assuming all cellular based + * connections are metered and all Wi-Fi based connections are not. + */ +public final class NetworkCapabilities implements Parcelable { + private static final String TAG = "NetworkCapabilities"; + + // Set to true when private DNS is broken. + private boolean mPrivateDnsBroken; + + /** + * Uid of the app making the request. + */ + private int mRequestorUid; + + /** + * Package name of the app making the request. + */ + private String mRequestorPackageName; + + /** + * Indicates whether parceling should preserve fields that are set based on permissions of + * the process receiving the {@link NetworkCapabilities}. + */ + private final boolean mParcelLocationSensitiveFields; + + public NetworkCapabilities() { + mParcelLocationSensitiveFields = false; + clearAll(); + mNetworkCapabilities = DEFAULT_CAPABILITIES; + } + + public NetworkCapabilities(NetworkCapabilities nc) { + this(nc, false /* parcelLocationSensitiveFields */); + } + + /** + * Make a copy of NetworkCapabilities. + * + * @param nc Original NetworkCapabilities + * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not. + * @hide + */ + @SystemApi + public NetworkCapabilities( + @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) { + mParcelLocationSensitiveFields = parcelLocationSensitiveFields; + if (nc != null) { + set(nc); + } + } + + /** + * Completely clears the contents of this object, removing even the capabilities that are set + * by default when the object is constructed. + * @hide + */ + public void clearAll() { + // Ensures that the internal copies maintained by the connectivity stack does not set + // this bit. + if (mParcelLocationSensitiveFields) { + throw new UnsupportedOperationException( + "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set"); + } + mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; + mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; + mNetworkSpecifier = null; + mTransportInfo = null; + mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; + mUids = null; + mAdministratorUids = new int[0]; + mOwnerUid = Process.INVALID_UID; + mSSID = null; + mPrivateDnsBroken = false; + mRequestorUid = Process.INVALID_UID; + mRequestorPackageName = null; + } + + /** + * Set all contents of this object to the contents of a NetworkCapabilities. + * + * @param nc Original NetworkCapabilities + * @hide + */ + public void set(@NonNull NetworkCapabilities nc) { + mNetworkCapabilities = nc.mNetworkCapabilities; + mTransportTypes = nc.mTransportTypes; + mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; + mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; + mNetworkSpecifier = nc.mNetworkSpecifier; + if (nc.getTransportInfo() != null) { + setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields)); + } else { + setTransportInfo(null); + } + mSignalStrength = nc.mSignalStrength; + setUids(nc.mUids); // Will make the defensive copy + setAdministratorUids(nc.getAdministratorUids()); + mOwnerUid = nc.mOwnerUid; + mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; + mSSID = nc.mSSID; + mPrivateDnsBroken = nc.mPrivateDnsBroken; + mRequestorUid = nc.mRequestorUid; + mRequestorPackageName = nc.mRequestorPackageName; + } + + /** + * Represents the network's capabilities. If any are specified they will be satisfied + * by any Network that matches all of them. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + private long mNetworkCapabilities; + + /** + * If any capabilities specified here they must not exist in the matching Network. + */ + private long mUnwantedNetworkCapabilities; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "NET_CAPABILITY_" }, value = { + NET_CAPABILITY_MMS, + NET_CAPABILITY_SUPL, + NET_CAPABILITY_DUN, + NET_CAPABILITY_FOTA, + NET_CAPABILITY_IMS, + NET_CAPABILITY_CBS, + NET_CAPABILITY_WIFI_P2P, + NET_CAPABILITY_IA, + NET_CAPABILITY_RCS, + NET_CAPABILITY_XCAP, + NET_CAPABILITY_EIMS, + NET_CAPABILITY_NOT_METERED, + NET_CAPABILITY_INTERNET, + NET_CAPABILITY_NOT_RESTRICTED, + NET_CAPABILITY_TRUSTED, + NET_CAPABILITY_NOT_VPN, + NET_CAPABILITY_VALIDATED, + NET_CAPABILITY_CAPTIVE_PORTAL, + NET_CAPABILITY_NOT_ROAMING, + NET_CAPABILITY_FOREGROUND, + NET_CAPABILITY_NOT_CONGESTED, + NET_CAPABILITY_NOT_SUSPENDED, + NET_CAPABILITY_OEM_PAID, + NET_CAPABILITY_MCX, + NET_CAPABILITY_PARTIAL_CONNECTIVITY, + NET_CAPABILITY_TEMPORARILY_NOT_METERED, + NET_CAPABILITY_OEM_PRIVATE, + NET_CAPABILITY_VEHICLE_INTERNAL, + NET_CAPABILITY_NOT_VCN_MANAGED, + }) + public @interface NetCapability { } + + /** + * Indicates this is a network that has the ability to reach the + * carrier's MMSC for sending and receiving MMS messages. + */ + public static final int NET_CAPABILITY_MMS = 0; + + /** + * Indicates this is a network that has the ability to reach the carrier's + * SUPL server, used to retrieve GPS information. + */ + public static final int NET_CAPABILITY_SUPL = 1; + + /** + * Indicates this is a network that has the ability to reach the carrier's + * DUN or tethering gateway. + */ + public static final int NET_CAPABILITY_DUN = 2; + + /** + * Indicates this is a network that has the ability to reach the carrier's + * FOTA portal, used for over the air updates. + */ + public static final int NET_CAPABILITY_FOTA = 3; + + /** + * Indicates this is a network that has the ability to reach the carrier's + * IMS servers, used for network registration and signaling. + */ + public static final int NET_CAPABILITY_IMS = 4; + + /** + * Indicates this is a network that has the ability to reach the carrier's + * CBS servers, used for carrier specific services. + */ + public static final int NET_CAPABILITY_CBS = 5; + + /** + * Indicates this is a network that has the ability to reach a Wi-Fi direct + * peer. + */ + public static final int NET_CAPABILITY_WIFI_P2P = 6; + + /** + * Indicates this is a network that has the ability to reach a carrier's + * Initial Attach servers. + */ + public static final int NET_CAPABILITY_IA = 7; + + /** + * Indicates this is a network that has the ability to reach a carrier's + * RCS servers, used for Rich Communication Services. + */ + public static final int NET_CAPABILITY_RCS = 8; + + /** + * Indicates this is a network that has the ability to reach a carrier's + * XCAP servers, used for configuration and control. + */ + public static final int NET_CAPABILITY_XCAP = 9; + + /** + * Indicates this is a network that has the ability to reach a carrier's + * Emergency IMS servers or other services, used for network signaling + * during emergency calls. + */ + public static final int NET_CAPABILITY_EIMS = 10; + + /** + * Indicates that this network is unmetered. + */ + public static final int NET_CAPABILITY_NOT_METERED = 11; + + /** + * Indicates that this network should be able to reach the internet. + */ + public static final int NET_CAPABILITY_INTERNET = 12; + + /** + * Indicates that this network is available for general use. If this is not set + * applications should not attempt to communicate on this network. Note that this + * is simply informative and not enforcement - enforcement is handled via other means. + * Set by default. + */ + public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; + + /** + * Indicates that the user has indicated implicit trust of this network. This + * generally means it's a sim-selected carrier, a plugged in ethernet, a paired + * BT device or a wifi the user asked to connect to. Untrusted networks + * are probably limited to unknown wifi AP. Set by default. + */ + public static final int NET_CAPABILITY_TRUSTED = 14; + + /** + * Indicates that this network is not a VPN. This capability is set by default and should be + * explicitly cleared for VPN networks. + */ + public static final int NET_CAPABILITY_NOT_VPN = 15; + + /** + * Indicates that connectivity on this network was successfully validated. For example, for a + * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully + * detected. + */ + public static final int NET_CAPABILITY_VALIDATED = 16; + + /** + * Indicates that this network was found to have a captive portal in place last time it was + * probed. + */ + public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; + + /** + * Indicates that this network is not roaming. + */ + public static final int NET_CAPABILITY_NOT_ROAMING = 18; + + /** + * Indicates that this network is available for use by apps, and not a network that is being + * kept up in the background to facilitate fast network switching. + */ + public static final int NET_CAPABILITY_FOREGROUND = 19; + + /** + * Indicates that this network is not congested. + *

+ * When a network is congested, applications should defer network traffic + * that can be done at a later time, such as uploading analytics. + */ + public static final int NET_CAPABILITY_NOT_CONGESTED = 20; + + /** + * Indicates that this network is not currently suspended. + *

+ * When a network is suspended, the network's IP addresses and any connections + * established on the network remain valid, but the network is temporarily unable + * to transfer data. This can happen, for example, if a cellular network experiences + * a temporary loss of signal, such as when driving through a tunnel, etc. + * A network with this capability is not suspended, so is expected to be able to + * transfer data. + */ + public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; + + /** + * Indicates that traffic that goes through this network is paid by oem. For example, + * this network can be used by system apps to upload telemetry data. + * @hide + */ + @SystemApi + public static final int NET_CAPABILITY_OEM_PAID = 22; + + /** + * Indicates this is a network that has the ability to reach a carrier's Mission Critical + * servers. + */ + public static final int NET_CAPABILITY_MCX = 23; + + /** + * Indicates that this network was tested to only provide partial connectivity. + * @hide + */ + @SystemApi + public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; + + /** + * Indicates that this network is temporarily unmetered. + *

+ * This capability will be set for networks that are generally metered, but are currently + * unmetered, e.g., because the user is in a particular area. This capability can be changed at + * any time. When it is removed, applications are responsible for stopping any data transfer + * that should not occur on a metered network. + * Note that most apps should use {@link #NET_CAPABILITY_NOT_METERED} instead. For more + * information, see https://developer.android.com/about/versions/11/features/5g#meteredness. + */ + public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; + + /** + * Indicates that this network is private to the OEM and meant only for OEM use. + * @hide + */ + @SystemApi + public static final int NET_CAPABILITY_OEM_PRIVATE = 26; + + /** + * Indicates this is an internal vehicle network, meant to communicate with other + * automotive systems. + * + * @hide + */ + @SystemApi + public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; + + /** + * Indicates that this network is not managed by a Virtual Carrier Network (VCN). + * + * TODO(b/177299683): Add additional clarifying javadoc. + * @hide + */ + public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; + + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VCN_MANAGED; + + /** + * Network capabilities that are expected to be mutable, i.e., can change while a particular + * network is connected. + */ + private static final long MUTABLE_CAPABILITIES = + // TRUSTED can change when user explicitly connects to an untrusted network in Settings. + // http://b/18206275 + (1 << NET_CAPABILITY_TRUSTED) + | (1 << NET_CAPABILITY_VALIDATED) + | (1 << NET_CAPABILITY_CAPTIVE_PORTAL) + | (1 << NET_CAPABILITY_NOT_ROAMING) + | (1 << NET_CAPABILITY_FOREGROUND) + | (1 << NET_CAPABILITY_NOT_CONGESTED) + | (1 << NET_CAPABILITY_NOT_SUSPENDED) + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY) + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) + | (1 << NET_CAPABILITY_NOT_VCN_MANAGED); + + /** + * Network capabilities that are not allowed in NetworkRequests. This exists because the + * NetworkFactory / NetworkAgent model does not deal well with the situation where a + * capability's presence cannot be known in advance. If such a capability is requested, then we + * can get into a cycle where the NetworkFactory endlessly churns out NetworkAgents that then + * get immediately torn down because they do not have the requested capability. + */ + // Note that as a historical exception, the TRUSTED and NOT_VCN_MANAGED capabilities + // are mutable but requestable. Factories are responsible for not getting + // in an infinite loop about these. + private static final long NON_REQUESTABLE_CAPABILITIES = + MUTABLE_CAPABILITIES + & ~(1 << NET_CAPABILITY_TRUSTED) + & ~(1 << NET_CAPABILITY_NOT_VCN_MANAGED); + + /** + * Capabilities that are set by default when the object is constructed. + */ + private static final long DEFAULT_CAPABILITIES = + (1 << NET_CAPABILITY_NOT_RESTRICTED) + | (1 << NET_CAPABILITY_TRUSTED) + | (1 << NET_CAPABILITY_NOT_VPN); + + /** + * Capabilities that suggest that a network is restricted. + * {@see #maybeMarkCapabilitiesRestricted}, {@see #FORCE_RESTRICTED_CAPABILITIES} + */ + @VisibleForTesting + /* package */ static final long RESTRICTED_CAPABILITIES = + (1 << NET_CAPABILITY_CBS) + | (1 << NET_CAPABILITY_DUN) + | (1 << NET_CAPABILITY_EIMS) + | (1 << NET_CAPABILITY_FOTA) + | (1 << NET_CAPABILITY_IA) + | (1 << NET_CAPABILITY_IMS) + | (1 << NET_CAPABILITY_MCX) + | (1 << NET_CAPABILITY_RCS) + | (1 << NET_CAPABILITY_VEHICLE_INTERNAL) + | (1 << NET_CAPABILITY_XCAP); + + /** + * Capabilities that force network to be restricted. + * {@see #maybeMarkCapabilitiesRestricted}. + */ + private static final long FORCE_RESTRICTED_CAPABILITIES = + (1 << NET_CAPABILITY_OEM_PAID) + | (1 << NET_CAPABILITY_OEM_PRIVATE); + + /** + * Capabilities that suggest that a network is unrestricted. + * {@see #maybeMarkCapabilitiesRestricted}. + */ + @VisibleForTesting + /* package */ static final long UNRESTRICTED_CAPABILITIES = + (1 << NET_CAPABILITY_INTERNET) + | (1 << NET_CAPABILITY_MMS) + | (1 << NET_CAPABILITY_SUPL) + | (1 << NET_CAPABILITY_WIFI_P2P); + + /** + * Capabilities that are managed by ConnectivityService. + */ + private static final long CONNECTIVITY_MANAGED_CAPABILITIES = + (1 << NET_CAPABILITY_VALIDATED) + | (1 << NET_CAPABILITY_CAPTIVE_PORTAL) + | (1 << NET_CAPABILITY_FOREGROUND) + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); + + /** + * Capabilities that are allowed for test networks. This list must be set so that it is safe + * for an unprivileged user to create a network with these capabilities via shell. As such, + * it must never contain capabilities that are generally useful to the system, such as + * INTERNET, IMS, SUPL, etc. + */ + private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = + (1 << NET_CAPABILITY_NOT_METERED) + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) + | (1 << NET_CAPABILITY_NOT_RESTRICTED) + | (1 << NET_CAPABILITY_NOT_VPN) + | (1 << NET_CAPABILITY_NOT_ROAMING) + | (1 << NET_CAPABILITY_NOT_CONGESTED) + | (1 << NET_CAPABILITY_NOT_SUSPENDED) + | (1 << NET_CAPABILITY_NOT_VCN_MANAGED); + + /** + * Adds the given capability to this {@code NetworkCapability} instance. + * Note that when searching for a network to satisfy a request, all capabilities + * requested must be satisfied. + * + * @param capability the capability to be added. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { + // If the given capability was previously added to the list of unwanted capabilities + // then the capability will also be removed from the list of unwanted capabilities. + // TODO: Consider adding unwanted capabilities to the public API and mention this + // in the documentation. + checkValidCapability(capability); + mNetworkCapabilities |= 1 << capability; + mUnwantedNetworkCapabilities &= ~(1 << capability); // remove from unwanted capability list + return this; + } + + /** + * Adds the given capability to the list of unwanted capabilities of this + * {@code NetworkCapability} instance. Note that when searching for a network to + * satisfy a request, the network must not contain any capability from unwanted capability + * list. + *

+ * If the capability was previously added to the list of required capabilities (for + * example, it was there by default or added using {@link #addCapability(int)} method), then + * it will be removed from the list of required capabilities as well. + * + * @see #addCapability(int) + * @hide + */ + public void addUnwantedCapability(@NetCapability int capability) { + checkValidCapability(capability); + mUnwantedNetworkCapabilities |= 1 << capability; + mNetworkCapabilities &= ~(1 << capability); // remove from requested capabilities + } + + /** + * Removes (if found) the given capability from this {@code NetworkCapability} instance. + * + * @param capability the capability to be removed. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { + // Note that this method removes capabilities that were added via addCapability(int), + // addUnwantedCapability(int) or setCapabilities(int[], int[]). + checkValidCapability(capability); + final long mask = ~(1 << capability); + mNetworkCapabilities &= mask; + mUnwantedNetworkCapabilities &= mask; + return this; + } + + /** + * Sets (or clears) the given capability on this {@link NetworkCapabilities} + * instance. + * @hide + */ + public @NonNull NetworkCapabilities setCapability(@NetCapability int capability, + boolean value) { + if (value) { + addCapability(capability); + } else { + removeCapability(capability); + } + return this; + } + + /** + * Gets all the capabilities set on this {@code NetworkCapability} instance. + * + * @return an array of capability values for this instance. + * @hide + */ + @UnsupportedAppUsage + public @NetCapability int[] getCapabilities() { + return BitUtils.unpackBits(mNetworkCapabilities); + } + + /** + * Gets all the unwanted capabilities set on this {@code NetworkCapability} instance. + * + * @return an array of unwanted capability values for this instance. + * @hide + */ + public @NetCapability int[] getUnwantedCapabilities() { + return BitUtils.unpackBits(mUnwantedNetworkCapabilities); + } + + + /** + * Sets all the capabilities set on this {@code NetworkCapability} instance. + * This overwrites any existing capabilities. + * + * @hide + */ + public void setCapabilities(@NetCapability int[] capabilities, + @NetCapability int[] unwantedCapabilities) { + mNetworkCapabilities = BitUtils.packBits(capabilities); + mUnwantedNetworkCapabilities = BitUtils.packBits(unwantedCapabilities); + } + + /** + * @deprecated use {@link #setCapabilities(int[], int[])} + * @hide + */ + @Deprecated + public void setCapabilities(@NetCapability int[] capabilities) { + setCapabilities(capabilities, new int[] {}); + } + + /** + * Tests for the presence of a capability on this instance. + * + * @param capability the capabilities to be tested for. + * @return {@code true} if set on this instance. + */ + public boolean hasCapability(@NetCapability int capability) { + return isValidCapability(capability) + && ((mNetworkCapabilities & (1 << capability)) != 0); + } + + /** @hide */ + public boolean hasUnwantedCapability(@NetCapability int capability) { + return isValidCapability(capability) + && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0); + } + + /** + * Check if this NetworkCapabilities has system managed capabilities or not. + * @hide + */ + public boolean hasConnectivityManagedCapability() { + return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0); + } + + /** Note this method may result in having the same capability in wanted and unwanted lists. */ + private void combineNetCapabilities(@NonNull NetworkCapabilities nc) { + this.mNetworkCapabilities |= nc.mNetworkCapabilities; + this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities; + } + + /** + * Convenience function that returns a human-readable description of the first mutable + * capability we find. Used to present an error message to apps that request mutable + * capabilities. + * + * @hide + */ + public @Nullable String describeFirstNonRequestableCapability() { + final long nonRequestable = (mNetworkCapabilities | mUnwantedNetworkCapabilities) + & NON_REQUESTABLE_CAPABILITIES; + + if (nonRequestable != 0) { + return capabilityNameOf(BitUtils.unpackBits(nonRequestable)[0]); + } + if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth"; + if (hasSignalStrength()) return "signalStrength"; + if (isPrivateDnsBroken()) { + return "privateDnsBroken"; + } + return null; + } + + private boolean satisfiedByNetCapabilities(@NonNull NetworkCapabilities nc, + boolean onlyImmutable) { + long requestedCapabilities = mNetworkCapabilities; + long requestedUnwantedCapabilities = mUnwantedNetworkCapabilities; + long providedCapabilities = nc.mNetworkCapabilities; + + if (onlyImmutable) { + requestedCapabilities &= ~MUTABLE_CAPABILITIES; + requestedUnwantedCapabilities &= ~MUTABLE_CAPABILITIES; + } + return ((providedCapabilities & requestedCapabilities) == requestedCapabilities) + && ((requestedUnwantedCapabilities & providedCapabilities) == 0); + } + + /** @hide */ + public boolean equalsNetCapabilities(@NonNull NetworkCapabilities nc) { + return (nc.mNetworkCapabilities == this.mNetworkCapabilities) + && (nc.mUnwantedNetworkCapabilities == this.mUnwantedNetworkCapabilities); + } + + private boolean equalsNetCapabilitiesRequestable(@NonNull NetworkCapabilities that) { + return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == + (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)) + && ((this.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) == + (that.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES)); + } + + /** + * Deduces that all the capabilities it provides are typically provided by restricted networks + * or not. + * + * @return {@code true} if the network should be restricted. + * @hide + */ + public boolean deduceRestrictedCapability() { + // Check if we have any capability that forces the network to be restricted. + final boolean forceRestrictedCapability = + (mNetworkCapabilities & FORCE_RESTRICTED_CAPABILITIES) != 0; + + // Verify there aren't any unrestricted capabilities. If there are we say + // the whole thing is unrestricted unless it is forced to be restricted. + final boolean hasUnrestrictedCapabilities = + (mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0; + + // Must have at least some restricted capabilities. + final boolean hasRestrictedCapabilities = + (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0; + + return forceRestrictedCapability + || (hasRestrictedCapabilities && !hasUnrestrictedCapabilities); + } + + /** + * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if deducing the network is restricted. + * + * @hide + */ + public void maybeMarkCapabilitiesRestricted() { + if (deduceRestrictedCapability()) { + removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + } + } + + /** + * Test networks have strong restrictions on what capabilities they can have. Enforce these + * restrictions. + * @hide + */ + public void restrictCapabilitesForTestNetwork(int creatorUid) { + final long originalCapabilities = mNetworkCapabilities; + final long originalTransportTypes = mTransportTypes; + final NetworkSpecifier originalSpecifier = mNetworkSpecifier; + final int originalSignalStrength = mSignalStrength; + final int originalOwnerUid = getOwnerUid(); + final int[] originalAdministratorUids = getAdministratorUids(); + clearAll(); + mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS) + | (1 << TRANSPORT_TEST); + mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; + mNetworkSpecifier = originalSpecifier; + mSignalStrength = originalSignalStrength; + + // Only retain the owner and administrator UIDs if they match the app registering the remote + // caller that registered the network. + if (originalOwnerUid == creatorUid) { + setOwnerUid(creatorUid); + } + if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) { + setAdministratorUids(new int[] {creatorUid}); + } + // There is no need to clear the UIDs, they have already been cleared by clearAll() above. + } + + /** + * Representing the transport type. Apps should generally not care about transport. A + * request for a fast internet connection could be satisfied by a number of different + * transports. If any are specified here it will be satisfied a Network that matches + * any of them. If a caller doesn't care about the transport it should not specify any. + */ + private long mTransportTypes; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "TRANSPORT_" }, value = { + TRANSPORT_CELLULAR, + TRANSPORT_WIFI, + TRANSPORT_BLUETOOTH, + TRANSPORT_ETHERNET, + TRANSPORT_VPN, + TRANSPORT_WIFI_AWARE, + TRANSPORT_LOWPAN, + TRANSPORT_TEST, + }) + public @interface Transport { } + + /** + * Indicates this network uses a Cellular transport. + */ + public static final int TRANSPORT_CELLULAR = 0; + + /** + * Indicates this network uses a Wi-Fi transport. + */ + public static final int TRANSPORT_WIFI = 1; + + /** + * Indicates this network uses a Bluetooth transport. + */ + public static final int TRANSPORT_BLUETOOTH = 2; + + /** + * Indicates this network uses an Ethernet transport. + */ + public static final int TRANSPORT_ETHERNET = 3; + + /** + * Indicates this network uses a VPN transport. + */ + public static final int TRANSPORT_VPN = 4; + + /** + * Indicates this network uses a Wi-Fi Aware transport. + */ + public static final int TRANSPORT_WIFI_AWARE = 5; + + /** + * Indicates this network uses a LoWPAN transport. + */ + public static final int TRANSPORT_LOWPAN = 6; + + /** + * Indicates this network uses a Test-only virtual interface as a transport. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final int TRANSPORT_TEST = 7; + + /** @hide */ + public static final int MIN_TRANSPORT = TRANSPORT_CELLULAR; + /** @hide */ + public static final int MAX_TRANSPORT = TRANSPORT_TEST; + + /** @hide */ + public static boolean isValidTransport(@Transport int transportType) { + return (MIN_TRANSPORT <= transportType) && (transportType <= MAX_TRANSPORT); + } + + private static final String[] TRANSPORT_NAMES = { + "CELLULAR", + "WIFI", + "BLUETOOTH", + "ETHERNET", + "VPN", + "WIFI_AWARE", + "LOWPAN", + "TEST" + }; + + /** + * Allowed transports on a test network, in addition to TRANSPORT_TEST. + */ + private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST + // Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces + | 1 << TRANSPORT_ETHERNET + // Test VPN networks can be created but their UID ranges must be empty. + | 1 << TRANSPORT_VPN; + + /** + * Adds the given transport type to this {@code NetworkCapability} instance. + * Multiple transports may be applied. Note that when searching + * for a network to satisfy a request, any listed in the request will satisfy the request. + * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a + * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network + * to be selected. This is logically different than + * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above. + * + * @param transportType the transport type to be added. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mTransportTypes |= 1 << transportType; + setNetworkSpecifier(mNetworkSpecifier); // used for exception checking + return this; + } + + /** + * Removes (if found) the given transport from this {@code NetworkCapability} instance. + * + * @param transportType the transport type to be removed. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities removeTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mTransportTypes &= ~(1 << transportType); + setNetworkSpecifier(mNetworkSpecifier); // used for exception checking + return this; + } + + /** + * Sets (or clears) the given transport on this {@link NetworkCapabilities} + * instance. + * + * @hide + */ + public @NonNull NetworkCapabilities setTransportType(@Transport int transportType, + boolean value) { + if (value) { + addTransportType(transportType); + } else { + removeTransportType(transportType); + } + return this; + } + + /** + * Gets all the transports set on this {@code NetworkCapability} instance. + * + * @return an array of transport type values for this instance. + * @hide + */ + @SystemApi + @NonNull public @Transport int[] getTransportTypes() { + return BitUtils.unpackBits(mTransportTypes); + } + + /** + * Sets all the transports set on this {@code NetworkCapability} instance. + * This overwrites any existing transports. + * + * @hide + */ + public void setTransportTypes(@Transport int[] transportTypes) { + mTransportTypes = BitUtils.packBits(transportTypes); + } + + /** + * Tests for the presence of a transport on this instance. + * + * @param transportType the transport type to be tested for. + * @return {@code true} if set on this instance. + */ + public boolean hasTransport(@Transport int transportType) { + return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0); + } + + private void combineTransportTypes(NetworkCapabilities nc) { + this.mTransportTypes |= nc.mTransportTypes; + } + + private boolean satisfiedByTransportTypes(NetworkCapabilities nc) { + return ((this.mTransportTypes == 0) + || ((this.mTransportTypes & nc.mTransportTypes) != 0)); + } + + /** @hide */ + public boolean equalsTransportTypes(NetworkCapabilities nc) { + return (nc.mTransportTypes == this.mTransportTypes); + } + + /** + * UID of the app that owns this network, or Process#INVALID_UID if none/unknown. + * + *

This field keeps track of the UID of the app that created this network and is in charge of + * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running + * VPN, or Carrier Service app managing a cellular data connection. + * + *

For NetworkCapability instances being sent from ConnectivityService, this value MUST be + * reset to Process.INVALID_UID unless all the following conditions are met: + * + *

The caller is the network owner, AND one of the following sets of requirements is met: + * + *

    + *
  1. The described Network is a VPN + *
+ * + *

OR: + * + *

    + *
  1. The calling app is the network owner + *
  2. The calling app has the ACCESS_FINE_LOCATION permission granted + *
  3. The user's location toggle is on + *
+ * + * This is because the owner UID is location-sensitive. The apps that request a network could + * know where the device is if they can tell for sure the system has connected to the network + * they requested. + * + *

This is populated by the network agents and for the NetworkCapabilities instance sent by + * an app to the System Server, the value MUST be reset to Process.INVALID_UID by the system + * server. + */ + private int mOwnerUid = Process.INVALID_UID; + + /** + * Set the UID of the owner app. + * @hide + */ + public @NonNull NetworkCapabilities setOwnerUid(final int uid) { + mOwnerUid = uid; + return this; + } + + /** + * Retrieves the UID of the app that owns this network. + * + *

For user privacy reasons, this field will only be populated if the following conditions + * are met: + * + *

The caller is the network owner, AND one of the following sets of requirements is met: + * + *

    + *
  1. The described Network is a VPN + *
+ * + *

OR: + * + *

    + *
  1. The calling app is the network owner + *
  2. The calling app has the ACCESS_FINE_LOCATION permission granted + *
  3. The user's location toggle is on + *
+ * + * Instances of NetworkCapabilities sent to apps without the appropriate permissions will have + * this field cleared out. + */ + public int getOwnerUid() { + return mOwnerUid; + } + + private boolean equalsOwnerUid(@NonNull final NetworkCapabilities nc) { + return mOwnerUid == nc.mOwnerUid; + } + + /** + * UIDs of packages that are administrators of this network, or empty if none. + * + *

This field tracks the UIDs of packages that have permission to manage this network. + * + *

Network owners will also be listed as administrators. + * + *

For NetworkCapability instances being sent from the System Server, this value MUST be + * empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the + * receiving entity must have the ACCESS_FINE_LOCATION permission and target R+. + * + *

When received from an app in a NetworkRequest this is always cleared out by the system + * server. This field is never used for matching NetworkRequests to NetworkAgents. + */ + @NonNull private int[] mAdministratorUids = new int[0]; + + /** + * Sets the int[] of UIDs that are administrators of this network. + * + *

UIDs included in administratorUids gain administrator privileges over this Network. + * Examples of UIDs that should be included in administratorUids are: + * + *

    + *
  • Carrier apps with privileges for the relevant subscription + *
  • Active VPN apps + *
  • Other application groups with a particular Network-related role + *
+ * + *

In general, user-supplied networks (such as WiFi networks) do not have an administrator. + * + *

An app is granted owner privileges over Networks that it supplies. The owner UID MUST + * always be included in administratorUids. + * + *

The administrator UIDs are set by network agents. + * + * @param administratorUids the UIDs to be set as administrators of this Network. + * @throws IllegalArgumentException if duplicate UIDs are contained in administratorUids + * @see #mAdministratorUids + * @hide + */ + @NonNull + public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { + mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); + Arrays.sort(mAdministratorUids); + for (int i = 0; i < mAdministratorUids.length - 1; i++) { + if (mAdministratorUids[i] >= mAdministratorUids[i + 1]) { + throw new IllegalArgumentException("All administrator UIDs must be unique"); + } + } + return this; + } + + /** + * Retrieves the UIDs that are administrators of this Network. + * + *

This is only populated in NetworkCapabilities objects that come from network agents for + * networks that are managed by specific apps on the system, such as carrier privileged apps or + * wifi suggestion apps. This will include the network owner. + * + * @return the int[] of UIDs that are administrators of this Network + * @see #mAdministratorUids + * @hide + */ + @NonNull + @SystemApi + public int[] getAdministratorUids() { + return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); + } + + /** + * Tests if the set of administrator UIDs of this network is the same as that of the passed one. + * + *

The administrator UIDs must be in sorted order. + * + *

nc is assumed non-null. Else, NPE. + * + * @hide + */ + @VisibleForTesting(visibility = PRIVATE) + public boolean equalsAdministratorUids(@NonNull final NetworkCapabilities nc) { + return Arrays.equals(mAdministratorUids, nc.mAdministratorUids); + } + + /** + * Combine the administrator UIDs of the capabilities. + * + *

This is only legal if either of the administrators lists are empty, or if they are equal. + * Combining administrator UIDs is only possible for combining non-overlapping sets of UIDs. + * + *

If both administrator lists are non-empty but not equal, they conflict with each other. In + * this case, it would not make sense to add them together. + */ + private void combineAdministratorUids(@NonNull final NetworkCapabilities nc) { + if (nc.mAdministratorUids.length == 0) return; + if (mAdministratorUids.length == 0) { + mAdministratorUids = Arrays.copyOf(nc.mAdministratorUids, nc.mAdministratorUids.length); + return; + } + if (!equalsAdministratorUids(nc)) { + throw new IllegalStateException("Can't combine two different administrator UID lists"); + } + } + + /** + * Value indicating that link bandwidth is unspecified. + * @hide + */ + public static final int LINK_BANDWIDTH_UNSPECIFIED = 0; + + /** + * Passive link bandwidth. This is a rough guide of the expected peak bandwidth + * for the first hop on the given transport. It is not measured, but may take into account + * link parameters (Radio technology, allocated channels, etc). + */ + private int mLinkUpBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; + private int mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; + + /** + * Sets the upstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + *

+ * {@see Builder#setLinkUpstreamBandwidthKbps} + * + * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @hide + */ + public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { + mLinkUpBandwidthKbps = upKbps; + return this; + } + + /** + * Retrieves the upstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + * + * @return The estimated first hop upstream (device to network) bandwidth. + */ + public int getLinkUpstreamBandwidthKbps() { + return mLinkUpBandwidthKbps; + } + + /** + * Sets the downstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + *

+ * {@see Builder#setLinkUpstreamBandwidthKbps} + * + * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @hide + */ + public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { + mLinkDownBandwidthKbps = downKbps; + return this; + } + + /** + * Retrieves the downstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + * + * @return The estimated first hop downstream (network to device) bandwidth. + */ + public int getLinkDownstreamBandwidthKbps() { + return mLinkDownBandwidthKbps; + } + + private void combineLinkBandwidths(NetworkCapabilities nc) { + this.mLinkUpBandwidthKbps = + Math.max(this.mLinkUpBandwidthKbps, nc.mLinkUpBandwidthKbps); + this.mLinkDownBandwidthKbps = + Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps); + } + private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) { + return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps + || this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps); + } + private boolean equalsLinkBandwidths(NetworkCapabilities nc) { + return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps + && this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps); + } + /** @hide */ + public static int minBandwidth(int a, int b) { + if (a == LINK_BANDWIDTH_UNSPECIFIED) { + return b; + } else if (b == LINK_BANDWIDTH_UNSPECIFIED) { + return a; + } else { + return Math.min(a, b); + } + } + /** @hide */ + public static int maxBandwidth(int a, int b) { + return Math.max(a, b); + } + + private NetworkSpecifier mNetworkSpecifier = null; + private TransportInfo mTransportInfo = null; + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + *

+ * + * @param networkSpecifier A concrete, parcelable framework class that extends + * NetworkSpecifier. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities setNetworkSpecifier( + @NonNull NetworkSpecifier networkSpecifier) { + if (networkSpecifier != null && Long.bitCount(mTransportTypes) != 1) { + throw new IllegalStateException("Must have a single transport specified to use " + + "setNetworkSpecifier"); + } + + mNetworkSpecifier = networkSpecifier; + + return this; + } + + /** + * Sets the optional transport specific information. + * + * @param transportInfo A concrete, parcelable framework class that extends + * {@link TransportInfo}. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) { + mTransportInfo = transportInfo; + return this; + } + + /** + * Gets the optional bearer specific network specifier. May be {@code null} if not set. + * + * @return The optional {@link NetworkSpecifier} specifying the bearer specific network + * specifier or {@code null}. + */ + public @Nullable NetworkSpecifier getNetworkSpecifier() { + return mNetworkSpecifier; + } + + /** + * Returns a transport-specific information container. The application may cast this + * container to a concrete sub-class based on its knowledge of the network request. The + * application should be able to deal with a {@code null} return value or an invalid case, + * e.g. use {@code instanceof} operator to verify expected type. + * + * @return A concrete implementation of the {@link TransportInfo} class or null if not + * available for the network. + */ + @Nullable public TransportInfo getTransportInfo() { + return mTransportInfo; + } + + private void combineSpecifiers(NetworkCapabilities nc) { + if (mNetworkSpecifier != null && !mNetworkSpecifier.equals(nc.mNetworkSpecifier)) { + throw new IllegalStateException("Can't combine two networkSpecifiers"); + } + setNetworkSpecifier(nc.mNetworkSpecifier); + } + + private boolean satisfiedBySpecifier(NetworkCapabilities nc) { + return mNetworkSpecifier == null || mNetworkSpecifier.canBeSatisfiedBy(nc.mNetworkSpecifier) + || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier; + } + + private boolean equalsSpecifier(NetworkCapabilities nc) { + return Objects.equals(mNetworkSpecifier, nc.mNetworkSpecifier); + } + + private void combineTransportInfos(NetworkCapabilities nc) { + if (mTransportInfo != null && !mTransportInfo.equals(nc.mTransportInfo)) { + throw new IllegalStateException("Can't combine two TransportInfos"); + } + setTransportInfo(nc.mTransportInfo); + } + + private boolean equalsTransportInfo(NetworkCapabilities nc) { + return Objects.equals(mTransportInfo, nc.mTransportInfo); + } + + /** + * Magic value that indicates no signal strength provided. A request specifying this value is + * always satisfied. + */ + public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE; + + /** + * Signal strength. This is a signed integer, and higher values indicate better signal. + * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + private int mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a stronger + * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units + * reported by wifi code. + *

+ * Note that when used to register a network callback, this specifies the minimum acceptable + * signal strength. When received as the state of an existing network it specifies the current + * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no + * effect when requesting a callback. + * + * @param signalStrength the bearer-specific signal strength. + * @hide + */ + public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) { + mSignalStrength = signalStrength; + return this; + } + + /** + * Returns {@code true} if this object specifies a signal strength. + * + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public boolean hasSignalStrength() { + return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED; + } + + /** + * Retrieves the signal strength. + * + * @return The bearer-specific signal strength. + */ + public int getSignalStrength() { + return mSignalStrength; + } + + private void combineSignalStrength(NetworkCapabilities nc) { + this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength); + } + + private boolean satisfiedBySignalStrength(NetworkCapabilities nc) { + return this.mSignalStrength <= nc.mSignalStrength; + } + + private boolean equalsSignalStrength(NetworkCapabilities nc) { + return this.mSignalStrength == nc.mSignalStrength; + } + + /** + * List of UIDs this network applies to. No restriction if null. + *

+ * For networks, mUids represent the list of network this applies to, and null means this + * network applies to all UIDs. + * For requests, mUids is the list of UIDs this network MUST apply to to match ; ALL UIDs + * must be included in a network so that they match. As an exception to the general rule, + * a null mUids field for requests mean "no requirements" rather than what the general rule + * would suggest ("must apply to all UIDs") : this is because this has shown to be what users + * of this API expect in practice. A network that must match all UIDs can still be + * expressed with a set ranging the entire set of possible UIDs. + *

+ * mUids is typically (and at this time, only) used by VPN. This network is only available to + * the UIDs in this list, and it is their default network. Apps in this list that wish to + * bypass the VPN can do so iff the VPN app allows them to or if they are privileged. If this + * member is null, then the network is not restricted by app UID. If it's an empty list, then + * it means nobody can use it. + * As a special exception, the app managing this network (as identified by its UID stored in + * mOwnerUid) can always see this network. This is embodied by a special check in + * satisfiedByUids. That still does not mean the network necessarily applies + * to the app that manages it as determined by #appliesToUid. + *

+ * Please note that in principle a single app can be associated with multiple UIDs because + * each app will have a different UID when it's run as a different (macro-)user. A single + * macro user can only have a single active VPN app at any given time however. + *

+ * Also please be aware this class does not try to enforce any normalization on this. Callers + * can only alter the UIDs by setting them wholesale : this class does not provide any utility + * to add or remove individual UIDs or ranges. If callers have any normalization needs on + * their own (like requiring sortedness or no overlap) they need to enforce it + * themselves. Some of the internal methods also assume this is normalized as in no adjacent + * or overlapping ranges are present. + * + * @hide + */ + private ArraySet mUids = null; + + /** + * Convenience method to set the UIDs this network applies to to a single UID. + * @hide + */ + public @NonNull NetworkCapabilities setSingleUid(int uid) { + final ArraySet identity = new ArraySet<>(1); + identity.add(new UidRange(uid, uid)); + setUids(identity); + return this; + } + + /** + * Set the list of UIDs this network applies to. + * This makes a copy of the set so that callers can't modify it after the call. + * @hide + */ + public @NonNull NetworkCapabilities setUids(Set uids) { + if (null == uids) { + mUids = null; + } else { + mUids = new ArraySet<>(uids); + } + return this; + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set getUids() { + return null == mUids ? null : new ArraySet<>(mUids); + } + + /** + * Test whether this network applies to this UID. + * @hide + */ + public boolean appliesToUid(int uid) { + if (null == mUids) return true; + for (UidRange range : mUids) { + if (range.contains(uid)) { + return true; + } + } + return false; + } + + /** + * Tests if the set of UIDs that this network applies to is the same as the passed network. + *

+ * This test only checks whether equal range objects are in both sets. It will + * return false if the ranges are not exactly the same, even if the covered UIDs + * are for an equivalent result. + *

+ * Note that this method is not very optimized, which is fine as long as it's not used very + * often. + *

+ * nc is assumed nonnull. + * + * @hide + */ + @VisibleForTesting + public boolean equalsUids(@NonNull NetworkCapabilities nc) { + Set comparedUids = nc.mUids; + if (null == comparedUids) return null == mUids; + if (null == mUids) return false; + // Make a copy so it can be mutated to check that all ranges in mUids + // also are in uids. + final Set uids = new ArraySet<>(mUids); + for (UidRange range : comparedUids) { + if (!uids.contains(range)) { + return false; + } + uids.remove(range); + } + return uids.isEmpty(); + } + + /** + * Test whether the passed NetworkCapabilities satisfies the UIDs this capabilities require. + * + * This method is called on the NetworkCapabilities embedded in a request with the + * capabilities of an available network. It checks whether all the UIDs from this listen + * (representing the UIDs that must have access to the network) are satisfied by the UIDs + * in the passed nc (representing the UIDs that this network is available to). + *

+ * As a special exception, the UID that created the passed network (as represented by its + * mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN + * or REQUEST types alike), even if the network does not apply to it. That is so a VPN app + * can see its own network when it listens for it. + *

+ * nc is assumed nonnull. Else, NPE. + * @see #appliesToUid + * @hide + */ + public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) { + if (null == nc.mUids || null == mUids) return true; // The network satisfies everything. + for (UidRange requiredRange : mUids) { + if (requiredRange.contains(nc.mOwnerUid)) return true; + if (!nc.appliesToUidRange(requiredRange)) { + return false; + } + } + return true; + } + + /** + * Returns whether this network applies to the passed ranges. + * This assumes that to apply, the passed range has to be entirely contained + * within one of the ranges this network applies to. If the ranges are not normalized, + * this method may return false even though all required UIDs are covered because no + * single range contained them all. + * @hide + */ + @VisibleForTesting + public boolean appliesToUidRange(@Nullable UidRange requiredRange) { + if (null == mUids) return true; + for (UidRange uidRange : mUids) { + if (uidRange.containsRange(requiredRange)) { + return true; + } + } + return false; + } + + /** + * Combine the UIDs this network currently applies to with the UIDs the passed + * NetworkCapabilities apply to. + * nc is assumed nonnull. + */ + private void combineUids(@NonNull NetworkCapabilities nc) { + if (null == nc.mUids || null == mUids) { + mUids = null; + return; + } + mUids.addAll(nc.mUids); + } + + + /** + * The SSID of the network, or null if not applicable or unknown. + *

+ * This is filled in by wifi code. + * @hide + */ + private String mSSID; + + /** + * Sets the SSID of this network. + * @hide + */ + public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) { + mSSID = ssid; + return this; + } + + /** + * Gets the SSID of this network, or null if none or unknown. + * @hide + */ + @SystemApi + public @Nullable String getSsid() { + return mSSID; + } + + /** + * Tests if the SSID of this network is the same as the SSID of the passed network. + * @hide + */ + public boolean equalsSSID(@NonNull NetworkCapabilities nc) { + return Objects.equals(mSSID, nc.mSSID); + } + + /** + * Check if the SSID requirements of this object are matched by the passed object. + * @hide + */ + public boolean satisfiedBySSID(@NonNull NetworkCapabilities nc) { + return mSSID == null || mSSID.equals(nc.mSSID); + } + + /** + * Combine SSIDs of the capabilities. + *

+ * This is only legal if either the SSID of this object is null, or both SSIDs are + * equal. + * @hide + */ + private void combineSSIDs(@NonNull NetworkCapabilities nc) { + if (mSSID != null && !mSSID.equals(nc.mSSID)) { + throw new IllegalStateException("Can't combine two SSIDs"); + } + setSSID(nc.mSSID); + } + + /** + * Combine a set of Capabilities to this one. Useful for coming up with the complete set. + *

+ * Note that this method may break an invariant of having a particular capability in either + * wanted or unwanted lists but never in both. Requests that have the same capability in + * both lists will never be satisfied. + * @hide + */ + public void combineCapabilities(@NonNull NetworkCapabilities nc) { + combineNetCapabilities(nc); + combineTransportTypes(nc); + combineLinkBandwidths(nc); + combineSpecifiers(nc); + combineTransportInfos(nc); + combineSignalStrength(nc); + combineUids(nc); + combineSSIDs(nc); + combineRequestor(nc); + combineAdministratorUids(nc); + } + + /** + * Check if our requirements are satisfied by the given {@code NetworkCapabilities}. + * + * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. + * @param onlyImmutable if {@code true}, do not consider mutable requirements such as link + * bandwidth, signal strength, or validation / captive portal status. + * + * @hide + */ + private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { + return (nc != null + && satisfiedByNetCapabilities(nc, onlyImmutable) + && satisfiedByTransportTypes(nc) + && (onlyImmutable || satisfiedByLinkBandwidths(nc)) + && satisfiedBySpecifier(nc) + && (onlyImmutable || satisfiedBySignalStrength(nc)) + && (onlyImmutable || satisfiedByUids(nc)) + && (onlyImmutable || satisfiedBySSID(nc))) + && (onlyImmutable || satisfiedByRequestor(nc)); + } + + /** + * Check if our requirements are satisfied by the given {@code NetworkCapabilities}. + * + * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. + * + * @hide + */ + @SystemApi + public boolean satisfiedByNetworkCapabilities(@Nullable NetworkCapabilities nc) { + return satisfiedByNetworkCapabilities(nc, false); + } + + /** + * Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}. + * + * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements. + * + * @hide + */ + public boolean satisfiedByImmutableNetworkCapabilities(@Nullable NetworkCapabilities nc) { + return satisfiedByNetworkCapabilities(nc, true); + } + + /** + * Checks that our immutable capabilities are the same as those of the given + * {@code NetworkCapabilities} and return a String describing any difference. + * The returned String is empty if there is no difference. + * + * @hide + */ + public String describeImmutableDifferences(@Nullable NetworkCapabilities that) { + if (that == null) { + return "other NetworkCapabilities was null"; + } + + StringJoiner joiner = new StringJoiner(", "); + + // Ignore NOT_METERED being added or removed as it is effectively dynamic. http://b/63326103 + // TODO: properly support NOT_METERED as a mutable and requestable capability. + final long mask = ~MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_NOT_METERED); + long oldImmutableCapabilities = this.mNetworkCapabilities & mask; + long newImmutableCapabilities = that.mNetworkCapabilities & mask; + if (oldImmutableCapabilities != newImmutableCapabilities) { + String before = capabilityNamesOf(BitUtils.unpackBits(oldImmutableCapabilities)); + String after = capabilityNamesOf(BitUtils.unpackBits(newImmutableCapabilities)); + joiner.add(String.format("immutable capabilities changed: %s -> %s", before, after)); + } + + if (!equalsSpecifier(that)) { + NetworkSpecifier before = this.getNetworkSpecifier(); + NetworkSpecifier after = that.getNetworkSpecifier(); + joiner.add(String.format("specifier changed: %s -> %s", before, after)); + } + + if (!equalsTransportTypes(that)) { + String before = transportNamesOf(this.getTransportTypes()); + String after = transportNamesOf(that.getTransportTypes()); + joiner.add(String.format("transports changed: %s -> %s", before, after)); + } + + return joiner.toString(); + } + + /** + * Checks that our requestable capabilities are the same as those of the given + * {@code NetworkCapabilities}. + * + * @hide + */ + public boolean equalRequestableCapabilities(@Nullable NetworkCapabilities nc) { + if (nc == null) return false; + return (equalsNetCapabilitiesRequestable(nc) + && equalsTransportTypes(nc) + && equalsSpecifier(nc)); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj == null || (obj instanceof NetworkCapabilities == false)) return false; + NetworkCapabilities that = (NetworkCapabilities) obj; + return equalsNetCapabilities(that) + && equalsTransportTypes(that) + && equalsLinkBandwidths(that) + && equalsSignalStrength(that) + && equalsSpecifier(that) + && equalsTransportInfo(that) + && equalsUids(that) + && equalsSSID(that) + && equalsOwnerUid(that) + && equalsPrivateDnsBroken(that) + && equalsRequestor(that) + && equalsAdministratorUids(that); + } + + @Override + public int hashCode() { + return (int) (mNetworkCapabilities & 0xFFFFFFFF) + + ((int) (mNetworkCapabilities >> 32) * 3) + + ((int) (mUnwantedNetworkCapabilities & 0xFFFFFFFF) * 5) + + ((int) (mUnwantedNetworkCapabilities >> 32) * 7) + + ((int) (mTransportTypes & 0xFFFFFFFF) * 11) + + ((int) (mTransportTypes >> 32) * 13) + + mLinkUpBandwidthKbps * 17 + + mLinkDownBandwidthKbps * 19 + + Objects.hashCode(mNetworkSpecifier) * 23 + + mSignalStrength * 29 + + mOwnerUid * 31 + + Objects.hashCode(mUids) * 37 + + Objects.hashCode(mSSID) * 41 + + Objects.hashCode(mTransportInfo) * 43 + + Objects.hashCode(mPrivateDnsBroken) * 47 + + Objects.hashCode(mRequestorUid) * 53 + + Objects.hashCode(mRequestorPackageName) * 59 + + Arrays.hashCode(mAdministratorUids) * 61; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mNetworkCapabilities); + dest.writeLong(mUnwantedNetworkCapabilities); + dest.writeLong(mTransportTypes); + dest.writeInt(mLinkUpBandwidthKbps); + dest.writeInt(mLinkDownBandwidthKbps); + dest.writeParcelable((Parcelable) mNetworkSpecifier, flags); + dest.writeParcelable((Parcelable) mTransportInfo, flags); + dest.writeInt(mSignalStrength); + dest.writeArraySet(mUids); + dest.writeString(mSSID); + dest.writeBoolean(mPrivateDnsBroken); + dest.writeIntArray(getAdministratorUids()); + dest.writeInt(mOwnerUid); + dest.writeInt(mRequestorUid); + dest.writeString(mRequestorPackageName); + } + + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + @Override + public NetworkCapabilities createFromParcel(Parcel in) { + NetworkCapabilities netCap = new NetworkCapabilities(); + + netCap.mNetworkCapabilities = in.readLong(); + netCap.mUnwantedNetworkCapabilities = in.readLong(); + netCap.mTransportTypes = in.readLong(); + netCap.mLinkUpBandwidthKbps = in.readInt(); + netCap.mLinkDownBandwidthKbps = in.readInt(); + netCap.mNetworkSpecifier = in.readParcelable(null); + netCap.mTransportInfo = in.readParcelable(null); + netCap.mSignalStrength = in.readInt(); + netCap.mUids = (ArraySet) in.readArraySet( + null /* ClassLoader, null for default */); + netCap.mSSID = in.readString(); + netCap.mPrivateDnsBroken = in.readBoolean(); + netCap.setAdministratorUids(in.createIntArray()); + netCap.mOwnerUid = in.readInt(); + netCap.mRequestorUid = in.readInt(); + netCap.mRequestorPackageName = in.readString(); + return netCap; + } + @Override + public NetworkCapabilities[] newArray(int size) { + return new NetworkCapabilities[size]; + } + }; + + @Override + public @NonNull String toString() { + final StringBuilder sb = new StringBuilder("["); + if (0 != mTransportTypes) { + sb.append(" Transports: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mTransportTypes, + NetworkCapabilities::transportNameOf, "|"); + } + if (0 != mNetworkCapabilities) { + sb.append(" Capabilities: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities, + NetworkCapabilities::capabilityNameOf, "&"); + } + if (0 != mUnwantedNetworkCapabilities) { + sb.append(" Unwanted: "); + appendStringRepresentationOfBitMaskToStringBuilder(sb, mUnwantedNetworkCapabilities, + NetworkCapabilities::capabilityNameOf, "&"); + } + if (mLinkUpBandwidthKbps > 0) { + sb.append(" LinkUpBandwidth>=").append(mLinkUpBandwidthKbps).append("Kbps"); + } + if (mLinkDownBandwidthKbps > 0) { + sb.append(" LinkDnBandwidth>=").append(mLinkDownBandwidthKbps).append("Kbps"); + } + if (mNetworkSpecifier != null) { + sb.append(" Specifier: <").append(mNetworkSpecifier).append(">"); + } + if (mTransportInfo != null) { + sb.append(" TransportInfo: <").append(mTransportInfo).append(">"); + } + if (hasSignalStrength()) { + sb.append(" SignalStrength: ").append(mSignalStrength); + } + + if (null != mUids) { + if ((1 == mUids.size()) && (mUids.valueAt(0).count() == 1)) { + sb.append(" Uid: ").append(mUids.valueAt(0).start); + } else { + sb.append(" Uids: <").append(mUids).append(">"); + } + } + if (mOwnerUid != Process.INVALID_UID) { + sb.append(" OwnerUid: ").append(mOwnerUid); + } + + if (!ArrayUtils.isEmpty(mAdministratorUids)) { + sb.append(" AdminUids: ").append(Arrays.toString(mAdministratorUids)); + } + + if (mRequestorUid != Process.INVALID_UID) { + sb.append(" RequestorUid: ").append(mRequestorUid); + } + + if (mRequestorPackageName != null) { + sb.append(" RequestorPkg: ").append(mRequestorPackageName); + } + + if (null != mSSID) { + sb.append(" SSID: ").append(mSSID); + } + + + if (mPrivateDnsBroken) { + sb.append(" PrivateDnsBroken"); + } + + sb.append("]"); + return sb.toString(); + } + + + private interface NameOf { + String nameOf(int value); + } + + /** + * @hide + */ + public static void appendStringRepresentationOfBitMaskToStringBuilder(@NonNull StringBuilder sb, + long bitMask, @NonNull NameOf nameFetcher, @NonNull String separator) { + int bitPos = 0; + boolean firstElementAdded = false; + while (bitMask != 0) { + if ((bitMask & 1) != 0) { + if (firstElementAdded) { + sb.append(separator); + } else { + firstElementAdded = true; + } + sb.append(nameFetcher.nameOf(bitPos)); + } + bitMask >>= 1; + ++bitPos; + } + } + + /** @hide */ + public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + + for (int transport : getTransportTypes()) { + proto.write(NetworkCapabilitiesProto.TRANSPORTS, transport); + } + + for (int capability : getCapabilities()) { + proto.write(NetworkCapabilitiesProto.CAPABILITIES, capability); + } + + proto.write(NetworkCapabilitiesProto.LINK_UP_BANDWIDTH_KBPS, mLinkUpBandwidthKbps); + proto.write(NetworkCapabilitiesProto.LINK_DOWN_BANDWIDTH_KBPS, mLinkDownBandwidthKbps); + + if (mNetworkSpecifier != null) { + proto.write(NetworkCapabilitiesProto.NETWORK_SPECIFIER, mNetworkSpecifier.toString()); + } + if (mTransportInfo != null) { + // TODO b/120653863: write transport-specific info to proto? + } + + proto.write(NetworkCapabilitiesProto.CAN_REPORT_SIGNAL_STRENGTH, hasSignalStrength()); + proto.write(NetworkCapabilitiesProto.SIGNAL_STRENGTH, mSignalStrength); + + proto.end(token); + } + + /** + * @hide + */ + public static @NonNull String capabilityNamesOf(@Nullable @NetCapability int[] capabilities) { + StringJoiner joiner = new StringJoiner("|"); + if (capabilities != null) { + for (int c : capabilities) { + joiner.add(capabilityNameOf(c)); + } + } + return joiner.toString(); + } + + /** + * @hide + */ + public static @NonNull String capabilityNameOf(@NetCapability int capability) { + switch (capability) { + case NET_CAPABILITY_MMS: return "MMS"; + case NET_CAPABILITY_SUPL: return "SUPL"; + case NET_CAPABILITY_DUN: return "DUN"; + case NET_CAPABILITY_FOTA: return "FOTA"; + case NET_CAPABILITY_IMS: return "IMS"; + case NET_CAPABILITY_CBS: return "CBS"; + case NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P"; + case NET_CAPABILITY_IA: return "IA"; + case NET_CAPABILITY_RCS: return "RCS"; + case NET_CAPABILITY_XCAP: return "XCAP"; + case NET_CAPABILITY_EIMS: return "EIMS"; + case NET_CAPABILITY_NOT_METERED: return "NOT_METERED"; + case NET_CAPABILITY_INTERNET: return "INTERNET"; + case NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED"; + case NET_CAPABILITY_TRUSTED: return "TRUSTED"; + case NET_CAPABILITY_NOT_VPN: return "NOT_VPN"; + case NET_CAPABILITY_VALIDATED: return "VALIDATED"; + case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL"; + case NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING"; + case NET_CAPABILITY_FOREGROUND: return "FOREGROUND"; + case NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED"; + case NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED"; + case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; + case NET_CAPABILITY_MCX: return "MCX"; + case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; + case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; + case NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE"; + case NET_CAPABILITY_VEHICLE_INTERNAL: return "NET_CAPABILITY_VEHICLE_INTERNAL"; + case NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED"; + default: return Integer.toString(capability); + } + } + + /** + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static @NonNull String transportNamesOf(@Nullable @Transport int[] types) { + StringJoiner joiner = new StringJoiner("|"); + if (types != null) { + for (int t : types) { + joiner.add(transportNameOf(t)); + } + } + return joiner.toString(); + } + + /** + * @hide + */ + public static @NonNull String transportNameOf(@Transport int transport) { + if (!isValidTransport(transport)) { + return "UNKNOWN"; + } + return TRANSPORT_NAMES[transport]; + } + + private static void checkValidTransportType(@Transport int transport) { + Preconditions.checkArgument( + isValidTransport(transport), "Invalid TransportType " + transport); + } + + private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { + return capability >= MIN_NET_CAPABILITY && capability <= MAX_NET_CAPABILITY; + } + + private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { + Preconditions.checkArgument(isValidCapability(capability), + "NetworkCapability " + capability + "out of range"); + } + + /** + * Check if this {@code NetworkCapability} instance is metered. + * + * @return {@code true} if {@code NET_CAPABILITY_NOT_METERED} is not set on this instance. + * @hide + */ + public boolean isMetered() { + return !hasCapability(NET_CAPABILITY_NOT_METERED); + } + + /** + * Check if private dns is broken. + * + * @return {@code true} if {@code mPrivateDnsBroken} is set when private DNS is broken. + * @hide + */ + public boolean isPrivateDnsBroken() { + return mPrivateDnsBroken; + } + + /** + * Set mPrivateDnsBroken to true when private dns is broken. + * + * @param broken the status of private DNS to be set. + * @hide + */ + public void setPrivateDnsBroken(boolean broken) { + mPrivateDnsBroken = broken; + } + + private boolean equalsPrivateDnsBroken(NetworkCapabilities nc) { + return mPrivateDnsBroken == nc.mPrivateDnsBroken; + } + + /** + * Set the UID of the app making the request. + * + * For instances of NetworkCapabilities representing a request, sets the + * UID of the app making the request. For a network created by the system, + * sets the UID of the only app whose requests can match this network. + * This can be set to {@link Process#INVALID_UID} if there is no such app, + * or if this instance of NetworkCapabilities is about to be sent to a + * party that should not learn about this. + * + * @param uid UID of the app. + * @hide + */ + public @NonNull NetworkCapabilities setRequestorUid(int uid) { + mRequestorUid = uid; + return this; + } + + /** + * Returns the UID of the app making the request. + * + * For a NetworkRequest being made by an app, contains the app's UID. For a network + * created by the system, contains the UID of the only app whose requests can match + * this network, or {@link Process#INVALID_UID} if none or if the + * caller does not have permission to learn about this. + * + * @return the uid of the app making the request. + * @hide + */ + public int getRequestorUid() { + return mRequestorUid; + } + + /** + * Set the package name of the app making the request. + * + * For instances of NetworkCapabilities representing a request, sets the + * package name of the app making the request. For a network created by the system, + * sets the package name of the only app whose requests can match this network. + * This can be set to null if there is no such app, or if this instance of + * NetworkCapabilities is about to be sent to a party that should not learn about this. + * + * @param packageName package name of the app. + * @hide + */ + public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) { + mRequestorPackageName = packageName; + return this; + } + + /** + * Returns the package name of the app making the request. + * + * For a NetworkRequest being made by an app, contains the app's package name. For a + * network created by the system, contains the package name of the only app whose + * requests can match this network, or null if none or if the caller does not have + * permission to learn about this. + * + * @return the package name of the app making the request. + * @hide + */ + @Nullable + public String getRequestorPackageName() { + return mRequestorPackageName; + } + + /** + * Set the uid and package name of the app causing this network to exist. + * + * {@see #setRequestorUid} and {@link #setRequestorPackageName} + * + * @param uid UID of the app. + * @param packageName package name of the app. + * @hide + */ + public @NonNull NetworkCapabilities setRequestorUidAndPackageName( + int uid, @NonNull String packageName) { + return setRequestorUid(uid).setRequestorPackageName(packageName); + } + + /** + * Test whether the passed NetworkCapabilities satisfies the requestor restrictions of this + * capabilities. + * + * This method is called on the NetworkCapabilities embedded in a request with the + * capabilities of an available network. If the available network, sets a specific + * requestor (by uid and optionally package name), then this will only match a request from the + * same app. If either of the capabilities have an unset uid or package name, then it matches + * everything. + *

+ * nc is assumed nonnull. Else, NPE. + */ + private boolean satisfiedByRequestor(NetworkCapabilities nc) { + // No uid set, matches everything. + if (mRequestorUid == Process.INVALID_UID || nc.mRequestorUid == Process.INVALID_UID) { + return true; + } + // uids don't match. + if (mRequestorUid != nc.mRequestorUid) return false; + // No package names set, matches everything + if (null == nc.mRequestorPackageName || null == mRequestorPackageName) return true; + // check for package name match. + return TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); + } + + /** + * Combine requestor info of the capabilities. + *

+ * This is only legal if either the requestor info of this object is reset, or both info are + * equal. + * nc is assumed nonnull. + */ + private void combineRequestor(@NonNull NetworkCapabilities nc) { + if (mRequestorUid != Process.INVALID_UID && mRequestorUid != nc.mOwnerUid) { + throw new IllegalStateException("Can't combine two uids"); + } + if (mRequestorPackageName != null + && !mRequestorPackageName.equals(nc.mRequestorPackageName)) { + throw new IllegalStateException("Can't combine two package names"); + } + setRequestorUid(nc.mRequestorUid); + setRequestorPackageName(nc.mRequestorPackageName); + } + + private boolean equalsRequestor(NetworkCapabilities nc) { + return mRequestorUid == nc.mRequestorUid + && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); + } + + /** + * Builder class for NetworkCapabilities. + * + * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in + * the built class require holding a signature permission to use - mostly + * {@link android.Manifest.permission.NETWORK_FACTORY}, but refer to the specific + * description of each setter. As this class lives entirely in app space it does not + * enforce these restrictions itself but the system server clears out the relevant + * fields when receiving a NetworkCapabilities object from a caller without the + * appropriate permission. + * + * Apps don't use this builder directly. Instead, they use {@link NetworkRequest} via + * its builder object. + * + * @hide + */ + @SystemApi + public static final class Builder { + private final NetworkCapabilities mCaps; + + /** + * Creates a new Builder to construct NetworkCapabilities objects. + */ + public Builder() { + mCaps = new NetworkCapabilities(); + } + + /** + * Creates a new Builder of NetworkCapabilities from an existing instance. + */ + public Builder(@NonNull final NetworkCapabilities nc) { + Objects.requireNonNull(nc); + mCaps = new NetworkCapabilities(nc); + } + + /** + * Adds the given transport type. + * + * Multiple transports may be added. Note that when searching for a network to satisfy a + * request, satisfying any of the transports listed in the request will satisfy the request. + * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a + * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network + * to be selected. This is logically different than + * {@code NetworkCapabilities.NET_CAPABILITY_*}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder addTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.addTransportType(transportType); + return this; + } + + /** + * Removes the given transport type. + * + * {@see #addTransportType}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder removeTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.removeTransportType(transportType); + return this; + } + + /** + * Adds the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder addCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, true); + return this; + } + + /** + * Removes the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder removeCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, false); + return this; + } + + /** + * Sets the owner UID. + * + * The default value is {@link Process#INVALID_UID}. Pass this value to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param ownerUid the owner UID + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setOwnerUid(final int ownerUid) { + mCaps.setOwnerUid(ownerUid); + return this; + } + + /** + * Sets the list of UIDs that are administrators of this network. + * + *

UIDs included in administratorUids gain administrator privileges over this + * Network. Examples of UIDs that should be included in administratorUids are: + *

    + *
  • Carrier apps with privileges for the relevant subscription + *
  • Active VPN apps + *
  • Other application groups with a particular Network-related role + *
+ * + *

In general, user-supplied networks (such as WiFi networks) do not have + * administrators. + * + *

An app is granted owner privileges over Networks that it supplies. The owner + * UID MUST always be included in administratorUids. + * + * The default value is the empty array. Pass an empty array to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, such as an app using reflection to call this or + * mutate the member in the built object. + * + * @param administratorUids the UIDs to be set as administrators of this Network. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setAdministratorUids(@NonNull final int[] administratorUids) { + Objects.requireNonNull(administratorUids); + mCaps.setAdministratorUids(administratorUids); + return this; + } + + /** + * Sets the upstream bandwidth of the link. + * + * Sets the upstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + *

+ * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkUpstreamBandwidthKbps(final int upKbps) { + mCaps.setLinkUpstreamBandwidthKbps(upKbps); + return this; + } + + /** + * Sets the downstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + *

+ * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkDownstreamBandwidthKbps(final int downKbps) { + mCaps.setLinkDownstreamBandwidthKbps(downKbps); + return this; + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + *

+ * + * @param specifier a concrete, parcelable framework class that extends NetworkSpecifier, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setNetworkSpecifier(@Nullable final NetworkSpecifier specifier) { + mCaps.setNetworkSpecifier(specifier); + return this; + } + + /** + * Sets the optional transport specific information. + * + * @param info A concrete, parcelable framework class that extends {@link TransportInfo}, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setTransportInfo(@Nullable final TransportInfo info) { + mCaps.setTransportInfo(info); + return this; + } + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a + * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the + * same RSSI units reported by wifi code. + *

+ * Note that when used to register a network callback, this specifies the minimum + * acceptable signal strength. When received as the state of an existing network it + * specifies the current value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means + * no value when received and has no effect when requesting a callback. + * + * Note: for security the system will throw if it receives a NetworkRequest where + * the underlying NetworkCapabilities has this member set from a source that does + * not hold the {@link android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP} + * permission. Apps with this permission can use this indirectly through + * {@link android.net.NetworkRequest}. + * + * @param signalStrength the bearer-specific signal strength. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) + public Builder setSignalStrength(final int signalStrength) { + mCaps.setSignalStrength(signalStrength); + return this; + } + + /** + * Sets the SSID of this network. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, like an app using reflection to set this. + * + * @param ssid the SSID, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setSsid(@Nullable final String ssid) { + mCaps.setSSID(ssid); + return this; + } + + /** + * Set the uid of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param uid UID of the app. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorUid(final int uid) { + mCaps.setRequestorUid(uid); + return this; + } + + /** + * Set the package name of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param packageName package name of the app, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorPackageName(@Nullable final String packageName) { + mCaps.setRequestorPackageName(packageName); + return this; + } + + /** + * Builds the instance of the capabilities. + * + * @return the built instance of NetworkCapabilities. + */ + @NonNull + public NetworkCapabilities build() { + if (mCaps.getOwnerUid() != Process.INVALID_UID) { + if (!ArrayUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { + throw new IllegalStateException("The owner UID must be included in " + + " administrator UIDs."); + } + } + return new NetworkCapabilities(mCaps); + } + } +} diff --git a/framework/src/android/net/NetworkConfig.java b/framework/src/android/net/NetworkConfig.java new file mode 100644 index 0000000000..32a2cda003 --- /dev/null +++ b/framework/src/android/net/NetworkConfig.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import java.util.Locale; + +/** + * Describes the buildtime configuration of a network. + * Holds settings read from resources. + * @hide + */ +public class NetworkConfig { + /** + * Human readable string + */ + public String name; + + /** + * Type from ConnectivityManager + */ + public int type; + + /** + * the radio number from radio attributes config + */ + public int radio; + + /** + * higher number == higher priority when turning off connections + */ + public int priority; + + /** + * indicates the boot time dependencyMet setting + */ + public boolean dependencyMet; + + /** + * indicates the default restoral timer in seconds + * if the network is used as a special network feature + * -1 indicates no restoration of default + */ + public int restoreTime; + + /** + * input string from config.xml resource. Uses the form: + * [Connection name],[ConnectivityManager connection type], + * [associated radio-type],[priority],[dependencyMet] + */ + public NetworkConfig(String init) { + String fragments[] = init.split(","); + name = fragments[0].trim().toLowerCase(Locale.ROOT); + type = Integer.parseInt(fragments[1]); + radio = Integer.parseInt(fragments[2]); + priority = Integer.parseInt(fragments[3]); + restoreTime = Integer.parseInt(fragments[4]); + dependencyMet = Boolean.parseBoolean(fragments[5]); + } + + /** + * Indicates if this network is supposed to be default-routable + */ + public boolean isDefault() { + return (type == radio); + } +} diff --git a/framework/src/android/net/NetworkInfo.aidl b/framework/src/android/net/NetworkInfo.aidl new file mode 100644 index 0000000000..f501873029 --- /dev/null +++ b/framework/src/android/net/NetworkInfo.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2007, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable NetworkInfo; diff --git a/framework/src/android/net/NetworkInfo.java b/framework/src/android/net/NetworkInfo.java new file mode 100644 index 0000000000..d752901e2e --- /dev/null +++ b/framework/src/android/net/NetworkInfo.java @@ -0,0 +1,626 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.Annotation.NetworkType; +import android.text.TextUtils; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.EnumMap; + +/** + * Describes the status of a network interface. + *

Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents + * the current network connection. + * + * @deprecated Callers should instead use the {@link ConnectivityManager.NetworkCallback} API to + * learn about connectivity changes, or switch to use + * {@link ConnectivityManager#getNetworkCapabilities} or + * {@link ConnectivityManager#getLinkProperties} to get information synchronously. Keep + * in mind that while callbacks are guaranteed to be called for every event in order, + * synchronous calls have no such constraints, and as such it is unadvisable to use the + * synchronous methods inside the callbacks as they will often not offer a view of + * networking that is consistent (that is: they may return a past or a future state with + * respect to the event being processed by the callback). Instead, callers are advised + * to only use the arguments of the callbacks, possibly memorizing the specific bits of + * information they need to keep from one callback to another. + */ +@Deprecated +public class NetworkInfo implements Parcelable { + + /** + * Coarse-grained network state. This is probably what most applications should + * use, rather than {@link android.net.NetworkInfo.DetailedState DetailedState}. + * The mapping between the two is as follows: + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Detailed stateCoarse-grained state
IDLEDISCONNECTED
SCANNINGDISCONNECTED
CONNECTINGCONNECTING
AUTHENTICATINGCONNECTING
OBTAINING_IPADDRCONNECTING
VERIFYING_POOR_LINKCONNECTING
CAPTIVE_PORTAL_CHECKCONNECTING
CONNECTEDCONNECTED
SUSPENDEDSUSPENDED
DISCONNECTINGDISCONNECTING
DISCONNECTEDDISCONNECTED
FAILEDDISCONNECTED
BLOCKEDDISCONNECTED
+ * + * @deprecated See {@link NetworkInfo}. + */ + @Deprecated + public enum State { + CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN + } + + /** + * The fine-grained state of a network connection. This level of detail + * is probably of interest to few applications. Most should use + * {@link android.net.NetworkInfo.State State} instead. + * + * @deprecated See {@link NetworkInfo}. + */ + @Deprecated + public enum DetailedState { + /** Ready to start data connection setup. */ + IDLE, + /** Searching for an available access point. */ + SCANNING, + /** Currently setting up data connection. */ + CONNECTING, + /** Network link established, performing authentication. */ + AUTHENTICATING, + /** Awaiting response from DHCP server in order to assign IP address information. */ + OBTAINING_IPADDR, + /** IP traffic should be available. */ + CONNECTED, + /** IP traffic is suspended */ + SUSPENDED, + /** Currently tearing down data connection. */ + DISCONNECTING, + /** IP traffic not available. */ + DISCONNECTED, + /** Attempt to connect failed. */ + FAILED, + /** Access to this network is blocked. */ + BLOCKED, + /** Link has poor connectivity. */ + VERIFYING_POOR_LINK, + /** Checking if network is a captive portal */ + CAPTIVE_PORTAL_CHECK + } + + /** + * This is the map described in the Javadoc comment above. The positions + * of the elements of the array must correspond to the ordinal values + * of DetailedState. + */ + private static final EnumMap stateMap = + new EnumMap(DetailedState.class); + + static { + stateMap.put(DetailedState.IDLE, State.DISCONNECTED); + stateMap.put(DetailedState.SCANNING, State.DISCONNECTED); + stateMap.put(DetailedState.CONNECTING, State.CONNECTING); + stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING); + stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING); + stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING); + stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING); + stateMap.put(DetailedState.CONNECTED, State.CONNECTED); + stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED); + stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING); + stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); + stateMap.put(DetailedState.FAILED, State.DISCONNECTED); + stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED); + } + + private int mNetworkType; + private int mSubtype; + private String mTypeName; + private String mSubtypeName; + @NonNull + private State mState; + @NonNull + private DetailedState mDetailedState; + private String mReason; + private String mExtraInfo; + private boolean mIsFailover; + private boolean mIsAvailable; + private boolean mIsRoaming; + + /** + * Create a new instance of NetworkInfo. + * + * This may be useful for apps to write unit tests. + * + * @param type the legacy type of the network, as one of the ConnectivityManager.TYPE_* + * constants. + * @param subtype the subtype if applicable, as one of the TelephonyManager.NETWORK_TYPE_* + * constants. + * @param typeName a human-readable string for the network type, or an empty string or null. + * @param subtypeName a human-readable string for the subtype, or an empty string or null. + */ + public NetworkInfo(int type, @NetworkType int subtype, + @Nullable String typeName, @Nullable String subtypeName) { + if (!ConnectivityManager.isNetworkTypeValid(type) + && type != ConnectivityManager.TYPE_NONE) { + throw new IllegalArgumentException("Invalid network type: " + type); + } + mNetworkType = type; + mSubtype = subtype; + mTypeName = typeName; + mSubtypeName = subtypeName; + setDetailedState(DetailedState.IDLE, null, null); + mState = State.UNKNOWN; + } + + /** {@hide} */ + @UnsupportedAppUsage + public NetworkInfo(NetworkInfo source) { + if (source != null) { + synchronized (source) { + mNetworkType = source.mNetworkType; + mSubtype = source.mSubtype; + mTypeName = source.mTypeName; + mSubtypeName = source.mSubtypeName; + mState = source.mState; + mDetailedState = source.mDetailedState; + mReason = source.mReason; + mExtraInfo = source.mExtraInfo; + mIsFailover = source.mIsFailover; + mIsAvailable = source.mIsAvailable; + mIsRoaming = source.mIsRoaming; + } + } + } + + /** + * Reports the type of network to which the + * info in this {@code NetworkInfo} pertains. + * @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link + * ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link + * ConnectivityManager#TYPE_ETHERNET}, {@link ConnectivityManager#TYPE_BLUETOOTH}, or other + * types defined by {@link ConnectivityManager}. + * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport} + * instead with one of the NetworkCapabilities#TRANSPORT_* constants : + * {@link #getType} and {@link #getTypeName} cannot account for networks using + * multiple transports. Note that generally apps should not care about transport; + * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and + * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that + * apps concerned with meteredness or bandwidth should be looking at, as they + * offer this information with much better accuracy. + */ + @Deprecated + public int getType() { + synchronized (this) { + return mNetworkType; + } + } + + /** + * @deprecated Use {@link NetworkCapabilities} instead + * @hide + */ + @Deprecated + public void setType(int type) { + synchronized (this) { + mNetworkType = type; + } + } + + /** + * Return a network-type-specific integer describing the subtype + * of the network. + * @return the network subtype + * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. + */ + @Deprecated + public int getSubtype() { + synchronized (this) { + return mSubtype; + } + } + + /** + * @hide + */ + @UnsupportedAppUsage + public void setSubtype(int subtype, String subtypeName) { + synchronized (this) { + mSubtype = subtype; + mSubtypeName = subtypeName; + } + } + + /** + * Return a human-readable name describe the type of the network, + * for example "WIFI" or "MOBILE". + * @return the name of the network type + * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport} + * instead with one of the NetworkCapabilities#TRANSPORT_* constants : + * {@link #getType} and {@link #getTypeName} cannot account for networks using + * multiple transports. Note that generally apps should not care about transport; + * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and + * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that + * apps concerned with meteredness or bandwidth should be looking at, as they + * offer this information with much better accuracy. + */ + @Deprecated + public String getTypeName() { + synchronized (this) { + return mTypeName; + } + } + + /** + * Return a human-readable name describing the subtype of the network. + * @return the name of the network subtype + * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. + */ + @Deprecated + public String getSubtypeName() { + synchronized (this) { + return mSubtypeName; + } + } + + /** + * Indicates whether network connectivity exists or is in the process + * of being established. This is good for applications that need to + * do anything related to the network other than read or write data. + * For the latter, call {@link #isConnected()} instead, which guarantees + * that the network is fully usable. + * @return {@code true} if network connectivity exists or is in the process + * of being established, {@code false} otherwise. + * @deprecated Apps should instead use the + * {@link android.net.ConnectivityManager.NetworkCallback} API to + * learn about connectivity changes. + * {@link ConnectivityManager#registerDefaultNetworkCallback} and + * {@link ConnectivityManager#registerNetworkCallback}. These will + * give a more accurate picture of the connectivity state of + * the device and let apps react more easily and quickly to changes. + */ + @Deprecated + public boolean isConnectedOrConnecting() { + synchronized (this) { + return mState == State.CONNECTED || mState == State.CONNECTING; + } + } + + /** + * Indicates whether network connectivity exists and it is possible to establish + * connections and pass data. + *

Always call this before attempting to perform data transactions. + * @return {@code true} if network connectivity exists, {@code false} otherwise. + * @deprecated Apps should instead use the + * {@link android.net.ConnectivityManager.NetworkCallback} API to + * learn about connectivity changes. See + * {@link ConnectivityManager#registerDefaultNetworkCallback} and + * {@link ConnectivityManager#registerNetworkCallback}. These will + * give a more accurate picture of the connectivity state of + * the device and let apps react more easily and quickly to changes. + */ + @Deprecated + public boolean isConnected() { + synchronized (this) { + return mState == State.CONNECTED; + } + } + + /** + * Indicates whether network connectivity is possible. A network is unavailable + * when a persistent or semi-persistent condition prevents the possibility + * of connecting to that network. Examples include + *

    + *
  • The device is out of the coverage area for any network of this type.
  • + *
  • The device is on a network other than the home network (i.e., roaming), and + * data roaming has been disabled.
  • + *
  • The device's radio is turned off, e.g., because airplane mode is enabled.
  • + *
+ * Since Android L, this always returns {@code true}, because the system only + * returns info for available networks. + * @return {@code true} if the network is available, {@code false} otherwise + * @deprecated Apps should instead use the + * {@link android.net.ConnectivityManager.NetworkCallback} API to + * learn about connectivity changes. + * {@link ConnectivityManager#registerDefaultNetworkCallback} and + * {@link ConnectivityManager#registerNetworkCallback}. These will + * give a more accurate picture of the connectivity state of + * the device and let apps react more easily and quickly to changes. + */ + @Deprecated + public boolean isAvailable() { + synchronized (this) { + return mIsAvailable; + } + } + + /** + * Sets if the network is available, ie, if the connectivity is possible. + * @param isAvailable the new availability value. + * @deprecated Use {@link NetworkCapabilities} instead + * + * @hide + */ + @Deprecated + @UnsupportedAppUsage + public void setIsAvailable(boolean isAvailable) { + synchronized (this) { + mIsAvailable = isAvailable; + } + } + + /** + * Indicates whether the current attempt to connect to the network + * resulted from the ConnectivityManager trying to fail over to this + * network following a disconnect from another network. + * @return {@code true} if this is a failover attempt, {@code false} + * otherwise. + * @deprecated This field is not populated in recent Android releases, + * and does not make a lot of sense in a multi-network world. + */ + @Deprecated + public boolean isFailover() { + synchronized (this) { + return mIsFailover; + } + } + + /** + * Set the failover boolean. + * @param isFailover {@code true} to mark the current connection attempt + * as a failover. + * @deprecated This hasn't been set in any recent Android release. + * @hide + */ + @Deprecated + @UnsupportedAppUsage + public void setFailover(boolean isFailover) { + synchronized (this) { + mIsFailover = isFailover; + } + } + + /** + * Indicates whether the device is currently roaming on this network. When + * {@code true}, it suggests that use of data on this network may incur + * extra costs. + * + * @return {@code true} if roaming is in effect, {@code false} otherwise. + * @deprecated Callers should switch to checking + * {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} + * instead, since that handles more complex situations, such as + * VPNs. + */ + @Deprecated + public boolean isRoaming() { + synchronized (this) { + return mIsRoaming; + } + } + + /** + * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} instead. + * {@hide} + */ + @VisibleForTesting + @Deprecated + @UnsupportedAppUsage + public void setRoaming(boolean isRoaming) { + synchronized (this) { + mIsRoaming = isRoaming; + } + } + + /** + * Reports the current coarse-grained state of the network. + * @return the coarse-grained state + * @deprecated Apps should instead use the + * {@link android.net.ConnectivityManager.NetworkCallback} API to + * learn about connectivity changes. + * {@link ConnectivityManager#registerDefaultNetworkCallback} and + * {@link ConnectivityManager#registerNetworkCallback}. These will + * give a more accurate picture of the connectivity state of + * the device and let apps react more easily and quickly to changes. + */ + @Deprecated + public State getState() { + synchronized (this) { + return mState; + } + } + + /** + * Reports the current fine-grained state of the network. + * @return the fine-grained state + * @deprecated Apps should instead use the + * {@link android.net.ConnectivityManager.NetworkCallback} API to + * learn about connectivity changes. See + * {@link ConnectivityManager#registerDefaultNetworkCallback} and + * {@link ConnectivityManager#registerNetworkCallback}. These will + * give a more accurate picture of the connectivity state of + * the device and let apps react more easily and quickly to changes. + */ + @Deprecated + public @NonNull DetailedState getDetailedState() { + synchronized (this) { + return mDetailedState; + } + } + + /** + * Sets the fine-grained state of the network. + * + * This is only useful for testing. + * + * @param detailedState the {@link DetailedState}. + * @param reason a {@code String} indicating the reason for the state change, + * if one was supplied. May be {@code null}. + * @param extraInfo an optional {@code String} providing addditional network state + * information passed up from the lower networking layers. + * @deprecated Use {@link NetworkCapabilities} instead. + */ + @Deprecated + public void setDetailedState(@NonNull DetailedState detailedState, @Nullable String reason, + @Nullable String extraInfo) { + synchronized (this) { + this.mDetailedState = detailedState; + this.mState = stateMap.get(detailedState); + this.mReason = reason; + this.mExtraInfo = extraInfo; + } + } + + /** + * Set the extraInfo field. + * @param extraInfo an optional {@code String} providing addditional network state + * information passed up from the lower networking layers. + * @deprecated See {@link NetworkInfo#getExtraInfo}. + * @hide + */ + @Deprecated + public void setExtraInfo(String extraInfo) { + synchronized (this) { + this.mExtraInfo = extraInfo; + } + } + + /** + * Report the reason an attempt to establish connectivity failed, + * if one is available. + * @return the reason for failure, or null if not available + * @deprecated This method does not have a consistent contract that could make it useful + * to callers. + */ + public String getReason() { + synchronized (this) { + return mReason; + } + } + + /** + * Report the extra information about the network state, if any was + * provided by the lower networking layers. + * @return the extra information, or null if not available + * @deprecated Use other services e.g. WifiManager to get additional information passed up from + * the lower networking layers. + */ + @Deprecated + public String getExtraInfo() { + synchronized (this) { + return mExtraInfo; + } + } + + @Override + public String toString() { + synchronized (this) { + final StringBuilder builder = new StringBuilder("["); + builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). + append("], state: ").append(mState).append("/").append(mDetailedState). + append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). + append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). + append(", failover: ").append(mIsFailover). + append(", available: ").append(mIsAvailable). + append(", roaming: ").append(mIsRoaming). + append("]"); + return builder.toString(); + } + } + + /** + * Returns a brief summary string suitable for debugging. + * @hide + */ + public String toShortString() { + synchronized (this) { + final StringBuilder builder = new StringBuilder(); + builder.append(getTypeName()); + + final String subtype = getSubtypeName(); + if (!TextUtils.isEmpty(subtype)) { + builder.append("[").append(subtype).append("]"); + } + + builder.append(" "); + builder.append(mDetailedState); + if (mIsRoaming) { + builder.append(" ROAMING"); + } + if (mExtraInfo != null) { + builder.append(" extra: ").append(mExtraInfo); + } + return builder.toString(); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + synchronized (this) { + dest.writeInt(mNetworkType); + dest.writeInt(mSubtype); + dest.writeString(mTypeName); + dest.writeString(mSubtypeName); + dest.writeString(mState.name()); + dest.writeString(mDetailedState.name()); + dest.writeInt(mIsFailover ? 1 : 0); + dest.writeInt(mIsAvailable ? 1 : 0); + dest.writeInt(mIsRoaming ? 1 : 0); + dest.writeString(mReason); + dest.writeString(mExtraInfo); + } + } + + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { + @Override + public NetworkInfo createFromParcel(Parcel in) { + int netType = in.readInt(); + int subtype = in.readInt(); + String typeName = in.readString(); + String subtypeName = in.readString(); + NetworkInfo netInfo = new NetworkInfo(netType, subtype, typeName, subtypeName); + netInfo.mState = State.valueOf(in.readString()); + netInfo.mDetailedState = DetailedState.valueOf(in.readString()); + netInfo.mIsFailover = in.readInt() != 0; + netInfo.mIsAvailable = in.readInt() != 0; + netInfo.mIsRoaming = in.readInt() != 0; + netInfo.mReason = in.readString(); + netInfo.mExtraInfo = in.readString(); + return netInfo; + } + + @Override + public NetworkInfo[] newArray(int size) { + return new NetworkInfo[size]; + } + }; +} diff --git a/framework/src/android/net/NetworkProvider.java b/framework/src/android/net/NetworkProvider.java new file mode 100644 index 0000000000..14cb51c85d --- /dev/null +++ b/framework/src/android/net/NetworkProvider.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; +import android.util.Log; + +/** + * Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device + * to networks and makes them available to the core network stack by creating + * {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted + * with via networking APIs such as {@link ConnectivityManager}. + * + * Subclasses should implement {@link #onNetworkRequested} and {@link #onNetworkRequestWithdrawn} + * to receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the + * best (highest-scoring) network for any request is generally not used by the system, and torn + * down. + * + * @hide + */ +@SystemApi +public class NetworkProvider { + /** + * {@code providerId} value that indicates the absence of a provider. It is the providerId of + * any NetworkProvider that is not currently registered, and of any NetworkRequest that is not + * currently being satisfied by a network. + */ + public static final int ID_NONE = -1; + + /** + * The first providerId value that will be allocated. + * @hide only used by ConnectivityService. + */ + public static final int FIRST_PROVIDER_ID = 1; + + /** @hide only used by ConnectivityService */ + public static final int CMD_REQUEST_NETWORK = 1; + /** @hide only used by ConnectivityService */ + public static final int CMD_CANCEL_REQUEST = 2; + + private final Messenger mMessenger; + private final String mName; + private final Context mContext; + + private int mProviderId = ID_NONE; + + /** + * Constructs a new NetworkProvider. + * + * @param looper the Looper on which to run {@link #onNetworkRequested} and + * {@link #onNetworkRequestWithdrawn}. + * @param name the name of the listener, used only for debugging. + * + * @hide + */ + @SystemApi + public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) { + Handler handler = new Handler(looper) { + @Override + public void handleMessage(Message m) { + switch (m.what) { + case CMD_REQUEST_NETWORK: + onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2); + break; + case CMD_CANCEL_REQUEST: + onNetworkRequestWithdrawn((NetworkRequest) m.obj); + break; + default: + Log.e(mName, "Unhandled message: " + m.what); + } + } + }; + mContext = context; + mMessenger = new Messenger(handler); + mName = name; + } + + // TODO: consider adding a register() method so ConnectivityManager does not need to call this. + /** @hide */ + public @Nullable Messenger getMessenger() { + return mMessenger; + } + + /** @hide */ + public @NonNull String getName() { + return mName; + } + + /** + * Returns the ID of this provider. This is known only once the provider is registered via + * {@link ConnectivityManager#registerNetworkProvider()}, otherwise the ID is {@link #ID_NONE}. + * This ID must be used when registering any {@link NetworkAgent}s. + */ + public int getProviderId() { + return mProviderId; + } + + /** @hide */ + public void setProviderId(int providerId) { + mProviderId = providerId; + } + + /** + * Called when a NetworkRequest is received. The request may be a new request or an existing + * request with a different score. + * + * @param request the NetworkRequest being received + * @param score the score of the network currently satisfying the request, or 0 if none. + * @param providerId the ID of the provider that created the network currently satisfying this + * request, or {@link #ID_NONE} if none. + * + * @hide + */ + @SystemApi + public void onNetworkRequested(@NonNull NetworkRequest request, + @IntRange(from = 0, to = 99) int score, int providerId) {} + + /** + * Called when a NetworkRequest is withdrawn. + * @hide + */ + @SystemApi + public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {} + + /** + * Asserts that no provider will ever be able to satisfy the specified request. The provider + * must only call this method if it knows that it is the only provider on the system capable of + * satisfying this request, and that the request cannot be satisfied. The application filing the + * request will receive an {@link NetworkCallback#onUnavailable()} callback. + * + * @param request the request that permanently cannot be fulfilled + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) { + ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request); + } +} diff --git a/framework/src/android/net/NetworkRequest.aidl b/framework/src/android/net/NetworkRequest.aidl new file mode 100644 index 0000000000..508defc6b4 --- /dev/null +++ b/framework/src/android/net/NetworkRequest.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2014, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable NetworkRequest; + diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java new file mode 100644 index 0000000000..04011fc681 --- /dev/null +++ b/framework/src/android/net/NetworkRequest.java @@ -0,0 +1,582 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.net.NetworkCapabilities.NetCapability; +import android.net.NetworkCapabilities.Transport; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.Process; +import android.text.TextUtils; +import android.util.proto.ProtoOutputStream; + +import java.util.Objects; +import java.util.Set; + +/** + * Defines a request for a network, made through {@link NetworkRequest.Builder} and used + * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes + * via {@link ConnectivityManager#registerNetworkCallback}. + */ +public class NetworkRequest implements Parcelable { + /** + * The first requestId value that will be allocated. + * @hide only used by ConnectivityService. + */ + public static final int FIRST_REQUEST_ID = 1; + + /** + * The requestId value that represents the absence of a request. + * @hide only used by ConnectivityService. + */ + public static final int REQUEST_ID_NONE = -1; + + /** + * The {@link NetworkCapabilities} that define this request. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public final @NonNull NetworkCapabilities networkCapabilities; + + /** + * Identifies the request. NetworkRequests should only be constructed by + * the Framework and given out to applications as tokens to be used to identify + * the request. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public final int requestId; + + /** + * Set for legacy requests and the default. Set to TYPE_NONE for none. + * Causes CONNECTIVITY_ACTION broadcasts to be sent. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + public final int legacyType; + + /** + * A NetworkRequest as used by the system can be one of the following types: + * + * - LISTEN, for which the framework will issue callbacks about any + * and all networks that match the specified NetworkCapabilities, + * + * - REQUEST, capable of causing a specific network to be created + * first (e.g. a telephony DUN request), the framework will issue + * callbacks about the single, highest scoring current network + * (if any) that matches the specified NetworkCapabilities, or + * + * - TRACK_DEFAULT, a hybrid of the two designed such that the + * framework will issue callbacks for the single, highest scoring + * current network (if any) that matches the capabilities of the + * default Internet request (mDefaultRequest), but which cannot cause + * the framework to either create or retain the existence of any + * specific network. Note that from the point of view of the request + * matching code, TRACK_DEFAULT is identical to REQUEST: its special + * behaviour is not due to different semantics, but to the fact that + * the system will only ever create a TRACK_DEFAULT with capabilities + * that are identical to the default request's capabilities, thus + * causing it to share fate in every way with the default request. + * + * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks + * to retain the NET_CAPABILITY_FOREGROUND capability. A network with + * no foreground requests is in the background. A network that has + * one or more background requests and loses its last foreground + * request to a higher-scoring network will not go into the + * background immediately, but will linger and go into the background + * after the linger timeout. + * + * - The value NONE is used only by applications. When an application + * creates a NetworkRequest, it does not have a type; the type is set + * by the system depending on the method used to file the request + * (requestNetwork, registerNetworkCallback, etc.). + * + * @hide + */ + public static enum Type { + NONE, + LISTEN, + TRACK_DEFAULT, + REQUEST, + BACKGROUND_REQUEST, + }; + + /** + * The type of the request. This is only used by the system and is always NONE elsewhere. + * + * @hide + */ + public final Type type; + + /** + * @hide + */ + public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId, Type type) { + if (nc == null) { + throw new NullPointerException(); + } + requestId = rId; + networkCapabilities = nc; + this.legacyType = legacyType; + this.type = type; + } + + /** + * @hide + */ + public NetworkRequest(NetworkRequest that) { + networkCapabilities = new NetworkCapabilities(that.networkCapabilities); + requestId = that.requestId; + this.legacyType = that.legacyType; + this.type = that.type; + } + + /** + * Builder used to create {@link NetworkRequest} objects. Specify the Network features + * needed in terms of {@link NetworkCapabilities} features + */ + public static class Builder { + private final NetworkCapabilities mNetworkCapabilities; + + /** + * Default constructor for Builder. + */ + public Builder() { + // By default, restrict this request to networks available to this app. + // Apps can rescind this restriction, but ConnectivityService will enforce + // it for apps that do not have the NETWORK_SETTINGS permission. + mNetworkCapabilities = new NetworkCapabilities(); + mNetworkCapabilities.setSingleUid(Process.myUid()); + } + + /** + * Build {@link NetworkRequest} give the current set of capabilities. + */ + public NetworkRequest build() { + // Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED + // when later an unrestricted capability could be added to mNetworkCapabilities, in + // which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which + // maybeMarkCapabilitiesRestricted() doesn't add back. + final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); + nc.maybeMarkCapabilitiesRestricted(); + return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, + ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); + } + + /** + * Add the given capability requirement to this builder. These represent + * the requested network's required capabilities. Note that when searching + * for a network to satisfy a request, all capabilities requested must be + * satisfied. + * + * @param capability The capability to add. + * @return The builder to facilitate chaining + * {@code builder.addCapability(...).addCapability();}. + */ + public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { + mNetworkCapabilities.addCapability(capability); + return this; + } + + /** + * Removes (if found) the given capability from this builder instance. + * + * @param capability The capability to remove. + * @return The builder to facilitate chaining. + */ + public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { + mNetworkCapabilities.removeCapability(capability); + return this; + } + + /** + * Set the {@code NetworkCapabilities} for this builder instance, + * overriding any capabilities that had been previously set. + * + * @param nc The superseding {@code NetworkCapabilities} instance. + * @return The builder to facilitate chaining. + * @hide + */ + public Builder setCapabilities(NetworkCapabilities nc) { + mNetworkCapabilities.set(nc); + return this; + } + + /** + * Set the watched UIDs for this request. This will be reset and wiped out unless + * the calling app holds the CHANGE_NETWORK_STATE permission. + * + * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @return The builder to facilitate chaining. + * @hide + */ + public Builder setUids(Set uids) { + mNetworkCapabilities.setUids(uids); + return this; + } + + /** + * Add a capability that must not exist in the requested network. + *

+ * If the capability was previously added to the list of required capabilities (for + * example, it was there by default or added using {@link #addCapability(int)} method), then + * it will be removed from the list of required capabilities as well. + * + * @see #addCapability(int) + * + * @param capability The capability to add to unwanted capability list. + * @return The builder to facilitate chaining. + * + * @hide + */ + public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) { + mNetworkCapabilities.addUnwantedCapability(capability); + return this; + } + + /** + * Completely clears all the {@code NetworkCapabilities} from this builder instance, + * removing even the capabilities that are set by default when the object is constructed. + * + * @return The builder to facilitate chaining. + */ + @NonNull + public Builder clearCapabilities() { + mNetworkCapabilities.clearAll(); + return this; + } + + /** + * Adds the given transport requirement to this builder. These represent + * the set of allowed transports for the request. Only networks using one + * of these transports will satisfy the request. If no particular transports + * are required, none should be specified here. + * + * @param transportType The transport type to add. + * @return The builder to facilitate chaining. + */ + public Builder addTransportType(@NetworkCapabilities.Transport int transportType) { + mNetworkCapabilities.addTransportType(transportType); + return this; + } + + /** + * Removes (if found) the given transport from this builder instance. + * + * @param transportType The transport type to remove. + * @return The builder to facilitate chaining. + */ + public Builder removeTransportType(@NetworkCapabilities.Transport int transportType) { + mNetworkCapabilities.removeTransportType(transportType); + return this; + } + + /** + * @hide + */ + public Builder setLinkUpstreamBandwidthKbps(int upKbps) { + mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps); + return this; + } + /** + * @hide + */ + public Builder setLinkDownstreamBandwidthKbps(int downKbps) { + mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps); + return this; + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + *

+ * If the {@code networkSpecifier} is provided, it shall be interpreted as follows: + *
    + *
  • If the specifier can be parsed as an integer, it will be treated as a + * {@link android.net TelephonyNetworkSpecifier}, and the provided integer will be + * interpreted as a SubscriptionId. + *
  • If the value is an ethernet interface name, it will be treated as such. + *
  • For all other cases, the behavior is undefined. + *
+ * + * @param networkSpecifier A {@code String} of either a SubscriptionId in cellular + * network request or an ethernet interface name in ethernet + * network request. + * + * @deprecated Use {@link #setNetworkSpecifier(NetworkSpecifier)} instead. + */ + @Deprecated + public Builder setNetworkSpecifier(String networkSpecifier) { + try { + int subId = Integer.parseInt(networkSpecifier); + return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() + .setSubscriptionId(subId).build()); + } catch (NumberFormatException nfe) { + // A StringNetworkSpecifier does not accept null or empty ("") strings. When network + // specifiers were strings a null string and an empty string were considered + // equivalent. Hence no meaning is attached to a null or empty ("") string. + return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null + : new StringNetworkSpecifier(networkSpecifier)); + } + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + *

+ * + * @param networkSpecifier A concrete, parcelable framework class that extends + * NetworkSpecifier. + */ + public Builder setNetworkSpecifier(NetworkSpecifier networkSpecifier) { + if (networkSpecifier instanceof MatchAllNetworkSpecifier) { + throw new IllegalArgumentException("A MatchAllNetworkSpecifier is not permitted"); + } + mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); + return this; + } + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a + * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same + * RSSI units reported by WifiManager. + *

+ * Note that when used to register a network callback, this specifies the minimum acceptable + * signal strength. When received as the state of an existing network it specifies the + * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when + * received and has no effect when requesting a callback. + * + *

This method requires the caller to hold the + * {@link android.Manifest.permission#NETWORK_SIGNAL_STRENGTH_WAKEUP} permission + * + * @param signalStrength the bearer-specific signal strength. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) + public @NonNull Builder setSignalStrength(int signalStrength) { + mNetworkCapabilities.setSignalStrength(signalStrength); + return this; + } + } + + // implement the Parcelable interface + public int describeContents() { + return 0; + } + public void writeToParcel(Parcel dest, int flags) { + networkCapabilities.writeToParcel(dest, flags); + dest.writeInt(legacyType); + dest.writeInt(requestId); + dest.writeString(type.name()); + } + + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public NetworkRequest createFromParcel(Parcel in) { + NetworkCapabilities nc = NetworkCapabilities.CREATOR.createFromParcel(in); + int legacyType = in.readInt(); + int requestId = in.readInt(); + Type type = Type.valueOf(in.readString()); // IllegalArgumentException if invalid. + NetworkRequest result = new NetworkRequest(nc, legacyType, requestId, type); + return result; + } + public NetworkRequest[] newArray(int size) { + return new NetworkRequest[size]; + } + }; + + /** + * Returns true iff. this NetworkRequest is of type LISTEN. + * + * @hide + */ + public boolean isListen() { + return type == Type.LISTEN; + } + + /** + * Returns true iff. the contained NetworkRequest is one that: + * + * - should be associated with at most one satisfying network + * at a time; + * + * - should cause a network to be kept up, but not necessarily in + * the foreground, if it is the best network which can satisfy the + * NetworkRequest. + * + * For full detail of how isRequest() is used for pairing Networks with + * NetworkRequests read rematchNetworkAndRequests(). + * + * @hide + */ + public boolean isRequest() { + return isForegroundRequest() || isBackgroundRequest(); + } + + /** + * Returns true iff. the contained NetworkRequest is one that: + * + * - should be associated with at most one satisfying network + * at a time; + * + * - should cause a network to be kept up and in the foreground if + * it is the best network which can satisfy the NetworkRequest. + * + * For full detail of how isRequest() is used for pairing Networks with + * NetworkRequests read rematchNetworkAndRequests(). + * + * @hide + */ + public boolean isForegroundRequest() { + return type == Type.TRACK_DEFAULT || type == Type.REQUEST; + } + + /** + * Returns true iff. this NetworkRequest is of type BACKGROUND_REQUEST. + * + * @hide + */ + public boolean isBackgroundRequest() { + return type == Type.BACKGROUND_REQUEST; + } + + /** + * @see Builder#addCapability(int) + */ + public boolean hasCapability(@NetCapability int capability) { + return networkCapabilities.hasCapability(capability); + } + + /** + * @see Builder#addUnwantedCapability(int) + * + * @hide + */ + public boolean hasUnwantedCapability(@NetCapability int capability) { + return networkCapabilities.hasUnwantedCapability(capability); + } + + /** + * Returns true if and only if the capabilities requested in this NetworkRequest are satisfied + * by the provided {@link NetworkCapabilities}. + * + * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not + * satisfy any request. + */ + public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) { + return networkCapabilities.satisfiedByNetworkCapabilities(nc); + } + + /** + * @see Builder#addTransportType(int) + */ + public boolean hasTransport(@Transport int transportType) { + return networkCapabilities.hasTransport(transportType); + } + + /** + * @see Builder#setNetworkSpecifier(NetworkSpecifier) + */ + @Nullable + public NetworkSpecifier getNetworkSpecifier() { + return networkCapabilities.getNetworkSpecifier(); + } + + /** + * @return the uid of the app making the request. + * + * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} object was + * not obtained from {@link ConnectivityManager}. + * @hide + */ + @SystemApi + public int getRequestorUid() { + return networkCapabilities.getRequestorUid(); + } + + /** + * @return the package name of the app making the request. + * + * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained + * from {@link ConnectivityManager}. + * @hide + */ + @SystemApi + @Nullable + public String getRequestorPackageName() { + return networkCapabilities.getRequestorPackageName(); + } + + public String toString() { + return "NetworkRequest [ " + type + " id=" + requestId + + (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") + + ", " + networkCapabilities.toString() + " ]"; + } + + private int typeToProtoEnum(Type t) { + switch (t) { + case NONE: + return NetworkRequestProto.TYPE_NONE; + case LISTEN: + return NetworkRequestProto.TYPE_LISTEN; + case TRACK_DEFAULT: + return NetworkRequestProto.TYPE_TRACK_DEFAULT; + case REQUEST: + return NetworkRequestProto.TYPE_REQUEST; + case BACKGROUND_REQUEST: + return NetworkRequestProto.TYPE_BACKGROUND_REQUEST; + default: + return NetworkRequestProto.TYPE_UNKNOWN; + } + } + + /** @hide */ + public void dumpDebug(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + + proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type)); + proto.write(NetworkRequestProto.REQUEST_ID, requestId); + proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType); + networkCapabilities.dumpDebug(proto, NetworkRequestProto.NETWORK_CAPABILITIES); + + proto.end(token); + } + + public boolean equals(Object obj) { + if (obj instanceof NetworkRequest == false) return false; + NetworkRequest that = (NetworkRequest)obj; + return (that.legacyType == this.legacyType && + that.requestId == this.requestId && + that.type == this.type && + Objects.equals(that.networkCapabilities, this.networkCapabilities)); + } + + public int hashCode() { + return Objects.hash(requestId, legacyType, networkCapabilities, type); + } +} diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java new file mode 100644 index 0000000000..8be4af7b13 --- /dev/null +++ b/framework/src/android/net/NetworkUtils.java @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.system.ErrnoException; +import android.util.Log; +import android.util.Pair; + +import com.android.net.module.util.Inet4AddressUtils; + +import java.io.FileDescriptor; +import java.math.BigInteger; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Locale; +import java.util.TreeSet; + +/** + * Native methods for managing network interfaces. + * + * {@hide} + */ +public class NetworkUtils { + + private static final String TAG = "NetworkUtils"; + + /** + * Attaches a socket filter that drops all of incoming packets. + * @param fd the socket's {@link FileDescriptor}. + */ + public static native void attachDropAllBPFFilter(FileDescriptor fd) throws SocketException; + + /** + * Detaches a socket filter. + * @param fd the socket's {@link FileDescriptor}. + */ + public static native void detachBPFFilter(FileDescriptor fd) throws SocketException; + + /** + * Binds the current process to the network designated by {@code netId}. All sockets created + * in the future (and not explicitly bound via a bound {@link SocketFactory} (see + * {@link Network#getSocketFactory}) will be bound to this network. Note that if this + * {@code Network} ever disconnects all sockets created in this way will cease to work. This + * is by design so an application doesn't accidentally use sockets it thinks are still bound to + * a particular {@code Network}. Passing NETID_UNSET clears the binding. + */ + public native static boolean bindProcessToNetwork(int netId); + + /** + * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if + * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}. + */ + public native static int getBoundNetworkForProcess(); + + /** + * Binds host resolutions performed by this process to the network designated by {@code netId}. + * {@link #bindProcessToNetwork} takes precedence over this setting. Passing NETID_UNSET clears + * the binding. + * + * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature(). + */ + @Deprecated + public native static boolean bindProcessToNetworkForHostResolution(int netId); + + /** + * Explicitly binds {@code fd} to the network designated by {@code netId}. This + * overrides any binding via {@link #bindProcessToNetwork}. + * @return 0 on success or negative errno on failure. + */ + public static native int bindSocketToNetwork(FileDescriptor fd, int netId); + + /** + * Protect {@code fd} from VPN connections. After protecting, data sent through + * this socket will go directly to the underlying network, so its traffic will not be + * forwarded through the VPN. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static native boolean protectFromVpn(FileDescriptor fd); + + /** + * Protect {@code socketfd} from VPN connections. After protecting, data sent through + * this socket will go directly to the underlying network, so its traffic will not be + * forwarded through the VPN. + */ + public native static boolean protectFromVpn(int socketfd); + + /** + * Determine if {@code uid} can access network designated by {@code netId}. + * @return {@code true} if {@code uid} can access network, {@code false} otherwise. + */ + public native static boolean queryUserAccess(int uid, int netId); + + /** + * DNS resolver series jni method. + * Issue the query {@code msg} on the network designated by {@code netId}. + * {@code flags} is an additional config to control actual querying behavior. + * @return a file descriptor to watch for read events + */ + public static native FileDescriptor resNetworkSend( + int netId, byte[] msg, int msglen, int flags) throws ErrnoException; + + /** + * DNS resolver series jni method. + * Look up the {@code nsClass} {@code nsType} Resource Record (RR) associated + * with Domain Name {@code dname} on the network designated by {@code netId}. + * {@code flags} is an additional config to control actual querying behavior. + * @return a file descriptor to watch for read events + */ + public static native FileDescriptor resNetworkQuery( + int netId, String dname, int nsClass, int nsType, int flags) throws ErrnoException; + + /** + * DNS resolver series jni method. + * Read a result for the query associated with the {@code fd}. + * @return DnsResponse containing blob answer and rcode + */ + public static native DnsResolver.DnsResponse resNetworkResult(FileDescriptor fd) + throws ErrnoException; + + /** + * DNS resolver series jni method. + * Attempts to cancel the in-progress query associated with the {@code fd}. + */ + public static native void resNetworkCancel(FileDescriptor fd); + + /** + * DNS resolver series jni method. + * Attempts to get network which resolver will use if no network is explicitly selected. + */ + public static native Network getDnsNetwork() throws ErrnoException; + + /** + * Get the tcp repair window associated with the {@code fd}. + * + * @param fd the tcp socket's {@link FileDescriptor}. + * @return a {@link TcpRepairWindow} object indicates tcp window size. + */ + public static native TcpRepairWindow getTcpRepairWindow(FileDescriptor fd) + throws ErrnoException; + + /** + * @see Inet4AddressUtils#intToInet4AddressHTL(int) + * @deprecated Use either {@link Inet4AddressUtils#intToInet4AddressHTH(int)} + * or {@link Inet4AddressUtils#intToInet4AddressHTL(int)} + */ + @Deprecated + @UnsupportedAppUsage + public static InetAddress intToInetAddress(int hostAddress) { + return Inet4AddressUtils.intToInet4AddressHTL(hostAddress); + } + + /** + * @see Inet4AddressUtils#inet4AddressToIntHTL(Inet4Address) + * @deprecated Use either {@link Inet4AddressUtils#inet4AddressToIntHTH(Inet4Address)} + * or {@link Inet4AddressUtils#inet4AddressToIntHTL(Inet4Address)} + */ + @Deprecated + public static int inetAddressToInt(Inet4Address inetAddr) + throws IllegalArgumentException { + return Inet4AddressUtils.inet4AddressToIntHTL(inetAddr); + } + + /** + * @see Inet4AddressUtils#prefixLengthToV4NetmaskIntHTL(int) + * @deprecated Use either {@link Inet4AddressUtils#prefixLengthToV4NetmaskIntHTH(int)} + * or {@link Inet4AddressUtils#prefixLengthToV4NetmaskIntHTL(int)} + */ + @Deprecated + @UnsupportedAppUsage + public static int prefixLengthToNetmaskInt(int prefixLength) + throws IllegalArgumentException { + return Inet4AddressUtils.prefixLengthToV4NetmaskIntHTL(prefixLength); + } + + /** + * Convert a IPv4 netmask integer to a prefix length + * @param netmask as an integer (0xff000000 for a /8 subnet) + * @return the network prefix length + */ + public static int netmaskIntToPrefixLength(int netmask) { + return Integer.bitCount(netmask); + } + + /** + * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous. + * @param netmask as a {@code Inet4Address}. + * @return the network prefix length + * @throws IllegalArgumentException the specified netmask was not contiguous. + * @hide + * @deprecated use {@link Inet4AddressUtils#netmaskToPrefixLength(Inet4Address)} + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Deprecated + public static int netmaskToPrefixLength(Inet4Address netmask) { + // This is only here because some apps seem to be using it (@UnsupportedAppUsage). + return Inet4AddressUtils.netmaskToPrefixLength(netmask); + } + + + /** + * Create an InetAddress from a string where the string must be a standard + * representation of a V4 or V6 address. Avoids doing a DNS lookup on failure + * but it will throw an IllegalArgumentException in that case. + * @param addrString + * @return the InetAddress + * @hide + * @deprecated Use {@link InetAddresses#parseNumericAddress(String)}, if possible. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) + @Deprecated + public static InetAddress numericToInetAddress(String addrString) + throws IllegalArgumentException { + return InetAddress.parseNumericAddress(addrString); + } + + /** + * Masks a raw IP address byte array with the specified prefix length. + */ + public static void maskRawAddress(byte[] array, int prefixLength) { + if (prefixLength < 0 || prefixLength > array.length * 8) { + throw new RuntimeException("IP address with " + array.length + + " bytes has invalid prefix length " + prefixLength); + } + + int offset = prefixLength / 8; + int remainder = prefixLength % 8; + byte mask = (byte)(0xFF << (8 - remainder)); + + if (offset < array.length) array[offset] = (byte)(array[offset] & mask); + + offset++; + + for (; offset < array.length; offset++) { + array[offset] = 0; + } + } + + /** + * Get InetAddress masked with prefixLength. Will never return null. + * @param address the IP address to mask with + * @param prefixLength the prefixLength used to mask the IP + */ + public static InetAddress getNetworkPart(InetAddress address, int prefixLength) { + byte[] array = address.getAddress(); + maskRawAddress(array, prefixLength); + + InetAddress netPart = null; + try { + netPart = InetAddress.getByAddress(array); + } catch (UnknownHostException e) { + throw new RuntimeException("getNetworkPart error - " + e.toString()); + } + return netPart; + } + + /** + * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static int getImplicitNetmask(Inet4Address address) { + // Only here because it seems to be used by apps + return Inet4AddressUtils.getImplicitNetmask(address); + } + + /** + * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64". + * @hide + */ + public static Pair parseIpAndMask(String ipAndMaskString) { + InetAddress address = null; + int prefixLength = -1; + try { + String[] pieces = ipAndMaskString.split("/", 2); + prefixLength = Integer.parseInt(pieces[1]); + address = InetAddress.parseNumericAddress(pieces[0]); + } catch (NullPointerException e) { // Null string. + } catch (ArrayIndexOutOfBoundsException e) { // No prefix length. + } catch (NumberFormatException e) { // Non-numeric prefix. + } catch (IllegalArgumentException e) { // Invalid IP address. + } + + if (address == null || prefixLength == -1) { + throw new IllegalArgumentException("Invalid IP address and mask " + ipAndMaskString); + } + + return new Pair(address, prefixLength); + } + + /** + * Convert a 32 char hex string into a Inet6Address. + * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be + * made into an Inet6Address + * @param addrHexString a 32 character hex string representing an IPv6 addr + * @return addr an InetAddress representation for the string + */ + public static InetAddress hexToInet6Address(String addrHexString) + throws IllegalArgumentException { + try { + return numericToInetAddress(String.format(Locale.US, "%s:%s:%s:%s:%s:%s:%s:%s", + addrHexString.substring(0,4), addrHexString.substring(4,8), + addrHexString.substring(8,12), addrHexString.substring(12,16), + addrHexString.substring(16,20), addrHexString.substring(20,24), + addrHexString.substring(24,28), addrHexString.substring(28,32))); + } catch (Exception e) { + Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e); + throw new IllegalArgumentException(e); + } + } + + /** + * Trim leading zeros from IPv4 address strings + * Our base libraries will interpret that as octel.. + * Must leave non v4 addresses and host names alone. + * For example, 192.168.000.010 -> 192.168.0.10 + * TODO - fix base libraries and remove this function + * @param addr a string representing an ip addr + * @return a string propertly trimmed + */ + @UnsupportedAppUsage + public static String trimV4AddrZeros(String addr) { + if (addr == null) return null; + String[] octets = addr.split("\\."); + if (octets.length != 4) return addr; + StringBuilder builder = new StringBuilder(16); + String result = null; + for (int i = 0; i < 4; i++) { + try { + if (octets[i].length() > 3) return addr; + builder.append(Integer.parseInt(octets[i])); + } catch (NumberFormatException e) { + return addr; + } + if (i < 3) builder.append('.'); + } + result = builder.toString(); + return result; + } + + /** + * Returns a prefix set without overlaps. + * + * This expects the src set to be sorted from shorter to longer. Results are undefined + * failing this condition. The returned prefix set is sorted in the same order as the + * passed set, with the same comparator. + */ + private static TreeSet deduplicatePrefixSet(final TreeSet src) { + final TreeSet dst = new TreeSet<>(src.comparator()); + // Prefixes match addresses that share their upper part up to their length, therefore + // the only kind of possible overlap in two prefixes is strict inclusion of the longer + // (more restrictive) in the shorter (including equivalence if they have the same + // length). + // Because prefixes in the src set are sorted from shorter to longer, deduplicating + // is done by simply iterating in order, and not adding any longer prefix that is + // already covered by a shorter one. + newPrefixes: + for (IpPrefix newPrefix : src) { + for (IpPrefix existingPrefix : dst) { + if (existingPrefix.containsPrefix(newPrefix)) { + continue newPrefixes; + } + } + dst.add(newPrefix); + } + return dst; + } + + /** + * Returns how many IPv4 addresses match any of the prefixes in the passed ordered set. + * + * Obviously this returns an integral value between 0 and 2**32. + * The behavior is undefined if any of the prefixes is not an IPv4 prefix or if the + * set is not ordered smallest prefix to longer prefix. + * + * @param prefixes the set of prefixes, ordered by length + */ + public static long routedIPv4AddressCount(final TreeSet prefixes) { + long routedIPCount = 0; + for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) { + if (!prefix.isIPv4()) { + Log.wtf(TAG, "Non-IPv4 prefix in routedIPv4AddressCount"); + } + int rank = 32 - prefix.getPrefixLength(); + routedIPCount += 1L << rank; + } + return routedIPCount; + } + + /** + * Returns how many IPv6 addresses match any of the prefixes in the passed ordered set. + * + * This returns a BigInteger between 0 and 2**128. + * The behavior is undefined if any of the prefixes is not an IPv6 prefix or if the + * set is not ordered smallest prefix to longer prefix. + */ + public static BigInteger routedIPv6AddressCount(final TreeSet prefixes) { + BigInteger routedIPCount = BigInteger.ZERO; + for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) { + if (!prefix.isIPv6()) { + Log.wtf(TAG, "Non-IPv6 prefix in routedIPv6AddressCount"); + } + int rank = 128 - prefix.getPrefixLength(); + routedIPCount = routedIPCount.add(BigInteger.ONE.shiftLeft(rank)); + } + return routedIPCount; + } + +} diff --git a/framework/src/android/net/PacProxySelector.java b/framework/src/android/net/PacProxySelector.java new file mode 100644 index 0000000000..326943a27d --- /dev/null +++ b/framework/src/android/net/PacProxySelector.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.ServiceManager; +import android.util.Log; + +import com.android.net.IProxyService; + +import com.google.android.collect.Lists; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.Proxy.Type; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +/** + * @hide + */ +public class PacProxySelector extends ProxySelector { + private static final String TAG = "PacProxySelector"; + public static final String PROXY_SERVICE = "com.android.net.IProxyService"; + private static final String SOCKS = "SOCKS "; + private static final String PROXY = "PROXY "; + + private IProxyService mProxyService; + private final List mDefaultList; + + public PacProxySelector() { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + if (mProxyService == null) { + // Added because of b10267814 where mako is restarting. + Log.e(TAG, "PacProxyInstaller: no proxy service"); + } + mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY); + } + + @Override + public List select(URI uri) { + if (mProxyService == null) { + mProxyService = IProxyService.Stub.asInterface( + ServiceManager.getService(PROXY_SERVICE)); + } + if (mProxyService == null) { + Log.e(TAG, "select: no proxy service return NO_PROXY"); + return Lists.newArrayList(java.net.Proxy.NO_PROXY); + } + String response = null; + String urlString; + try { + // Strip path and username/password from URI so it's not visible to PAC script. The + // path often contains credentials the app does not want exposed to a potentially + // malicious PAC script. + if (!"http".equalsIgnoreCase(uri.getScheme())) { + uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null); + } + urlString = uri.toURL().toString(); + } catch (URISyntaxException e) { + urlString = uri.getHost(); + } catch (MalformedURLException e) { + urlString = uri.getHost(); + } + try { + response = mProxyService.resolvePacFile(uri.getHost(), urlString); + } catch (Exception e) { + Log.e(TAG, "Error resolving PAC File", e); + } + if (response == null) { + return mDefaultList; + } + + return parseResponse(response); + } + + private static List parseResponse(String response) { + String[] split = response.split(";"); + List ret = Lists.newArrayList(); + for (String s : split) { + String trimmed = s.trim(); + if (trimmed.equals("DIRECT")) { + ret.add(java.net.Proxy.NO_PROXY); + } else if (trimmed.startsWith(PROXY)) { + Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length())); + if (proxy != null) { + ret.add(proxy); + } + } else if (trimmed.startsWith(SOCKS)) { + Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length())); + if (proxy != null) { + ret.add(proxy); + } + } + } + if (ret.size() == 0) { + ret.add(java.net.Proxy.NO_PROXY); + } + return ret; + } + + private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) { + try { + String[] hostPort = hostPortString.split(":"); + String host = hostPort[0]; + int port = Integer.parseInt(hostPort[1]); + return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); + } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) { + Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e); + return null; + } + } + + @Override + public void connectFailed(URI uri, SocketAddress address, IOException failure) { + + } + +} diff --git a/framework/src/android/net/Proxy.java b/framework/src/android/net/Proxy.java new file mode 100644 index 0000000000..03b07e080a --- /dev/null +++ b/framework/src/android/net/Proxy.java @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; + +import com.android.net.module.util.ProxyUtils; + +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A convenience class for accessing the user and default proxy + * settings. + */ +public final class Proxy { + + private static final String TAG = "Proxy"; + + private static final ProxySelector sDefaultProxySelector; + + /** + * Used to notify an app that's caching the proxy that either the default + * connection has changed or any connection's proxy has changed. The new + * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}. + * + *

This is a protected intent that can only be sent by the system + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; + /** + * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents. + * It describes the new proxy being used (as a {@link ProxyInfo} object). + * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy + * for any network on the system changes, applications should always use + * {@link ConnectivityManager#getDefaultProxy()} or + * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()} + * to get the proxy for the Network(s) they are using. + */ + @Deprecated + public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + + /** @hide */ + public static final int PROXY_VALID = 0; + /** @hide */ + public static final int PROXY_HOSTNAME_EMPTY = 1; + /** @hide */ + public static final int PROXY_HOSTNAME_INVALID = 2; + /** @hide */ + public static final int PROXY_PORT_EMPTY = 3; + /** @hide */ + public static final int PROXY_PORT_INVALID = 4; + /** @hide */ + public static final int PROXY_EXCLLIST_INVALID = 5; + + private static ConnectivityManager sConnectivityManager = null; + + // Hostname / IP REGEX validation + // Matches blank input, ips, and domain names + private static final String NAME_IP_REGEX = + "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*"; + + private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$"; + + private static final Pattern HOSTNAME_PATTERN; + + private static final String EXCL_REGEX = + "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*"; + + private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$"; + + private static final Pattern EXCLLIST_PATTERN; + + static { + HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP); + EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP); + sDefaultProxySelector = ProxySelector.getDefault(); + } + + /** + * Return the proxy object to be used for the URL given as parameter. + * @param ctx A Context used to get the settings for the proxy host. + * @param url A URL to be accessed. Used to evaluate exclusion list. + * @return Proxy (java.net) object containing the host name. If the + * user did not set a hostname it returns the default host. + * A null value means that no host is to be used. + * {@hide} + */ + @UnsupportedAppUsage + public static final java.net.Proxy getProxy(Context ctx, String url) { + String host = ""; + if ((url != null) && !isLocalHost(host)) { + URI uri = URI.create(url); + ProxySelector proxySelector = ProxySelector.getDefault(); + + List proxyList = proxySelector.select(uri); + + if (proxyList.size() > 0) { + return proxyList.get(0); + } + } + return java.net.Proxy.NO_PROXY; + } + + + /** + * Return the proxy host set by the user. + * @param ctx A Context used to get the settings for the proxy host. + * @return String containing the host name. If the user did not set a host + * name it returns the default host. A null value means that no + * host is to be used. + * @deprecated Use standard java vm proxy values to find the host, port + * and exclusion list. This call ignores the exclusion list. + */ + @Deprecated + public static final String getHost(Context ctx) { + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return null; + try { + return ((InetSocketAddress)(proxy.address())).getHostName(); + } catch (Exception e) { + return null; + } + } + + /** + * Return the proxy port set by the user. + * @param ctx A Context used to get the settings for the proxy port. + * @return The port number to use or -1 if no proxy is to be used. + * @deprecated Use standard java vm proxy values to find the host, port + * and exclusion list. This call ignores the exclusion list. + */ + @Deprecated + public static final int getPort(Context ctx) { + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return -1; + try { + return ((InetSocketAddress)(proxy.address())).getPort(); + } catch (Exception e) { + return -1; + } + } + + /** + * Return the default proxy host specified by the carrier. + * @return String containing the host name or null if there is no proxy for + * this carrier. + * @deprecated Use standard java vm proxy values to find the host, port and + * exclusion list. This call ignores the exclusion list and no + * longer reports only mobile-data apn-based proxy values. + */ + @Deprecated + public static final String getDefaultHost() { + String host = System.getProperty("http.proxyHost"); + if (TextUtils.isEmpty(host)) return null; + return host; + } + + /** + * Return the default proxy port specified by the carrier. + * @return The port number to be used with the proxy host or -1 if there is + * no proxy for this carrier. + * @deprecated Use standard java vm proxy values to find the host, port and + * exclusion list. This call ignores the exclusion list and no + * longer reports only mobile-data apn-based proxy values. + */ + @Deprecated + public static final int getDefaultPort() { + if (getDefaultHost() == null) return -1; + try { + return Integer.parseInt(System.getProperty("http.proxyPort")); + } catch (NumberFormatException e) { + return -1; + } + } + + private static final boolean isLocalHost(String host) { + if (host == null) { + return false; + } + try { + if (host != null) { + if (host.equalsIgnoreCase("localhost")) { + return true; + } + if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) { + return true; + } + } + } catch (IllegalArgumentException iex) { + } + return false; + } + + /** + * Validate syntax of hostname, port and exclusion list entries + * {@hide} + */ + public static int validate(String hostname, String port, String exclList) { + Matcher match = HOSTNAME_PATTERN.matcher(hostname); + Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList); + + if (!match.matches()) return PROXY_HOSTNAME_INVALID; + + if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID; + + if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY; + + if (port.length() > 0) { + if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY; + int portVal = -1; + try { + portVal = Integer.parseInt(port); + } catch (NumberFormatException ex) { + return PROXY_PORT_INVALID; + } + if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID; + } + return PROXY_VALID; + } + + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public static final void setHttpProxySystemProperty(ProxyInfo p) { + String host = null; + String port = null; + String exclList = null; + Uri pacFileUrl = Uri.EMPTY; + if (p != null) { + host = p.getHost(); + port = Integer.toString(p.getPort()); + exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); + pacFileUrl = p.getPacFileUrl(); + } + setHttpProxySystemProperty(host, port, exclList, pacFileUrl); + } + + /** @hide */ + public static final void setHttpProxySystemProperty(String host, String port, String exclList, + Uri pacFileUrl) { + if (exclList != null) exclList = exclList.replace(",", "|"); + if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); + if (host != null) { + System.setProperty("http.proxyHost", host); + System.setProperty("https.proxyHost", host); + } else { + System.clearProperty("http.proxyHost"); + System.clearProperty("https.proxyHost"); + } + if (port != null) { + System.setProperty("http.proxyPort", port); + System.setProperty("https.proxyPort", port); + } else { + System.clearProperty("http.proxyPort"); + System.clearProperty("https.proxyPort"); + } + if (exclList != null) { + System.setProperty("http.nonProxyHosts", exclList); + System.setProperty("https.nonProxyHosts", exclList); + } else { + System.clearProperty("http.nonProxyHosts"); + System.clearProperty("https.nonProxyHosts"); + } + if (!Uri.EMPTY.equals(pacFileUrl)) { + ProxySelector.setDefault(new PacProxySelector()); + } else { + ProxySelector.setDefault(sDefaultProxySelector); + } + } +} diff --git a/framework/src/android/net/ProxyInfo.aidl b/framework/src/android/net/ProxyInfo.aidl new file mode 100644 index 0000000000..a5d0c120e7 --- /dev/null +++ b/framework/src/android/net/ProxyInfo.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright (C) 2010 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +@JavaOnlyStableParcelable parcelable ProxyInfo; + diff --git a/framework/src/android/net/ProxyInfo.java b/framework/src/android/net/ProxyInfo.java new file mode 100644 index 0000000000..c9bca2876b --- /dev/null +++ b/framework/src/android/net/ProxyInfo.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.net.InetSocketAddress; +import java.net.URLConnection; +import java.util.List; +import java.util.Locale; + +/** + * Describes a proxy configuration. + * + * Proxy configurations are already integrated within the {@code java.net} and + * Apache HTTP stack. So {@link URLConnection} and Apache's {@code HttpClient} will use + * them automatically. + * + * Other HTTP stacks will need to obtain the proxy info from + * {@link Proxy#PROXY_CHANGE_ACTION} broadcast as the extra {@link Proxy#EXTRA_PROXY_INFO}. + */ +public class ProxyInfo implements Parcelable { + + private final String mHost; + private final int mPort; + private final String mExclusionList; + private final String[] mParsedExclusionList; + private final Uri mPacFileUrl; + + /** + *@hide + */ + public static final String LOCAL_EXCL_LIST = ""; + /** + *@hide + */ + public static final int LOCAL_PORT = -1; + /** + *@hide + */ + public static final String LOCAL_HOST = "localhost"; + + /** + * Constructs a {@link ProxyInfo} object that points at a Direct proxy + * on the specified host and port. + */ + public static ProxyInfo buildDirectProxy(String host, int port) { + return new ProxyInfo(host, port, null); + } + + /** + * Constructs a {@link ProxyInfo} object that points at a Direct proxy + * on the specified host and port. + * + * The proxy will not be used to access any host in exclusion list, exclList. + * + * @param exclList Hosts to exclude using the proxy on connections for. These + * hosts can use wildcards such as *.example.com. + */ + public static ProxyInfo buildDirectProxy(String host, int port, List exclList) { + String[] array = exclList.toArray(new String[exclList.size()]); + return new ProxyInfo(host, port, TextUtils.join(",", array), array); + } + + /** + * Construct a {@link ProxyInfo} that will download and run the PAC script + * at the specified URL. + */ + public static ProxyInfo buildPacProxy(Uri pacUri) { + return new ProxyInfo(pacUri); + } + + /** + * Construct a {@link ProxyInfo} object that will download and run the PAC script at the + * specified URL and port. + */ + @NonNull + public static ProxyInfo buildPacProxy(@NonNull Uri pacUrl, int port) { + return new ProxyInfo(pacUrl, port); + } + + /** + * Create a ProxyProperties that points at a HTTP Proxy. + * @hide + */ + @UnsupportedAppUsage + public ProxyInfo(String host, int port, String exclList) { + mHost = host; + mPort = port; + mExclusionList = exclList; + mParsedExclusionList = parseExclusionList(mExclusionList); + mPacFileUrl = Uri.EMPTY; + } + + /** + * Create a ProxyProperties that points at a PAC URL. + * @hide + */ + public ProxyInfo(@NonNull Uri pacFileUrl) { + mHost = LOCAL_HOST; + mPort = LOCAL_PORT; + mExclusionList = LOCAL_EXCL_LIST; + mParsedExclusionList = parseExclusionList(mExclusionList); + if (pacFileUrl == null) { + throw new NullPointerException(); + } + mPacFileUrl = pacFileUrl; + } + + /** + * Only used in PacProxyInstaller after Local Proxy is bound. + * @hide + */ + public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) { + mHost = LOCAL_HOST; + mPort = localProxyPort; + mExclusionList = LOCAL_EXCL_LIST; + mParsedExclusionList = parseExclusionList(mExclusionList); + if (pacFileUrl == null) { + throw new NullPointerException(); + } + mPacFileUrl = pacFileUrl; + } + + private static String[] parseExclusionList(String exclusionList) { + if (exclusionList == null) { + return new String[0]; + } else { + return exclusionList.toLowerCase(Locale.ROOT).split(","); + } + } + + private ProxyInfo(String host, int port, String exclList, String[] parsedExclList) { + mHost = host; + mPort = port; + mExclusionList = exclList; + mParsedExclusionList = parsedExclList; + mPacFileUrl = Uri.EMPTY; + } + + /** + * A copy constructor to hold proxy properties. + */ + public ProxyInfo(@Nullable ProxyInfo source) { + if (source != null) { + mHost = source.getHost(); + mPort = source.getPort(); + mPacFileUrl = source.mPacFileUrl; + mExclusionList = source.getExclusionListAsString(); + mParsedExclusionList = source.mParsedExclusionList; + } else { + mHost = null; + mPort = 0; + mExclusionList = null; + mParsedExclusionList = null; + mPacFileUrl = Uri.EMPTY; + } + } + + /** + * @hide + */ + public InetSocketAddress getSocketAddress() { + InetSocketAddress inetSocketAddress = null; + try { + inetSocketAddress = new InetSocketAddress(mHost, mPort); + } catch (IllegalArgumentException e) { } + return inetSocketAddress; + } + + /** + * Returns the URL of the current PAC script or null if there is + * no PAC script. + */ + public Uri getPacFileUrl() { + return mPacFileUrl; + } + + /** + * When configured to use a Direct Proxy this returns the host + * of the proxy. + */ + public String getHost() { + return mHost; + } + + /** + * When configured to use a Direct Proxy this returns the port + * of the proxy + */ + public int getPort() { + return mPort; + } + + /** + * When configured to use a Direct Proxy this returns the list + * of hosts for which the proxy is ignored. + */ + public String[] getExclusionList() { + return mParsedExclusionList; + } + + /** + * comma separated + * @hide + */ + @Nullable + public String getExclusionListAsString() { + return mExclusionList; + } + + /** + * Return true if the pattern of proxy is valid, otherwise return false. + */ + public boolean isValid() { + if (!Uri.EMPTY.equals(mPacFileUrl)) return true; + return Proxy.PROXY_VALID == Proxy.validate(mHost == null ? "" : mHost, + mPort == 0 ? "" : Integer.toString(mPort), + mExclusionList == null ? "" : mExclusionList); + } + + /** + * @hide + */ + public java.net.Proxy makeProxy() { + java.net.Proxy proxy = java.net.Proxy.NO_PROXY; + if (mHost != null) { + try { + InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort); + proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress); + } catch (IllegalArgumentException e) { + } + } + return proxy; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (!Uri.EMPTY.equals(mPacFileUrl)) { + sb.append("PAC Script: "); + sb.append(mPacFileUrl); + } + if (mHost != null) { + sb.append("["); + sb.append(mHost); + sb.append("] "); + sb.append(Integer.toString(mPort)); + if (mExclusionList != null) { + sb.append(" xl=").append(mExclusionList); + } + } else { + sb.append("[ProxyProperties.mHost == null]"); + } + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ProxyInfo)) return false; + ProxyInfo p = (ProxyInfo)o; + // If PAC URL is present in either then they must be equal. + // Other parameters will only be for fall back. + if (!Uri.EMPTY.equals(mPacFileUrl)) { + return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort; + } + if (!Uri.EMPTY.equals(p.mPacFileUrl)) { + return false; + } + if (mExclusionList != null && !mExclusionList.equals(p.getExclusionListAsString())) { + return false; + } + if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) { + return false; + } + if (mHost != null && p.mHost == null) return false; + if (mHost == null && p.mHost != null) return false; + if (mPort != p.mPort) return false; + return true; + } + + /** + * Implement the Parcelable interface + * @hide + */ + public int describeContents() { + return 0; + } + + @Override + /* + * generate hashcode based on significant fields + */ + public int hashCode() { + return ((null == mHost) ? 0 : mHost.hashCode()) + + ((null == mExclusionList) ? 0 : mExclusionList.hashCode()) + + mPort; + } + + /** + * Implement the Parcelable interface. + * @hide + */ + public void writeToParcel(Parcel dest, int flags) { + if (!Uri.EMPTY.equals(mPacFileUrl)) { + dest.writeByte((byte)1); + mPacFileUrl.writeToParcel(dest, 0); + dest.writeInt(mPort); + return; + } else { + dest.writeByte((byte)0); + } + if (mHost != null) { + dest.writeByte((byte)1); + dest.writeString(mHost); + dest.writeInt(mPort); + } else { + dest.writeByte((byte)0); + } + dest.writeString(mExclusionList); + dest.writeStringArray(mParsedExclusionList); + } + + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public ProxyInfo createFromParcel(Parcel in) { + String host = null; + int port = 0; + if (in.readByte() != 0) { + Uri url = Uri.CREATOR.createFromParcel(in); + int localPort = in.readInt(); + return new ProxyInfo(url, localPort); + } + if (in.readByte() != 0) { + host = in.readString(); + port = in.readInt(); + } + String exclList = in.readString(); + String[] parsedExclList = in.createStringArray(); + ProxyInfo proxyProperties = new ProxyInfo(host, port, exclList, parsedExclList); + return proxyProperties; + } + + public ProxyInfo[] newArray(int size) { + return new ProxyInfo[size]; + } + }; +} diff --git a/framework/src/android/net/RouteInfo.aidl b/framework/src/android/net/RouteInfo.aidl new file mode 100644 index 0000000000..7af9fdaef3 --- /dev/null +++ b/framework/src/android/net/RouteInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +@JavaOnlyStableParcelable parcelable RouteInfo; diff --git a/framework/src/android/net/RouteInfo.java b/framework/src/android/net/RouteInfo.java new file mode 100644 index 0000000000..94f849f006 --- /dev/null +++ b/framework/src/android/net/RouteInfo.java @@ -0,0 +1,658 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.net.module.util.NetUtils; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Objects; + +/** + * Represents a network route. + *

+ * This is used both to describe static network configuration and live network + * configuration information. + * + * A route contains three pieces of information: + *

    + *
  • a destination {@link IpPrefix} specifying the network destinations covered by this route. + * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6) + * implied by the gateway IP address. + *
  • a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it + * indicates a directly-connected route. + *
  • an interface (which may be unspecified). + *
+ * Either the destination or the gateway may be {@code null}, but not both. If the + * destination and gateway are both specified, they must be of the same address family + * (IPv4 or IPv6). + */ +public final class RouteInfo implements Parcelable { + /** @hide */ + @IntDef(value = { + RTN_UNICAST, + RTN_UNREACHABLE, + RTN_THROW, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RouteType {} + + /** + * The IP destination address for this route. + */ + @NonNull + private final IpPrefix mDestination; + + /** + * The gateway address for this route. + */ + @UnsupportedAppUsage + @Nullable + private final InetAddress mGateway; + + /** + * The interface for this route. + */ + @Nullable + private final String mInterface; + + + /** Unicast route. @hide */ + @SystemApi + public static final int RTN_UNICAST = 1; + + /** Unreachable route. @hide */ + @SystemApi + public static final int RTN_UNREACHABLE = 7; + + /** Throw route. @hide */ + @SystemApi + public static final int RTN_THROW = 9; + + /** + * The type of this route; one of the RTN_xxx constants above. + */ + private final int mType; + + /** + * The maximum transmission unit size for this route. + */ + private final int mMtu; + + // Derived data members. + // TODO: remove these. + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + private final boolean mIsHost; + private final boolean mHasGateway; + + /** + * Constructs a RouteInfo object. + * + * If destination is null, then gateway must be specified and the + * constructed route is either the IPv4 default route 0.0.0.0 + * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default + * route ::/0 if gateway is an instance of + * {@link Inet6Address}. + *

+ * destination and gateway may not both be null. + * + * @param destination the destination prefix + * @param gateway the IP address to route packets through + * @param iface the interface name to send packets on + * @param type the type of this route + * + * @hide + */ + @SystemApi + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface, @RouteType int type) { + this(destination, gateway, iface, type, 0); + } + + /** + * Constructs a RouteInfo object. + * + * If destination is null, then gateway must be specified and the + * constructed route is either the IPv4 default route 0.0.0.0 + * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default + * route ::/0 if gateway is an instance of + * {@link Inet6Address}. + *

+ * destination and gateway may not both be null. + * + * @param destination the destination prefix + * @param gateway the IP address to route packets through + * @param iface the interface name to send packets on + * @param type the type of this route + * @param mtu the maximum transmission unit size for this route + * + * @hide + */ + @SystemApi + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface, @RouteType int type, int mtu) { + switch (type) { + case RTN_UNICAST: + case RTN_UNREACHABLE: + case RTN_THROW: + // TODO: It would be nice to ensure that route types that don't have nexthops or + // interfaces, such as unreachable or throw, can't be created if an interface or + // a gateway is specified. This is a bit too complicated to do at the moment + // because: + // + // - LinkProperties sets the interface on routes added to it, and modifies the + // interfaces of all the routes when its interface name changes. + // - Even when the gateway is null, we store a non-null gateway here. + // + // For now, we just rely on the code that sets routes to do things properly. + break; + default: + throw new IllegalArgumentException("Unknown route type " + type); + } + + if (destination == null) { + if (gateway != null) { + if (gateway instanceof Inet4Address) { + destination = new IpPrefix(Inet4Address.ANY, 0); + } else { + destination = new IpPrefix(Inet6Address.ANY, 0); + } + } else { + // no destination, no gateway. invalid. + throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," + + destination); + } + } + // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and + // matches the documented behaviour. Before we can do this we need to fix all callers (e.g., + // ConnectivityService) to stop doing things like r.getGateway().equals(), ... . + if (gateway == null) { + if (destination.getAddress() instanceof Inet4Address) { + gateway = Inet4Address.ANY; + } else { + gateway = Inet6Address.ANY; + } + } + mHasGateway = (!gateway.isAnyLocalAddress()); + + if ((destination.getAddress() instanceof Inet4Address + && !(gateway instanceof Inet4Address)) + || (destination.getAddress() instanceof Inet6Address + && !(gateway instanceof Inet6Address))) { + throw new IllegalArgumentException("address family mismatch in RouteInfo constructor"); + } + mDestination = destination; // IpPrefix objects are immutable. + mGateway = gateway; // InetAddress objects are immutable. + mInterface = iface; // Strings are immutable. + mType = type; + mIsHost = isHost(); + mMtu = mtu; + } + + /** + * Constructs a {@code RouteInfo} object. + * + * If destination is null, then gateway must be specified and the + * constructed route is either the IPv4 default route 0.0.0.0 + * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default + * route ::/0 if gateway is an instance of {@link Inet6Address}. + *

+ * Destination and gateway may not both be null. + * + * @param destination the destination address and prefix in an {@link IpPrefix} + * @param gateway the {@link InetAddress} to route packets through + * @param iface the interface name to send packets on + * + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface) { + this(destination, gateway, iface, RTN_UNICAST); + } + + /** + * @hide + */ + @UnsupportedAppUsage + public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway, + @Nullable String iface) { + this(destination == null ? null : + new IpPrefix(destination.getAddress(), destination.getPrefixLength()), + gateway, iface); + } + + /** + * Constructs a {@code RouteInfo} object. + * + * If destination is null, then gateway must be specified and the + * constructed route is either the IPv4 default route 0.0.0.0 + * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default + * route ::/0 if gateway is an instance of {@link Inet6Address}. + *

+ * Destination and gateway may not both be null. + * + * @param destination the destination address and prefix in an {@link IpPrefix} + * @param gateway the {@link InetAddress} to route packets through + * + * @hide + */ + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) { + this(destination, gateway, null); + } + + /** + * @hide + * + * TODO: Remove this. + */ + @UnsupportedAppUsage + public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) { + this(destination, gateway, null); + } + + /** + * Constructs a default {@code RouteInfo} object. + * + * @param gateway the {@link InetAddress} to route packets through + * + * @hide + */ + @UnsupportedAppUsage + public RouteInfo(@NonNull InetAddress gateway) { + this((IpPrefix) null, gateway, null); + } + + /** + * Constructs a {@code RouteInfo} object representing a direct connected subnet. + * + * @param destination the {@link IpPrefix} describing the address and prefix + * length of the subnet. + * + * @hide + */ + public RouteInfo(@NonNull IpPrefix destination) { + this(destination, null, null); + } + + /** + * @hide + */ + public RouteInfo(@NonNull LinkAddress destination) { + this(destination, null, null); + } + + /** + * @hide + */ + public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) { + this(destination, null, null, type); + } + + /** + * @hide + */ + public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) { + return makeHostRoute(host, null, iface); + } + + /** + * @hide + */ + public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway, + @Nullable String iface) { + if (host == null) return null; + + if (host instanceof Inet4Address) { + return new RouteInfo(new IpPrefix(host, 32), gateway, iface); + } else { + return new RouteInfo(new IpPrefix(host, 128), gateway, iface); + } + } + + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + private boolean isHost() { + return (mDestination.getAddress() instanceof Inet4Address && + mDestination.getPrefixLength() == 32) || + (mDestination.getAddress() instanceof Inet6Address && + mDestination.getPrefixLength() == 128); + } + + /** + * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}. + * + * @return {@link IpPrefix} specifying the destination. This is never {@code null}. + */ + @NonNull + public IpPrefix getDestination() { + return mDestination; + } + + /** + * TODO: Convert callers to use IpPrefix and then remove. + * @hide + */ + @NonNull + public LinkAddress getDestinationLinkAddress() { + return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength()); + } + + /** + * Retrieves the gateway or next hop {@link InetAddress} for this route. + * + * @return {@link InetAddress} specifying the gateway or next hop. This may be + * {@code null} for a directly-connected route." + */ + @Nullable + public InetAddress getGateway() { + return mGateway; + } + + /** + * Retrieves the interface used for this route if specified, else {@code null}. + * + * @return The name of the interface used for this route. + */ + @Nullable + public String getInterface() { + return mInterface; + } + + /** + * Retrieves the type of this route. + * + * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class. + * + * @hide + */ + @SystemApi + @RouteType + public int getType() { + return mType; + } + + /** + * Retrieves the MTU size for this route. + * + * @return The MTU size, or 0 if it has not been set. + * @hide + */ + @SystemApi + public int getMtu() { + return mMtu; + } + + /** + * Indicates if this route is a default route (ie, has no destination specified). + * + * @return {@code true} if the destination has a prefix length of 0. + */ + public boolean isDefaultRoute() { + return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0; + } + + /** + * Indicates if this route is an unreachable default route. + * + * @return {@code true} if it's an unreachable route with prefix length of 0. + * @hide + */ + private boolean isUnreachableDefaultRoute() { + return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0; + } + + /** + * Indicates if this route is an IPv4 default route. + * @hide + */ + public boolean isIPv4Default() { + return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address; + } + + /** + * Indicates if this route is an IPv4 unreachable default route. + * @hide + */ + public boolean isIPv4UnreachableDefault() { + return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address; + } + + /** + * Indicates if this route is an IPv6 default route. + * @hide + */ + public boolean isIPv6Default() { + return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address; + } + + /** + * Indicates if this route is an IPv6 unreachable default route. + * @hide + */ + public boolean isIPv6UnreachableDefault() { + return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address; + } + + /** + * Indicates if this route is a host route (ie, matches only a single host address). + * + * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6, + * respectively. + * @hide + */ + public boolean isHostRoute() { + return mIsHost; + } + + /** + * Indicates if this route has a next hop ({@code true}) or is directly-connected + * ({@code false}). + * + * @return {@code true} if a gateway is specified + */ + public boolean hasGateway() { + return mHasGateway; + } + + /** + * Determines whether the destination and prefix of this route includes the specified + * address. + * + * @param destination A {@link InetAddress} to test to see if it would match this route. + * @return {@code true} if the destination and prefix length cover the given address. + */ + public boolean matches(InetAddress destination) { + return mDestination.contains(destination); + } + + /** + * Find the route from a Collection of routes that best matches a given address. + * May return null if no routes are applicable. + * @param routes a Collection of RouteInfos to chose from + * @param dest the InetAddress your trying to get to + * @return the RouteInfo from the Collection that best fits the given address + * + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Nullable + public static RouteInfo selectBestRoute(Collection routes, InetAddress dest) { + return NetUtils.selectBestRoute(routes, dest); + } + + /** + * Returns a human-readable description of this object. + */ + public String toString() { + String val = ""; + if (mDestination != null) val = mDestination.toString(); + if (mType == RTN_UNREACHABLE) { + val += " unreachable"; + } else if (mType == RTN_THROW) { + val += " throw"; + } else { + val += " ->"; + if (mGateway != null) val += " " + mGateway.getHostAddress(); + if (mInterface != null) val += " " + mInterface; + if (mType != RTN_UNICAST) { + val += " unknown type " + mType; + } + } + val += " mtu " + mMtu; + return val; + } + + /** + * Compares this RouteInfo object against the specified object and indicates if they are equal. + * @return {@code true} if the objects are equal, {@code false} otherwise. + */ + public boolean equals(Object obj) { + if (this == obj) return true; + + if (!(obj instanceof RouteInfo)) return false; + + RouteInfo target = (RouteInfo) obj; + + return Objects.equals(mDestination, target.getDestination()) && + Objects.equals(mGateway, target.getGateway()) && + Objects.equals(mInterface, target.getInterface()) && + mType == target.getType() && mMtu == target.getMtu(); + } + + /** + * A helper class that contains the destination, the gateway and the interface in a + * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or + * {@link LinkProperties#addRoute} to calculate the list to be updated. + * {@code RouteInfo} objects with different interfaces are treated as different routes because + * *usually* on Android different interfaces use different routing tables, and moving a route + * to a new routing table never constitutes an update, but is always a remove and an add. + * + * @hide + */ + public static class RouteKey { + @NonNull private final IpPrefix mDestination; + @Nullable private final InetAddress mGateway; + @Nullable private final String mInterface; + + RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface) { + mDestination = destination; + mGateway = gateway; + mInterface = iface; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof RouteKey)) { + return false; + } + RouteKey p = (RouteKey) o; + // No need to do anything special for scoped addresses. Inet6Address#equals does not + // consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel) + // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only + // look at RTA_OIF. + return Objects.equals(p.mDestination, mDestination) + && Objects.equals(p.mGateway, mGateway) + && Objects.equals(p.mInterface, mInterface); + } + + @Override + public int hashCode() { + return Objects.hash(mDestination, mGateway, mInterface); + } + } + + /** + * Get {@code RouteKey} of this {@code RouteInfo}. + * @return a {@code RouteKey} object. + * + * @hide + */ + @NonNull + public RouteKey getRouteKey() { + return new RouteKey(mDestination, mGateway, mInterface); + } + + /** + * Returns a hashcode for this RouteInfo object. + */ + public int hashCode() { + return (mDestination.hashCode() * 41) + + (mGateway == null ? 0 :mGateway.hashCode() * 47) + + (mInterface == null ? 0 :mInterface.hashCode() * 67) + + (mType * 71) + (mMtu * 89); + } + + /** + * Implement the Parcelable interface + */ + public int describeContents() { + return 0; + } + + /** + * Implement the Parcelable interface + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mDestination, flags); + byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress(); + dest.writeByteArray(gatewayBytes); + dest.writeString(mInterface); + dest.writeInt(mType); + dest.writeInt(mMtu); + } + + /** + * Implement the Parcelable interface. + */ + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public RouteInfo createFromParcel(Parcel in) { + IpPrefix dest = in.readParcelable(null); + + InetAddress gateway = null; + byte[] addr = in.createByteArray(); + try { + gateway = InetAddress.getByAddress(addr); + } catch (UnknownHostException e) {} + + String iface = in.readString(); + int type = in.readInt(); + int mtu = in.readInt(); + + return new RouteInfo(dest, gateway, iface, type, mtu); + } + + public RouteInfo[] newArray(int size) { + return new RouteInfo[size]; + } + }; +} diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java new file mode 100644 index 0000000000..d007a9520c --- /dev/null +++ b/framework/src/android/net/SocketKeepalive.java @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Binder; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; + +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.concurrent.Executor; + +/** + * Allows applications to request that the system periodically send specific packets on their + * behalf, using hardware offload to save battery power. + * + * To request that the system send keepalives, call one of the methods that return a + * {@link SocketKeepalive} object, such as {@link ConnectivityManager#createSocketKeepalive}, + * passing in a non-null callback. If the {@link SocketKeepalive} is successfully + * started, the callback's {@code onStarted} method will be called. If an error occurs, + * {@code onError} will be called, specifying one of the {@code ERROR_*} constants in this + * class. + * + * To stop an existing keepalive, call {@link SocketKeepalive#stop}. The system will call + * {@link SocketKeepalive.Callback#onStopped} if the operation was successful or + * {@link SocketKeepalive.Callback#onError} if an error occurred. + * + * For cellular, the device MUST support at least 1 keepalive slot. + * + * For WiFi, the device SHOULD support keepalive offload. If it does not, it MUST reply with + * {@link SocketKeepalive.Callback#onError} with {@code ERROR_UNSUPPORTED} to any keepalive offload + * request. If it does, it MUST support at least 3 concurrent keepalive slots. + */ +public abstract class SocketKeepalive implements AutoCloseable { + static final String TAG = "SocketKeepalive"; + + /** + * No errors. + * @hide + */ + @SystemApi + public static final int SUCCESS = 0; + + /** @hide */ + public static final int NO_KEEPALIVE = -1; + + /** @hide */ + public static final int DATA_RECEIVED = -2; + + /** @hide */ + public static final int BINDER_DIED = -10; + + /** The specified {@code Network} is not connected. */ + public static final int ERROR_INVALID_NETWORK = -20; + /** The specified IP addresses are invalid. For example, the specified source IP address is + * not configured on the specified {@code Network}. */ + public static final int ERROR_INVALID_IP_ADDRESS = -21; + /** The requested port is invalid. */ + public static final int ERROR_INVALID_PORT = -22; + /** The packet length is invalid (e.g., too long). */ + public static final int ERROR_INVALID_LENGTH = -23; + /** The packet transmission interval is invalid (e.g., too short). */ + public static final int ERROR_INVALID_INTERVAL = -24; + /** The target socket is invalid. */ + public static final int ERROR_INVALID_SOCKET = -25; + /** The target socket is not idle. */ + public static final int ERROR_SOCKET_NOT_IDLE = -26; + /** + * The stop reason is uninitialized. This should only be internally used as initial state + * of stop reason, instead of propagating to application. + * @hide + */ + public static final int ERROR_STOP_REASON_UNINITIALIZED = -27; + + /** The device does not support this request. */ + public static final int ERROR_UNSUPPORTED = -30; + /** @hide TODO: delete when telephony code has been updated. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = ERROR_UNSUPPORTED; + /** The hardware returned an error. */ + public static final int ERROR_HARDWARE_ERROR = -31; + /** The limitation of resource is reached. */ + public static final int ERROR_INSUFFICIENT_RESOURCES = -32; + + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "ERROR_" }, value = { + ERROR_INVALID_NETWORK, + ERROR_INVALID_IP_ADDRESS, + ERROR_INVALID_PORT, + ERROR_INVALID_LENGTH, + ERROR_INVALID_INTERVAL, + ERROR_INVALID_SOCKET, + ERROR_SOCKET_NOT_IDLE + }) + public @interface ErrorCode {} + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + SUCCESS, + ERROR_INVALID_LENGTH, + ERROR_UNSUPPORTED, + ERROR_INSUFFICIENT_RESOURCES, + ERROR_HARDWARE_UNSUPPORTED + }) + public @interface KeepaliveEvent {} + + /** + * The minimum interval in seconds between keepalive packet transmissions. + * + * @hide + **/ + public static final int MIN_INTERVAL_SEC = 10; + + /** + * The maximum interval in seconds between keepalive packet transmissions. + * + * @hide + **/ + public static final int MAX_INTERVAL_SEC = 3600; + + /** + * An exception that embarks an error code. + * @hide + */ + public static class ErrorCodeException extends Exception { + public final int error; + public ErrorCodeException(final int error, final Throwable e) { + super(e); + this.error = error; + } + public ErrorCodeException(final int error) { + this.error = error; + } + } + + /** + * This socket is invalid. + * See the error code for details, and the optional cause. + * @hide + */ + public static class InvalidSocketException extends ErrorCodeException { + public InvalidSocketException(final int error, final Throwable e) { + super(error, e); + } + public InvalidSocketException(final int error) { + super(error); + } + } + + @NonNull final IConnectivityManager mService; + @NonNull final Network mNetwork; + @NonNull final ParcelFileDescriptor mPfd; + @NonNull final Executor mExecutor; + @NonNull final ISocketKeepaliveCallback mCallback; + // TODO: remove slot since mCallback could be used to identify which keepalive to stop. + @Nullable Integer mSlot; + + SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, + @NonNull ParcelFileDescriptor pfd, + @NonNull Executor executor, @NonNull Callback callback) { + mService = service; + mNetwork = network; + mPfd = pfd; + mExecutor = executor; + mCallback = new ISocketKeepaliveCallback.Stub() { + @Override + public void onStarted(int slot) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> { + mSlot = slot; + callback.onStarted(); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void onStopped() { + final long token = Binder.clearCallingIdentity(); + try { + executor.execute(() -> { + mSlot = null; + callback.onStopped(); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void onError(int error) { + final long token = Binder.clearCallingIdentity(); + try { + executor.execute(() -> { + mSlot = null; + callback.onError(error); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void onDataReceived() { + final long token = Binder.clearCallingIdentity(); + try { + executor.execute(() -> { + mSlot = null; + callback.onDataReceived(); + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + }; + } + + /** + * Request that keepalive be started with the given {@code intervalSec}. See + * {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an exception + * when invoking start or stop of the {@link SocketKeepalive}, a {@link RemoteException} will be + * thrown into the {@code executor}. This is typically not important to catch because the remote + * party is the system, so if it is not in shape to communicate through binder the system is + * probably going down anyway. If the caller cares regardless, it can use a custom + * {@link Executor} to catch the {@link RemoteException}. + * + * @param intervalSec The target interval in seconds between keepalive packet transmissions. + * The interval should be between 10 seconds and 3600 seconds, otherwise + * {@link #ERROR_INVALID_INTERVAL} will be returned. + */ + public final void start(@IntRange(from = MIN_INTERVAL_SEC, to = MAX_INTERVAL_SEC) + int intervalSec) { + startImpl(intervalSec); + } + + abstract void startImpl(int intervalSec); + + /** + * Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped} + * before using the object. See {@link SocketKeepalive}. + */ + public final void stop() { + stopImpl(); + } + + abstract void stopImpl(); + + /** + * Deactivate this {@link SocketKeepalive} and free allocated resources. The instance won't be + * usable again if {@code close()} is called. + */ + @Override + public final void close() { + stop(); + try { + mPfd.close(); + } catch (IOException e) { + // Nothing much can be done. + } + } + + /** + * The callback which app can use to learn the status changes of {@link SocketKeepalive}. See + * {@link SocketKeepalive}. + */ + public static class Callback { + /** The requested keepalive was successfully started. */ + public void onStarted() {} + /** The keepalive was successfully stopped. */ + public void onStopped() {} + /** An error occurred. */ + public void onError(@ErrorCode int error) {} + /** The keepalive on a TCP socket was stopped because the socket received data. This is + * never called for UDP sockets. */ + public void onDataReceived() {} + } +} diff --git a/framework/src/android/net/StaticIpConfiguration.aidl b/framework/src/android/net/StaticIpConfiguration.aidl new file mode 100644 index 0000000000..8aac701fe7 --- /dev/null +++ b/framework/src/android/net/StaticIpConfiguration.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright (C) 2019 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +@JavaOnlyStableParcelable parcelable StaticIpConfiguration; \ No newline at end of file diff --git a/framework/src/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java new file mode 100644 index 0000000000..ce545974f5 --- /dev/null +++ b/framework/src/android/net/StaticIpConfiguration.java @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; +import com.android.net.module.util.InetAddressUtils; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Class that describes static IP configuration. + * + *

This class is different from {@link LinkProperties} because it represents + * configuration intent. The general contract is that if we can represent + * a configuration here, then we should be able to configure it on a network. + * The intent is that it closely match the UI we have for configuring networks. + * + *

In contrast, {@link LinkProperties} represents current state. It is much more + * expressive. For example, it supports multiple IP addresses, multiple routes, + * stacked interfaces, and so on. Because LinkProperties is so expressive, + * using it to represent configuration intent as well as current state causes + * problems. For example, we could unknowingly save a configuration that we are + * not in fact capable of applying, or we could save a configuration that the + * UI cannot display, which has the potential for malicious code to hide + * hostile or unexpected configuration from the user. + * + * @hide + */ +@SystemApi +public final class StaticIpConfiguration implements Parcelable { + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Nullable + public LinkAddress ipAddress; + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Nullable + public InetAddress gateway; + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @NonNull + public final ArrayList dnsServers; + /** @hide */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @Nullable + public String domains; + + public StaticIpConfiguration() { + dnsServers = new ArrayList<>(); + } + + public StaticIpConfiguration(@Nullable StaticIpConfiguration source) { + this(); + if (source != null) { + // All of these except dnsServers are immutable, so no need to make copies. + ipAddress = source.ipAddress; + gateway = source.gateway; + dnsServers.addAll(source.dnsServers); + domains = source.domains; + } + } + + public void clear() { + ipAddress = null; + gateway = null; + dnsServers.clear(); + domains = null; + } + + /** + * Get the static IP address included in the configuration. + */ + public @Nullable LinkAddress getIpAddress() { + return ipAddress; + } + + /** + * Get the gateway included in the configuration. + */ + public @Nullable InetAddress getGateway() { + return gateway; + } + + /** + * Get the DNS servers included in the configuration. + */ + public @NonNull List getDnsServers() { + return dnsServers; + } + + /** + * Get a {@link String} containing the comma separated domains to search when resolving host + * names on this link, in priority order. + */ + public @Nullable String getDomains() { + return domains; + } + + /** + * Helper class to build a new instance of {@link StaticIpConfiguration}. + */ + public static final class Builder { + private LinkAddress mIpAddress; + private InetAddress mGateway; + private Iterable mDnsServers; + private String mDomains; + + /** + * Set the IP address to be included in the configuration; null by default. + * @return The {@link Builder} for chaining. + */ + public @NonNull Builder setIpAddress(@Nullable LinkAddress ipAddress) { + mIpAddress = ipAddress; + return this; + } + + /** + * Set the address of the gateway to be included in the configuration; null by default. + * @return The {@link Builder} for chaining. + */ + public @NonNull Builder setGateway(@Nullable InetAddress gateway) { + mGateway = gateway; + return this; + } + + /** + * Set the addresses of the DNS servers included in the configuration; empty by default. + * @return The {@link Builder} for chaining. + */ + public @NonNull Builder setDnsServers(@NonNull Iterable dnsServers) { + Preconditions.checkNotNull(dnsServers); + mDnsServers = dnsServers; + return this; + } + + /** + * Sets the DNS domain search path to be used on the link; null by default. + * @param newDomains A {@link String} containing the comma separated domains to search when + * resolving host names on this link, in priority order. + * @return The {@link Builder} for chaining. + */ + public @NonNull Builder setDomains(@Nullable String newDomains) { + mDomains = newDomains; + return this; + } + + /** + * Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}. + * @return The newly created StaticIpConfiguration. + */ + public @NonNull StaticIpConfiguration build() { + final StaticIpConfiguration config = new StaticIpConfiguration(); + config.ipAddress = mIpAddress; + config.gateway = mGateway; + if (mDnsServers != null) { + for (InetAddress server : mDnsServers) { + config.dnsServers.add(server); + } + } + config.domains = mDomains; + return config; + } + } + + /** + * Add a DNS server to this configuration. + */ + public void addDnsServer(@NonNull InetAddress server) { + dnsServers.add(server); + } + + /** + * Returns the network routes specified by this object. Will typically include a + * directly-connected route for the IP address's local subnet and a default route. + * @param iface Interface to include in the routes. + */ + public @NonNull List getRoutes(@Nullable String iface) { + List routes = new ArrayList(3); + if (ipAddress != null) { + RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface); + routes.add(connectedRoute); + // If the default gateway is not covered by the directly-connected route, also add a + // host route to the gateway as well. This configuration is arguably invalid, but it + // used to work in K and earlier, and other OSes appear to accept it. + if (gateway != null && !connectedRoute.matches(gateway)) { + routes.add(RouteInfo.makeHostRoute(gateway, iface)); + } + } + if (gateway != null) { + routes.add(new RouteInfo((IpPrefix) null, gateway, iface)); + } + return routes; + } + + /** + * Returns a LinkProperties object expressing the data in this object. Note that the information + * contained in the LinkProperties will not be a complete picture of the link's configuration, + * because any configuration information that is obtained dynamically by the network (e.g., + * IPv6 configuration) will not be included. + * @hide + */ + public @NonNull LinkProperties toLinkProperties(String iface) { + LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(iface); + if (ipAddress != null) { + lp.addLinkAddress(ipAddress); + } + for (RouteInfo route : getRoutes(iface)) { + lp.addRoute(route); + } + for (InetAddress dns : dnsServers) { + lp.addDnsServer(dns); + } + lp.setDomains(domains); + return lp; + } + + @NonNull + @Override + public String toString() { + StringBuffer str = new StringBuffer(); + + str.append("IP address "); + if (ipAddress != null ) str.append(ipAddress).append(" "); + + str.append("Gateway "); + if (gateway != null) str.append(gateway.getHostAddress()).append(" "); + + str.append(" DNS servers: ["); + for (InetAddress dnsServer : dnsServers) { + str.append(" ").append(dnsServer.getHostAddress()); + } + + str.append(" ] Domains "); + if (domains != null) str.append(domains); + return str.toString(); + } + + @Override + public int hashCode() { + int result = 13; + result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode()); + result = 47 * result + (gateway == null ? 0 : gateway.hashCode()); + result = 47 * result + (domains == null ? 0 : domains.hashCode()); + result = 47 * result + dnsServers.hashCode(); + return result; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (this == obj) return true; + + if (!(obj instanceof StaticIpConfiguration)) return false; + + StaticIpConfiguration other = (StaticIpConfiguration) obj; + + return other != null && + Objects.equals(ipAddress, other.ipAddress) && + Objects.equals(gateway, other.gateway) && + dnsServers.equals(other.dnsServers) && + Objects.equals(domains, other.domains); + } + + /** Implement the Parcelable interface */ + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + public StaticIpConfiguration createFromParcel(Parcel in) { + return readFromParcel(in); + } + + public StaticIpConfiguration[] newArray(int size) { + return new StaticIpConfiguration[size]; + } + }; + + /** Implement the Parcelable interface */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(ipAddress, flags); + InetAddressUtils.parcelInetAddress(dest, gateway, flags); + dest.writeInt(dnsServers.size()); + for (InetAddress dnsServer : dnsServers) { + InetAddressUtils.parcelInetAddress(dest, dnsServer, flags); + } + dest.writeString(domains); + } + + /** @hide */ + public static StaticIpConfiguration readFromParcel(Parcel in) { + final StaticIpConfiguration s = new StaticIpConfiguration(); + s.ipAddress = in.readParcelable(null); + s.gateway = InetAddressUtils.unparcelInetAddress(in); + s.dnsServers.clear(); + int size = in.readInt(); + for (int i = 0; i < size; i++) { + s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in)); + } + s.domains = in.readString(); + return s; + } +} diff --git a/framework/src/android/net/TcpKeepalivePacketData.java b/framework/src/android/net/TcpKeepalivePacketData.java new file mode 100644 index 0000000000..ddb3a6a72f --- /dev/null +++ b/framework/src/android/net/TcpKeepalivePacketData.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.net.InetAddress; +import java.util.Objects; + +/** + * Represents the actual tcp keep alive packets which will be used for hardware offload. + * @hide + */ +@SystemApi +public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable { + private static final String TAG = "TcpKeepalivePacketData"; + + /** TCP sequence number. */ + public final int tcpSeq; + + /** TCP ACK number. */ + public final int tcpAck; + + /** TCP RCV window. */ + public final int tcpWindow; + + /** TCP RCV window scale. */ + public final int tcpWindowScale; + + /** IP TOS. */ + public final int ipTos; + + /** IP TTL. */ + public final int ipTtl; + + public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort, + @NonNull final InetAddress dstAddress, int dstPort, @NonNull final byte[] data, + int tcpSeq, int tcpAck, int tcpWindow, int tcpWindowScale, int ipTos, int ipTtl) + throws InvalidPacketException { + super(srcAddress, srcPort, dstAddress, dstPort, data); + this.tcpSeq = tcpSeq; + this.tcpAck = tcpAck; + this.tcpWindow = tcpWindow; + this.tcpWindowScale = tcpWindowScale; + this.ipTos = ipTos; + this.ipTtl = ipTtl; + } + + @Override + public boolean equals(@Nullable final Object o) { + if (!(o instanceof TcpKeepalivePacketData)) return false; + final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o; + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort() + && this.tcpAck == other.tcpAck + && this.tcpSeq == other.tcpSeq + && this.tcpWindow == other.tcpWindow + && this.tcpWindowScale == other.tcpWindowScale + && this.ipTos == other.ipTos + && this.ipTtl == other.ipTtl; + } + + @Override + public int hashCode() { + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(), + tcpAck, tcpSeq, tcpWindow, tcpWindowScale, ipTos, ipTtl); + } + + /** + * Parcelable Implementation. + * Note that this object implements parcelable (and needs to keep doing this as it inherits + * from a class that does), but should usually be parceled as a stable parcelable using + * the toStableParcelable() and fromStableParcelable() methods. + */ + @Override + public int describeContents() { + return 0; + } + + /** Write to parcel. */ + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); + out.writeByteArray(getPacket()); + out.writeInt(tcpSeq); + out.writeInt(tcpAck); + out.writeInt(tcpWindow); + out.writeInt(tcpWindowScale); + out.writeInt(ipTos); + out.writeInt(ipTtl); + } + + private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException { + InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString()); + InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString()); + int srcPort = in.readInt(); + int dstPort = in.readInt(); + byte[] packet = in.createByteArray(); + int tcpSeq = in.readInt(); + int tcpAck = in.readInt(); + int tcpWnd = in.readInt(); + int tcpWndScale = in.readInt(); + int ipTos = in.readInt(); + int ipTtl = in.readInt(); + return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq, + tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl); + } + + /** Parcelable Creator. */ + public static final @NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public TcpKeepalivePacketData createFromParcel(Parcel in) { + try { + return readFromParcel(in); + } catch (InvalidPacketException e) { + throw new IllegalArgumentException( + "Invalid TCP keepalive data: " + e.getError()); + } + } + + public TcpKeepalivePacketData[] newArray(int size) { + return new TcpKeepalivePacketData[size]; + } + }; + + @Override + public String toString() { + return "saddr: " + getSrcAddress() + + " daddr: " + getDstAddress() + + " sport: " + getSrcPort() + + " dport: " + getDstPort() + + " seq: " + tcpSeq + + " ack: " + tcpAck + + " window: " + tcpWindow + + " windowScale: " + tcpWindowScale + + " tos: " + ipTos + + " ttl: " + ipTtl; + } +} diff --git a/framework/src/android/net/TcpRepairWindow.java b/framework/src/android/net/TcpRepairWindow.java new file mode 100644 index 0000000000..f062fa9034 --- /dev/null +++ b/framework/src/android/net/TcpRepairWindow.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; + +/** + * Corresponds to C's {@code struct tcp_repair_window} from + * include/uapi/linux/tcp.h + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class TcpRepairWindow { + public final int sndWl1; + public final int sndWnd; + public final int maxWindow; + public final int rcvWnd; + public final int rcvWup; + public final int rcvWndScale; + + /** + * Constructs an instance with the given field values. + */ + public TcpRepairWindow(final int sndWl1, final int sndWnd, final int maxWindow, + final int rcvWnd, final int rcvWup, final int rcvWndScale) { + this.sndWl1 = sndWl1; + this.sndWnd = sndWnd; + this.maxWindow = maxWindow; + this.rcvWnd = rcvWnd; + this.rcvWup = rcvWup; + this.rcvWndScale = rcvWndScale; + } +} diff --git a/framework/src/android/net/TcpSocketKeepalive.java b/framework/src/android/net/TcpSocketKeepalive.java new file mode 100644 index 0000000000..d89814d49b --- /dev/null +++ b/framework/src/android/net/TcpSocketKeepalive.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.util.Log; + +import java.util.concurrent.Executor; + +/** @hide */ +final class TcpSocketKeepalive extends SocketKeepalive { + + TcpSocketKeepalive(@NonNull IConnectivityManager service, + @NonNull Network network, + @NonNull ParcelFileDescriptor pfd, + @NonNull Executor executor, + @NonNull Callback callback) { + super(service, network, pfd, executor, callback); + } + + /** + * Starts keepalives. {@code mSocket} must be a connected TCP socket. + * + * - The application must not write to or read from the socket after calling this method, until + * onDataReceived, onStopped, or onError are called. If it does, the keepalive will fail + * with {@link #ERROR_SOCKET_NOT_IDLE}, or {@code #ERROR_INVALID_SOCKET} if the socket + * experienced an error (as in poll(2) returned POLLERR or POLLHUP); if this happens, the data + * received from the socket may be invalid, and the socket can't be recovered. + * - If the socket has data in the send or receive buffer, then this call will fail with + * {@link #ERROR_SOCKET_NOT_IDLE} and can be retried after the data has been processed. + * An app could ensure this by using an application-layer protocol to receive acknowledgement + * that indicates all data has been delivered to server, e.g. HTTP 200 OK. + * Then the app could go into keepalive mode after reading all remaining data within the + * acknowledgement. + */ + @Override + void startImpl(int intervalSec) { + mExecutor.execute(() -> { + try { + mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback); + } catch (RemoteException e) { + Log.e(TAG, "Error starting packet keepalive: ", e); + throw e.rethrowFromSystemServer(); + } + }); + } + + @Override + void stopImpl() { + mExecutor.execute(() -> { + try { + if (mSlot != null) { + mService.stopKeepalive(mNetwork, mSlot); + } + } catch (RemoteException e) { + Log.e(TAG, "Error stopping packet keepalive: ", e); + throw e.rethrowFromSystemServer(); + } + }); + } +} diff --git a/framework/src/android/net/TestNetworkInterface.aidl b/framework/src/android/net/TestNetworkInterface.aidl new file mode 100644 index 0000000000..e1f4f9f794 --- /dev/null +++ b/framework/src/android/net/TestNetworkInterface.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +parcelable TestNetworkInterface; diff --git a/framework/src/android/net/TestNetworkInterface.java b/framework/src/android/net/TestNetworkInterface.java new file mode 100644 index 0000000000..4449ff8018 --- /dev/null +++ b/framework/src/android/net/TestNetworkInterface.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; + +/** + * This class is used to return the interface name and fd of the test interface + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class TestNetworkInterface implements Parcelable { + @NonNull + private final ParcelFileDescriptor mFileDescriptor; + @NonNull + private final String mInterfaceName; + + @Override + public int describeContents() { + return (mFileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(mFileDescriptor, PARCELABLE_WRITE_RETURN_VALUE); + out.writeString(mInterfaceName); + } + + public TestNetworkInterface(@NonNull ParcelFileDescriptor pfd, @NonNull String intf) { + mFileDescriptor = pfd; + mInterfaceName = intf; + } + + private TestNetworkInterface(@NonNull Parcel in) { + mFileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); + mInterfaceName = in.readString(); + } + + @NonNull + public ParcelFileDescriptor getFileDescriptor() { + return mFileDescriptor; + } + + @NonNull + public String getInterfaceName() { + return mInterfaceName; + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public TestNetworkInterface createFromParcel(Parcel in) { + return new TestNetworkInterface(in); + } + + public TestNetworkInterface[] newArray(int size) { + return new TestNetworkInterface[size]; + } + }; +} diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java new file mode 100644 index 0000000000..4e894143bf --- /dev/null +++ b/framework/src/android/net/TestNetworkManager.java @@ -0,0 +1,178 @@ +/* + * 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. + */ +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.IBinder; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +import java.util.Arrays; +import java.util.Collection; + +/** + * Class that allows creation and management of per-app, test-only networks + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public class TestNetworkManager { + /** + * Prefix for tun interfaces created by this class. + * @hide + */ + public static final String TEST_TUN_PREFIX = "testtun"; + + /** + * Prefix for tap interfaces created by this class. + * @hide + */ + public static final String TEST_TAP_PREFIX = "testtap"; + + @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName(); + + @NonNull private final ITestNetworkManager mService; + + /** @hide */ + public TestNetworkManager(@NonNull ITestNetworkManager service) { + mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager"); + } + + /** + * Teardown the capability-limited, testing-only network for a given interface + * + * @param network The test network that should be torn down + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void teardownTestNetwork(@NonNull Network network) { + try { + mService.teardownTestNetwork(network.netId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private void setupTestNetwork( + @NonNull String iface, + @Nullable LinkProperties lp, + boolean isMetered, + @NonNull int[] administratorUids, + @NonNull IBinder binder) { + try { + mService.setupTestNetwork(iface, lp, isMetered, administratorUids, binder); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Sets up a capability-limited, testing-only network for a given interface + * + * @param lp The LinkProperties for the TestNetworkService to use for this test network. Note + * that the interface name and link addresses will be overwritten, and the passed-in values + * discarded. + * @param isMetered Whether or not the network should be considered metered. + * @param binder A binder object guarding the lifecycle of this test network. + * @hide + */ + public void setupTestNetwork( + @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { + Preconditions.checkNotNull(lp, "Invalid LinkProperties"); + setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); + } + + /** + * Sets up a capability-limited, testing-only network for a given interface + * + * @param iface the name of the interface to be used for the Network LinkProperties. + * @param binder A binder object guarding the lifecycle of this test network. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) { + setupTestNetwork(iface, null, true, new int[0], binder); + } + + /** + * Sets up a capability-limited, testing-only network for a given interface with the given + * administrator UIDs. + * + * @param iface the name of the interface to be used for the Network LinkProperties. + * @param administratorUids The administrator UIDs to be used for the test-only network + * @param binder A binder object guarding the lifecycle of this test network. + * @hide + */ + public void setupTestNetwork( + @NonNull String iface, @NonNull int[] administratorUids, @NonNull IBinder binder) { + setupTestNetwork(iface, null, true, administratorUids, binder); + } + + /** + * Create a tun interface for testing purposes + * + * @param linkAddrs an array of LinkAddresses to assign to the TUN interface + * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the + * TUN interface. + * @deprecated Use {@link #createTunInterface(Collection)} instead. + * @hide + */ + @Deprecated + @NonNull + public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) { + return createTunInterface(Arrays.asList(linkAddrs)); + } + + /** + * Create a tun interface for testing purposes + * + * @param linkAddrs an array of LinkAddresses to assign to the TUN interface + * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the + * TUN interface. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @NonNull + public TestNetworkInterface createTunInterface(@NonNull Collection linkAddrs) { + try { + final LinkAddress[] arr = new LinkAddress[linkAddrs.size()]; + return mService.createTunInterface(linkAddrs.toArray(arr)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Create a tap interface for testing purposes + * + * @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the + * TAP interface. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @NonNull + public TestNetworkInterface createTapInterface() { + try { + return mService.createTapInterface(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + +} diff --git a/framework/src/android/net/TransportInfo.java b/framework/src/android/net/TransportInfo.java new file mode 100644 index 0000000000..aa4bbb0511 --- /dev/null +++ b/framework/src/android/net/TransportInfo.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.SystemApi; + +/** + * A container for transport-specific capabilities which is returned by + * {@link NetworkCapabilities#getTransportInfo()}. Specific networks + * may provide concrete implementations of this interface. + * @see android.net.wifi.aware.WifiAwareNetworkInfo + * @see android.net.wifi.WifiInfo + */ +public interface TransportInfo { + + /** + * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that + * were set based on the permissions of the process that originally received it. + * + *

By default {@link TransportInfo} does not preserve such fields during parceling, as + * they should not be shared outside of the process that receives them without appropriate + * checks. + * + * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept + * when parceling + * @return Copy of this instance. + * @hide + */ + @SystemApi + @NonNull + default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { + return this; + } + + /** + * Returns whether this TransportInfo type has location sensitive fields or not (helps + * to determine whether to perform a location permission check or not before sending to + * apps). + * + * @return {@code true} if this instance contains location sensitive info, {@code false} + * otherwise. + * @hide + */ + @SystemApi + default boolean hasLocationSensitiveFields() { + return false; + } +} diff --git a/framework/src/android/net/UidRange.aidl b/framework/src/android/net/UidRange.aidl new file mode 100644 index 0000000000..f70fc8e2fe --- /dev/null +++ b/framework/src/android/net/UidRange.aidl @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package android.net; + +/** + * An inclusive range of UIDs. + * + * {@hide} + */ +parcelable UidRange; \ No newline at end of file diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java new file mode 100644 index 0000000000..c87b8279c4 --- /dev/null +++ b/framework/src/android/net/VpnManager.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.os.RemoteException; + +import com.android.internal.net.VpnProfile; + +import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.security.GeneralSecurityException; + +/** + * This class provides an interface for apps to manage platform VPN profiles + * + *

Apps can use this API to provide profiles with which the platform can set up a VPN without + * further app intermediation. When a VPN profile is present and the app is selected as an always-on + * VPN, the platform will directly trigger the negotiation of the VPN without starting or waking the + * app (unlike VpnService). + * + *

VPN apps using supported protocols should preferentially use this API over the {@link + * VpnService} API for ease-of-development and reduced maintainance burden. This also give the user + * the guarantee that VPN network traffic is not subjected to on-device packet interception. + * + * @see Ikev2VpnProfile + */ +public class VpnManager { + /** Type representing a lack of VPN @hide */ + public static final int TYPE_VPN_NONE = -1; + /** VPN service type code @hide */ + public static final int TYPE_VPN_SERVICE = 1; + /** Platform VPN type code @hide */ + public static final int TYPE_VPN_PLATFORM = 2; + + /** @hide */ + @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM}) + @Retention(RetentionPolicy.SOURCE) + public @interface VpnType {} + + @NonNull private final Context mContext; + @NonNull private final IConnectivityManager mService; + + private static Intent getIntentForConfirmation() { + final Intent intent = new Intent(); + final ComponentName componentName = ComponentName.unflattenFromString( + Resources.getSystem().getString( + com.android.internal.R.string.config_platformVpnConfirmDialogComponent)); + intent.setComponent(componentName); + return intent; + } + + /** + * Create an instance of the VpnManager with the given context. + * + *

Internal only. Applications are expected to obtain an instance of the VpnManager via the + * {@link Context.getSystemService()} method call. + * + * @hide + */ + public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) { + mContext = checkNotNull(ctx, "missing Context"); + mService = checkNotNull(service, "missing IConnectivityManager"); + } + + /** + * Install a VpnProfile configuration keyed on the calling app's package name. + * + *

This method returns {@code null} if user consent has already been granted, or an {@link + * Intent} to a system activity. If an intent is returned, the application should launch the + * activity using {@link Activity#startActivityForResult} to request user consent. The activity + * may pop up a dialog to require user action, and the result will come back via its {@link + * Activity#onActivityResult}. If the result is {@link Activity#RESULT_OK}, the user has + * consented, and the VPN profile can be started. + * + * @param profile the VpnProfile provided by this package. Will override any previous VpnProfile + * stored for this package. + * @return an Intent requesting user consent to start the VPN, or null if consent is not + * required based on privileges or previous user consent. + */ + @Nullable + public Intent provisionVpnProfile(@NonNull PlatformVpnProfile profile) { + final VpnProfile internalProfile; + + try { + internalProfile = profile.toVpnProfile(); + } catch (GeneralSecurityException | IOException e) { + // Conversion to VpnProfile failed; this is an invalid profile. Both of these exceptions + // indicate a failure to convert a PrivateKey or X509Certificate to a Base64 encoded + // string as required by the VpnProfile. + throw new IllegalArgumentException("Failed to serialize PlatformVpnProfile", e); + } + + try { + // Profile can never be null; it either gets set, or an exception is thrown. + if (mService.provisionVpnProfile(internalProfile, mContext.getOpPackageName())) { + return null; + } + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return getIntentForConfirmation(); + } + + /** + * Delete the VPN profile configuration that was provisioned by the calling app + * + * @throws SecurityException if this would violate user settings + */ + public void deleteProvisionedVpnProfile() { + try { + mService.deleteVpnProfile(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Request the startup of a previously provisioned VPN. + * + * @throws SecurityException exception if user or device settings prevent this VPN from being + * setup, or if user consent has not been granted + */ + public void startProvisionedVpnProfile() { + try { + mService.startVpnProfile(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** Tear down the VPN provided by the calling app (if any) */ + public void stopProvisionedVpnProfile() { + try { + mService.stopVpnProfile(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/framework/src/android/net/VpnService.java b/framework/src/android/net/VpnService.java new file mode 100644 index 0000000000..8e90a119fe --- /dev/null +++ b/framework/src/android/net/VpnService.java @@ -0,0 +1,903 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.app.Activity; +import android.app.PendingIntent; +import android.app.Service; +import android.app.admin.DevicePolicyManager; +import android.compat.annotation.UnsupportedAppUsage; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.IPackageManager; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.IBinder; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; + +import com.android.internal.net.VpnConfig; + +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * VpnService is a base class for applications to extend and build their + * own VPN solutions. In general, it creates a virtual network interface, + * configures addresses and routing rules, and returns a file descriptor + * to the application. Each read from the descriptor retrieves an outgoing + * packet which was routed to the interface. Each write to the descriptor + * injects an incoming packet just like it was received from the interface. + * The interface is running on Internet Protocol (IP), so packets are + * always started with IP headers. The application then completes a VPN + * connection by processing and exchanging packets with the remote server + * over a tunnel. + * + *

Letting applications intercept packets raises huge security concerns. + * A VPN application can easily break the network. Besides, two of them may + * conflict with each other. The system takes several actions to address + * these issues. Here are some key points: + *

    + *
  • User action is required the first time an application creates a VPN + * connection.
  • + *
  • There can be only one VPN connection running at the same time. The + * existing interface is deactivated when a new one is created.
  • + *
  • A system-managed notification is shown during the lifetime of a + * VPN connection.
  • + *
  • A system-managed dialog gives the information of the current VPN + * connection. It also provides a button to disconnect.
  • + *
  • The network is restored automatically when the file descriptor is + * closed. It also covers the cases when a VPN application is crashed + * or killed by the system.
  • + *
+ * + *

There are two primary methods in this class: {@link #prepare} and + * {@link Builder#establish}. The former deals with user action and stops + * the VPN connection created by another application. The latter creates + * a VPN interface using the parameters supplied to the {@link Builder}. + * An application must call {@link #prepare} to grant the right to use + * other methods in this class, and the right can be revoked at any time. + * Here are the general steps to create a VPN connection: + *

    + *
  1. When the user presses the button to connect, call {@link #prepare} + * and launch the returned intent, if non-null.
  2. + *
  3. When the application becomes prepared, start the service.
  4. + *
  5. Create a tunnel to the remote server and negotiate the network + * parameters for the VPN connection.
  6. + *
  7. Supply those parameters to a {@link Builder} and create a VPN + * interface by calling {@link Builder#establish}.
  8. + *
  9. Process and exchange packets between the tunnel and the returned + * file descriptor.
  10. + *
  11. When {@link #onRevoke} is invoked, close the file descriptor and + * shut down the tunnel gracefully.
  12. + *
+ * + *

Services extending this class need to be declared with an appropriate + * permission and intent filter. Their access must be secured by + * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and + * their intent filter must match {@link #SERVICE_INTERFACE} action. Here + * is an example of declaring a VPN service in {@code AndroidManifest.xml}: + *

+ * <service android:name=".ExampleVpnService"
+ *         android:permission="android.permission.BIND_VPN_SERVICE">
+ *     <intent-filter>
+ *         <action android:name="android.net.VpnService"/>
+ *     </intent-filter>
+ * </service>
+ * + *

The Android system starts a VPN in the background by calling + * {@link android.content.Context#startService startService()}. In Android 8.0 + * (API level 26) and higher, the system places VPN apps on the temporary + * allowlist for a short period so the app can start in the background. The VPN + * app must promote itself to the foreground after it's launched or the system + * will shut down the app. + * + *

Developer's guide

+ * + *

To learn more about developing VPN apps, read the + * VPN developer's guide. + * + * @see Builder + */ +public class VpnService extends Service { + + /** + * The action must be matched by the intent filter of this service. It also + * needs to require {@link android.Manifest.permission#BIND_VPN_SERVICE} + * permission so that other applications cannot abuse it. + */ + public static final String SERVICE_INTERFACE = VpnConfig.SERVICE_INTERFACE; + + /** + * Key for boolean meta-data field indicating whether this VpnService supports always-on mode. + * + *

For a VPN app targeting {@link android.os.Build.VERSION_CODES#N API 24} or above, Android + * provides users with the ability to set it as always-on, so that VPN connection is + * persisted after device reboot and app upgrade. Always-on VPN can also be enabled by device + * owner and profile owner apps through + * {@link DevicePolicyManager#setAlwaysOnVpnPackage}. + * + *

VPN apps not supporting this feature should opt out by adding this meta-data field to the + * {@code VpnService} component of {@code AndroidManifest.xml}. In case there is more than one + * {@code VpnService} component defined in {@code AndroidManifest.xml}, opting out any one of + * them will opt out the entire app. For example, + *

 {@code
+     * 
+     *     
+     *         
+     *     
+     *     
+     * 
+     * } 
+ * + *

This meta-data field defaults to {@code true} if absent. It will only have effect on + * {@link android.os.Build.VERSION_CODES#O_MR1} or higher. + */ + public static final String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = + "android.net.VpnService.SUPPORTS_ALWAYS_ON"; + + /** + * Use IConnectivityManager since those methods are hidden and not + * available in ConnectivityManager. + */ + private static IConnectivityManager getService() { + return IConnectivityManager.Stub.asInterface( + ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + } + + /** + * Prepare to establish a VPN connection. This method returns {@code null} + * if the VPN application is already prepared or if the user has previously + * consented to the VPN application. Otherwise, it returns an + * {@link Intent} to a system activity. The application should launch the + * activity using {@link Activity#startActivityForResult} to get itself + * prepared. The activity may pop up a dialog to require user action, and + * the result will come back via its {@link Activity#onActivityResult}. + * If the result is {@link Activity#RESULT_OK}, the application becomes + * prepared and is granted to use other methods in this class. + * + *

Only one application can be granted at the same time. The right + * is revoked when another application is granted. The application + * losing the right will be notified via its {@link #onRevoke}. Unless + * it becomes prepared again, subsequent calls to other methods in this + * class will fail. + * + *

The user may disable the VPN at any time while it is activated, in + * which case this method will return an intent the next time it is + * executed to obtain the user's consent again. + * + * @see #onRevoke + */ + public static Intent prepare(Context context) { + try { + if (getService().prepareVpn(context.getPackageName(), null, context.getUserId())) { + return null; + } + } catch (RemoteException e) { + // ignore + } + return VpnConfig.getIntentForConfirmation(); + } + + /** + * Version of {@link #prepare(Context)} which does not require user consent. + * + *

Requires {@link android.Manifest.permission#CONTROL_VPN} and should generally not be + * used. Only acceptable in situations where user consent has been obtained through other means. + * + *

Once this is run, future preparations may be done with the standard prepare method as this + * will authorize the package to prepare the VPN without consent in the future. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.CONTROL_VPN) + public static void prepareAndAuthorize(Context context) { + IConnectivityManager cm = getService(); + String packageName = context.getPackageName(); + try { + // Only prepare if we're not already prepared. + int userId = context.getUserId(); + if (!cm.prepareVpn(packageName, null, userId)) { + cm.prepareVpn(null, packageName, userId); + } + cm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); + } catch (RemoteException e) { + // ignore + } + } + + /** + * Protect a socket from VPN connections. After protecting, data sent + * through this socket will go directly to the underlying network, + * so its traffic will not be forwarded through the VPN. + * This method is useful if some connections need to be kept + * outside of VPN. For example, a VPN tunnel should protect itself if its + * destination is covered by VPN routes. Otherwise its outgoing packets + * will be sent back to the VPN interface and cause an infinite loop. This + * method will fail if the application is not prepared or is revoked. + * + *

The socket is NOT closed by this method. + * + * @return {@code true} on success. + */ + public boolean protect(int socket) { + return NetworkUtils.protectFromVpn(socket); + } + + /** + * Convenience method to protect a {@link Socket} from VPN connections. + * + * @return {@code true} on success. + * @see #protect(int) + */ + public boolean protect(Socket socket) { + return protect(socket.getFileDescriptor$().getInt$()); + } + + /** + * Convenience method to protect a {@link DatagramSocket} from VPN + * connections. + * + * @return {@code true} on success. + * @see #protect(int) + */ + public boolean protect(DatagramSocket socket) { + return protect(socket.getFileDescriptor$().getInt$()); + } + + /** + * Adds a network address to the VPN interface. + * + * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the + * address is already in use or cannot be assigned to the interface for any other reason. + * + * Adding an address implicitly allows traffic from that address family (i.e., IPv4 or IPv6) to + * be routed over the VPN. @see Builder#allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * + * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface. + * @param prefixLength The prefix length of the address. + * + * @return {@code true} on success. + * @see Builder#addAddress + * + * @hide + */ + public boolean addAddress(InetAddress address, int prefixLength) { + check(address, prefixLength); + try { + return getService().addVpnAddress(address.getHostAddress(), prefixLength); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Removes a network address from the VPN interface. + * + * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the + * address is not assigned to the VPN interface, or if it is the only address assigned (thus + * cannot be removed), or if the address cannot be removed for any other reason. + * + * After removing an address, if there are no addresses, routes or DNS servers of a particular + * address family (i.e., IPv4 or IPv6) configured on the VPN, that DOES NOT block that + * family from being routed. In other words, once an address family has been allowed, it stays + * allowed for the rest of the VPN's session. @see Builder#allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * + * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface. + * @param prefixLength The prefix length of the address. + * + * @return {@code true} on success. + * + * @hide + */ + public boolean removeAddress(InetAddress address, int prefixLength) { + check(address, prefixLength); + try { + return getService().removeVpnAddress(address.getHostAddress(), prefixLength); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Sets the underlying networks used by the VPN for its upstream connections. + * + *

Used by the system to know the actual networks that carry traffic for apps affected by + * this VPN in order to present this information to the user (e.g., via status bar icons). + * + *

This method only needs to be called if the VPN has explicitly bound its underlying + * communications channels — such as the socket(s) passed to {@link #protect(int)} — + * to a {@code Network} using APIs such as {@link Network#bindSocket(Socket)} or + * {@link Network#bindSocket(DatagramSocket)}. The VPN should call this method every time + * the set of {@code Network}s it is using changes. + * + *

{@code networks} is one of the following: + *

    + *
  • a non-empty array: an array of one or more {@link Network}s, in + * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) + * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear + * first in the array.
  • + *
  • an empty array: a zero-element array, meaning that the VPN has no + * underlying network connection, and thus, app traffic will not be sent or received.
  • + *
  • null: (default) signifies that the VPN uses whatever is the system's + * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} + * APIs mentioned above to send traffic over specific channels.
  • + *
+ * + *

This call will succeed only if the VPN is currently established. For setting this value + * when the VPN has not yet been established, see {@link Builder#setUnderlyingNetworks}. + * + * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. + * + * @return {@code true} on success. + */ + public boolean setUnderlyingNetworks(Network[] networks) { + try { + return getService().setUnderlyingNetworksForVpn(networks); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns whether the service is running in always-on VPN mode. In this mode the system ensures + * that the service is always running by restarting it when necessary, e.g. after reboot. + * + * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) + */ + public final boolean isAlwaysOn() { + try { + return getService().isCallerCurrentAlwaysOnVpnApp(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns whether the service is running in always-on VPN lockdown mode. In this mode the + * system ensures that the service is always running and that the apps aren't allowed to bypass + * the VPN. + * + * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) + */ + public final boolean isLockdownEnabled() { + try { + return getService().isCallerCurrentAlwaysOnVpnLockdownApp(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return the communication interface to the service. This method returns + * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE} + * action. Applications overriding this method must identify the intent + * and return the corresponding interface accordingly. + * + * @see Service#onBind + */ + @Override + public IBinder onBind(Intent intent) { + if (intent != null && SERVICE_INTERFACE.equals(intent.getAction())) { + return new Callback(); + } + return null; + } + + /** + * Invoked when the application is revoked. At this moment, the VPN + * interface is already deactivated by the system. The application should + * close the file descriptor and shut down gracefully. The default + * implementation of this method is calling {@link Service#stopSelf()}. + * + *

Calls to this method may not happen on the main thread + * of the process. + * + * @see #prepare + */ + public void onRevoke() { + stopSelf(); + } + + /** + * Use raw Binder instead of AIDL since now there is only one usage. + */ + private class Callback extends Binder { + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) { + if (code == IBinder.LAST_CALL_TRANSACTION) { + onRevoke(); + return true; + } + return false; + } + } + + /** + * Private method to validate address and prefixLength. + */ + private static void check(InetAddress address, int prefixLength) { + if (address.isLoopbackAddress()) { + throw new IllegalArgumentException("Bad address"); + } + if (address instanceof Inet4Address) { + if (prefixLength < 0 || prefixLength > 32) { + throw new IllegalArgumentException("Bad prefixLength"); + } + } else if (address instanceof Inet6Address) { + if (prefixLength < 0 || prefixLength > 128) { + throw new IllegalArgumentException("Bad prefixLength"); + } + } else { + throw new IllegalArgumentException("Unsupported family"); + } + } + + /** + * Helper class to create a VPN interface. This class should be always + * used within the scope of the outer {@link VpnService}. + * + * @see VpnService + */ + public class Builder { + + private final VpnConfig mConfig = new VpnConfig(); + @UnsupportedAppUsage + private final List mAddresses = new ArrayList(); + @UnsupportedAppUsage + private final List mRoutes = new ArrayList(); + + public Builder() { + mConfig.user = VpnService.this.getClass().getName(); + } + + /** + * Set the name of this session. It will be displayed in + * system-managed dialogs and notifications. This is recommended + * not required. + */ + @NonNull + public Builder setSession(@NonNull String session) { + mConfig.session = session; + return this; + } + + /** + * Set the {@link PendingIntent} to an activity for users to + * configure the VPN connection. If it is not set, the button + * to configure will not be shown in system-managed dialogs. + */ + @NonNull + public Builder setConfigureIntent(@NonNull PendingIntent intent) { + mConfig.configureIntent = intent; + return this; + } + + /** + * Set the maximum transmission unit (MTU) of the VPN interface. If + * it is not set, the default value in the operating system will be + * used. + * + * @throws IllegalArgumentException if the value is not positive. + */ + @NonNull + public Builder setMtu(int mtu) { + if (mtu <= 0) { + throw new IllegalArgumentException("Bad mtu"); + } + mConfig.mtu = mtu; + return this; + } + + /** + * Sets an HTTP proxy for the VPN network. This proxy is only a recommendation + * and it is possible that some apps will ignore it. + */ + @NonNull + public Builder setHttpProxy(@NonNull ProxyInfo proxyInfo) { + mConfig.proxyInfo = proxyInfo; + return this; + } + + /** + * Add a network address to the VPN interface. Both IPv4 and IPv6 + * addresses are supported. At least one address must be set before + * calling {@link #establish}. + * + * Adding an address implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + */ + @NonNull + public Builder addAddress(@NonNull InetAddress address, int prefixLength) { + check(address, prefixLength); + + if (address.isAnyLocalAddress()) { + throw new IllegalArgumentException("Bad address"); + } + mAddresses.add(new LinkAddress(address, prefixLength)); + mConfig.updateAllowedFamilies(address); + return this; + } + + /** + * Convenience method to add a network address to the VPN interface + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * Adding an address implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * @see #addAddress(InetAddress, int) + */ + @NonNull + public Builder addAddress(@NonNull String address, int prefixLength) { + return addAddress(InetAddress.parseNumericAddress(address), prefixLength); + } + + /** + * Add a network route to the VPN interface. Both IPv4 and IPv6 + * routes are supported. + * + * Adding a route implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the route is invalid. + */ + @NonNull + public Builder addRoute(@NonNull InetAddress address, int prefixLength) { + check(address, prefixLength); + + int offset = prefixLength / 8; + byte[] bytes = address.getAddress(); + if (offset < bytes.length) { + for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) { + if (bytes[offset] != 0) { + throw new IllegalArgumentException("Bad address"); + } + } + } + mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null)); + mConfig.updateAllowedFamilies(address); + return this; + } + + /** + * Convenience method to add a network route to the VPN interface + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * Adding a route implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the route is invalid. + * @see #addRoute(InetAddress, int) + */ + @NonNull + public Builder addRoute(@NonNull String address, int prefixLength) { + return addRoute(InetAddress.parseNumericAddress(address), prefixLength); + } + + /** + * Add a DNS server to the VPN connection. Both IPv4 and IPv6 + * addresses are supported. If none is set, the DNS servers of + * the default network will be used. + * + * Adding a server implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + */ + @NonNull + public Builder addDnsServer(@NonNull InetAddress address) { + if (address.isLoopbackAddress() || address.isAnyLocalAddress()) { + throw new IllegalArgumentException("Bad address"); + } + if (mConfig.dnsServers == null) { + mConfig.dnsServers = new ArrayList(); + } + mConfig.dnsServers.add(address.getHostAddress()); + return this; + } + + /** + * Convenience method to add a DNS server to the VPN connection + * using a numeric address string. See {@link InetAddress} for the + * definitions of numeric address formats. + * + * Adding a server implicitly allows traffic from that address family + * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily + * + * @throws IllegalArgumentException if the address is invalid. + * @see #addDnsServer(InetAddress) + */ + @NonNull + public Builder addDnsServer(@NonNull String address) { + return addDnsServer(InetAddress.parseNumericAddress(address)); + } + + /** + * Add a search domain to the DNS resolver. + */ + @NonNull + public Builder addSearchDomain(@NonNull String domain) { + if (mConfig.searchDomains == null) { + mConfig.searchDomains = new ArrayList(); + } + mConfig.searchDomains.add(domain); + return this; + } + + /** + * Allows traffic from the specified address family. + * + * By default, if no address, route or DNS server of a specific family (IPv4 or IPv6) is + * added to this VPN, then all outgoing traffic of that family is blocked. If any address, + * route or DNS server is added, that family is allowed. + * + * This method allows an address family to be unblocked even without adding an address, + * route or DNS server of that family. Traffic of that family will then typically + * fall-through to the underlying network if it's supported. + * + * {@code family} must be either {@code AF_INET} (for IPv4) or {@code AF_INET6} (for IPv6). + * {@link IllegalArgumentException} is thrown if it's neither. + * + * @param family The address family ({@code AF_INET} or {@code AF_INET6}) to allow. + * + * @return this {@link Builder} object to facilitate chaining of method calls. + */ + @NonNull + public Builder allowFamily(int family) { + if (family == AF_INET) { + mConfig.allowIPv4 = true; + } else if (family == AF_INET6) { + mConfig.allowIPv6 = true; + } else { + throw new IllegalArgumentException(family + " is neither " + AF_INET + " nor " + + AF_INET6); + } + return this; + } + + private void verifyApp(String packageName) throws PackageManager.NameNotFoundException { + IPackageManager pm = IPackageManager.Stub.asInterface( + ServiceManager.getService("package")); + try { + pm.getApplicationInfo(packageName, 0, UserHandle.getCallingUserId()); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + + /** + * Adds an application that's allowed to access the VPN connection. + * + * If this method is called at least once, only applications added through this method (and + * no others) are allowed access. Else (if this method is never called), all applications + * are allowed by default. If some applications are added, other, un-added applications + * will use networking as if the VPN wasn't running. + * + * A {@link Builder} may have only a set of allowed applications OR a set of disallowed + * ones, but not both. Calling this method after {@link #addDisallowedApplication} has + * already been called, or vice versa, will throw an {@link UnsupportedOperationException}. + * + * {@code packageName} must be the canonical name of a currently installed application. + * {@link PackageManager.NameNotFoundException} is thrown if there's no such application. + * + * @throws PackageManager.NameNotFoundException If the application isn't installed. + * + * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder addAllowedApplication(@NonNull String packageName) + throws PackageManager.NameNotFoundException { + if (mConfig.disallowedApplications != null) { + throw new UnsupportedOperationException("addDisallowedApplication already called"); + } + verifyApp(packageName); + if (mConfig.allowedApplications == null) { + mConfig.allowedApplications = new ArrayList(); + } + mConfig.allowedApplications.add(packageName); + return this; + } + + /** + * Adds an application that's denied access to the VPN connection. + * + * By default, all applications are allowed access, except for those denied through this + * method. Denied applications will use networking as if the VPN wasn't running. + * + * A {@link Builder} may have only a set of allowed applications OR a set of disallowed + * ones, but not both. Calling this method after {@link #addAllowedApplication} has already + * been called, or vice versa, will throw an {@link UnsupportedOperationException}. + * + * {@code packageName} must be the canonical name of a currently installed application. + * {@link PackageManager.NameNotFoundException} is thrown if there's no such application. + * + * @throws PackageManager.NameNotFoundException If the application isn't installed. + * + * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder addDisallowedApplication(@NonNull String packageName) + throws PackageManager.NameNotFoundException { + if (mConfig.allowedApplications != null) { + throw new UnsupportedOperationException("addAllowedApplication already called"); + } + verifyApp(packageName); + if (mConfig.disallowedApplications == null) { + mConfig.disallowedApplications = new ArrayList(); + } + mConfig.disallowedApplications.add(packageName); + return this; + } + + /** + * Allows all apps to bypass this VPN connection. + * + * By default, all traffic from apps is forwarded through the VPN interface and it is not + * possible for apps to side-step the VPN. If this method is called, apps may use methods + * such as {@link ConnectivityManager#bindProcessToNetwork} to instead send/receive + * directly over the underlying network or any other network they have permissions for. + * + * @return this {@link Builder} object to facilitate chaining of method calls. + */ + @NonNull + public Builder allowBypass() { + mConfig.allowBypass = true; + return this; + } + + /** + * Sets the VPN interface's file descriptor to be in blocking/non-blocking mode. + * + * By default, the file descriptor returned by {@link #establish} is non-blocking. + * + * @param blocking True to put the descriptor into blocking mode; false for non-blocking. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder setBlocking(boolean blocking) { + mConfig.blocking = blocking; + return this; + } + + /** + * Sets the underlying networks used by the VPN for its upstream connections. + * + * @see VpnService#setUnderlyingNetworks + * + * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. + * + * @return this {@link Builder} object to facilitate chaining method calls. + */ + @NonNull + public Builder setUnderlyingNetworks(@Nullable Network[] networks) { + mConfig.underlyingNetworks = networks != null ? networks.clone() : null; + return this; + } + + /** + * Marks the VPN network as metered. A VPN network is classified as metered when the user is + * sensitive to heavy data usage due to monetary costs and/or data limitations. In such + * cases, you should set this to {@code true} so that apps on the system can avoid doing + * large data transfers. Otherwise, set this to {@code false}. Doing so would cause VPN + * network to inherit its meteredness from its underlying networks. + * + *

VPN apps targeting {@link android.os.Build.VERSION_CODES#Q} or above will be + * considered metered by default. + * + * @param isMetered {@code true} if VPN network should be treated as metered regardless of + * underlying network meteredness + * @return this {@link Builder} object to facilitate chaining method calls + * @see #setUnderlyingNetworks(Network[]) + * @see ConnectivityManager#isActiveNetworkMetered() + */ + @NonNull + public Builder setMetered(boolean isMetered) { + mConfig.isMetered = isMetered; + return this; + } + + /** + * Create a VPN interface using the parameters supplied to this + * builder. The interface works on IP packets, and a file descriptor + * is returned for the application to access them. Each read + * retrieves an outgoing packet which was routed to the interface. + * Each write injects an incoming packet just like it was received + * from the interface. The file descriptor is put into non-blocking + * mode by default to avoid blocking Java threads. To use the file + * descriptor completely in native space, see + * {@link ParcelFileDescriptor#detachFd()}. The application MUST + * close the file descriptor when the VPN connection is terminated. + * The VPN interface will be removed and the network will be + * restored by the system automatically. + * + *

To avoid conflicts, there can be only one active VPN interface + * at the same time. Usually network parameters are never changed + * during the lifetime of a VPN connection. It is also common for an + * application to create a new file descriptor after closing the + * previous one. However, it is rare but not impossible to have two + * interfaces while performing a seamless handover. In this case, the + * old interface will be deactivated when the new one is created + * successfully. Both file descriptors are valid but now outgoing + * packets will be routed to the new interface. Therefore, after + * draining the old file descriptor, the application MUST close it + * and start using the new file descriptor. If the new interface + * cannot be created, the existing interface and its file descriptor + * remain untouched. + * + *

An exception will be thrown if the interface cannot be created + * for any reason. However, this method returns {@code null} if the + * application is not prepared or is revoked. This helps solve + * possible race conditions between other VPN applications. + * + * @return {@link ParcelFileDescriptor} of the VPN interface, or + * {@code null} if the application is not prepared. + * @throws IllegalArgumentException if a parameter is not accepted + * by the operating system. + * @throws IllegalStateException if a parameter cannot be applied + * by the operating system. + * @throws SecurityException if the service is not properly declared + * in {@code AndroidManifest.xml}. + * @see VpnService + */ + @Nullable + public ParcelFileDescriptor establish() { + mConfig.addresses = mAddresses; + mConfig.routes = mRoutes; + + try { + return getService().establishVpn(mConfig); + } catch (RemoteException e) { + throw new IllegalStateException(e); + } + } + } +} diff --git a/framework/src/android/net/apf/ApfCapabilities.aidl b/framework/src/android/net/apf/ApfCapabilities.aidl new file mode 100644 index 0000000000..7c4d4c2da4 --- /dev/null +++ b/framework/src/android/net/apf/ApfCapabilities.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright (C) 2019 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net.apf; + +@JavaOnlyStableParcelable parcelable ApfCapabilities; \ No newline at end of file diff --git a/framework/src/android/net/apf/ApfCapabilities.java b/framework/src/android/net/apf/ApfCapabilities.java new file mode 100644 index 0000000000..bf5b26e278 --- /dev/null +++ b/framework/src/android/net/apf/ApfCapabilities.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.apf; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.content.res.Resources; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.R; + +/** + * APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible + * way to drop unwanted network packets to save power. + * + * See documentation at hardware/google/apf/apf.h + * + * This class is immutable. + * @hide + */ +@SystemApi +public final class ApfCapabilities implements Parcelable { + /** + * Version of APF instruction set supported for packet filtering. 0 indicates no support for + * packet filtering using APF programs. + */ + public final int apfVersionSupported; + + /** + * Maximum size of APF program allowed. + */ + public final int maximumApfProgramSize; + + /** + * Format of packets passed to APF filter. Should be one of ARPHRD_* + */ + public final int apfPacketFormat; + + public ApfCapabilities( + int apfVersionSupported, int maximumApfProgramSize, int apfPacketFormat) { + this.apfVersionSupported = apfVersionSupported; + this.maximumApfProgramSize = maximumApfProgramSize; + this.apfPacketFormat = apfPacketFormat; + } + + private ApfCapabilities(Parcel in) { + apfVersionSupported = in.readInt(); + maximumApfProgramSize = in.readInt(); + apfPacketFormat = in.readInt(); + } + + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(apfVersionSupported); + dest.writeInt(maximumApfProgramSize); + dest.writeInt(apfPacketFormat); + } + + public static final Creator CREATOR = new Creator() { + @Override + public ApfCapabilities createFromParcel(Parcel in) { + return new ApfCapabilities(in); + } + + @Override + public ApfCapabilities[] newArray(int size) { + return new ApfCapabilities[size]; + } + }; + + @NonNull + @Override + public String toString() { + return String.format("%s{version: %d, maxSize: %d, format: %d}", getClass().getSimpleName(), + apfVersionSupported, maximumApfProgramSize, apfPacketFormat); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (!(obj instanceof ApfCapabilities)) return false; + final ApfCapabilities other = (ApfCapabilities) obj; + return apfVersionSupported == other.apfVersionSupported + && maximumApfProgramSize == other.maximumApfProgramSize + && apfPacketFormat == other.apfPacketFormat; + } + + /** + * Determines whether the APF interpreter advertises support for the data buffer access opcodes + * LDDW (LoaD Data Word) and STDW (STore Data Word). Full LDDW (LoaD Data Word) and + * STDW (STore Data Word) support is present from APFv4 on. + * + * @return {@code true} if the IWifiStaIface#readApfPacketFilterData is supported. + */ + public boolean hasDataAccess() { + return apfVersionSupported >= 4; + } + + /** + * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. + */ + public static boolean getApfDrop8023Frames() { + return Resources.getSystem().getBoolean(R.bool.config_apfDrop802_3Frames); + } + + /** + * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. + */ + public static @NonNull int[] getApfEtherTypeBlackList() { + return Resources.getSystem().getIntArray(R.array.config_apfEthTypeBlackList); + } +} diff --git a/framework/src/android/net/util/DnsUtils.java b/framework/src/android/net/util/DnsUtils.java new file mode 100644 index 0000000000..7908353eed --- /dev/null +++ b/framework/src/android/net/util/DnsUtils.java @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.util; + +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.system.OsConstants.IPPROTO_UDP; +import static android.system.OsConstants.SOCK_DGRAM; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.InetAddresses; +import android.net.Network; +import android.system.ErrnoException; +import android.system.Os; +import android.util.Log; + +import com.android.internal.util.BitUtils; + +import libcore.io.IoUtils; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * @hide + */ +public class DnsUtils { + private static final String TAG = "DnsUtils"; + private static final int CHAR_BIT = 8; + public static final int IPV6_ADDR_SCOPE_NODELOCAL = 0x01; + public static final int IPV6_ADDR_SCOPE_LINKLOCAL = 0x02; + public static final int IPV6_ADDR_SCOPE_SITELOCAL = 0x05; + public static final int IPV6_ADDR_SCOPE_GLOBAL = 0x0e; + private static final Comparator sRfc6724Comparator = new Rfc6724Comparator(); + + /** + * Comparator to sort SortableAddress in Rfc6724 style. + */ + public static class Rfc6724Comparator implements Comparator { + // This function matches the behaviour of _rfc6724_compare in the native resolver. + @Override + public int compare(SortableAddress span1, SortableAddress span2) { + // Rule 1: Avoid unusable destinations. + if (span1.hasSrcAddr != span2.hasSrcAddr) { + return span2.hasSrcAddr - span1.hasSrcAddr; + } + + // Rule 2: Prefer matching scope. + if (span1.scopeMatch != span2.scopeMatch) { + return span2.scopeMatch - span1.scopeMatch; + } + + // TODO: Implement rule 3: Avoid deprecated addresses. + // TODO: Implement rule 4: Prefer home addresses. + + // Rule 5: Prefer matching label. + if (span1.labelMatch != span2.labelMatch) { + return span2.labelMatch - span1.labelMatch; + } + + // Rule 6: Prefer higher precedence. + if (span1.precedence != span2.precedence) { + return span2.precedence - span1.precedence; + } + + // TODO: Implement rule 7: Prefer native transport. + + // Rule 8: Prefer smaller scope. + if (span1.scope != span2.scope) { + return span1.scope - span2.scope; + } + + // Rule 9: Use longest matching prefix. IPv6 only. + if (span1.prefixMatchLen != span2.prefixMatchLen) { + return span2.prefixMatchLen - span1.prefixMatchLen; + } + + // Rule 10: Leave the order unchanged. Collections.sort is a stable sort. + return 0; + } + } + + /** + * Class used to sort with RFC 6724 + */ + public static class SortableAddress { + public final int label; + public final int labelMatch; + public final int scope; + public final int scopeMatch; + public final int precedence; + public final int prefixMatchLen; + public final int hasSrcAddr; + public final InetAddress address; + + public SortableAddress(@NonNull InetAddress addr, @Nullable InetAddress srcAddr) { + address = addr; + hasSrcAddr = (srcAddr != null) ? 1 : 0; + label = findLabel(addr); + scope = findScope(addr); + precedence = findPrecedence(addr); + labelMatch = ((srcAddr != null) && (label == findLabel(srcAddr))) ? 1 : 0; + scopeMatch = ((srcAddr != null) && (scope == findScope(srcAddr))) ? 1 : 0; + if (isIpv6Address(addr) && isIpv6Address(srcAddr)) { + prefixMatchLen = compareIpv6PrefixMatchLen(srcAddr, addr); + } else { + prefixMatchLen = 0; + } + } + } + + /** + * Sort the given address list in RFC6724 order. + * Will leave the list unchanged if an error occurs. + * + * This function matches the behaviour of _rfc6724_sort in the native resolver. + */ + public static @NonNull List rfc6724Sort(@Nullable Network network, + @NonNull List answers) { + final ArrayList sortableAnswerList = new ArrayList<>(); + for (InetAddress addr : answers) { + sortableAnswerList.add(new SortableAddress(addr, findSrcAddress(network, addr))); + } + + Collections.sort(sortableAnswerList, sRfc6724Comparator); + + final List sortedAnswers = new ArrayList<>(); + for (SortableAddress ans : sortableAnswerList) { + sortedAnswers.add(ans.address); + } + + return sortedAnswers; + } + + private static @Nullable InetAddress findSrcAddress(@Nullable Network network, + @NonNull InetAddress addr) { + final int domain; + if (isIpv4Address(addr)) { + domain = AF_INET; + } else if (isIpv6Address(addr)) { + domain = AF_INET6; + } else { + return null; + } + final FileDescriptor socket; + try { + socket = Os.socket(domain, SOCK_DGRAM, IPPROTO_UDP); + } catch (ErrnoException e) { + Log.e(TAG, "findSrcAddress:" + e.toString()); + return null; + } + try { + if (network != null) network.bindSocket(socket); + Os.connect(socket, new InetSocketAddress(addr, 0)); + return ((InetSocketAddress) Os.getsockname(socket)).getAddress(); + } catch (IOException | ErrnoException e) { + return null; + } finally { + IoUtils.closeQuietly(socket); + } + } + + /** + * Get the label for a given IPv4/IPv6 address. + * RFC 6724, section 2.1. + * + * Note that Java will return an IPv4-mapped address as an IPv4 address. + */ + private static int findLabel(@NonNull InetAddress addr) { + if (isIpv4Address(addr)) { + return 4; + } else if (isIpv6Address(addr)) { + if (addr.isLoopbackAddress()) { + return 0; + } else if (isIpv6Address6To4(addr)) { + return 2; + } else if (isIpv6AddressTeredo(addr)) { + return 5; + } else if (isIpv6AddressULA(addr)) { + return 13; + } else if (((Inet6Address) addr).isIPv4CompatibleAddress()) { + return 3; + } else if (addr.isSiteLocalAddress()) { + return 11; + } else if (isIpv6Address6Bone(addr)) { + return 12; + } else { + // All other IPv6 addresses, including global unicast addresses. + return 1; + } + } else { + // This should never happen. + return 1; + } + } + + private static boolean isIpv6Address(@Nullable InetAddress addr) { + return addr instanceof Inet6Address; + } + + private static boolean isIpv4Address(@Nullable InetAddress addr) { + return addr instanceof Inet4Address; + } + + private static boolean isIpv6Address6To4(@NonNull InetAddress addr) { + if (!isIpv6Address(addr)) return false; + final byte[] byteAddr = addr.getAddress(); + return byteAddr[0] == 0x20 && byteAddr[1] == 0x02; + } + + private static boolean isIpv6AddressTeredo(@NonNull InetAddress addr) { + if (!isIpv6Address(addr)) return false; + final byte[] byteAddr = addr.getAddress(); + return byteAddr[0] == 0x20 && byteAddr[1] == 0x01 && byteAddr[2] == 0x00 + && byteAddr[3] == 0x00; + } + + private static boolean isIpv6AddressULA(@NonNull InetAddress addr) { + return isIpv6Address(addr) && (addr.getAddress()[0] & 0xfe) == 0xfc; + } + + private static boolean isIpv6Address6Bone(@NonNull InetAddress addr) { + if (!isIpv6Address(addr)) return false; + final byte[] byteAddr = addr.getAddress(); + return byteAddr[0] == 0x3f && byteAddr[1] == (byte) 0xfe; + } + + private static int getIpv6MulticastScope(@NonNull InetAddress addr) { + return !isIpv6Address(addr) ? 0 : (addr.getAddress()[1] & 0x0f); + } + + private static int findScope(@NonNull InetAddress addr) { + if (isIpv6Address(addr)) { + if (addr.isMulticastAddress()) { + return getIpv6MulticastScope(addr); + } else if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { + /** + * RFC 4291 section 2.5.3 says loopback is to be treated as having + * link-local scope. + */ + return IPV6_ADDR_SCOPE_LINKLOCAL; + } else if (addr.isSiteLocalAddress()) { + return IPV6_ADDR_SCOPE_SITELOCAL; + } else { + return IPV6_ADDR_SCOPE_GLOBAL; + } + } else if (isIpv4Address(addr)) { + if (addr.isLoopbackAddress() || addr.isLinkLocalAddress()) { + return IPV6_ADDR_SCOPE_LINKLOCAL; + } else { + /** + * RFC 6724 section 3.2. Other IPv4 addresses, including private addresses + * and shared addresses (100.64.0.0/10), are assigned global scope. + */ + return IPV6_ADDR_SCOPE_GLOBAL; + } + } else { + /** + * This should never happen. + * Return a scope with low priority as a last resort. + */ + return IPV6_ADDR_SCOPE_NODELOCAL; + } + } + + /** + * Get the precedence for a given IPv4/IPv6 address. + * RFC 6724, section 2.1. + * + * Note that Java will return an IPv4-mapped address as an IPv4 address. + */ + private static int findPrecedence(@NonNull InetAddress addr) { + if (isIpv4Address(addr)) { + return 35; + } else if (isIpv6Address(addr)) { + if (addr.isLoopbackAddress()) { + return 50; + } else if (isIpv6Address6To4(addr)) { + return 30; + } else if (isIpv6AddressTeredo(addr)) { + return 5; + } else if (isIpv6AddressULA(addr)) { + return 3; + } else if (((Inet6Address) addr).isIPv4CompatibleAddress() || addr.isSiteLocalAddress() + || isIpv6Address6Bone(addr)) { + return 1; + } else { + // All other IPv6 addresses, including global unicast addresses. + return 40; + } + } else { + return 1; + } + } + + /** + * Find number of matching initial bits between the two addresses. + */ + private static int compareIpv6PrefixMatchLen(@NonNull InetAddress srcAddr, + @NonNull InetAddress dstAddr) { + final byte[] srcByte = srcAddr.getAddress(); + final byte[] dstByte = dstAddr.getAddress(); + + // This should never happen. + if (srcByte.length != dstByte.length) return 0; + + for (int i = 0; i < dstByte.length; ++i) { + if (srcByte[i] == dstByte[i]) { + continue; + } + int x = BitUtils.uint8(srcByte[i]) ^ BitUtils.uint8(dstByte[i]); + return i * CHAR_BIT + (Integer.numberOfLeadingZeros(x) - 24); // Java ints are 32 bits + } + return dstByte.length * CHAR_BIT; + } + + /** + * Check if given network has Ipv4 capability + * This function matches the behaviour of have_ipv4 in the native resolver. + */ + public static boolean haveIpv4(@Nullable Network network) { + final SocketAddress addrIpv4 = + new InetSocketAddress(InetAddresses.parseNumericAddress("8.8.8.8"), 0); + return checkConnectivity(network, AF_INET, addrIpv4); + } + + /** + * Check if given network has Ipv6 capability + * This function matches the behaviour of have_ipv6 in the native resolver. + */ + public static boolean haveIpv6(@Nullable Network network) { + final SocketAddress addrIpv6 = + new InetSocketAddress(InetAddresses.parseNumericAddress("2000::"), 0); + return checkConnectivity(network, AF_INET6, addrIpv6); + } + + private static boolean checkConnectivity(@Nullable Network network, + int domain, @NonNull SocketAddress addr) { + final FileDescriptor socket; + try { + socket = Os.socket(domain, SOCK_DGRAM, IPPROTO_UDP); + } catch (ErrnoException e) { + return false; + } + try { + if (network != null) network.bindSocket(socket); + Os.connect(socket, addr); + } catch (IOException | ErrnoException e) { + return false; + } finally { + IoUtils.closeQuietly(socket); + } + return true; + } +} diff --git a/framework/src/android/net/util/KeepaliveUtils.java b/framework/src/android/net/util/KeepaliveUtils.java new file mode 100644 index 0000000000..bfc4563fbf --- /dev/null +++ b/framework/src/android/net/util/KeepaliveUtils.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.util; + +import android.annotation.NonNull; +import android.content.Context; +import android.content.res.Resources; +import android.net.NetworkCapabilities; +import android.text.TextUtils; +import android.util.AndroidRuntimeException; + +import com.android.internal.R; + +/** + * Collection of utilities for socket keepalive offload. + * + * @hide + */ +public final class KeepaliveUtils { + + public static final String TAG = "KeepaliveUtils"; + + public static class KeepaliveDeviceConfigurationException extends AndroidRuntimeException { + public KeepaliveDeviceConfigurationException(final String msg) { + super(msg); + } + } + + /** + * Read supported keepalive count for each transport type from overlay resource. This should be + * used to create a local variable store of resource customization, and use it as the input for + * {@link getSupportedKeepalivesForNetworkCapabilities}. + * + * @param context The context to read resource from. + * @return An array of supported keepalive count for each transport type. + */ + @NonNull + public static int[] getSupportedKeepalives(@NonNull Context context) { + String[] res = null; + try { + res = context.getResources().getStringArray( + R.array.config_networkSupportedKeepaliveCount); + } catch (Resources.NotFoundException unused) { + } + if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource"); + + final int[] ret = new int[NetworkCapabilities.MAX_TRANSPORT + 1]; + for (final String row : res) { + if (TextUtils.isEmpty(row)) { + throw new KeepaliveDeviceConfigurationException("Empty string"); + } + final String[] arr = row.split(","); + if (arr.length != 2) { + throw new KeepaliveDeviceConfigurationException("Invalid parameter length"); + } + + int transport; + int supported; + try { + transport = Integer.parseInt(arr[0]); + supported = Integer.parseInt(arr[1]); + } catch (NumberFormatException e) { + throw new KeepaliveDeviceConfigurationException("Invalid number format"); + } + + if (!NetworkCapabilities.isValidTransport(transport)) { + throw new KeepaliveDeviceConfigurationException("Invalid transport " + transport); + } + + if (supported < 0) { + throw new KeepaliveDeviceConfigurationException( + "Invalid supported count " + supported + " for " + + NetworkCapabilities.transportNameOf(transport)); + } + ret[transport] = supported; + } + return ret; + } + + /** + * Get supported keepalive count for the given {@link NetworkCapabilities}. + * + * @param supportedKeepalives An array of supported keepalive count for each transport type. + * @param nc The {@link NetworkCapabilities} of the network the socket keepalive is on. + * + * @return Supported keepalive count for the given {@link NetworkCapabilities}. + */ + public static int getSupportedKeepalivesForNetworkCapabilities( + @NonNull int[] supportedKeepalives, @NonNull NetworkCapabilities nc) { + final int[] transports = nc.getTransportTypes(); + if (transports.length == 0) return 0; + int supportedCount = supportedKeepalives[transports[0]]; + // Iterate through transports and return minimum supported value. + for (final int transport : transports) { + if (supportedCount > supportedKeepalives[transport]) { + supportedCount = supportedKeepalives[transport]; + } + } + return supportedCount; + } +} diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java new file mode 100644 index 0000000000..85e3fa3048 --- /dev/null +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.util; + +import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI; +import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; + +import android.annotation.NonNull; +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.provider.Settings; +import android.telephony.PhoneStateListener; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.util.Log; + +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; + +import java.util.Arrays; +import java.util.List; + +/** + * A class to encapsulate management of the "Smart Networking" capability of + * avoiding bad Wi-Fi when, for example upstream connectivity is lost or + * certain critical link failures occur. + * + * This enables the device to switch to another form of connectivity, like + * mobile, if it's available and working. + * + * The Runnable |avoidBadWifiCallback|, if given, is posted to the supplied + * Handler' whenever the computed "avoid bad wifi" value changes. + * + * Disabling this reverts the device to a level of networking sophistication + * circa 2012-13 by disabling disparate code paths each of which contribute to + * maintaining continuous, working Internet connectivity. + * + * @hide + */ +public class MultinetworkPolicyTracker { + private static String TAG = MultinetworkPolicyTracker.class.getSimpleName(); + + private final Context mContext; + private final Handler mHandler; + private final Runnable mAvoidBadWifiCallback; + private final List mSettingsUris; + private final ContentResolver mResolver; + private final SettingObserver mSettingObserver; + private final BroadcastReceiver mBroadcastReceiver; + + private volatile boolean mAvoidBadWifi = true; + private volatile int mMeteredMultipathPreference; + private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + + public MultinetworkPolicyTracker(Context ctx, Handler handler) { + this(ctx, handler, null); + } + + public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) { + mContext = ctx; + mHandler = handler; + mAvoidBadWifiCallback = avoidBadWifiCallback; + mSettingsUris = Arrays.asList( + Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), + Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); + mResolver = mContext.getContentResolver(); + mSettingObserver = new SettingObserver(); + mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + reevaluateInternal(); + } + }; + + ctx.getSystemService(TelephonyManager.class).listen( + new PhoneStateListener(handler.getLooper()) { + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + mActiveSubId = subId; + reevaluateInternal(); + } + }, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); + + updateAvoidBadWifi(); + updateMeteredMultipathPreference(); + } + + public void start() { + for (Uri uri : mSettingsUris) { + mResolver.registerContentObserver(uri, false, mSettingObserver); + } + + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + mContext.registerReceiverForAllUsers(mBroadcastReceiver, intentFilter, + null /* broadcastPermission */, mHandler); + + reevaluate(); + } + + public void shutdown() { + mResolver.unregisterContentObserver(mSettingObserver); + + mContext.unregisterReceiver(mBroadcastReceiver); + } + + public boolean getAvoidBadWifi() { + return mAvoidBadWifi; + } + + // TODO: move this to MultipathPolicyTracker. + public int getMeteredMultipathPreference() { + return mMeteredMultipathPreference; + } + + /** + * Whether the device or carrier configuration disables avoiding bad wifi by default. + */ + public boolean configRestrictsAvoidBadWifi() { + return (getResourcesForActiveSubId().getInteger(R.integer.config_networkAvoidBadWifi) == 0); + } + + @NonNull + private Resources getResourcesForActiveSubId() { + return SubscriptionManager.getResourcesForSubId(mContext, mActiveSubId); + } + + /** + * Whether we should display a notification when wifi becomes unvalidated. + */ + public boolean shouldNotifyWifiUnvalidated() { + return configRestrictsAvoidBadWifi() && getAvoidBadWifiSetting() == null; + } + + public String getAvoidBadWifiSetting() { + return Settings.Global.getString(mResolver, NETWORK_AVOID_BAD_WIFI); + } + + @VisibleForTesting + public void reevaluate() { + mHandler.post(this::reevaluateInternal); + } + + /** + * Reevaluate the settings. Must be called on the handler thread. + */ + private void reevaluateInternal() { + if (updateAvoidBadWifi() && mAvoidBadWifiCallback != null) { + mAvoidBadWifiCallback.run(); + } + updateMeteredMultipathPreference(); + } + + public boolean updateAvoidBadWifi() { + final boolean settingAvoidBadWifi = "1".equals(getAvoidBadWifiSetting()); + final boolean prev = mAvoidBadWifi; + mAvoidBadWifi = settingAvoidBadWifi || !configRestrictsAvoidBadWifi(); + return mAvoidBadWifi != prev; + } + + /** + * The default (device and carrier-dependent) value for metered multipath preference. + */ + public int configMeteredMultipathPreference() { + return mContext.getResources().getInteger( + R.integer.config_networkMeteredMultipathPreference); + } + + public void updateMeteredMultipathPreference() { + String setting = Settings.Global.getString(mResolver, NETWORK_METERED_MULTIPATH_PREFERENCE); + try { + mMeteredMultipathPreference = Integer.parseInt(setting); + } catch (NumberFormatException e) { + mMeteredMultipathPreference = configMeteredMultipathPreference(); + } + } + + private class SettingObserver extends ContentObserver { + public SettingObserver() { + super(null); + } + + @Override + public void onChange(boolean selfChange) { + Log.wtf(TAG, "Should never be reached."); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + if (!mSettingsUris.contains(uri)) { + Log.wtf(TAG, "Unexpected settings observation: " + uri); + } + reevaluate(); + } + } +} diff --git a/framework/src/android/net/util/SocketUtils.java b/framework/src/android/net/util/SocketUtils.java new file mode 100644 index 0000000000..e64060f1b2 --- /dev/null +++ b/framework/src/android/net/util/SocketUtils.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.util; + +import static android.system.OsConstants.SOL_SOCKET; +import static android.system.OsConstants.SO_BINDTODEVICE; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.NetworkUtils; +import android.system.ErrnoException; +import android.system.NetlinkSocketAddress; +import android.system.Os; +import android.system.PacketSocketAddress; + +import libcore.io.IoBridge; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.net.SocketAddress; + +/** + * Collection of utilities to interact with raw sockets. + * @hide + */ +@SystemApi +public final class SocketUtils { + /** + * Create a raw datagram socket that is bound to an interface. + * + *

Data sent through the socket will go directly to the underlying network, ignoring VPNs. + */ + public static void bindSocketToInterface(@NonNull FileDescriptor socket, @NonNull String iface) + throws ErrnoException { + // SO_BINDTODEVICE actually takes a string. This works because the first member + // of struct ifreq is a NULL-terminated interface name. + // TODO: add a setsockoptString() + Os.setsockoptIfreq(socket, SOL_SOCKET, SO_BINDTODEVICE, iface); + NetworkUtils.protectFromVpn(socket); + } + + /** + * Make a socket address to communicate with netlink. + */ + @NonNull + public static SocketAddress makeNetlinkSocketAddress(int portId, int groupsMask) { + return new NetlinkSocketAddress(portId, groupsMask); + } + + /** + * Make socket address that packet sockets can bind to. + * + * @param protocol the layer 2 protocol of the packets to receive. One of the {@code ETH_P_*} + * constants in {@link android.system.OsConstants}. + * @param ifIndex the interface index on which packets will be received. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + null /* sll_addr */); + } + + /** + * Make a socket address that packet socket can send packets to. + * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead. + * + * @param ifIndex the interface index on which packets will be sent. + * @param hwAddr the hardware address to which packets will be sent. + */ + @Deprecated + @NonNull + public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + 0 /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + + /** + * Make a socket address that a packet socket can send packets to. + * + * @param protocol the layer 2 protocol of the packets to send. One of the {@code ETH_P_*} + * constants in {@link android.system.OsConstants}. + * @param ifIndex the interface index on which packets will be sent. + * @param hwAddr the hardware address to which packets will be sent. + */ + @NonNull + public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex, + @NonNull byte[] hwAddr) { + return new PacketSocketAddress( + protocol /* sll_protocol */, + ifIndex /* sll_ifindex */, + hwAddr /* sll_addr */); + } + + /** + * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor) + */ + public static void closeSocket(@Nullable FileDescriptor fd) throws IOException { + IoBridge.closeAndSignalBlockedThreads(fd); + } + + private SocketUtils() {} +} From 91444cae5662c194f82184e4a73e19eb1cbc66d5 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 15 Jan 2021 23:02:47 +0900 Subject: [PATCH 010/343] Have connectivity self-register manager classes As connectivity services are planned to move to a separate module, move the manager classes registration from SystemServiceRegistry to ConnectivityServicesRegistrar, using the registerContextAwareService APIs. This follows patterns and naming in WifiFrameworkInitializer. Bug: 171540887 Test: device boots, connectivity working Change-Id: I62ced1275750c73f209bac8ec3a3204b95695b83 --- .../net/ConnectivityFrameworkInitializer.java | 83 +++++++++++++++++++ .../src/android/net/ConnectivityManager.java | 22 +++++ 2 files changed, 105 insertions(+) create mode 100644 framework/src/android/net/ConnectivityFrameworkInitializer.java diff --git a/framework/src/android/net/ConnectivityFrameworkInitializer.java b/framework/src/android/net/ConnectivityFrameworkInitializer.java new file mode 100644 index 0000000000..9afa5d1311 --- /dev/null +++ b/framework/src/android/net/ConnectivityFrameworkInitializer.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; +import android.app.SystemServiceRegistry; +import android.content.Context; + +/** + * Class for performing registration for all core connectivity services. + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class ConnectivityFrameworkInitializer { + private ConnectivityFrameworkInitializer() {} + + /** + * Called by {@link SystemServiceRegistry}'s static initializer and registers all core + * connectivity services to {@link Context}, so that {@link Context#getSystemService} can + * return them. + * + * @throws IllegalStateException if this is called anywhere besides + * {@link SystemServiceRegistry}. + */ + public static void registerServiceWrappers() { + // registerContextAwareService will throw if this is called outside of SystemServiceRegistry + // initialization. + SystemServiceRegistry.registerContextAwareService( + Context.CONNECTIVITY_SERVICE, + ConnectivityManager.class, + (context, serviceBinder) -> { + IConnectivityManager icm = IConnectivityManager.Stub.asInterface(serviceBinder); + return new ConnectivityManager(context, icm); + } + ); + + // TODO: move outside of the connectivity JAR + SystemServiceRegistry.registerContextAwareService( + Context.VPN_MANAGEMENT_SERVICE, + VpnManager.class, + (context) -> { + final ConnectivityManager cm = context.getSystemService( + ConnectivityManager.class); + return cm.createVpnManager(); + } + ); + + SystemServiceRegistry.registerContextAwareService( + Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, + ConnectivityDiagnosticsManager.class, + (context) -> { + final ConnectivityManager cm = context.getSystemService( + ConnectivityManager.class); + return cm.createDiagnosticsManager(); + } + ); + + SystemServiceRegistry.registerContextAwareService( + Context.TEST_NETWORK_SERVICE, + TestNetworkManager.class, + context -> { + final ConnectivityManager cm = context.getSystemService( + ConnectivityManager.class); + return cm.startOrGetTestNetworkManager(); + } + ); + } +} diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 7f07bba668..987dcc4898 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4823,6 +4823,28 @@ public class ConnectivityManager { } } + /** @hide */ + public TestNetworkManager startOrGetTestNetworkManager() { + final IBinder tnBinder; + try { + tnBinder = mService.startOrGetTestNetworkService(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); + } + + /** @hide */ + public VpnManager createVpnManager() { + return new VpnManager(mContext, mService); + } + + /** @hide */ + public ConnectivityDiagnosticsManager createDiagnosticsManager() { + return new ConnectivityDiagnosticsManager(mContext, mService); + } + /** * Simulates a Data Stall for the specified Network. * From 3c2297a2ab1ac0dfce2e351bc8dbd9881a2059e5 Mon Sep 17 00:00:00 2001 From: paulhu Date: Mon, 1 Feb 2021 16:30:08 +0800 Subject: [PATCH 011/343] Remove ArrayUtils usage in connectivity frameworks classes Instead, use CollectionUtils from frameworks/libs/net. Bug: 174541037 Test: atest FrameworksNetTests Change-Id: I610e00302cf76510e9e34ac8a9a5f738e5ecd0c7 --- framework/src/android/net/NetworkCapabilities.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 3843b9ab93..0832152d6a 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -34,9 +34,9 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; +import com.android.net.module.util.CollectionUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -767,7 +767,7 @@ public final class NetworkCapabilities implements Parcelable { if (originalOwnerUid == creatorUid) { setOwnerUid(creatorUid); } - if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) { + if (CollectionUtils.contains(originalAdministratorUids, creatorUid)) { setAdministratorUids(new int[] {creatorUid}); } // There is no need to clear the UIDs, they have already been cleared by clearAll() above. @@ -1873,7 +1873,7 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" OwnerUid: ").append(mOwnerUid); } - if (!ArrayUtils.isEmpty(mAdministratorUids)) { + if (mAdministratorUids != null && mAdministratorUids.length != 0) { sb.append(" AdminUids: ").append(Arrays.toString(mAdministratorUids)); } @@ -2506,7 +2506,7 @@ public final class NetworkCapabilities implements Parcelable { @NonNull public NetworkCapabilities build() { if (mCaps.getOwnerUid() != Process.INVALID_UID) { - if (!ArrayUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { + if (!CollectionUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { throw new IllegalStateException("The owner UID must be included in " + " administrator UIDs."); } From 515b26ae980b83ad9864bedd468a90937f457e33 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Fri, 29 Jan 2021 12:15:00 +0100 Subject: [PATCH 012/343] API: Suppress existing NullableCollections lints Bug: 152525509 Bug: 154763999 Test: make checkapi Change-Id: Iecd0927e6be5496b2fbd1a49396db5439257ffe4 --- framework/src/android/net/NetworkAgent.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index d22d82d1f4..27aa15d1e1 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -775,7 +776,8 @@ public abstract class NetworkAgent { * @param underlyingNetworks the new list of underlying networks. * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])} */ - public final void setUnderlyingNetworks(@Nullable List underlyingNetworks) { + public final void setUnderlyingNetworks( + @SuppressLint("NullableCollection") @Nullable List underlyingNetworks) { final ArrayList underlyingArray = (underlyingNetworks != null) ? new ArrayList<>(underlyingNetworks) : null; queueOrSendMessage(reg -> reg.sendUnderlyingNetworks(underlyingArray)); From d5c54eca669bb186e7a737c0a1f6188efee23229 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 29 Jan 2021 00:25:31 +0800 Subject: [PATCH 013/343] [VCN08] Expose NOT_VCN_MANAGED capability as system API Test: m -j doc-comment-check-docs Fix: 177299683 Bug: 175662146 Change-Id: Iaa53d21774ea48af5fe339b57bf1235c77f295a0 --- framework/src/android/net/NetworkCapabilities.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 3843b9ab93..e9b9a9362f 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -401,11 +401,18 @@ public final class NetworkCapabilities implements Parcelable { public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; /** - * Indicates that this network is not managed by a Virtual Carrier Network (VCN). - * - * TODO(b/177299683): Add additional clarifying javadoc. + * Indicates that this network is not subsumed by a Virtual Carrier Network (VCN). + *

+ * To provide an experience on a VCN similar to a single traditional carrier network, in + * some cases the system sets this bit is set by default in application's network requests, + * and may choose to remove it at its own discretion when matching the request to a network. + *

+ * Applications that want to know about a Virtual Carrier Network's underlying networks, + * for example to use them for multipath purposes, should remove this bit from their network + * requests ; the system will not add it back once removed. * @hide */ + @SystemApi public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; From f4a7b149c1bd3d0951b58652038f6e5c0e91d40d Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 2 Feb 2021 12:57:26 +0800 Subject: [PATCH 014/343] Reimplement [read|write]ArraySet of Parcel inside NetworkCapabilities Both of readArraySet and writeArraySet are hidden APIs inside Parcel, so reimplement those two methods inside NetworkCapabilities to prevent calling hidden APIs. Bug: 170598012 Test: atest FrameworksNetTests Change-Id: I70f75c1a0db92c6a5575c6a9917843d783dfaeea --- .../src/android/net/NetworkCapabilities.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 3843b9ab93..a9fd38198b 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -1779,6 +1779,15 @@ public final class NetworkCapabilities implements Parcelable { return 0; } + private void writeParcelableArraySet(Parcel in, + @Nullable ArraySet val, int flags) { + final int size = (val != null) ? val.size() : -1; + in.writeInt(size); + for (int i = 0; i < size; i++) { + in.writeParcelable(val.valueAt(i), flags); + } + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(mNetworkCapabilities); @@ -1789,7 +1798,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeParcelable((Parcelable) mNetworkSpecifier, flags); dest.writeParcelable((Parcelable) mTransportInfo, flags); dest.writeInt(mSignalStrength); - dest.writeArraySet(mUids); + writeParcelableArraySet(dest, mUids, flags); dest.writeString(mSSID); dest.writeBoolean(mPrivateDnsBroken); dest.writeIntArray(getAdministratorUids()); @@ -1812,8 +1821,7 @@ public final class NetworkCapabilities implements Parcelable { netCap.mNetworkSpecifier = in.readParcelable(null); netCap.mTransportInfo = in.readParcelable(null); netCap.mSignalStrength = in.readInt(); - netCap.mUids = (ArraySet) in.readArraySet( - null /* ClassLoader, null for default */); + netCap.mUids = readParcelableArraySet(in, null /* ClassLoader, null for default */); netCap.mSSID = in.readString(); netCap.mPrivateDnsBroken = in.readBoolean(); netCap.setAdministratorUids(in.createIntArray()); @@ -1826,6 +1834,20 @@ public final class NetworkCapabilities implements Parcelable { public NetworkCapabilities[] newArray(int size) { return new NetworkCapabilities[size]; } + + private @Nullable ArraySet readParcelableArraySet(Parcel in, + @Nullable ClassLoader loader) { + final int size = in.readInt(); + if (size < 0) { + return null; + } + final ArraySet result = new ArraySet<>(size); + for (int i = 0; i < size; i++) { + final T value = in.readParcelable(loader); + result.append(value); + } + return result; + } }; @Override From 8a831d6e0700bed44e1f8f518475d4a85092ea4a Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 3 Feb 2021 10:18:20 +0900 Subject: [PATCH 015/343] Use formal API for ActivityThread to set proxy Add getProxyForNetwork to the public API, and use ConnectivityManager APIs from ActivityThread (instead of hidden APIs) to get/set the proxy for an app process. getProxyForNetwork allows clients to find which proxy applies, which can be a global proxy setting or a per-network proxy. The default proxy is now initialized with getDefaultProxy instead of getProxyForNetwork(null); this should not make a difference, as nothing should have called bindProcessToNetwork at that point yet. Bug: 174436414 Test: m; device boots Change-Id: Ifb516194ecde1567cea4b6806946091cdcf2f015 --- .../src/android/net/ConnectivityManager.java | 2 +- framework/src/android/net/Proxy.java | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 2a0a74ed06..2716e092c6 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4609,7 +4609,7 @@ public class ConnectivityManager { // Set HTTP proxy system properties to match network. // TODO: Deprecate this static method and replace it with a non-static version. try { - Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy()); + Proxy.setHttpProxyConfiguration(getInstance().getDefaultProxy()); } catch (SecurityException e) { // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy. Log.e(TAG, "Can't set proxy properties", e); diff --git a/framework/src/android/net/Proxy.java b/framework/src/android/net/Proxy.java index 03b07e080a..03cfbbb4a2 100644 --- a/framework/src/android/net/Proxy.java +++ b/framework/src/android/net/Proxy.java @@ -16,8 +16,10 @@ package android.net; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; @@ -245,7 +247,19 @@ public final class Proxy { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final void setHttpProxySystemProperty(ProxyInfo p) { + @Deprecated + public static void setHttpProxySystemProperty(ProxyInfo p) { + setHttpProxyConfiguration(p); + } + + /** + * Set HTTP proxy configuration for the process to match the provided ProxyInfo. + * + * If the provided ProxyInfo is null, the proxy configuration will be cleared. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static void setHttpProxyConfiguration(@Nullable ProxyInfo p) { String host = null; String port = null; String exclList = null; @@ -256,11 +270,11 @@ public final class Proxy { exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); pacFileUrl = p.getPacFileUrl(); } - setHttpProxySystemProperty(host, port, exclList, pacFileUrl); + setHttpProxyConfiguration(host, port, exclList, pacFileUrl); } /** @hide */ - public static final void setHttpProxySystemProperty(String host, String port, String exclList, + public static void setHttpProxyConfiguration(String host, String port, String exclList, Uri pacFileUrl) { if (exclList != null) exclList = exclList.replace(",", "|"); if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); From a858d3bfebb4c61bb1dac771f0a0053c54e0f349 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 3 Feb 2021 18:40:42 +0800 Subject: [PATCH 016/343] Move shared methods to net shared lib The NetworkUtils.getNetworkPart() method is used by Settings and wifi. NetworkUtils is inside the incoming connectivity module. It will become inaccessible outside the module, so move the shared methods to shared lib and also move the related helper method. The corresponding usgae is also updated. Bug: 172183305 Test: atest FrameworksNetTests Change-Id: I47410afa27aad61f63759df41be959f323c1d100 --- framework/src/android/net/IpPrefix.java | 8 ++-- framework/src/android/net/NetworkUtils.java | 41 --------------------- 2 files changed, 5 insertions(+), 44 deletions(-) diff --git a/framework/src/android/net/IpPrefix.java b/framework/src/android/net/IpPrefix.java index e7c801475c..e970065e8f 100644 --- a/framework/src/android/net/IpPrefix.java +++ b/framework/src/android/net/IpPrefix.java @@ -23,6 +23,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.Pair; +import com.android.net.module.util.NetUtils; + import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -58,7 +60,7 @@ public final class IpPrefix implements Parcelable { throw new IllegalArgumentException( "IpPrefix has " + address.length + " bytes which is neither 4 nor 16"); } - NetworkUtils.maskRawAddress(address, prefixLength); + NetUtils.maskRawAddress(address, prefixLength); } /** @@ -189,7 +191,7 @@ public final class IpPrefix implements Parcelable { if (addrBytes == null || addrBytes.length != this.address.length) { return false; } - NetworkUtils.maskRawAddress(addrBytes, prefixLength); + NetUtils.maskRawAddress(addrBytes, prefixLength); return Arrays.equals(this.address, addrBytes); } @@ -203,7 +205,7 @@ public final class IpPrefix implements Parcelable { public boolean containsPrefix(@NonNull IpPrefix otherPrefix) { if (otherPrefix.getPrefixLength() < prefixLength) return false; final byte[] otherAddress = otherPrefix.getRawAddress(); - NetworkUtils.maskRawAddress(otherAddress, prefixLength); + NetUtils.maskRawAddress(otherAddress, prefixLength); return Arrays.equals(otherAddress, address); } diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java index 8be4af7b13..9ccb04a44a 100644 --- a/framework/src/android/net/NetworkUtils.java +++ b/framework/src/android/net/NetworkUtils.java @@ -29,7 +29,6 @@ import java.math.BigInteger; import java.net.Inet4Address; import java.net.InetAddress; import java.net.SocketException; -import java.net.UnknownHostException; import java.util.Locale; import java.util.TreeSet; @@ -231,46 +230,6 @@ public class NetworkUtils { return InetAddress.parseNumericAddress(addrString); } - /** - * Masks a raw IP address byte array with the specified prefix length. - */ - public static void maskRawAddress(byte[] array, int prefixLength) { - if (prefixLength < 0 || prefixLength > array.length * 8) { - throw new RuntimeException("IP address with " + array.length + - " bytes has invalid prefix length " + prefixLength); - } - - int offset = prefixLength / 8; - int remainder = prefixLength % 8; - byte mask = (byte)(0xFF << (8 - remainder)); - - if (offset < array.length) array[offset] = (byte)(array[offset] & mask); - - offset++; - - for (; offset < array.length; offset++) { - array[offset] = 0; - } - } - - /** - * Get InetAddress masked with prefixLength. Will never return null. - * @param address the IP address to mask with - * @param prefixLength the prefixLength used to mask the IP - */ - public static InetAddress getNetworkPart(InetAddress address, int prefixLength) { - byte[] array = address.getAddress(); - maskRawAddress(array, prefixLength); - - InetAddress netPart = null; - try { - netPart = InetAddress.getByAddress(array); - } catch (UnknownHostException e) { - throw new RuntimeException("getNetworkPart error - " + e.toString()); - } - return netPart; - } - /** * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. */ From 470efc161d61fbd9843288f1895e5f17226baa26 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 18:04:43 +0900 Subject: [PATCH 017/343] Remove legacy network factories Nothing on the system is using registerNetworkFactory, unregisterNetworkFactory at the moment. registerNetworkFactory, unregisterNetworkFactory are protected by signature permissions, so could not be used by anything outside of the system. Remove the two methods and the underlying support for this legacy, deprecated mechanism. Bug: 179229316 Test: atest FrameworksNetTests Change-Id: I7cdc9eed67f846c8774474af038133040aeccab3 --- .../src/android/net/ConnectivityManager.java | 26 ------------------- .../src/android/net/IConnectivityManager.aidl | 3 --- 2 files changed, 29 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 987dcc4898..06dec9335d 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -3231,32 +3231,6 @@ public class ConnectivityManager { } } - /** {@hide} - returns the factory serial number */ - @UnsupportedAppUsage - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public int registerNetworkFactory(Messenger messenger, String name) { - try { - return mService.registerNetworkFactory(messenger, name); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** {@hide} */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public void unregisterNetworkFactory(Messenger messenger) { - try { - mService.unregisterNetworkFactory(messenger); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - /** * Registers the specified {@link NetworkProvider}. * Each listener must only be registered once. The listener can be unregistered with diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 1b4d2e4139..db8b7ed3b1 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -156,9 +156,6 @@ interface IConnectivityManager boolean requestBandwidthUpdate(in Network network); - int registerNetworkFactory(in Messenger messenger, in String name); - void unregisterNetworkFactory(in Messenger messenger); - int registerNetworkProvider(in Messenger messenger, in String name); void unregisterNetworkProvider(in Messenger messenger); From 062b6480995ba69faa8b4c8bab08e2b01137fa4a Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 13 Jan 2021 18:13:11 +0800 Subject: [PATCH 018/343] [VCN07] Bypass VCN for non-internet app accessible cellular services Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities and user intention, which includes: 1. For the requests that don't have anything besides VCN_SUPPORTED_CAPABILITIES, add the NOT_VCN_MANAGED to allow the callers automatically utilize VCN networks if available. 2. For the requests that explicitly add or remove NOT_VCN_MANAGED, do not alter them to allow user fire request that suits their need. Test: atest NetworkRequestTest#testBypassingVcnForNonInternetRequest Bug: 175662146 Change-Id: I9936894b9530a22fb186cfd25cbee0fced65b72b --- framework/src/android/net/NetworkRequest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 04011fc681..9883692e7d 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -16,6 +16,22 @@ package android.net; +import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +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_RESTRICTED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -30,6 +46,8 @@ import android.os.Process; import android.text.TextUtils; import android.util.proto.ProtoOutputStream; +import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -156,8 +174,30 @@ public class NetworkRequest implements Parcelable { * needed in terms of {@link NetworkCapabilities} features */ public static class Builder { + /** + * Capabilities that are currently compatible with VCN networks. + */ + private static final List VCN_SUPPORTED_CAPABILITIES = Arrays.asList( + NET_CAPABILITY_CAPTIVE_PORTAL, + NET_CAPABILITY_DUN, + NET_CAPABILITY_FOREGROUND, + NET_CAPABILITY_INTERNET, + NET_CAPABILITY_NOT_CONGESTED, + NET_CAPABILITY_NOT_METERED, + NET_CAPABILITY_NOT_RESTRICTED, + NET_CAPABILITY_NOT_ROAMING, + NET_CAPABILITY_NOT_SUSPENDED, + NET_CAPABILITY_NOT_VPN, + NET_CAPABILITY_PARTIAL_CONNECTIVITY, + NET_CAPABILITY_TEMPORARILY_NOT_METERED, + NET_CAPABILITY_TRUSTED, + NET_CAPABILITY_VALIDATED); + private final NetworkCapabilities mNetworkCapabilities; + // A boolean that represents the user modified NOT_VCN_MANAGED capability. + private boolean mModifiedNotVcnManaged = false; + /** * Default constructor for Builder. */ @@ -179,6 +219,7 @@ public class NetworkRequest implements Parcelable { // maybeMarkCapabilitiesRestricted() doesn't add back. final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); nc.maybeMarkCapabilitiesRestricted(); + deduceNotVcnManagedCapability(nc); return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); } @@ -195,6 +236,9 @@ public class NetworkRequest implements Parcelable { */ public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addCapability(capability); + if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { + mModifiedNotVcnManaged = true; + } return this; } @@ -206,6 +250,9 @@ public class NetworkRequest implements Parcelable { */ public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.removeCapability(capability); + if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { + mModifiedNotVcnManaged = true; + } return this; } @@ -263,6 +310,9 @@ public class NetworkRequest implements Parcelable { @NonNull public Builder clearCapabilities() { mNetworkCapabilities.clearAll(); + // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities + // should not be add back later. + mModifiedNotVcnManaged = true; return this; } @@ -382,6 +432,25 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.setSignalStrength(signalStrength); return this; } + + /** + * Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities + * and user intention, which includes: + * 1. For the requests that don't have anything besides + * {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to + * allow the callers automatically utilize VCN networks if available. + * 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED, + * do not alter them to allow user fire request that suits their need. + * + * @hide + */ + private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) { + if (mModifiedNotVcnManaged) return; + for (final int cap : nc.getCapabilities()) { + if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return; + } + nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); + } } // implement the Parcelable interface From 452c6ffa61c5d0a11c79e9311ce12b4da486e97b Mon Sep 17 00:00:00 2001 From: James Mattis Date: Fri, 1 Jan 2021 14:13:35 -0800 Subject: [PATCH 019/343] Stubbed setOemNetworkPreference in Connectivity Stubbed setOemNetworkPreference() in ConnectivityService and connected it to ConnectivityManager. Bug: 176495254 Bug: 176494815 Test: atest FrameworksNetTests atest FrameworksNetIntegrationTests atest CtsNetTestCasesLatestSdk Change-Id: Iabad7300a8b058e1edcb0defab8a031d21e6433c --- framework/src/android/net/ConnectivityManager.java | 10 +++++++--- framework/src/android/net/IConnectivityManager.aidl | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 987dcc4898..c162b4396e 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4871,9 +4871,13 @@ public class ConnectivityManager { } } - private void setOemNetworkPreference(@NonNull OemNetworkPreferences preference) { - Log.d(TAG, "setOemNetworkPreference called with preference: " - + preference.toString()); + private void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference) { + try { + mService.setOemNetworkPreference(preference); + } catch (RemoteException e) { + Log.e(TAG, "setOemNetworkPreference() failed for preference: " + preference.toString()); + throw e.rethrowFromSystemServer(); + } } @NonNull diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 1b4d2e4139..615f54dde9 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -29,6 +29,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.NetworkState; +import android.net.OemNetworkPreferences; import android.net.ProxyInfo; import android.net.UidRange; import android.net.QosSocketInfo; @@ -243,4 +244,6 @@ interface IConnectivityManager void registerQosSocketCallback(in QosSocketInfo socketInfo, in IQosCallback callback); void unregisterQosCallback(in IQosCallback callback); + + void setOemNetworkPreference(in OemNetworkPreferences preference); } From 0b6f2908c5411aa8d39ad7aab1b10a398c7535dc Mon Sep 17 00:00:00 2001 From: Roman Kalukiewicz Date: Wed, 14 Oct 2020 15:59:06 -0700 Subject: [PATCH 020/343] Add @Nullable to Object#equals() This is a partial cherry-pick of change: I5eedb571c9d78862115dfdc5dae1cf2a35343580 for connectivity classes. Bug: 170883422 Test: m Merged-In: I5eedb571c9d78862115dfdc5dae1cf2a35343580 Change-Id: I7dc661863b73f4198ddb4f3a1566583d0f07db3c --- framework/src/android/net/CaptivePortalData.java | 2 +- framework/src/android/net/IpConfiguration.java | 2 +- framework/src/android/net/IpPrefix.java | 3 ++- framework/src/android/net/LinkAddress.java | 2 +- framework/src/android/net/LinkProperties.java | 2 +- framework/src/android/net/MacAddress.java | 2 +- framework/src/android/net/Network.java | 3 ++- framework/src/android/net/NetworkRequest.java | 2 +- framework/src/android/net/ProxyInfo.java | 2 +- framework/src/android/net/RouteInfo.java | 4 ++-- 10 files changed, 13 insertions(+), 11 deletions(-) diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java index 18467fad8e..9b56b23cc8 100644 --- a/framework/src/android/net/CaptivePortalData.java +++ b/framework/src/android/net/CaptivePortalData.java @@ -276,7 +276,7 @@ public final class CaptivePortalData implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof CaptivePortalData)) return false; final CaptivePortalData other = (CaptivePortalData) obj; return mRefreshTimeMillis == other.mRefreshTimeMillis diff --git a/framework/src/android/net/IpConfiguration.java b/framework/src/android/net/IpConfiguration.java index 0b205642b3..d5f8b2edb6 100644 --- a/framework/src/android/net/IpConfiguration.java +++ b/framework/src/android/net/IpConfiguration.java @@ -167,7 +167,7 @@ public final class IpConfiguration implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o == this) { return true; } diff --git a/framework/src/android/net/IpPrefix.java b/framework/src/android/net/IpPrefix.java index e7c801475c..bcb65fab85 100644 --- a/framework/src/android/net/IpPrefix.java +++ b/framework/src/android/net/IpPrefix.java @@ -18,6 +18,7 @@ package android.net; import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -124,7 +125,7 @@ public final class IpPrefix implements Parcelable { * @return {@code true} if both objects are equal, {@code false} otherwise. */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof IpPrefix)) { return false; } diff --git a/framework/src/android/net/LinkAddress.java b/framework/src/android/net/LinkAddress.java index 44d25a1ab0..d1bdaa078c 100644 --- a/framework/src/android/net/LinkAddress.java +++ b/framework/src/android/net/LinkAddress.java @@ -349,7 +349,7 @@ public class LinkAddress implements Parcelable { * @return {@code true} if both objects are equal, {@code false} otherwise. */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof LinkAddress)) { return false; } diff --git a/framework/src/android/net/LinkProperties.java b/framework/src/android/net/LinkProperties.java index 486e2d74dd..e41ed72b25 100644 --- a/framework/src/android/net/LinkProperties.java +++ b/framework/src/android/net/LinkProperties.java @@ -1613,7 +1613,7 @@ public final class LinkProperties implements Parcelable { * @return {@code true} if both objects are equal, {@code false} otherwise. */ @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof LinkProperties)) return false; diff --git a/framework/src/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java index c7116b41e8..c83c23a4b6 100644 --- a/framework/src/android/net/MacAddress.java +++ b/framework/src/android/net/MacAddress.java @@ -161,7 +161,7 @@ public final class MacAddress implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { return (o instanceof MacAddress) && ((MacAddress) o).mAddr == mAddr; } diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java index b07bd68a0f..46141e0d0c 100644 --- a/framework/src/android/net/Network.java +++ b/framework/src/android/net/Network.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; @@ -510,7 +511,7 @@ public class Network implements Parcelable { }; @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof Network)) return false; Network other = (Network)obj; return this.netId == other.netId; diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 04011fc681..c4d1b09a5c 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -567,7 +567,7 @@ public class NetworkRequest implements Parcelable { proto.end(token); } - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof NetworkRequest == false) return false; NetworkRequest that = (NetworkRequest)obj; return (that.legacyType == this.legacyType && diff --git a/framework/src/android/net/ProxyInfo.java b/framework/src/android/net/ProxyInfo.java index c9bca2876b..9c9fed1028 100644 --- a/framework/src/android/net/ProxyInfo.java +++ b/framework/src/android/net/ProxyInfo.java @@ -275,7 +275,7 @@ public class ProxyInfo implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!(o instanceof ProxyInfo)) return false; ProxyInfo p = (ProxyInfo)o; // If PAC URL is present in either then they must be equal. diff --git a/framework/src/android/net/RouteInfo.java b/framework/src/android/net/RouteInfo.java index 94f849f006..5b6684ace0 100644 --- a/framework/src/android/net/RouteInfo.java +++ b/framework/src/android/net/RouteInfo.java @@ -534,7 +534,7 @@ public final class RouteInfo implements Parcelable { * Compares this RouteInfo object against the specified object and indicates if they are equal. * @return {@code true} if the objects are equal, {@code false} otherwise. */ - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof RouteInfo)) return false; @@ -570,7 +570,7 @@ public final class RouteInfo implements Parcelable { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (!(o instanceof RouteKey)) { return false; } From 3d7a74f4d0ee0ce72c623faedbb7c0cf5970c0be Mon Sep 17 00:00:00 2001 From: lucaslin Date: Sat, 6 Feb 2021 17:02:21 +0800 Subject: [PATCH 021/343] Expose TEST_TAP_PREFIX as system API TestNetworkManager is a part of connectivity mainline module and it is already a system API, but its constant - TEST_TAP_PREFIX is hidden, so expose it for the callers inside framework. Bug: 172183305 Test: make update-api Change-Id: I7fc08be4a6ca6325d5b576b761afda17865cefaa --- framework/src/android/net/TestNetworkManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java index 4e894143bf..a174a7be85 100644 --- a/framework/src/android/net/TestNetworkManager.java +++ b/framework/src/android/net/TestNetworkManager.java @@ -41,7 +41,6 @@ public class TestNetworkManager { /** * Prefix for tap interfaces created by this class. - * @hide */ public static final String TEST_TAP_PREFIX = "testtap"; From 7a0f31b944d9a7825d2db704dddba780f8b08d84 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 29 Jan 2021 20:18:03 +0900 Subject: [PATCH 022/343] More cleanly separate requests and listens. Currently, NetworkRequest has several types of requests (LISTEN, TRACK_DEFAULT, REQUEST, BACKGROUND_REQUEST), and we expect more to be added. There are really three categories of request: 1. Requests satisfied by only one network and will keep that network up, and thus need to be sent to NetworkProviders: REQUEST, BACKGROUND_REQUEST. 2. Requests satisfied by only one network but will not keep that network up: TRACK_DEFAULT 3. Requests satisfied by multiple networks and will not keep any networks up: LISTEN. Unfortunately the separation is not very clear. Currently, for any valid request, either isListen() will return true or isRequest() will return true. This makes it impossible to tell whether a particular request should be sent to NetworkProviders, so the current code sends TRACK_DEFAULT requests to NetworkProviders as well. This is incorrect - a TRACK_DEFAULT should never keep a network up, for example. This CL attempts to clarify things by making isRequest() return false for TRACK_DEFAULT requests and thus never sending them to NetworkProviders. After this CL: - isRequest will return true only for requests that attempt to bring up or keep up a network. - isListen will return true only for requests that match multiple networks but do not keep any of them up. - Neither will return true for TRACK_DEFAULT. Test: atest ConnectivityServiceTest Change-Id: I7aad30ade8f7ab2a179e53483d9afd8675f64a12 --- framework/src/android/net/NetworkRequest.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index c4d1b09a5c..b9ef4c21ef 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -435,25 +435,7 @@ public class NetworkRequest implements Parcelable { * @hide */ public boolean isRequest() { - return isForegroundRequest() || isBackgroundRequest(); - } - - /** - * Returns true iff. the contained NetworkRequest is one that: - * - * - should be associated with at most one satisfying network - * at a time; - * - * - should cause a network to be kept up and in the foreground if - * it is the best network which can satisfy the NetworkRequest. - * - * For full detail of how isRequest() is used for pairing Networks with - * NetworkRequests read rematchNetworkAndRequests(). - * - * @hide - */ - public boolean isForegroundRequest() { - return type == Type.TRACK_DEFAULT || type == Type.REQUEST; + return type == Type.REQUEST || type == Type.BACKGROUND_REQUEST; } /** From d9a569fd4a0e635a68d6f57e70c7f77449569c73 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 5 Feb 2021 01:10:56 +0900 Subject: [PATCH 023/343] Add to VpnManager the VPN APIs used by Settings and SystemUI. Settings and SystemUI use these through raw AIDL calls. Make them proper manager calls so we can move the implementation without touching the callers again. For now these still call into ConnectivityService via IConnectivityManager. In an upcoming CL the implementation will move to VpnManagerService. Test: m Bug: 173331190 Change-Id: I91528e1ad9948fbaa1fc5e37c61c5eb95f54964e --- framework/src/android/net/VpnManager.java | 105 +++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java index c87b8279c4..1812509ba6 100644 --- a/framework/src/android/net/VpnManager.java +++ b/framework/src/android/net/VpnManager.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; import android.content.Context; @@ -28,6 +29,8 @@ import android.content.Intent; import android.content.res.Resources; import android.os.RemoteException; +import com.android.internal.net.LegacyVpnInfo; +import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import java.io.IOException; @@ -161,4 +164,104 @@ public class VpnManager { throw e.rethrowFromSystemServer(); } } -} + + /** + * Return the VPN configuration for the given user ID. + * @hide + */ + @Nullable + public VpnConfig getVpnConfig(@UserIdInt int userId) { + try { + return mService.getVpnConfig(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Prepare for a VPN application. + * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, + * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. + * + * @param oldPackage Package name of the application which currently controls VPN, which will + * be replaced. If there is no such application, this should should either be + * {@code null} or {@link VpnConfig.LEGACY_VPN}. + * @param newPackage Package name of the application which should gain control of VPN, or + * {@code null} to disable. + * @param userId User for whom to prepare the new VPN. + * + * @hide + */ + public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, + int userId) { + try { + return mService.prepareVpn(oldPackage, newPackage, userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set whether the VPN package has the ability to launch VPNs without user intervention. This + * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn} + * class. If the caller is not {@code userId}, {@link + * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. + * + * @param packageName The package for which authorization state should change. + * @param userId User for whom {@code packageName} is installed. + * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN + * permissions should be granted. When unauthorizing an app, {@link + * VpnManager.TYPE_VPN_NONE} should be used. + * @hide + */ + public void setVpnPackageAuthorization( + String packageName, int userId, @VpnManager.VpnType int vpnType) { + try { + mService.setVpnPackageAuthorization(packageName, userId, vpnType); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Return the legacy VPN information for the specified user ID. + * @hide + */ + public LegacyVpnInfo getLegacyVpnInfo(@UserIdInt int userId) { + try { + return mService.getLegacyVpnInfo(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Starts a legacy VPN. + * @hide + */ + public void startLegacyVpn(VpnProfile profile) { + try { + mService.startLegacyVpn(profile); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Informs the service that legacy lockdown VPN state should be updated (e.g., if its keystore + * entry has been updated). If the LockdownVpn mechanism is enabled, updates the vpn + * with a reload of its profile. + * + *

This method can only be called by the system UID + * @return a boolean indicating success + * + * @hide + */ + public boolean updateLockdownVpn() { + try { + return mService.updateLockdownVpn(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} \ No newline at end of file From f151290e0c518ef4d28d4ce9349838e4a0897840 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Fri, 5 Feb 2021 17:33:53 +0800 Subject: [PATCH 024/343] Move shared Proxy method and constants to shared lib The static validate() method an PROXY_* constants in Proxy are used by both module and Settings. After Proxy is moving into connectivity module, Setting will not able to access them. Thus, move them to ProxyUtils in net shared lib. Bug: 172183305 Test: atest FrameworksNetTests Test: atest CtsNetTestCases:ProxyInfoTest Change-Id: I02c88aeaeb53d62b87a42a2d8ead9b140b054650 --- framework/src/android/net/Proxy.java | 60 ------------------------ framework/src/android/net/ProxyInfo.java | 4 +- 2 files changed, 3 insertions(+), 61 deletions(-) diff --git a/framework/src/android/net/Proxy.java b/framework/src/android/net/Proxy.java index 03b07e080a..9cd7ab2c3e 100644 --- a/framework/src/android/net/Proxy.java +++ b/framework/src/android/net/Proxy.java @@ -30,8 +30,6 @@ import java.net.InetSocketAddress; import java.net.ProxySelector; import java.net.URI; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * A convenience class for accessing the user and default proxy @@ -64,40 +62,9 @@ public final class Proxy { @Deprecated public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; - /** @hide */ - public static final int PROXY_VALID = 0; - /** @hide */ - public static final int PROXY_HOSTNAME_EMPTY = 1; - /** @hide */ - public static final int PROXY_HOSTNAME_INVALID = 2; - /** @hide */ - public static final int PROXY_PORT_EMPTY = 3; - /** @hide */ - public static final int PROXY_PORT_INVALID = 4; - /** @hide */ - public static final int PROXY_EXCLLIST_INVALID = 5; - private static ConnectivityManager sConnectivityManager = null; - // Hostname / IP REGEX validation - // Matches blank input, ips, and domain names - private static final String NAME_IP_REGEX = - "[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*"; - - private static final String HOSTNAME_REGEXP = "^$|^" + NAME_IP_REGEX + "$"; - - private static final Pattern HOSTNAME_PATTERN; - - private static final String EXCL_REGEX = - "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*"; - - private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$"; - - private static final Pattern EXCLLIST_PATTERN; - static { - HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP); - EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP); sDefaultProxySelector = ProxySelector.getDefault(); } @@ -216,33 +183,6 @@ public final class Proxy { return false; } - /** - * Validate syntax of hostname, port and exclusion list entries - * {@hide} - */ - public static int validate(String hostname, String port, String exclList) { - Matcher match = HOSTNAME_PATTERN.matcher(hostname); - Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList); - - if (!match.matches()) return PROXY_HOSTNAME_INVALID; - - if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID; - - if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY; - - if (port.length() > 0) { - if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY; - int portVal = -1; - try { - portVal = Integer.parseInt(port); - } catch (NumberFormatException ex) { - return PROXY_PORT_INVALID; - } - if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID; - } - return PROXY_VALID; - } - /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final void setHttpProxySystemProperty(ProxyInfo p) { diff --git a/framework/src/android/net/ProxyInfo.java b/framework/src/android/net/ProxyInfo.java index c9bca2876b..fb37fbe492 100644 --- a/framework/src/android/net/ProxyInfo.java +++ b/framework/src/android/net/ProxyInfo.java @@ -23,6 +23,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import com.android.net.module.util.ProxyUtils; + import java.net.InetSocketAddress; import java.net.URLConnection; import java.util.List; @@ -233,7 +235,7 @@ public class ProxyInfo implements Parcelable { */ public boolean isValid() { if (!Uri.EMPTY.equals(mPacFileUrl)) return true; - return Proxy.PROXY_VALID == Proxy.validate(mHost == null ? "" : mHost, + return ProxyUtils.PROXY_VALID == ProxyUtils.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort), mExclusionList == null ? "" : mExclusionList); } From a8a477b84e17475b225da9dec3418b953c3c8136 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 17 Dec 2020 14:53:09 -0800 Subject: [PATCH 025/343] ConnectivityService: Plumb attribution tag for location permission checks Not currently setting the atttribution tag for location permission checks. Plumb the attribution tag for all location permision checks (so that location access is correctly attributed to individual components within an app) Bug: 162602799 Test: atest android.net Test: atest com.android.server Change-Id: Iee95f05204f51a4f8cb1f36acfb60e8cdeb156f4 --- framework/src/android/net/ConnectivityManager.java | 13 ++++++++----- framework/src/android/net/IConnectivityManager.aidl | 11 +++++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index fef41522bd..d04a5bee51 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1368,7 +1368,7 @@ public class ConnectivityManager { public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) { try { return mService.getDefaultNetworkCapabilitiesForUser( - userId, mContext.getOpPackageName()); + userId, mContext.getOpPackageName(), getAttributionTag()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1450,7 +1450,8 @@ public class ConnectivityManager { @Nullable public NetworkCapabilities getNetworkCapabilities(@Nullable Network network) { try { - return mService.getNetworkCapabilities(network, mContext.getOpPackageName()); + return mService.getNetworkCapabilities( + network, mContext.getOpPackageName(), getAttributionTag()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2142,7 +2143,7 @@ public class ConnectivityManager { */ // TODO: Remove method and replace with direct call once R code is pushed to AOSP private @Nullable String getAttributionTag() { - return null; + return mContext.getAttributionTag(); } /** @@ -3735,7 +3736,8 @@ public class ConnectivityManager { Binder binder = new Binder(); if (reqType == LISTEN) { request = mService.listenForNetwork( - need, messenger, binder, callingPackageName); + need, messenger, binder, callingPackageName, + getAttributionTag()); } else { request = mService.requestNetwork( need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType, @@ -4180,7 +4182,8 @@ public class ConnectivityManager { checkPendingIntentNotNull(operation); try { mService.pendingListenForNetwork( - request.networkCapabilities, operation, mContext.getOpPackageName()); + request.networkCapabilities, operation, mContext.getOpPackageName(), + getAttributionTag()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index e2672c480c..f909d13625 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -66,7 +66,7 @@ interface IConnectivityManager Network getNetworkForType(int networkType); Network[] getAllNetworks(); NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser( - int userId, String callingPackageName); + int userId, String callingPackageName, String callingAttributionTag); boolean isNetworkSupported(int networkType); @@ -75,7 +75,8 @@ interface IConnectivityManager LinkProperties getLinkPropertiesForType(int networkType); LinkProperties getLinkProperties(in Network network); - NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName); + NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName, + String callingAttributionTag); @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) NetworkState[] getAllNetworkState(); @@ -176,10 +177,12 @@ interface IConnectivityManager void releasePendingNetworkRequest(in PendingIntent operation); NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, in IBinder binder, String callingPackageName); + in Messenger messenger, in IBinder binder, String callingPackageName, + String callingAttributionTag); void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, - in PendingIntent operation, String callingPackageName); + in PendingIntent operation, String callingPackageName, + String callingAttributionTag); void releaseNetworkRequest(in NetworkRequest networkRequest); From 7c85e7d4d67fe02573666d201b54c30d2327f0f3 Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Thu, 4 Feb 2021 19:34:06 -0800 Subject: [PATCH 026/343] Support for Terms & Conditions notification - Added API to add T&C URL in the CaptivePortalData class, and to indicate if the source is from Passpoint. - Added source indication for the Venue URL API. - Allow the connectivity service to send a new T&C acceptance notification. - Updated the merge method to prefer the Capport data over the network agent data, if the source is not authenticated (not from Passpoint). - Propagate the Venue Friendly name to the captive portal activity to be used instead of SSID, when available. Bug: 162785447 Test: End-to-end test Test: atest ConnectivityServiceTest Test: atest CtsNetTestCasesLatestSdk:CaptivePortalDataTest Test: atest NetworkNotificationManagerTest Change-Id: I4e77c3b6c01941b03c46ad32da70c77e0fecac64 --- .../src/android/net/CaptivePortalData.java | 90 +++++++++++++++++-- 1 file changed, 82 insertions(+), 8 deletions(-) diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java index 18467fad8e..f4b46e9f11 100644 --- a/framework/src/android/net/CaptivePortalData.java +++ b/framework/src/android/net/CaptivePortalData.java @@ -16,12 +16,15 @@ package android.net; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -40,10 +43,29 @@ public final class CaptivePortalData implements Parcelable { private final long mExpiryTimeMillis; private final boolean mCaptive; private final String mVenueFriendlyName; + private final int mVenueInfoUrlSource; + private final int mTermsAndConditionsSource; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"CAPTIVE_PORTAL_DATA_SOURCE_"}, value = { + CAPTIVE_PORTAL_DATA_SOURCE_OTHER, + CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT}) + public @interface CaptivePortalDataSource {} + + /** + * Source of information: Other (default) + */ + public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; + + /** + * Source of information: Wi-Fi Passpoint + */ + public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - String venueFriendlyName) { + String venueFriendlyName, int venueInfoUrlSource, int termsAndConditionsSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -52,11 +74,14 @@ public final class CaptivePortalData implements Parcelable { mExpiryTimeMillis = expiryTimeMillis; mCaptive = captive; mVenueFriendlyName = venueFriendlyName; + mVenueInfoUrlSource = venueInfoUrlSource; + mTermsAndConditionsSource = termsAndConditionsSource; } private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), - p.readLong(), p.readLong(), p.readBoolean(), p.readString()); + p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(), + p.readInt()); } @Override @@ -74,6 +99,8 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); dest.writeString(mVenueFriendlyName); + dest.writeInt(mVenueInfoUrlSource); + dest.writeInt(mTermsAndConditionsSource); } /** @@ -88,6 +115,9 @@ public final class CaptivePortalData implements Parcelable { private long mExpiryTime = -1; private boolean mCaptive; private String mVenueFriendlyName; + private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; + private @CaptivePortalDataSource int mUserPortalUrlSource = + CAPTIVE_PORTAL_DATA_SOURCE_OTHER; /** * Create an empty builder. @@ -100,8 +130,8 @@ public final class CaptivePortalData implements Parcelable { public Builder(@Nullable CaptivePortalData data) { if (data == null) return; setRefreshTime(data.mRefreshTimeMillis) - .setUserPortalUrl(data.mUserPortalUrl) - .setVenueInfoUrl(data.mVenueInfoUrl) + .setUserPortalUrl(data.mUserPortalUrl, data.mTermsAndConditionsSource) + .setVenueInfoUrl(data.mVenueInfoUrl, data.mVenueInfoUrlSource) .setSessionExtendable(data.mIsSessionExtendable) .setBytesRemaining(data.mByteLimit) .setExpiryTime(data.mExpiryTimeMillis) @@ -123,7 +153,18 @@ public final class CaptivePortalData implements Parcelable { */ @NonNull public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) { + return setUserPortalUrl(userPortalUrl, CAPTIVE_PORTAL_DATA_SOURCE_OTHER); + } + + /** + * Set the URL to be used for users to login to the portal, if captive, and the source of + * the data, see {@link CaptivePortalDataSource} + */ + @NonNull + public Builder setUserPortalUrl(@Nullable Uri userPortalUrl, + @CaptivePortalDataSource int source) { mUserPortalUrl = userPortalUrl; + mUserPortalUrlSource = source; return this; } @@ -132,7 +173,18 @@ public final class CaptivePortalData implements Parcelable { */ @NonNull public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) { + return setVenueInfoUrl(venueInfoUrl, CAPTIVE_PORTAL_DATA_SOURCE_OTHER); + } + + /** + * Set the URL that can be used by users to view information about the network venue, and + * the source of the data, see {@link CaptivePortalDataSource} + */ + @NonNull + public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl, + @CaptivePortalDataSource int source) { mVenueInfoUrl = venueInfoUrl; + mVenueInfoUrlSource = source; return this; } @@ -188,7 +240,8 @@ public final class CaptivePortalData implements Parcelable { public CaptivePortalData build() { return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive, - mVenueFriendlyName); + mVenueFriendlyName, mVenueInfoUrlSource, + mUserPortalUrlSource); } } @@ -248,6 +301,22 @@ public final class CaptivePortalData implements Parcelable { return mCaptive; } + /** + * Get the information source of the Venue URL + * @return The source that the Venue URL was obtained from + */ + public @CaptivePortalDataSource int getVenueInfoUrlSource() { + return mVenueInfoUrlSource; + } + + /** + * Get the information source of the user portal URL + * @return The source that the user portal URL was obtained from + */ + public @CaptivePortalDataSource int getUserPortalUrlSource() { + return mTermsAndConditionsSource; + } + /** * Get the venue friendly name */ @@ -272,11 +341,12 @@ public final class CaptivePortalData implements Parcelable { @Override public int hashCode() { return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, - mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName); + mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName, + mVenueInfoUrlSource, mTermsAndConditionsSource); } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof CaptivePortalData)) return false; final CaptivePortalData other = (CaptivePortalData) obj; return mRefreshTimeMillis == other.mRefreshTimeMillis @@ -286,7 +356,9 @@ public final class CaptivePortalData implements Parcelable { && mByteLimit == other.mByteLimit && mExpiryTimeMillis == other.mExpiryTimeMillis && mCaptive == other.mCaptive - && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName); + && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName) + && mVenueInfoUrlSource == other.mVenueInfoUrlSource + && mTermsAndConditionsSource == other.mTermsAndConditionsSource; } @Override @@ -300,6 +372,8 @@ public final class CaptivePortalData implements Parcelable { + ", expiryTime: " + mExpiryTimeMillis + ", captive: " + mCaptive + ", venueFriendlyName: " + mVenueFriendlyName + + ", venueInfoUrlSource: " + mVenueInfoUrlSource + + ", termsAndConditionsSource: " + mTermsAndConditionsSource + "}"; } } From a77d05ec0afa867a64115431b7ec9370db5660ef Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 29 Jan 2021 20:14:04 +0900 Subject: [PATCH 027/343] Add a registerSystemDefaultNetworkCallback method. This method allows internal components to track the system default network. This differs from registerDefaultNetworkCallback because that method sends callbacks for the default network for the UID that called it. This may not be the system default network, for example, when a VPN is up and applies to the UID. Bug: 173331190 Test: new unit tests in ConnectivityServiceTest Test: new unit tests in ConnectivityManagerTest Test: new CTS tests in ConnectivityServiceTest Test: new CTS tests in HostsideVpnTests in other CL in this topic Change-Id: Id02748a2183f71b71ff2a53a580466b9dcecaa93 --- .../src/android/net/ConnectivityManager.java | 66 +++++++++++++++---- framework/src/android/net/NetworkRequest.java | 22 +++---- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index d04a5bee51..0976b753e6 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.REQUEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; +import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; import android.annotation.CallbackExecutor; @@ -3721,7 +3722,8 @@ public class ConnectivityManager { printStackTrace(); checkCallbackNotNull(callback); Preconditions.checkArgument( - reqType == TRACK_DEFAULT || need != null, "null NetworkCapabilities"); + reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null, + "null NetworkCapabilities"); final NetworkRequest request; final String callingPackageName = mContext.getOpPackageName(); try { @@ -4192,8 +4194,9 @@ public class ConnectivityManager { } /** - * Registers to receive notifications about changes in the system default network. The callbacks - * will continue to be called until either the application exits or + * Registers to receive notifications about changes in the application's default network. This + * may be a physical network or a virtual network, such as a VPN that applies to the + * application. The callbacks will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. * *

To avoid performance issues due to apps leaking callbacks, the system will limit the @@ -4206,7 +4209,7 @@ public class ConnectivityManager { * {@link #unregisterNetworkCallback(NetworkCallback)}. * * @param networkCallback The {@link NetworkCallback} that the system will call as the - * system default network changes. + * application's default network changes. * The callback is invoked on the default internal Handler. * @throws RuntimeException if the app already has too many callbacks registered. */ @@ -4215,11 +4218,47 @@ public class ConnectivityManager { registerDefaultNetworkCallback(networkCallback, getDefaultHandler()); } + /** + * Registers to receive notifications about changes in the application's default network. This + * may be a physical network or a virtual network, such as a VPN that applies to the + * application. The callbacks will continue to be called until either the application exits or + * {@link #unregisterNetworkCallback(NetworkCallback)} is called. + * + *

To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param networkCallback The {@link NetworkCallback} that the system will call as the + * application's default network changes. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, + @NonNull Handler handler) { + CallbackHandler cbHandler = new CallbackHandler(handler); + sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, + TRACK_DEFAULT, TYPE_NONE, cbHandler); + } + /** * Registers to receive notifications about changes in the system default network. The callbacks * will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. * + * This method should not be used to determine networking state seen by applications, because in + * many cases, most or even all application traffic may not use the default network directly, + * and traffic from different applications may go on different networks by default. As an + * example, if a VPN is connected, traffic from all applications might be sent through the VPN + * and not onto the system default network. Applications or system components desiring to do + * determine network state as seen by applications should use other methods such as + * {@link #registerDefaultNetworkCallback(NetworkCallback, Handler)}. + * *

To avoid performance issues due to apps leaking callbacks, the system will limit the * number of outstanding requests to 100 per app (identified by their UID), shared with * all variants of this method, of {@link #requestNetwork} as well as @@ -4233,20 +4272,19 @@ public class ConnectivityManager { * system default network changes. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. * @throws RuntimeException if the app already has too many callbacks registered. + * + * @hide */ - @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) - public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, + @SystemApi(client = MODULE_LIBRARIES) + @SuppressLint({"ExecutorRegistration", "PairedRegistration"}) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - // This works because if the NetworkCapabilities are null, - // ConnectivityService takes them from the default request. - // - // Since the capabilities are exactly the same as the default request's - // capabilities, this request is guaranteed, at all times, to be - // satisfied by the same network, if any, that satisfies the default - // request, i.e., the system default network. CallbackHandler cbHandler = new CallbackHandler(handler); sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, - TRACK_DEFAULT, TYPE_NONE, cbHandler); + TRACK_SYSTEM_DEFAULT, TYPE_NONE, cbHandler); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 6540397d62..b4a651c060 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -104,17 +104,14 @@ public class NetworkRequest implements Parcelable { * callbacks about the single, highest scoring current network * (if any) that matches the specified NetworkCapabilities, or * - * - TRACK_DEFAULT, a hybrid of the two designed such that the - * framework will issue callbacks for the single, highest scoring - * current network (if any) that matches the capabilities of the - * default Internet request (mDefaultRequest), but which cannot cause - * the framework to either create or retain the existence of any - * specific network. Note that from the point of view of the request - * matching code, TRACK_DEFAULT is identical to REQUEST: its special - * behaviour is not due to different semantics, but to the fact that - * the system will only ever create a TRACK_DEFAULT with capabilities - * that are identical to the default request's capabilities, thus - * causing it to share fate in every way with the default request. + * - TRACK_DEFAULT, which causes the framework to issue callbacks for + * the single, highest scoring current network (if any) that will + * be chosen for an app, but which cannot cause the framework to + * either create or retain the existence of any specific network. + * + * - TRACK_SYSTEM_DEFAULT, which causes the framework to send callbacks + * for the network (if any) that satisfies the default Internet + * request. * * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks * to retain the NET_CAPABILITY_FOREGROUND capability. A network with @@ -137,6 +134,7 @@ public class NetworkRequest implements Parcelable { TRACK_DEFAULT, REQUEST, BACKGROUND_REQUEST, + TRACK_SYSTEM_DEFAULT, }; /** @@ -601,6 +599,8 @@ public class NetworkRequest implements Parcelable { return NetworkRequestProto.TYPE_REQUEST; case BACKGROUND_REQUEST: return NetworkRequestProto.TYPE_BACKGROUND_REQUEST; + case TRACK_SYSTEM_DEFAULT: + return NetworkRequestProto.TYPE_TRACK_SYSTEM_DEFAULT; default: return NetworkRequestProto.TYPE_UNKNOWN; } From 026fbb8a1fd6abfe69a135d4654c7701396a6f7e Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 3 Feb 2021 03:12:15 +0900 Subject: [PATCH 028/343] Add a VpnTransportInfo object. This currently stores the VPN type and a session name, but can be extended in the future. Bug: 173331190 Test: added coverage in VpnTest Test: added coverage in ConnectivityServiceTest Test: added coverage in NetworkAgentTest Change-Id: I450858a9fa332c8d896dbdb4c14337d5ec23677f --- .../src/android/net/NetworkCapabilities.java | 2 ++ framework/src/android/net/VpnManager.java | 22 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 55b2c3c9e1..9d67f0b843 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -762,12 +762,14 @@ public final class NetworkCapabilities implements Parcelable { final int originalSignalStrength = mSignalStrength; final int originalOwnerUid = getOwnerUid(); final int[] originalAdministratorUids = getAdministratorUids(); + final TransportInfo originalTransportInfo = getTransportInfo(); clearAll(); mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS) | (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; mSignalStrength = originalSignalStrength; + mTransportInfo = originalTransportInfo; // Only retain the owner and administrator UIDs if they match the app registering the remote // caller that registered the network. diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java index 1812509ba6..1e30283a9e 100644 --- a/framework/src/android/net/VpnManager.java +++ b/framework/src/android/net/VpnManager.java @@ -55,13 +55,29 @@ import java.security.GeneralSecurityException; public class VpnManager { /** Type representing a lack of VPN @hide */ public static final int TYPE_VPN_NONE = -1; - /** VPN service type code @hide */ + + /** + * A VPN created by an app using the {@link VpnService} API. + * @hide + */ public static final int TYPE_VPN_SERVICE = 1; - /** Platform VPN type code @hide */ + + /** + * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}. + * @hide + */ public static final int TYPE_VPN_PLATFORM = 2; + /** + * An IPsec VPN created by the built-in LegacyVpnRunner. + * @deprecated new Android devices should use VPN_TYPE_PLATFORM instead. + * @hide + */ + @Deprecated + public static final int TYPE_VPN_LEGACY = 3; + /** @hide */ - @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM}) + @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY}) @Retention(RetentionPolicy.SOURCE) public @interface VpnType {} From c71cff88374c7f0fd5904ffce064caa5993657be Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 15 Jan 2021 01:29:01 +0900 Subject: [PATCH 029/343] Convert LockdownVpnTracker to NetworkCallbacks. This will allow moving LockdownVpnTracker from the connectivity to the VPN code. This requires moderate refactoring since it's pretty tightly coupled to both. In this CL: 1. Add an @hide API to tell ConnectivityService that legacy lockdown VPN is enabled. I chose not to use the existing setVpnRequiredForUids API because that method has specific semantics and because it will be required long term since it's used by non-legacy VPN types. 2. Instead of updating LockdownVpnTracker inline from the ConnectivityService handler thread, have it listen to NetworkCallbacks. This introduces an extra thread hop, but most of the interactions between the lockdown VPN and CS were via NetworkAgent, which is asynchronous anyway. 3. Add code to LegacyTypeTracker to send the extra CONNECTIVITY_ACTION broadcast for the underlying network type that is sent after the VPN connects. In order to do this, make Make LockdownVpnTracker specify its underlying network (via setUnderlyingNetworks) when it connects. 4. Reimplement LockdownVpnTracker#augmentNetworkInfo based on information that is available in ConnectivityService. 5. Remove the code in LockdownVpnTracker that counted errors. I think this code has not worked since lollipop, because ConnectivityService never sees NetworkInfo objects in state FAILED. This is because ConnectivityService only hears about NetworkInfo objects via NetworkAgents, and LegacyVpnRunner only registers its NetworkAgent when the connection succeeds. Bug: 173331190 Test: passes existing tests in ConnectivityServiceTest Change-Id: I66d18512882efd468ee0ecec61f28786a195b357 --- .../src/android/net/ConnectivityManager.java | 39 +++++++++++++++++++ .../src/android/net/IConnectivityManager.aidl | 1 + 2 files changed, 40 insertions(+) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 0976b753e6..8437798b7b 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1220,6 +1220,45 @@ public class ConnectivityManager { } } + /** + * Informs ConnectivityService of whether the legacy lockdown VPN, as implemented by + * LockdownVpnTracker, is in use. This is deprecated for new devices starting from Android 12 + * but is still supported for backwards compatibility. + *

+ * This type of VPN is assumed always to use the system default network, and must always declare + * exactly one underlying network, which is the network that was the default when the VPN + * connected. + *

+ * Calling this method with {@code true} enables legacy behaviour, specifically: + *

    + *
  • Any VPN that applies to userId 0 behaves specially with respect to deprecated + * {@link #CONNECTIVITY_ACTION} broadcasts. Any such broadcasts will have the state in the + * {@link #EXTRA_NETWORK_INFO} replaced by state of the VPN network. Also, any time the VPN + * connects, a {@link #CONNECTIVITY_ACTION} broadcast will be sent for the network + * underlying the VPN.
  • + *
  • Deprecated APIs that return {@link NetworkInfo} objects will have their state + * similarly replaced by the VPN network state.
  • + *
  • Information on current network interfaces passed to NetworkStatsService will not + * include any VPN interfaces.
  • + *
+ * + * @param enabled whether legacy lockdown VPN is enabled or disabled + * + * TODO: @SystemApi(client = MODULE_LIBRARIES) + * + * @hide + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + public void setLegacyLockdownVpnEnabled(boolean enabled) { + try { + mService.setLegacyLockdownVpnEnabled(enabled); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Returns details about the currently active default data network * for a given uid. This is for internal use only to avoid spying diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index f909d13625..ab134eb6d2 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -151,6 +151,7 @@ interface IConnectivityManager boolean isVpnLockdownEnabled(int userId); List getVpnLockdownWhitelist(int userId); void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges); + void setLegacyLockdownVpnEnabled(boolean enabled); void setProvisioningNotificationVisible(boolean visible, int networkType, in String action); From d97b404c487fd27b8b0a4d74a9fe8ff816a03f86 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 9 Nov 2020 10:34:03 +0900 Subject: [PATCH 030/343] Add a skeleton VpnManagerService, and start it on boot. This adds a lot of unused code but this should make it easier to review subsequent CLs. Bug: 173331190 Test: builds, boots, "dumpsys vpnmanager" succeeds Change-Id: Ied379654a0c3ab6242d3125661fe30f322395059 --- framework/src/android/net/VpnManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java index 1e30283a9e..a65769cc72 100644 --- a/framework/src/android/net/VpnManager.java +++ b/framework/src/android/net/VpnManager.java @@ -76,6 +76,12 @@ public class VpnManager { @Deprecated public static final int TYPE_VPN_LEGACY = 3; + /** + * Channel for VPN notifications. + * @hide + */ + public static final String NOTIFICATION_CHANNEL_VPN = "VPN"; + /** @hide */ @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY}) @Retention(RetentionPolicy.SOURCE) From 842075ed8e87a6936f29476070dcb39addc4e7f0 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 4 Feb 2021 17:32:07 +0900 Subject: [PATCH 031/343] Move VPN code from ConnectivityService to VpnManagerService. ConnectivityService itself does not depend on mVpns or the Vpn class any more. Most of this CL is simply moving code from one class to another: - Move the AIDL calls from IConnectivityManager to IVpnManager. - Move the implementation from ConnectivityService to the new VpnManagerService. - Move the APIs from ConnectivityManager to VpnManager, but temporarily maintain some shims in ConnectivityManager for the moved calls so that existing callers do not have to be modified in this CL. - Update VpnService to call IVpnManager instead of IConnectivityManager. - Move the code that registers the VpnManager service from ConnectivityFrameworkInitializer to SystemServiceRegistry. Bug: 173331190 Test: atest HostsideVpnTests FrameworksNetTests CtsNetTestCases Change-Id: I4911e2144df721a94fa00da9edf0dc372a7091c2 --- .../net/ConnectivityFrameworkInitializer.java | 11 -- .../src/android/net/ConnectivityManager.java | 129 ++++++------------ .../src/android/net/IConnectivityManager.aidl | 37 ----- framework/src/android/net/VpnManager.java | 123 ++++++++++++++++- framework/src/android/net/VpnService.java | 17 ++- 5 files changed, 167 insertions(+), 150 deletions(-) diff --git a/framework/src/android/net/ConnectivityFrameworkInitializer.java b/framework/src/android/net/ConnectivityFrameworkInitializer.java index 9afa5d1311..92a792b784 100644 --- a/framework/src/android/net/ConnectivityFrameworkInitializer.java +++ b/framework/src/android/net/ConnectivityFrameworkInitializer.java @@ -49,17 +49,6 @@ public final class ConnectivityFrameworkInitializer { } ); - // TODO: move outside of the connectivity JAR - SystemServiceRegistry.registerContextAwareService( - Context.VPN_MANAGEMENT_SERVICE, - VpnManager.class, - (context) -> { - final ConnectivityManager cm = context.getSystemService( - ConnectivityManager.class); - return cm.createVpnManager(); - } - ); - SystemServiceRegistry.registerContextAwareService( Context.CONNECTIVITY_DIAGNOSTICS_SERVICE, ConnectivityDiagnosticsManager.class, diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 8437798b7b..25b6460ddf 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -824,6 +824,7 @@ public class ConnectivityManager { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private final IConnectivityManager mService; + /** * A kludge to facilitate static access where a Context pointer isn't available, like in the * case of the static set/getProcessDefaultNetwork methods and from the Network class. @@ -1069,106 +1070,55 @@ public class ConnectivityManager { } /** - * Checks if a VPN app supports always-on mode. - * - * In order to support the always-on feature, an app has to - *
    - *
  • target {@link VERSION_CODES#N API 24} or above, and - *
  • not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} - * meta-data field. - *
- * - * @param userId The identifier of the user for whom the VPN app is installed. - * @param vpnPackage The canonical package name of the VPN app. - * @return {@code true} if and only if the VPN app exists and supports always-on mode. + * Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser. + * @deprecated TODO: remove when callers have migrated to VpnManager. * @hide */ + @Deprecated public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { - try { - return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage); } /** - * Configures an always-on VPN connection through a specific application. - * This connection is automatically granted and persisted after a reboot. - * - *

The designated package should declare a {@link VpnService} in its - * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, - * otherwise the call will fail. - * - * @param userId The identifier of the user to set an always-on VPN for. - * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} - * to remove an existing always-on VPN configuration. - * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or - * {@code false} otherwise. - * @param lockdownAllowlist The list of packages that are allowed to access network directly - * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so - * this method must be called when a package that should be allowed is installed or - * uninstalled. - * @return {@code true} if the package is set as always-on VPN controller; - * {@code false} otherwise. + * Calls VpnManager#setAlwaysOnVpnPackageForUser. + * @deprecated TODO: remove when callers have migrated to VpnManager. * @hide */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + @Deprecated public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, boolean lockdownEnabled, @Nullable List lockdownAllowlist) { - try { - return mService.setAlwaysOnVpnPackage( - userId, vpnPackage, lockdownEnabled, lockdownAllowlist); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled, + lockdownAllowlist); } - /** - * Returns the package name of the currently set always-on VPN application. - * If there is no always-on VPN set, or the VPN is provided by the system instead - * of by an app, {@code null} will be returned. - * - * @return Package name of VPN controller responsible for always-on VPN, - * or {@code null} if none is set. + /** + * Calls VpnManager#getAlwaysOnVpnPackageForUser. + * @deprecated TODO: remove when callers have migrated to VpnManager. * @hide */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + @Deprecated public String getAlwaysOnVpnPackageForUser(int userId) { - try { - return mService.getAlwaysOnVpnPackage(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getVpnManager().getAlwaysOnVpnPackageForUser(userId); } /** - * @return whether always-on VPN is in lockdown mode. - * + * Calls VpnManager#isVpnLockdownEnabled. + * @deprecated TODO: remove when callers have migrated to VpnManager. * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + */ + @Deprecated public boolean isVpnLockdownEnabled(int userId) { - try { - return mService.isVpnLockdownEnabled(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - + return getVpnManager().isVpnLockdownEnabled(userId); } /** - * @return the list of packages that are allowed to access network when always-on VPN is in - * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. - * + * Calls VpnManager#getVpnLockdownAllowlist. + * @deprecated TODO: remove when callers have migrated to VpnManager. * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + */ + @Deprecated public List getVpnLockdownWhitelist(int userId) { - try { - return mService.getVpnLockdownWhitelist(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getVpnManager().getVpnLockdownAllowlist(userId); } /** @@ -3219,20 +3169,13 @@ public class ConnectivityManager { } /** - * If the LockdownVpn mechanism is enabled, updates the vpn - * with a reload of its profile. - * - * @return a boolean with {@code} indicating success - * - *

This method can only be called by the system UID - * {@hide} + * Calls VpnManager#updateLockdownVpn. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide */ + @Deprecated public boolean updateLockdownVpn() { - try { - return mService.updateLockdownVpn(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getVpnManager().updateLockdownVpn(); } /** @@ -4596,6 +4539,8 @@ public class ConnectivityManager { try { mService.factoryReset(); mTetheringManager.stopAllTethering(); + // TODO: Migrate callers to VpnManager#factoryReset. + getVpnManager().factoryReset(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4889,9 +4834,13 @@ public class ConnectivityManager { return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); } - /** @hide */ - public VpnManager createVpnManager() { - return new VpnManager(mContext, mService); + /** + * Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a + * private final mVpnManager because ConnectivityManager is initialized before VpnManager. + * @hide TODO: remove. + */ + public VpnManager getVpnManager() { + return mContext.getSystemService(VpnManager.class); } /** @hide */ diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index ab134eb6d2..77aee5ec6f 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -42,9 +42,6 @@ import android.os.PersistableBundle; import android.os.ResultReceiver; import com.android.connectivity.aidl.INetworkAgent; -import com.android.internal.net.LegacyVpnInfo; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; /** * Interface that answers queries about, and allows changing, the @@ -122,34 +119,6 @@ interface IConnectivityManager ProxyInfo getProxyForNetwork(in Network nework); - boolean prepareVpn(String oldPackage, String newPackage, int userId); - - void setVpnPackageAuthorization(String packageName, int userId, int vpnType); - - ParcelFileDescriptor establishVpn(in VpnConfig config); - - boolean provisionVpnProfile(in VpnProfile profile, String packageName); - - void deleteVpnProfile(String packageName); - - void startVpnProfile(String packageName); - - void stopVpnProfile(String packageName); - - VpnConfig getVpnConfig(int userId); - - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - void startLegacyVpn(in VpnProfile profile); - - LegacyVpnInfo getLegacyVpnInfo(int userId); - - boolean updateLockdownVpn(); - boolean isAlwaysOnVpnPackageSupported(int userId, String packageName); - boolean setAlwaysOnVpnPackage(int userId, String packageName, boolean lockdown, - in List lockdownWhitelist); - String getAlwaysOnVpnPackage(int userId); - boolean isVpnLockdownEnabled(int userId); - List getVpnLockdownWhitelist(int userId); void setRequireVpnForUids(boolean requireVpn, in UidRange[] ranges); void setLegacyLockdownVpnEnabled(boolean enabled); @@ -200,10 +169,6 @@ interface IConnectivityManager int getRestoreDefaultNetworkDelay(int networkType); - boolean addVpnAddress(String address, int prefixLength); - boolean removeVpnAddress(String address, int prefixLength); - boolean setUnderlyingNetworksForVpn(in Network[] networks); - void factoryReset(); void startNattKeepalive(in Network network, int intervalSeconds, @@ -223,8 +188,6 @@ interface IConnectivityManager byte[] getNetworkWatchlistConfigHash(); int getConnectionOwnerUid(in ConnectionInfo connectionInfo); - boolean isCallerCurrentAlwaysOnVpnApp(); - boolean isCallerCurrentAlwaysOnVpnLockdownApp(); void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, in NetworkRequest request, String callingPackageName); diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java index a65769cc72..f472ed4381 100644 --- a/framework/src/android/net/VpnManager.java +++ b/framework/src/android/net/VpnManager.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; @@ -37,6 +38,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.GeneralSecurityException; +import java.util.List; /** * This class provides an interface for apps to manage platform VPN profiles @@ -88,7 +90,7 @@ public class VpnManager { public @interface VpnType {} @NonNull private final Context mContext; - @NonNull private final IConnectivityManager mService; + @NonNull private final IVpnManager mService; private static Intent getIntentForConfirmation() { final Intent intent = new Intent(); @@ -107,9 +109,9 @@ public class VpnManager { * * @hide */ - public VpnManager(@NonNull Context ctx, @NonNull IConnectivityManager service) { + public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) { mContext = checkNotNull(ctx, "missing Context"); - mService = checkNotNull(service, "missing IConnectivityManager"); + mService = checkNotNull(service, "missing IVpnManager"); } /** @@ -200,6 +202,19 @@ public class VpnManager { } } + /** + * Resets all VPN settings back to factory defaults. + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void factoryReset() { + try { + mService.factoryReset(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Prepare for a VPN application. * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, @@ -245,6 +260,108 @@ public class VpnManager { } } + /** + * Checks if a VPN app supports always-on mode. + * + * In order to support the always-on feature, an app has to + *

    + *
  • target {@link VERSION_CODES#N API 24} or above, and + *
  • not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} + * meta-data field. + *
+ * + * @param userId The identifier of the user for whom the VPN app is installed. + * @param vpnPackage The canonical package name of the VPN app. + * @return {@code true} if and only if the VPN app exists and supports always-on mode. + * @hide + */ + public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { + try { + return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Configures an always-on VPN connection through a specific application. + * This connection is automatically granted and persisted after a reboot. + * + *

The designated package should declare a {@link VpnService} in its + * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, + * otherwise the call will fail. + * + * @param userId The identifier of the user to set an always-on VPN for. + * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} + * to remove an existing always-on VPN configuration. + * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or + * {@code false} otherwise. + * @param lockdownAllowlist The list of packages that are allowed to access network directly + * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so + * this method must be called when a package that should be allowed is installed or + * uninstalled. + * @return {@code true} if the package is set as always-on VPN controller; + * {@code false} otherwise. + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, + boolean lockdownEnabled, @Nullable List lockdownAllowlist) { + try { + return mService.setAlwaysOnVpnPackage( + userId, vpnPackage, lockdownEnabled, lockdownAllowlist); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the package name of the currently set always-on VPN application. + * If there is no always-on VPN set, or the VPN is provided by the system instead + * of by an app, {@code null} will be returned. + * + * @return Package name of VPN controller responsible for always-on VPN, + * or {@code null} if none is set. + * @hide + */ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public String getAlwaysOnVpnPackageForUser(int userId) { + try { + return mService.getAlwaysOnVpnPackage(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @return whether always-on VPN is in lockdown mode. + * + * @hide + **/ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public boolean isVpnLockdownEnabled(int userId) { + try { + return mService.isVpnLockdownEnabled(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @return the list of packages that are allowed to access network when always-on VPN is in + * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. + * + * @hide + **/ + @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) + public List getVpnLockdownAllowlist(int userId) { + try { + return mService.getVpnLockdownAllowlist(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Return the legacy VPN information for the specified user ID. * @hide diff --git a/framework/src/android/net/VpnService.java b/framework/src/android/net/VpnService.java index 8e90a119fe..e43b0b6fa6 100644 --- a/framework/src/android/net/VpnService.java +++ b/framework/src/android/net/VpnService.java @@ -170,12 +170,11 @@ public class VpnService extends Service { "android.net.VpnService.SUPPORTS_ALWAYS_ON"; /** - * Use IConnectivityManager since those methods are hidden and not - * available in ConnectivityManager. + * Use IVpnManager since those methods are hidden and not available in VpnManager. */ - private static IConnectivityManager getService() { - return IConnectivityManager.Stub.asInterface( - ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); + private static IVpnManager getService() { + return IVpnManager.Stub.asInterface( + ServiceManager.getService(Context.VPN_MANAGEMENT_SERVICE)); } /** @@ -226,15 +225,15 @@ public class VpnService extends Service { @SystemApi @RequiresPermission(android.Manifest.permission.CONTROL_VPN) public static void prepareAndAuthorize(Context context) { - IConnectivityManager cm = getService(); + IVpnManager vm = getService(); String packageName = context.getPackageName(); try { // Only prepare if we're not already prepared. int userId = context.getUserId(); - if (!cm.prepareVpn(packageName, null, userId)) { - cm.prepareVpn(null, packageName, userId); + if (!vm.prepareVpn(packageName, null, userId)) { + vm.prepareVpn(null, packageName, userId); } - cm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); + vm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); } catch (RemoteException e) { // ignore } From b3d24768eea2ebfa1e32d949c172a884a0d00dc1 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 12 Feb 2021 04:09:15 +0000 Subject: [PATCH 032/343] Revert "[VCN07] Bypass VCN for non-internet app accessible cellu..." Revert submission 1579872-vcn07 Reason for revert: Possible culprit for b/179768816, broken ConnectivityControllerTest Reverted Changes: Id09b19c13:Address comments on aosp/1550755 I245bd69e0:[VCN07.1] Add test for bypassing VCN for non-inter... I9936894b9:[VCN07] Bypass VCN for non-internet app accessible... Change-Id: Ie5f8c3051fed40623e5d4705ac2243ef51a898bd --- framework/src/android/net/NetworkRequest.java | 69 ------------------- 1 file changed, 69 deletions(-) diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 9883692e7d..04011fc681 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -16,22 +16,6 @@ package android.net; -import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; -import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -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_RESTRICTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; -import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; - import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -46,8 +30,6 @@ import android.os.Process; import android.text.TextUtils; import android.util.proto.ProtoOutputStream; -import java.util.Arrays; -import java.util.List; import java.util.Objects; import java.util.Set; @@ -174,30 +156,8 @@ public class NetworkRequest implements Parcelable { * needed in terms of {@link NetworkCapabilities} features */ public static class Builder { - /** - * Capabilities that are currently compatible with VCN networks. - */ - private static final List VCN_SUPPORTED_CAPABILITIES = Arrays.asList( - NET_CAPABILITY_CAPTIVE_PORTAL, - NET_CAPABILITY_DUN, - NET_CAPABILITY_FOREGROUND, - NET_CAPABILITY_INTERNET, - NET_CAPABILITY_NOT_CONGESTED, - NET_CAPABILITY_NOT_METERED, - NET_CAPABILITY_NOT_RESTRICTED, - NET_CAPABILITY_NOT_ROAMING, - NET_CAPABILITY_NOT_SUSPENDED, - NET_CAPABILITY_NOT_VPN, - NET_CAPABILITY_PARTIAL_CONNECTIVITY, - NET_CAPABILITY_TEMPORARILY_NOT_METERED, - NET_CAPABILITY_TRUSTED, - NET_CAPABILITY_VALIDATED); - private final NetworkCapabilities mNetworkCapabilities; - // A boolean that represents the user modified NOT_VCN_MANAGED capability. - private boolean mModifiedNotVcnManaged = false; - /** * Default constructor for Builder. */ @@ -219,7 +179,6 @@ public class NetworkRequest implements Parcelable { // maybeMarkCapabilitiesRestricted() doesn't add back. final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); nc.maybeMarkCapabilitiesRestricted(); - deduceNotVcnManagedCapability(nc); return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); } @@ -236,9 +195,6 @@ public class NetworkRequest implements Parcelable { */ public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mModifiedNotVcnManaged = true; - } return this; } @@ -250,9 +206,6 @@ public class NetworkRequest implements Parcelable { */ public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.removeCapability(capability); - if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { - mModifiedNotVcnManaged = true; - } return this; } @@ -310,9 +263,6 @@ public class NetworkRequest implements Parcelable { @NonNull public Builder clearCapabilities() { mNetworkCapabilities.clearAll(); - // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities - // should not be add back later. - mModifiedNotVcnManaged = true; return this; } @@ -432,25 +382,6 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.setSignalStrength(signalStrength); return this; } - - /** - * Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities - * and user intention, which includes: - * 1. For the requests that don't have anything besides - * {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to - * allow the callers automatically utilize VCN networks if available. - * 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED, - * do not alter them to allow user fire request that suits their need. - * - * @hide - */ - private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) { - if (mModifiedNotVcnManaged) return; - for (final int cap : nc.getCapabilities()) { - if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return; - } - nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); - } } // implement the Parcelable interface From 12aeab88bd332aff738900982a82a8c7403342a4 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Sun, 10 Jan 2021 14:24:24 -0800 Subject: [PATCH 033/343] Implementation of setOemNetworkPreference Main implementation of ConnectivityService.setOemNetworkPreference. This covers the main requirements of this method including listener functionality. Bug: 176495594 Bug: 177101287 Bug: 176494815 Test: atest FrameworksNetTests atest NetworkStackTests atest FrameworksNetIntegrationTests atest NetworkStackIntegrationTests atest CtsNetTestCasesLatestSdk Change-Id: I8d318ab07785e52dd84d6261fdea8f318dce9bc5 --- .../src/android/net/ConnectivityManager.java | 60 ++++++++++++++++--- .../src/android/net/IConnectivityManager.aidl | 4 +- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 0976b753e6..c820a7e80f 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4886,15 +4886,6 @@ public class ConnectivityManager { } } - private void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference) { - try { - mService.setOemNetworkPreference(preference); - } catch (RemoteException e) { - Log.e(TAG, "setOemNetworkPreference() failed for preference: " + preference.toString()); - throw e.rethrowFromSystemServer(); - } - } - @NonNull private final List mQosCallbackConnections = new ArrayList<>(); @@ -5096,4 +5087,55 @@ public class ConnectivityManager { sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST, TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler)); } + + /** + * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor, + * OnSetOemNetworkPreferenceListener)}. + */ + private interface OnSetOemNetworkPreferenceListener { + /** + * Called when setOemNetworkPreference() successfully completes. + */ + void onComplete(); + } + + /** + * Used by automotive devices to set the network preferences used to direct traffic at an + * application level as per the given OemNetworkPreferences. An example use-case would be an + * automotive OEM wanting to provide connectivity for applications critical to the usage of a + * vehicle via a particular network. + * + * Calling this will overwrite the existing preference. + * + * @param preference {@link OemNetworkPreferences} The application network preference to be set. + * @param executor the executor on which listener will be invoked. + * @param listener {@link OnSetOemNetworkPreferenceListener} optional listener used to + * communicate completion of setOemNetworkPreference(). This will only be + * called once upon successful completion of setOemNetworkPreference(). + * @throws IllegalArgumentException if {@code preference} contains invalid preference values. + * @throws SecurityException if missing the appropriate permissions. + * @throws UnsupportedOperationException if called on a non-automotive device. + */ + private void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, + @Nullable @CallbackExecutor final Executor executor, + @Nullable final OnSetOemNetworkPreferenceListener listener) { + Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); + if (null != listener) { + Objects.requireNonNull(executor, "Executor must be non-null"); + } + final IOnSetOemNetworkPreferenceListener listenerInternal = listener == null ? null : + new IOnSetOemNetworkPreferenceListener.Stub() { + @Override + public void onComplete() { + executor.execute(listener::onComplete); + } + }; + + try { + mService.setOemNetworkPreference(preference, listenerInternal); + } catch (RemoteException e) { + Log.e(TAG, "setOemNetworkPreference() failed for preference: " + preference.toString()); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index f909d13625..befd4fb03d 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -20,6 +20,7 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; +import android.net.IOnSetOemNetworkPreferenceListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.LinkProperties; @@ -245,5 +246,6 @@ interface IConnectivityManager void registerQosSocketCallback(in QosSocketInfo socketInfo, in IQosCallback callback); void unregisterQosCallback(in IQosCallback callback); - void setOemNetworkPreference(in OemNetworkPreferences preference); + void setOemNetworkPreference(in OemNetworkPreferences preference, + in IOnSetOemNetworkPreferenceListener listener); } From a46c1446172562802d773d9b5841eec9976c6d4f Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 26 Jan 2021 14:05:36 -0800 Subject: [PATCH 034/343] Adding permission for OEM managed preferences Adding CONTROL_OEM_PAID_NETWORK_PREFERENCE as a signature level permission to allow an application to control OEM managed network preferences. Bug: 176496438 Bug: 176494815 Test: atest FrameworksNetTests atest NetworkStackTests atest FrameworksNetIntegrationTests atest NetworkStackIntegrationTests atest CtsNetTestCasesLatestSdk Change-Id: Iee13e89f3931c7079c2d88cb57b249b1b1cf93ad Change-Id: Id29cafe1eaf5dff8a0605cb2579204d9c77b7e70 --- framework/src/android/net/ConnectivityManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index c820a7e80f..811b053332 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5116,6 +5116,7 @@ public class ConnectivityManager { * @throws SecurityException if missing the appropriate permissions. * @throws UnsupportedOperationException if called on a non-automotive device. */ + @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) private void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, @Nullable @CallbackExecutor final Executor executor, @Nullable final OnSetOemNetworkPreferenceListener listener) { From 6e2d702d373b25603b85436e66b06315e5f12cbf Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 26 Jan 2021 16:23:52 -0800 Subject: [PATCH 035/343] Marking setOemNetworkPreference as @SystemApi Marking setOemNetworkPreference in ConnectivityManager as @SystemApi. Bug: 176496438 Bug: 176494815 Test: atest FrameworksNetTests atest FrameworksNetIntegrationTests atest CtsNetTestCasesLatestSdk Change-Id: I4681c88dc3a83f71c387b29610c33594e57cb43f --- framework/src/android/net/ConnectivityManager.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 811b053332..a972d9fbe9 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5091,8 +5091,10 @@ public class ConnectivityManager { /** * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor, * OnSetOemNetworkPreferenceListener)}. + * @hide */ - private interface OnSetOemNetworkPreferenceListener { + @SystemApi + public interface OnSetOemNetworkPreferenceListener { /** * Called when setOemNetworkPreference() successfully completes. */ @@ -5115,9 +5117,11 @@ public class ConnectivityManager { * @throws IllegalArgumentException if {@code preference} contains invalid preference values. * @throws SecurityException if missing the appropriate permissions. * @throws UnsupportedOperationException if called on a non-automotive device. + * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) - private void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, + public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, @Nullable @CallbackExecutor final Executor executor, @Nullable final OnSetOemNetworkPreferenceListener listener) { Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); From 56ad0aba41500933277fb26ec79c407be24893a9 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 12 Feb 2021 12:40:52 +0900 Subject: [PATCH 036/343] Expose VpnTransportInfo as module-lib API. This information originates in non-mainline system server code and needs to be passed to the connectivity mainline code. Bug: 173331190 Test: already covered by CTS tests Change-Id: Ic612b6a51f7ec13e2213c8754312cf716130c876 --- .../src/android/net/VpnTransportInfo.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 framework/src/android/net/VpnTransportInfo.java diff --git a/framework/src/android/net/VpnTransportInfo.java b/framework/src/android/net/VpnTransportInfo.java new file mode 100644 index 0000000000..0242ba0874 --- /dev/null +++ b/framework/src/android/net/VpnTransportInfo.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.SparseArray; + +import com.android.internal.util.MessageUtils; + +import java.util.Objects; + +/** + * Container for VPN-specific transport information. + * + * @see android.net.TransportInfo + * @see NetworkCapabilities#getTransportInfo() + * + * @hide + */ +@SystemApi(client = MODULE_LIBRARIES) +public final class VpnTransportInfo implements TransportInfo, Parcelable { + private static final SparseArray sTypeToString = + MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"}); + + /** Type of this VPN. */ + @VpnManager.VpnType public final int type; + + public VpnTransportInfo(@VpnManager.VpnType int type) { + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof VpnTransportInfo)) return false; + + VpnTransportInfo that = (VpnTransportInfo) o; + return this.type == that.type; + } + + @Override + public int hashCode() { + return Objects.hash(type); + } + + @Override + public String toString() { + final String typeString = sTypeToString.get(type, "VPN_TYPE_???"); + return String.format("VpnTransportInfo{%s}", typeString); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(type); + } + + public static final @NonNull Creator CREATOR = + new Creator() { + public VpnTransportInfo createFromParcel(Parcel in) { + return new VpnTransportInfo(in.readInt()); + } + public VpnTransportInfo[] newArray(int size) { + return new VpnTransportInfo[size]; + } + }; +} From ba26988b1ce994e626c47414c2481a855b2fadec Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 8 Feb 2021 16:25:42 +0900 Subject: [PATCH 037/343] Rename getVpnLockdownWhitelist to -Allowlist Test: m Bug: 173331190 Change-Id: Id02a37624655c4ff88744c9c57af9f2a17953667 --- framework/src/android/net/ConnectivityManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index ef02a7e7b9..92d7bf06aa 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1117,7 +1117,7 @@ public class ConnectivityManager { * @hide */ @Deprecated - public List getVpnLockdownWhitelist(int userId) { + public List getVpnLockdownAllowlist(int userId) { return getVpnManager().getVpnLockdownAllowlist(userId); } From b6bd8a54a11e5ce78eaca894f08b7d3c6f28dbc6 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 8 Feb 2021 16:25:42 +0900 Subject: [PATCH 038/343] Rename getVpnLockdownWhitelist to -Allowlist Test: m Change-Id: Id02a37624655c4ff88744c9c57af9f2a17953667 Merged-In: Id02a37624655c4ff88744c9c57af9f2a17953667 --- framework/src/android/net/ConnectivityManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 27386bcaa9..4213f8af95 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1117,7 +1117,7 @@ public class ConnectivityManager { * @hide */ @Deprecated - public List getVpnLockdownWhitelist(int userId) { + public List getVpnLockdownAllowlist(int userId) { return getVpnManager().getVpnLockdownAllowlist(userId); } From 2bfd3f95def6e1e3e952a38a210b44de6443426a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 15 Feb 2021 17:07:57 +0900 Subject: [PATCH 039/343] Move the VPN code out of packages/Connectivity. Bug: 173331190 Test: atest FrameworksNetTests HostsideVpnTests CtsNetTestCases Change-Id: Idc6ed1a544e744f8661d1e387da278736d407489 --- framework/src/android/net/VpnManager.java | 406 -------- framework/src/android/net/VpnService.java | 902 ------------------ service/Android.bp | 1 - .../com_android_server_connectivity_Vpn.cpp | 377 -------- service/jni/onload.cpp | 6 +- 5 files changed, 2 insertions(+), 1690 deletions(-) delete mode 100644 framework/src/android/net/VpnManager.java delete mode 100644 framework/src/android/net/VpnService.java delete mode 100644 service/jni/com_android_server_connectivity_Vpn.cpp diff --git a/framework/src/android/net/VpnManager.java b/framework/src/android/net/VpnManager.java deleted file mode 100644 index f472ed4381..0000000000 --- a/framework/src/android/net/VpnManager.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static com.android.internal.util.Preconditions.checkNotNull; - -import android.annotation.IntDef; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.UserIdInt; -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.os.RemoteException; - -import com.android.internal.net.LegacyVpnInfo; -import com.android.internal.net.VpnConfig; -import com.android.internal.net.VpnProfile; - -import java.io.IOException; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.security.GeneralSecurityException; -import java.util.List; - -/** - * This class provides an interface for apps to manage platform VPN profiles - * - *

Apps can use this API to provide profiles with which the platform can set up a VPN without - * further app intermediation. When a VPN profile is present and the app is selected as an always-on - * VPN, the platform will directly trigger the negotiation of the VPN without starting or waking the - * app (unlike VpnService). - * - *

VPN apps using supported protocols should preferentially use this API over the {@link - * VpnService} API for ease-of-development and reduced maintainance burden. This also give the user - * the guarantee that VPN network traffic is not subjected to on-device packet interception. - * - * @see Ikev2VpnProfile - */ -public class VpnManager { - /** Type representing a lack of VPN @hide */ - public static final int TYPE_VPN_NONE = -1; - - /** - * A VPN created by an app using the {@link VpnService} API. - * @hide - */ - public static final int TYPE_VPN_SERVICE = 1; - - /** - * A VPN created using a {@link VpnManager} API such as {@link #startProvisionedVpnProfile}. - * @hide - */ - public static final int TYPE_VPN_PLATFORM = 2; - - /** - * An IPsec VPN created by the built-in LegacyVpnRunner. - * @deprecated new Android devices should use VPN_TYPE_PLATFORM instead. - * @hide - */ - @Deprecated - public static final int TYPE_VPN_LEGACY = 3; - - /** - * Channel for VPN notifications. - * @hide - */ - public static final String NOTIFICATION_CHANNEL_VPN = "VPN"; - - /** @hide */ - @IntDef(value = {TYPE_VPN_NONE, TYPE_VPN_SERVICE, TYPE_VPN_PLATFORM, TYPE_VPN_LEGACY}) - @Retention(RetentionPolicy.SOURCE) - public @interface VpnType {} - - @NonNull private final Context mContext; - @NonNull private final IVpnManager mService; - - private static Intent getIntentForConfirmation() { - final Intent intent = new Intent(); - final ComponentName componentName = ComponentName.unflattenFromString( - Resources.getSystem().getString( - com.android.internal.R.string.config_platformVpnConfirmDialogComponent)); - intent.setComponent(componentName); - return intent; - } - - /** - * Create an instance of the VpnManager with the given context. - * - *

Internal only. Applications are expected to obtain an instance of the VpnManager via the - * {@link Context.getSystemService()} method call. - * - * @hide - */ - public VpnManager(@NonNull Context ctx, @NonNull IVpnManager service) { - mContext = checkNotNull(ctx, "missing Context"); - mService = checkNotNull(service, "missing IVpnManager"); - } - - /** - * Install a VpnProfile configuration keyed on the calling app's package name. - * - *

This method returns {@code null} if user consent has already been granted, or an {@link - * Intent} to a system activity. If an intent is returned, the application should launch the - * activity using {@link Activity#startActivityForResult} to request user consent. The activity - * may pop up a dialog to require user action, and the result will come back via its {@link - * Activity#onActivityResult}. If the result is {@link Activity#RESULT_OK}, the user has - * consented, and the VPN profile can be started. - * - * @param profile the VpnProfile provided by this package. Will override any previous VpnProfile - * stored for this package. - * @return an Intent requesting user consent to start the VPN, or null if consent is not - * required based on privileges or previous user consent. - */ - @Nullable - public Intent provisionVpnProfile(@NonNull PlatformVpnProfile profile) { - final VpnProfile internalProfile; - - try { - internalProfile = profile.toVpnProfile(); - } catch (GeneralSecurityException | IOException e) { - // Conversion to VpnProfile failed; this is an invalid profile. Both of these exceptions - // indicate a failure to convert a PrivateKey or X509Certificate to a Base64 encoded - // string as required by the VpnProfile. - throw new IllegalArgumentException("Failed to serialize PlatformVpnProfile", e); - } - - try { - // Profile can never be null; it either gets set, or an exception is thrown. - if (mService.provisionVpnProfile(internalProfile, mContext.getOpPackageName())) { - return null; - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - return getIntentForConfirmation(); - } - - /** - * Delete the VPN profile configuration that was provisioned by the calling app - * - * @throws SecurityException if this would violate user settings - */ - public void deleteProvisionedVpnProfile() { - try { - mService.deleteVpnProfile(mContext.getOpPackageName()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Request the startup of a previously provisioned VPN. - * - * @throws SecurityException exception if user or device settings prevent this VPN from being - * setup, or if user consent has not been granted - */ - public void startProvisionedVpnProfile() { - try { - mService.startVpnProfile(mContext.getOpPackageName()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** Tear down the VPN provided by the calling app (if any) */ - public void stopProvisionedVpnProfile() { - try { - mService.stopVpnProfile(mContext.getOpPackageName()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Return the VPN configuration for the given user ID. - * @hide - */ - @Nullable - public VpnConfig getVpnConfig(@UserIdInt int userId) { - try { - return mService.getVpnConfig(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Resets all VPN settings back to factory defaults. - * @hide - */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void factoryReset() { - try { - mService.factoryReset(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Prepare for a VPN application. - * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, - * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. - * - * @param oldPackage Package name of the application which currently controls VPN, which will - * be replaced. If there is no such application, this should should either be - * {@code null} or {@link VpnConfig.LEGACY_VPN}. - * @param newPackage Package name of the application which should gain control of VPN, or - * {@code null} to disable. - * @param userId User for whom to prepare the new VPN. - * - * @hide - */ - public boolean prepareVpn(@Nullable String oldPackage, @Nullable String newPackage, - int userId) { - try { - return mService.prepareVpn(oldPackage, newPackage, userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Set whether the VPN package has the ability to launch VPNs without user intervention. This - * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn} - * class. If the caller is not {@code userId}, {@link - * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. - * - * @param packageName The package for which authorization state should change. - * @param userId User for whom {@code packageName} is installed. - * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN - * permissions should be granted. When unauthorizing an app, {@link - * VpnManager.TYPE_VPN_NONE} should be used. - * @hide - */ - public void setVpnPackageAuthorization( - String packageName, int userId, @VpnManager.VpnType int vpnType) { - try { - mService.setVpnPackageAuthorization(packageName, userId, vpnType); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Checks if a VPN app supports always-on mode. - * - * In order to support the always-on feature, an app has to - *

    - *
  • target {@link VERSION_CODES#N API 24} or above, and - *
  • not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON} - * meta-data field. - *
- * - * @param userId The identifier of the user for whom the VPN app is installed. - * @param vpnPackage The canonical package name of the VPN app. - * @return {@code true} if and only if the VPN app exists and supports always-on mode. - * @hide - */ - public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { - try { - return mService.isAlwaysOnVpnPackageSupported(userId, vpnPackage); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Configures an always-on VPN connection through a specific application. - * This connection is automatically granted and persisted after a reboot. - * - *

The designated package should declare a {@link VpnService} in its - * manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE}, - * otherwise the call will fail. - * - * @param userId The identifier of the user to set an always-on VPN for. - * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} - * to remove an existing always-on VPN configuration. - * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or - * {@code false} otherwise. - * @param lockdownAllowlist The list of packages that are allowed to access network directly - * when VPN is in lockdown mode but is not running. Non-existent packages are ignored so - * this method must be called when a package that should be allowed is installed or - * uninstalled. - * @return {@code true} if the package is set as always-on VPN controller; - * {@code false} otherwise. - * @hide - */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List lockdownAllowlist) { - try { - return mService.setAlwaysOnVpnPackage( - userId, vpnPackage, lockdownEnabled, lockdownAllowlist); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns the package name of the currently set always-on VPN application. - * If there is no always-on VPN set, or the VPN is provided by the system instead - * of by an app, {@code null} will be returned. - * - * @return Package name of VPN controller responsible for always-on VPN, - * or {@code null} if none is set. - * @hide - */ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public String getAlwaysOnVpnPackageForUser(int userId) { - try { - return mService.getAlwaysOnVpnPackage(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * @return whether always-on VPN is in lockdown mode. - * - * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public boolean isVpnLockdownEnabled(int userId) { - try { - return mService.isVpnLockdownEnabled(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * @return the list of packages that are allowed to access network when always-on VPN is in - * lockdown mode but not connected. Returns {@code null} when VPN lockdown is not active. - * - * @hide - **/ - @RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN) - public List getVpnLockdownAllowlist(int userId) { - try { - return mService.getVpnLockdownAllowlist(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Return the legacy VPN information for the specified user ID. - * @hide - */ - public LegacyVpnInfo getLegacyVpnInfo(@UserIdInt int userId) { - try { - return mService.getLegacyVpnInfo(userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Starts a legacy VPN. - * @hide - */ - public void startLegacyVpn(VpnProfile profile) { - try { - mService.startLegacyVpn(profile); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Informs the service that legacy lockdown VPN state should be updated (e.g., if its keystore - * entry has been updated). If the LockdownVpn mechanism is enabled, updates the vpn - * with a reload of its profile. - * - *

This method can only be called by the system UID - * @return a boolean indicating success - * - * @hide - */ - public boolean updateLockdownVpn() { - try { - return mService.updateLockdownVpn(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } -} \ No newline at end of file diff --git a/framework/src/android/net/VpnService.java b/framework/src/android/net/VpnService.java deleted file mode 100644 index e43b0b6fa6..0000000000 --- a/framework/src/android/net/VpnService.java +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import static android.system.OsConstants.AF_INET; -import static android.system.OsConstants.AF_INET6; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SystemApi; -import android.app.Activity; -import android.app.PendingIntent; -import android.app.Service; -import android.app.admin.DevicePolicyManager; -import android.compat.annotation.UnsupportedAppUsage; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.IPackageManager; -import android.content.pm.PackageManager; -import android.os.Binder; -import android.os.IBinder; -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; - -import com.android.internal.net.VpnConfig; - -import java.net.DatagramSocket; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.Socket; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * VpnService is a base class for applications to extend and build their - * own VPN solutions. In general, it creates a virtual network interface, - * configures addresses and routing rules, and returns a file descriptor - * to the application. Each read from the descriptor retrieves an outgoing - * packet which was routed to the interface. Each write to the descriptor - * injects an incoming packet just like it was received from the interface. - * The interface is running on Internet Protocol (IP), so packets are - * always started with IP headers. The application then completes a VPN - * connection by processing and exchanging packets with the remote server - * over a tunnel. - * - *

Letting applications intercept packets raises huge security concerns. - * A VPN application can easily break the network. Besides, two of them may - * conflict with each other. The system takes several actions to address - * these issues. Here are some key points: - *

    - *
  • User action is required the first time an application creates a VPN - * connection.
  • - *
  • There can be only one VPN connection running at the same time. The - * existing interface is deactivated when a new one is created.
  • - *
  • A system-managed notification is shown during the lifetime of a - * VPN connection.
  • - *
  • A system-managed dialog gives the information of the current VPN - * connection. It also provides a button to disconnect.
  • - *
  • The network is restored automatically when the file descriptor is - * closed. It also covers the cases when a VPN application is crashed - * or killed by the system.
  • - *
- * - *

There are two primary methods in this class: {@link #prepare} and - * {@link Builder#establish}. The former deals with user action and stops - * the VPN connection created by another application. The latter creates - * a VPN interface using the parameters supplied to the {@link Builder}. - * An application must call {@link #prepare} to grant the right to use - * other methods in this class, and the right can be revoked at any time. - * Here are the general steps to create a VPN connection: - *

    - *
  1. When the user presses the button to connect, call {@link #prepare} - * and launch the returned intent, if non-null.
  2. - *
  3. When the application becomes prepared, start the service.
  4. - *
  5. Create a tunnel to the remote server and negotiate the network - * parameters for the VPN connection.
  6. - *
  7. Supply those parameters to a {@link Builder} and create a VPN - * interface by calling {@link Builder#establish}.
  8. - *
  9. Process and exchange packets between the tunnel and the returned - * file descriptor.
  10. - *
  11. When {@link #onRevoke} is invoked, close the file descriptor and - * shut down the tunnel gracefully.
  12. - *
- * - *

Services extending this class need to be declared with an appropriate - * permission and intent filter. Their access must be secured by - * {@link android.Manifest.permission#BIND_VPN_SERVICE} permission, and - * their intent filter must match {@link #SERVICE_INTERFACE} action. Here - * is an example of declaring a VPN service in {@code AndroidManifest.xml}: - *

- * <service android:name=".ExampleVpnService"
- *         android:permission="android.permission.BIND_VPN_SERVICE">
- *     <intent-filter>
- *         <action android:name="android.net.VpnService"/>
- *     </intent-filter>
- * </service>
- * - *

The Android system starts a VPN in the background by calling - * {@link android.content.Context#startService startService()}. In Android 8.0 - * (API level 26) and higher, the system places VPN apps on the temporary - * allowlist for a short period so the app can start in the background. The VPN - * app must promote itself to the foreground after it's launched or the system - * will shut down the app. - * - *

Developer's guide

- * - *

To learn more about developing VPN apps, read the - * VPN developer's guide. - * - * @see Builder - */ -public class VpnService extends Service { - - /** - * The action must be matched by the intent filter of this service. It also - * needs to require {@link android.Manifest.permission#BIND_VPN_SERVICE} - * permission so that other applications cannot abuse it. - */ - public static final String SERVICE_INTERFACE = VpnConfig.SERVICE_INTERFACE; - - /** - * Key for boolean meta-data field indicating whether this VpnService supports always-on mode. - * - *

For a VPN app targeting {@link android.os.Build.VERSION_CODES#N API 24} or above, Android - * provides users with the ability to set it as always-on, so that VPN connection is - * persisted after device reboot and app upgrade. Always-on VPN can also be enabled by device - * owner and profile owner apps through - * {@link DevicePolicyManager#setAlwaysOnVpnPackage}. - * - *

VPN apps not supporting this feature should opt out by adding this meta-data field to the - * {@code VpnService} component of {@code AndroidManifest.xml}. In case there is more than one - * {@code VpnService} component defined in {@code AndroidManifest.xml}, opting out any one of - * them will opt out the entire app. For example, - *

 {@code
-     * 
-     *     
-     *         
-     *     
-     *     
-     * 
-     * } 
- * - *

This meta-data field defaults to {@code true} if absent. It will only have effect on - * {@link android.os.Build.VERSION_CODES#O_MR1} or higher. - */ - public static final String SERVICE_META_DATA_SUPPORTS_ALWAYS_ON = - "android.net.VpnService.SUPPORTS_ALWAYS_ON"; - - /** - * Use IVpnManager since those methods are hidden and not available in VpnManager. - */ - private static IVpnManager getService() { - return IVpnManager.Stub.asInterface( - ServiceManager.getService(Context.VPN_MANAGEMENT_SERVICE)); - } - - /** - * Prepare to establish a VPN connection. This method returns {@code null} - * if the VPN application is already prepared or if the user has previously - * consented to the VPN application. Otherwise, it returns an - * {@link Intent} to a system activity. The application should launch the - * activity using {@link Activity#startActivityForResult} to get itself - * prepared. The activity may pop up a dialog to require user action, and - * the result will come back via its {@link Activity#onActivityResult}. - * If the result is {@link Activity#RESULT_OK}, the application becomes - * prepared and is granted to use other methods in this class. - * - *

Only one application can be granted at the same time. The right - * is revoked when another application is granted. The application - * losing the right will be notified via its {@link #onRevoke}. Unless - * it becomes prepared again, subsequent calls to other methods in this - * class will fail. - * - *

The user may disable the VPN at any time while it is activated, in - * which case this method will return an intent the next time it is - * executed to obtain the user's consent again. - * - * @see #onRevoke - */ - public static Intent prepare(Context context) { - try { - if (getService().prepareVpn(context.getPackageName(), null, context.getUserId())) { - return null; - } - } catch (RemoteException e) { - // ignore - } - return VpnConfig.getIntentForConfirmation(); - } - - /** - * Version of {@link #prepare(Context)} which does not require user consent. - * - *

Requires {@link android.Manifest.permission#CONTROL_VPN} and should generally not be - * used. Only acceptable in situations where user consent has been obtained through other means. - * - *

Once this is run, future preparations may be done with the standard prepare method as this - * will authorize the package to prepare the VPN without consent in the future. - * - * @hide - */ - @SystemApi - @RequiresPermission(android.Manifest.permission.CONTROL_VPN) - public static void prepareAndAuthorize(Context context) { - IVpnManager vm = getService(); - String packageName = context.getPackageName(); - try { - // Only prepare if we're not already prepared. - int userId = context.getUserId(); - if (!vm.prepareVpn(packageName, null, userId)) { - vm.prepareVpn(null, packageName, userId); - } - vm.setVpnPackageAuthorization(packageName, userId, VpnManager.TYPE_VPN_SERVICE); - } catch (RemoteException e) { - // ignore - } - } - - /** - * Protect a socket from VPN connections. After protecting, data sent - * through this socket will go directly to the underlying network, - * so its traffic will not be forwarded through the VPN. - * This method is useful if some connections need to be kept - * outside of VPN. For example, a VPN tunnel should protect itself if its - * destination is covered by VPN routes. Otherwise its outgoing packets - * will be sent back to the VPN interface and cause an infinite loop. This - * method will fail if the application is not prepared or is revoked. - * - *

The socket is NOT closed by this method. - * - * @return {@code true} on success. - */ - public boolean protect(int socket) { - return NetworkUtils.protectFromVpn(socket); - } - - /** - * Convenience method to protect a {@link Socket} from VPN connections. - * - * @return {@code true} on success. - * @see #protect(int) - */ - public boolean protect(Socket socket) { - return protect(socket.getFileDescriptor$().getInt$()); - } - - /** - * Convenience method to protect a {@link DatagramSocket} from VPN - * connections. - * - * @return {@code true} on success. - * @see #protect(int) - */ - public boolean protect(DatagramSocket socket) { - return protect(socket.getFileDescriptor$().getInt$()); - } - - /** - * Adds a network address to the VPN interface. - * - * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the - * address is already in use or cannot be assigned to the interface for any other reason. - * - * Adding an address implicitly allows traffic from that address family (i.e., IPv4 or IPv6) to - * be routed over the VPN. @see Builder#allowFamily - * - * @throws IllegalArgumentException if the address is invalid. - * - * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface. - * @param prefixLength The prefix length of the address. - * - * @return {@code true} on success. - * @see Builder#addAddress - * - * @hide - */ - public boolean addAddress(InetAddress address, int prefixLength) { - check(address, prefixLength); - try { - return getService().addVpnAddress(address.getHostAddress(), prefixLength); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - - /** - * Removes a network address from the VPN interface. - * - * Both IPv4 and IPv6 addresses are supported. The VPN must already be established. Fails if the - * address is not assigned to the VPN interface, or if it is the only address assigned (thus - * cannot be removed), or if the address cannot be removed for any other reason. - * - * After removing an address, if there are no addresses, routes or DNS servers of a particular - * address family (i.e., IPv4 or IPv6) configured on the VPN, that DOES NOT block that - * family from being routed. In other words, once an address family has been allowed, it stays - * allowed for the rest of the VPN's session. @see Builder#allowFamily - * - * @throws IllegalArgumentException if the address is invalid. - * - * @param address The IP address (IPv4 or IPv6) to assign to the VPN interface. - * @param prefixLength The prefix length of the address. - * - * @return {@code true} on success. - * - * @hide - */ - public boolean removeAddress(InetAddress address, int prefixLength) { - check(address, prefixLength); - try { - return getService().removeVpnAddress(address.getHostAddress(), prefixLength); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - - /** - * Sets the underlying networks used by the VPN for its upstream connections. - * - *

Used by the system to know the actual networks that carry traffic for apps affected by - * this VPN in order to present this information to the user (e.g., via status bar icons). - * - *

This method only needs to be called if the VPN has explicitly bound its underlying - * communications channels — such as the socket(s) passed to {@link #protect(int)} — - * to a {@code Network} using APIs such as {@link Network#bindSocket(Socket)} or - * {@link Network#bindSocket(DatagramSocket)}. The VPN should call this method every time - * the set of {@code Network}s it is using changes. - * - *

{@code networks} is one of the following: - *

    - *
  • a non-empty array: an array of one or more {@link Network}s, in - * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) - * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear - * first in the array.
  • - *
  • an empty array: a zero-element array, meaning that the VPN has no - * underlying network connection, and thus, app traffic will not be sent or received.
  • - *
  • null: (default) signifies that the VPN uses whatever is the system's - * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} - * APIs mentioned above to send traffic over specific channels.
  • - *
- * - *

This call will succeed only if the VPN is currently established. For setting this value - * when the VPN has not yet been established, see {@link Builder#setUnderlyingNetworks}. - * - * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. - * - * @return {@code true} on success. - */ - public boolean setUnderlyingNetworks(Network[] networks) { - try { - return getService().setUnderlyingNetworksForVpn(networks); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - - /** - * Returns whether the service is running in always-on VPN mode. In this mode the system ensures - * that the service is always running by restarting it when necessary, e.g. after reboot. - * - * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) - */ - public final boolean isAlwaysOn() { - try { - return getService().isCallerCurrentAlwaysOnVpnApp(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Returns whether the service is running in always-on VPN lockdown mode. In this mode the - * system ensures that the service is always running and that the apps aren't allowed to bypass - * the VPN. - * - * @see DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set) - */ - public final boolean isLockdownEnabled() { - try { - return getService().isCallerCurrentAlwaysOnVpnLockdownApp(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Return the communication interface to the service. This method returns - * {@code null} on {@link Intent}s other than {@link #SERVICE_INTERFACE} - * action. Applications overriding this method must identify the intent - * and return the corresponding interface accordingly. - * - * @see Service#onBind - */ - @Override - public IBinder onBind(Intent intent) { - if (intent != null && SERVICE_INTERFACE.equals(intent.getAction())) { - return new Callback(); - } - return null; - } - - /** - * Invoked when the application is revoked. At this moment, the VPN - * interface is already deactivated by the system. The application should - * close the file descriptor and shut down gracefully. The default - * implementation of this method is calling {@link Service#stopSelf()}. - * - *

Calls to this method may not happen on the main thread - * of the process. - * - * @see #prepare - */ - public void onRevoke() { - stopSelf(); - } - - /** - * Use raw Binder instead of AIDL since now there is only one usage. - */ - private class Callback extends Binder { - @Override - protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) { - if (code == IBinder.LAST_CALL_TRANSACTION) { - onRevoke(); - return true; - } - return false; - } - } - - /** - * Private method to validate address and prefixLength. - */ - private static void check(InetAddress address, int prefixLength) { - if (address.isLoopbackAddress()) { - throw new IllegalArgumentException("Bad address"); - } - if (address instanceof Inet4Address) { - if (prefixLength < 0 || prefixLength > 32) { - throw new IllegalArgumentException("Bad prefixLength"); - } - } else if (address instanceof Inet6Address) { - if (prefixLength < 0 || prefixLength > 128) { - throw new IllegalArgumentException("Bad prefixLength"); - } - } else { - throw new IllegalArgumentException("Unsupported family"); - } - } - - /** - * Helper class to create a VPN interface. This class should be always - * used within the scope of the outer {@link VpnService}. - * - * @see VpnService - */ - public class Builder { - - private final VpnConfig mConfig = new VpnConfig(); - @UnsupportedAppUsage - private final List mAddresses = new ArrayList(); - @UnsupportedAppUsage - private final List mRoutes = new ArrayList(); - - public Builder() { - mConfig.user = VpnService.this.getClass().getName(); - } - - /** - * Set the name of this session. It will be displayed in - * system-managed dialogs and notifications. This is recommended - * not required. - */ - @NonNull - public Builder setSession(@NonNull String session) { - mConfig.session = session; - return this; - } - - /** - * Set the {@link PendingIntent} to an activity for users to - * configure the VPN connection. If it is not set, the button - * to configure will not be shown in system-managed dialogs. - */ - @NonNull - public Builder setConfigureIntent(@NonNull PendingIntent intent) { - mConfig.configureIntent = intent; - return this; - } - - /** - * Set the maximum transmission unit (MTU) of the VPN interface. If - * it is not set, the default value in the operating system will be - * used. - * - * @throws IllegalArgumentException if the value is not positive. - */ - @NonNull - public Builder setMtu(int mtu) { - if (mtu <= 0) { - throw new IllegalArgumentException("Bad mtu"); - } - mConfig.mtu = mtu; - return this; - } - - /** - * Sets an HTTP proxy for the VPN network. This proxy is only a recommendation - * and it is possible that some apps will ignore it. - */ - @NonNull - public Builder setHttpProxy(@NonNull ProxyInfo proxyInfo) { - mConfig.proxyInfo = proxyInfo; - return this; - } - - /** - * Add a network address to the VPN interface. Both IPv4 and IPv6 - * addresses are supported. At least one address must be set before - * calling {@link #establish}. - * - * Adding an address implicitly allows traffic from that address family - * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily - * - * @throws IllegalArgumentException if the address is invalid. - */ - @NonNull - public Builder addAddress(@NonNull InetAddress address, int prefixLength) { - check(address, prefixLength); - - if (address.isAnyLocalAddress()) { - throw new IllegalArgumentException("Bad address"); - } - mAddresses.add(new LinkAddress(address, prefixLength)); - mConfig.updateAllowedFamilies(address); - return this; - } - - /** - * Convenience method to add a network address to the VPN interface - * using a numeric address string. See {@link InetAddress} for the - * definitions of numeric address formats. - * - * Adding an address implicitly allows traffic from that address family - * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily - * - * @throws IllegalArgumentException if the address is invalid. - * @see #addAddress(InetAddress, int) - */ - @NonNull - public Builder addAddress(@NonNull String address, int prefixLength) { - return addAddress(InetAddress.parseNumericAddress(address), prefixLength); - } - - /** - * Add a network route to the VPN interface. Both IPv4 and IPv6 - * routes are supported. - * - * Adding a route implicitly allows traffic from that address family - * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily - * - * @throws IllegalArgumentException if the route is invalid. - */ - @NonNull - public Builder addRoute(@NonNull InetAddress address, int prefixLength) { - check(address, prefixLength); - - int offset = prefixLength / 8; - byte[] bytes = address.getAddress(); - if (offset < bytes.length) { - for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) { - if (bytes[offset] != 0) { - throw new IllegalArgumentException("Bad address"); - } - } - } - mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null)); - mConfig.updateAllowedFamilies(address); - return this; - } - - /** - * Convenience method to add a network route to the VPN interface - * using a numeric address string. See {@link InetAddress} for the - * definitions of numeric address formats. - * - * Adding a route implicitly allows traffic from that address family - * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily - * - * @throws IllegalArgumentException if the route is invalid. - * @see #addRoute(InetAddress, int) - */ - @NonNull - public Builder addRoute(@NonNull String address, int prefixLength) { - return addRoute(InetAddress.parseNumericAddress(address), prefixLength); - } - - /** - * Add a DNS server to the VPN connection. Both IPv4 and IPv6 - * addresses are supported. If none is set, the DNS servers of - * the default network will be used. - * - * Adding a server implicitly allows traffic from that address family - * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily - * - * @throws IllegalArgumentException if the address is invalid. - */ - @NonNull - public Builder addDnsServer(@NonNull InetAddress address) { - if (address.isLoopbackAddress() || address.isAnyLocalAddress()) { - throw new IllegalArgumentException("Bad address"); - } - if (mConfig.dnsServers == null) { - mConfig.dnsServers = new ArrayList(); - } - mConfig.dnsServers.add(address.getHostAddress()); - return this; - } - - /** - * Convenience method to add a DNS server to the VPN connection - * using a numeric address string. See {@link InetAddress} for the - * definitions of numeric address formats. - * - * Adding a server implicitly allows traffic from that address family - * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily - * - * @throws IllegalArgumentException if the address is invalid. - * @see #addDnsServer(InetAddress) - */ - @NonNull - public Builder addDnsServer(@NonNull String address) { - return addDnsServer(InetAddress.parseNumericAddress(address)); - } - - /** - * Add a search domain to the DNS resolver. - */ - @NonNull - public Builder addSearchDomain(@NonNull String domain) { - if (mConfig.searchDomains == null) { - mConfig.searchDomains = new ArrayList(); - } - mConfig.searchDomains.add(domain); - return this; - } - - /** - * Allows traffic from the specified address family. - * - * By default, if no address, route or DNS server of a specific family (IPv4 or IPv6) is - * added to this VPN, then all outgoing traffic of that family is blocked. If any address, - * route or DNS server is added, that family is allowed. - * - * This method allows an address family to be unblocked even without adding an address, - * route or DNS server of that family. Traffic of that family will then typically - * fall-through to the underlying network if it's supported. - * - * {@code family} must be either {@code AF_INET} (for IPv4) or {@code AF_INET6} (for IPv6). - * {@link IllegalArgumentException} is thrown if it's neither. - * - * @param family The address family ({@code AF_INET} or {@code AF_INET6}) to allow. - * - * @return this {@link Builder} object to facilitate chaining of method calls. - */ - @NonNull - public Builder allowFamily(int family) { - if (family == AF_INET) { - mConfig.allowIPv4 = true; - } else if (family == AF_INET6) { - mConfig.allowIPv6 = true; - } else { - throw new IllegalArgumentException(family + " is neither " + AF_INET + " nor " + - AF_INET6); - } - return this; - } - - private void verifyApp(String packageName) throws PackageManager.NameNotFoundException { - IPackageManager pm = IPackageManager.Stub.asInterface( - ServiceManager.getService("package")); - try { - pm.getApplicationInfo(packageName, 0, UserHandle.getCallingUserId()); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - - /** - * Adds an application that's allowed to access the VPN connection. - * - * If this method is called at least once, only applications added through this method (and - * no others) are allowed access. Else (if this method is never called), all applications - * are allowed by default. If some applications are added, other, un-added applications - * will use networking as if the VPN wasn't running. - * - * A {@link Builder} may have only a set of allowed applications OR a set of disallowed - * ones, but not both. Calling this method after {@link #addDisallowedApplication} has - * already been called, or vice versa, will throw an {@link UnsupportedOperationException}. - * - * {@code packageName} must be the canonical name of a currently installed application. - * {@link PackageManager.NameNotFoundException} is thrown if there's no such application. - * - * @throws PackageManager.NameNotFoundException If the application isn't installed. - * - * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application. - * - * @return this {@link Builder} object to facilitate chaining method calls. - */ - @NonNull - public Builder addAllowedApplication(@NonNull String packageName) - throws PackageManager.NameNotFoundException { - if (mConfig.disallowedApplications != null) { - throw new UnsupportedOperationException("addDisallowedApplication already called"); - } - verifyApp(packageName); - if (mConfig.allowedApplications == null) { - mConfig.allowedApplications = new ArrayList(); - } - mConfig.allowedApplications.add(packageName); - return this; - } - - /** - * Adds an application that's denied access to the VPN connection. - * - * By default, all applications are allowed access, except for those denied through this - * method. Denied applications will use networking as if the VPN wasn't running. - * - * A {@link Builder} may have only a set of allowed applications OR a set of disallowed - * ones, but not both. Calling this method after {@link #addAllowedApplication} has already - * been called, or vice versa, will throw an {@link UnsupportedOperationException}. - * - * {@code packageName} must be the canonical name of a currently installed application. - * {@link PackageManager.NameNotFoundException} is thrown if there's no such application. - * - * @throws PackageManager.NameNotFoundException If the application isn't installed. - * - * @param packageName The full name (e.g.: "com.google.apps.contacts") of an application. - * - * @return this {@link Builder} object to facilitate chaining method calls. - */ - @NonNull - public Builder addDisallowedApplication(@NonNull String packageName) - throws PackageManager.NameNotFoundException { - if (mConfig.allowedApplications != null) { - throw new UnsupportedOperationException("addAllowedApplication already called"); - } - verifyApp(packageName); - if (mConfig.disallowedApplications == null) { - mConfig.disallowedApplications = new ArrayList(); - } - mConfig.disallowedApplications.add(packageName); - return this; - } - - /** - * Allows all apps to bypass this VPN connection. - * - * By default, all traffic from apps is forwarded through the VPN interface and it is not - * possible for apps to side-step the VPN. If this method is called, apps may use methods - * such as {@link ConnectivityManager#bindProcessToNetwork} to instead send/receive - * directly over the underlying network or any other network they have permissions for. - * - * @return this {@link Builder} object to facilitate chaining of method calls. - */ - @NonNull - public Builder allowBypass() { - mConfig.allowBypass = true; - return this; - } - - /** - * Sets the VPN interface's file descriptor to be in blocking/non-blocking mode. - * - * By default, the file descriptor returned by {@link #establish} is non-blocking. - * - * @param blocking True to put the descriptor into blocking mode; false for non-blocking. - * - * @return this {@link Builder} object to facilitate chaining method calls. - */ - @NonNull - public Builder setBlocking(boolean blocking) { - mConfig.blocking = blocking; - return this; - } - - /** - * Sets the underlying networks used by the VPN for its upstream connections. - * - * @see VpnService#setUnderlyingNetworks - * - * @param networks An array of networks the VPN uses to tunnel traffic to/from its servers. - * - * @return this {@link Builder} object to facilitate chaining method calls. - */ - @NonNull - public Builder setUnderlyingNetworks(@Nullable Network[] networks) { - mConfig.underlyingNetworks = networks != null ? networks.clone() : null; - return this; - } - - /** - * Marks the VPN network as metered. A VPN network is classified as metered when the user is - * sensitive to heavy data usage due to monetary costs and/or data limitations. In such - * cases, you should set this to {@code true} so that apps on the system can avoid doing - * large data transfers. Otherwise, set this to {@code false}. Doing so would cause VPN - * network to inherit its meteredness from its underlying networks. - * - *

VPN apps targeting {@link android.os.Build.VERSION_CODES#Q} or above will be - * considered metered by default. - * - * @param isMetered {@code true} if VPN network should be treated as metered regardless of - * underlying network meteredness - * @return this {@link Builder} object to facilitate chaining method calls - * @see #setUnderlyingNetworks(Network[]) - * @see ConnectivityManager#isActiveNetworkMetered() - */ - @NonNull - public Builder setMetered(boolean isMetered) { - mConfig.isMetered = isMetered; - return this; - } - - /** - * Create a VPN interface using the parameters supplied to this - * builder. The interface works on IP packets, and a file descriptor - * is returned for the application to access them. Each read - * retrieves an outgoing packet which was routed to the interface. - * Each write injects an incoming packet just like it was received - * from the interface. The file descriptor is put into non-blocking - * mode by default to avoid blocking Java threads. To use the file - * descriptor completely in native space, see - * {@link ParcelFileDescriptor#detachFd()}. The application MUST - * close the file descriptor when the VPN connection is terminated. - * The VPN interface will be removed and the network will be - * restored by the system automatically. - * - *

To avoid conflicts, there can be only one active VPN interface - * at the same time. Usually network parameters are never changed - * during the lifetime of a VPN connection. It is also common for an - * application to create a new file descriptor after closing the - * previous one. However, it is rare but not impossible to have two - * interfaces while performing a seamless handover. In this case, the - * old interface will be deactivated when the new one is created - * successfully. Both file descriptors are valid but now outgoing - * packets will be routed to the new interface. Therefore, after - * draining the old file descriptor, the application MUST close it - * and start using the new file descriptor. If the new interface - * cannot be created, the existing interface and its file descriptor - * remain untouched. - * - *

An exception will be thrown if the interface cannot be created - * for any reason. However, this method returns {@code null} if the - * application is not prepared or is revoked. This helps solve - * possible race conditions between other VPN applications. - * - * @return {@link ParcelFileDescriptor} of the VPN interface, or - * {@code null} if the application is not prepared. - * @throws IllegalArgumentException if a parameter is not accepted - * by the operating system. - * @throws IllegalStateException if a parameter cannot be applied - * by the operating system. - * @throws SecurityException if the service is not properly declared - * in {@code AndroidManifest.xml}. - * @see VpnService - */ - @Nullable - public ParcelFileDescriptor establish() { - mConfig.addresses = mAddresses; - mConfig.routes = mRoutes; - - try { - return getService().establishVpn(mConfig); - } catch (RemoteException e) { - throw new IllegalStateException(e); - } - } - } -} diff --git a/service/Android.bp b/service/Android.bp index 8fc3181807..ed1716fad8 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -25,7 +25,6 @@ cc_library_shared { ], srcs: [ "jni/com_android_server_TestNetworkService.cpp", - "jni/com_android_server_connectivity_Vpn.cpp", "jni/onload.cpp", ], shared_libs: [ diff --git a/service/jni/com_android_server_connectivity_Vpn.cpp b/service/jni/com_android_server_connectivity_Vpn.cpp deleted file mode 100644 index ea5e7183c9..0000000000 --- a/service/jni/com_android_server_connectivity_Vpn.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2011 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 "VpnJni" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "netutils/ifc.h" - -#include "jni.h" -#include - -namespace android -{ - -static int inet4 = -1; -static int inet6 = -1; - -static inline in_addr_t *as_in_addr(sockaddr *sa) { - return &((sockaddr_in *)sa)->sin_addr.s_addr; -} - -//------------------------------------------------------------------------------ - -#define SYSTEM_ERROR (-1) -#define BAD_ARGUMENT (-2) - -static int create_interface(int mtu) -{ - int tun = open("/dev/tun", O_RDWR | O_NONBLOCK | O_CLOEXEC); - - ifreq ifr4; - memset(&ifr4, 0, sizeof(ifr4)); - - // Allocate interface. - ifr4.ifr_flags = IFF_TUN | IFF_NO_PI; - if (ioctl(tun, TUNSETIFF, &ifr4)) { - ALOGE("Cannot allocate TUN: %s", strerror(errno)); - goto error; - } - - // Activate interface. - ifr4.ifr_flags = IFF_UP; - if (ioctl(inet4, SIOCSIFFLAGS, &ifr4)) { - ALOGE("Cannot activate %s: %s", ifr4.ifr_name, strerror(errno)); - goto error; - } - - // Set MTU if it is specified. - ifr4.ifr_mtu = mtu; - if (mtu > 0 && ioctl(inet4, SIOCSIFMTU, &ifr4)) { - ALOGE("Cannot set MTU on %s: %s", ifr4.ifr_name, strerror(errno)); - goto error; - } - - return tun; - -error: - close(tun); - return SYSTEM_ERROR; -} - -static int get_interface_name(char *name, int tun) -{ - ifreq ifr4; - if (ioctl(tun, TUNGETIFF, &ifr4)) { - ALOGE("Cannot get interface name: %s", strerror(errno)); - return SYSTEM_ERROR; - } - strncpy(name, ifr4.ifr_name, IFNAMSIZ); - return 0; -} - -static int get_interface_index(const char *name) -{ - ifreq ifr4; - strncpy(ifr4.ifr_name, name, IFNAMSIZ); - if (ioctl(inet4, SIOGIFINDEX, &ifr4)) { - ALOGE("Cannot get index of %s: %s", name, strerror(errno)); - return SYSTEM_ERROR; - } - return ifr4.ifr_ifindex; -} - -static int set_addresses(const char *name, const char *addresses) -{ - int index = get_interface_index(name); - if (index < 0) { - return index; - } - - ifreq ifr4; - memset(&ifr4, 0, sizeof(ifr4)); - strncpy(ifr4.ifr_name, name, IFNAMSIZ); - ifr4.ifr_addr.sa_family = AF_INET; - ifr4.ifr_netmask.sa_family = AF_INET; - - in6_ifreq ifr6; - memset(&ifr6, 0, sizeof(ifr6)); - ifr6.ifr6_ifindex = index; - - char address[65]; - int prefix; - int chars; - int count = 0; - - while (sscanf(addresses, " %64[^/]/%d %n", address, &prefix, &chars) == 2) { - addresses += chars; - - if (strchr(address, ':')) { - // Add an IPv6 address. - if (inet_pton(AF_INET6, address, &ifr6.ifr6_addr) != 1 || - prefix < 0 || prefix > 128) { - count = BAD_ARGUMENT; - break; - } - - ifr6.ifr6_prefixlen = prefix; - if (ioctl(inet6, SIOCSIFADDR, &ifr6)) { - count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; - break; - } - } else { - // Add an IPv4 address. - if (inet_pton(AF_INET, address, as_in_addr(&ifr4.ifr_addr)) != 1 || - prefix < 0 || prefix > 32) { - count = BAD_ARGUMENT; - break; - } - - if (count) { - snprintf(ifr4.ifr_name, sizeof(ifr4.ifr_name), "%s:%d", name, count); - } - if (ioctl(inet4, SIOCSIFADDR, &ifr4)) { - count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; - break; - } - - in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0; - *as_in_addr(&ifr4.ifr_netmask) = htonl(mask); - if (ioctl(inet4, SIOCSIFNETMASK, &ifr4)) { - count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; - break; - } - } - ALOGD("Address added on %s: %s/%d", name, address, prefix); - ++count; - } - - if (count == BAD_ARGUMENT) { - ALOGE("Invalid address: %s/%d", address, prefix); - } else if (count == SYSTEM_ERROR) { - ALOGE("Cannot add address: %s/%d: %s", address, prefix, strerror(errno)); - } else if (*addresses) { - ALOGE("Invalid address: %s", addresses); - count = BAD_ARGUMENT; - } - - return count; -} - -static int reset_interface(const char *name) -{ - ifreq ifr4; - strncpy(ifr4.ifr_name, name, IFNAMSIZ); - ifr4.ifr_flags = 0; - - if (ioctl(inet4, SIOCSIFFLAGS, &ifr4) && errno != ENODEV) { - ALOGE("Cannot reset %s: %s", name, strerror(errno)); - return SYSTEM_ERROR; - } - return 0; -} - -static int check_interface(const char *name) -{ - ifreq ifr4; - strncpy(ifr4.ifr_name, name, IFNAMSIZ); - ifr4.ifr_flags = 0; - - if (ioctl(inet4, SIOCGIFFLAGS, &ifr4) && errno != ENODEV) { - ALOGE("Cannot check %s: %s", name, strerror(errno)); - } - return ifr4.ifr_flags; -} - -static bool modifyAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, - jint jPrefixLength, bool add) -{ - int error = SYSTEM_ERROR; - const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; - const char *address = jAddress ? env->GetStringUTFChars(jAddress, NULL) : NULL; - - if (!name) { - jniThrowNullPointerException(env, "name"); - } else if (!address) { - jniThrowNullPointerException(env, "address"); - } else { - if (add) { - if ((error = ifc_add_address(name, address, jPrefixLength)) != 0) { - ALOGE("Cannot add address %s/%d on interface %s (%s)", address, jPrefixLength, name, - strerror(-error)); - } - } else { - if ((error = ifc_del_address(name, address, jPrefixLength)) != 0) { - ALOGE("Cannot del address %s/%d on interface %s (%s)", address, jPrefixLength, name, - strerror(-error)); - } - } - } - - if (name) { - env->ReleaseStringUTFChars(jName, name); - } - if (address) { - env->ReleaseStringUTFChars(jAddress, address); - } - return !error; -} - -//------------------------------------------------------------------------------ - -static void throwException(JNIEnv *env, int error, const char *message) -{ - if (error == SYSTEM_ERROR) { - jniThrowException(env, "java/lang/IllegalStateException", message); - } else { - jniThrowException(env, "java/lang/IllegalArgumentException", message); - } -} - -static jint create(JNIEnv *env, jobject /* thiz */, jint mtu) -{ - int tun = create_interface(mtu); - if (tun < 0) { - throwException(env, tun, "Cannot create interface"); - return -1; - } - return tun; -} - -static jstring getName(JNIEnv *env, jobject /* thiz */, jint tun) -{ - char name[IFNAMSIZ]; - if (get_interface_name(name, tun) < 0) { - throwException(env, SYSTEM_ERROR, "Cannot get interface name"); - return NULL; - } - return env->NewStringUTF(name); -} - -static jint setAddresses(JNIEnv *env, jobject /* thiz */, jstring jName, - jstring jAddresses) -{ - const char *name = NULL; - const char *addresses = NULL; - int count = -1; - - name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; - if (!name) { - jniThrowNullPointerException(env, "name"); - goto error; - } - addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL; - if (!addresses) { - jniThrowNullPointerException(env, "addresses"); - goto error; - } - count = set_addresses(name, addresses); - if (count < 0) { - throwException(env, count, "Cannot set address"); - count = -1; - } - -error: - if (name) { - env->ReleaseStringUTFChars(jName, name); - } - if (addresses) { - env->ReleaseStringUTFChars(jAddresses, addresses); - } - return count; -} - -static void reset(JNIEnv *env, jobject /* thiz */, jstring jName) -{ - const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; - if (!name) { - jniThrowNullPointerException(env, "name"); - return; - } - if (reset_interface(name) < 0) { - throwException(env, SYSTEM_ERROR, "Cannot reset interface"); - } - env->ReleaseStringUTFChars(jName, name); -} - -static jint check(JNIEnv *env, jobject /* thiz */, jstring jName) -{ - const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; - if (!name) { - jniThrowNullPointerException(env, "name"); - return 0; - } - int flags = check_interface(name); - env->ReleaseStringUTFChars(jName, name); - return flags; -} - -static bool addAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, - jint jPrefixLength) -{ - return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, true); -} - -static bool delAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, - jint jPrefixLength) -{ - return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, false); -} - -//------------------------------------------------------------------------------ - -static const JNINativeMethod gMethods[] = { - {"jniCreate", "(I)I", (void *)create}, - {"jniGetName", "(I)Ljava/lang/String;", (void *)getName}, - {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses}, - {"jniReset", "(Ljava/lang/String;)V", (void *)reset}, - {"jniCheck", "(Ljava/lang/String;)I", (void *)check}, - {"jniAddAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)addAddress}, - {"jniDelAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)delAddress}, -}; - -int register_android_server_connectivity_Vpn(JNIEnv *env) -{ - if (inet4 == -1) { - inet4 = socket(AF_INET, SOCK_DGRAM, 0); - } - if (inet6 == -1) { - inet6 = socket(AF_INET6, SOCK_DGRAM, 0); - } - return jniRegisterNativeMethods(env, "com/android/server/connectivity/Vpn", - gMethods, NELEM(gMethods)); -} - -}; diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp index 3afcb0e8f6..00128794bc 100644 --- a/service/jni/onload.cpp +++ b/service/jni/onload.cpp @@ -19,7 +19,6 @@ namespace android { -int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_TestNetworkService(JNIEnv* env); extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { @@ -29,12 +28,11 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { return JNI_ERR; } - if (register_android_server_connectivity_Vpn(env) < 0 - || register_android_server_TestNetworkService(env) < 0) { + if (register_android_server_TestNetworkService(env) < 0) { return JNI_ERR; } return JNI_VERSION_1_6; } -}; \ No newline at end of file +}; From c4e2f637584a4a1928cebe1b3efc0c4a613fc1c0 Mon Sep 17 00:00:00 2001 From: lifr Date: Mon, 1 Feb 2021 16:52:18 +0800 Subject: [PATCH 040/343] [CS01]Remove hidden API usage of NetworkCapabilities The connection service will become the mainline module. The mutable NetworkCapabilities is deprecated, and the NetworkCapabilities should be built through their Builder instead. Bug: 170598012 Test: atest FrameworksNetTests Test: atest IpConnectivityMetricsTest Change-Id: I73a4d3a7c118b9cef037ed52efb96ed123da2fa5 --- framework/src/android/net/NetworkCapabilities.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 9d67f0b843..26d14cbfaa 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -2085,9 +2085,10 @@ public final class NetworkCapabilities implements Parcelable { /** * Check if private dns is broken. * - * @return {@code true} if {@code mPrivateDnsBroken} is set when private DNS is broken. + * @return {@code true} if private DNS is broken on this network. * @hide */ + @SystemApi public boolean isPrivateDnsBroken() { return mPrivateDnsBroken; } @@ -2329,6 +2330,17 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Completely clears the contents of this object, removing even the capabilities that are + * set by default when the object is constructed. + * @return this builder + */ + @NonNull + public Builder clearAll() { + mCaps.clearAll(); + return this; + } + /** * Sets the owner UID. * From 6c7ed9dddc93ff7aea2c2508058b3a441a335d70 Mon Sep 17 00:00:00 2001 From: Bob Badour Date: Fri, 12 Feb 2021 17:07:05 -0800 Subject: [PATCH 041/343] [LSC] Add LOCAL_LICENSE_KINDS to frameworks/base Added SPDX-license-identifier-Apache-2.0 to: apct-tests/perftests/autofill/Android.bp apct-tests/perftests/blobstore/Android.bp apct-tests/perftests/core/Android.bp apct-tests/perftests/core/apps/overlay/Android.bp apct-tests/perftests/core/apps/reources_manager/Android.bp apct-tests/perftests/core/jni/Android.bp apct-tests/perftests/multiuser/Android.bp apct-tests/perftests/multiuser/apps/dummyapp/Android.bp apct-tests/perftests/packagemanager/Android.bp apct-tests/perftests/packagemanager/apps/query-all/Android.bp apct-tests/perftests/textclassifier/Android.bp apct-tests/perftests/utils/Android.bp apct-tests/perftests/windowmanager/Android.bp apex/Android.bp apex/blobstore/framework/Android.bp apex/blobstore/service/Android.bp apex/jobscheduler/framework/Android.bp apex/jobscheduler/service/Android.bp apex/media/Android.bp apex/media/aidl/Android.bp apex/media/framework/Android.bp cmds/am/Android.bp cmds/app_process/Android.bp cmds/appops/Android.bp cmds/appwidget/Android.bp cmds/backup/Android.bp cmds/bmgr/Android.bp cmds/bootanimation/Android.bp cmds/bu/Android.bp cmds/content/Android.bp cmds/dpm/Android.bp cmds/hid/Android.bp cmds/hid/jni/Android.bp cmds/idmap2/Android.bp cmds/ime/Android.bp cmds/incident/Android.bp cmds/incident_helper/Android.bp cmds/incidentd/Android.bp cmds/input/Android.bp cmds/interrupter/Android.bp cmds/locksettings/Android.bp cmds/pm/Android.bp cmds/requestsync/Android.bp cmds/screencap/Android.bp cmds/sm/Android.bp cmds/svc/Android.bp cmds/telecom/Android.bp cmds/uiautomator/Android.bp cmds/uiautomator/cmds/uiautomator/Android.bp cmds/uiautomator/instrumentation/Android.bp cmds/uiautomator/library/Android.bp cmds/vr/Android.bp cmds/wm/Android.bp config/Android.bp core/java/android/service/wallpaper/Android.bp core/jni/Android.bp core/sysprop/Android.bp core/tests/BroadcastRadioTests/Android.bp core/tests/ConnectivityManagerTest/Android.bp core/tests/PackageInstallerSessions/Android.bp core/tests/PlatformCompatFramework/Android.bp core/tests/bandwidthtests/Android.bp core/tests/benchmarks/Android.bp core/tests/bluetoothtests/Android.bp core/tests/bugreports/Android.bp core/tests/coretests/Android.bp core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp core/tests/coretests/BinderProxyCountingTestApp/Android.bp core/tests/coretests/BinderProxyCountingTestService/Android.bp core/tests/coretests/BstatsTestApp/Android.bp core/tests/coretests/DisabledTestApp/Android.bp core/tests/coretests/EnabledTestApp/Android.bp core/tests/coretests/aidl/Android.bp core/tests/coretests/apks/Android.bp core/tests/coretests/apks/install/Android.bp core/tests/coretests/apks/install_bad_dex/Android.bp core/tests/coretests/apks/install_complete_package_info/Android.bp core/tests/coretests/apks/install_decl_perm/Android.bp core/tests/coretests/apks/install_jni_lib/Android.bp core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp core/tests/coretests/apks/install_loc_auto/Android.bp core/tests/coretests/apks/install_loc_internal/Android.bp core/tests/coretests/apks/install_loc_sdcard/Android.bp core/tests/coretests/apks/install_loc_unspecified/Android.bp core/tests/coretests/apks/install_use_perm_good/Android.bp core/tests/coretests/apks/install_uses_feature/Android.bp core/tests/coretests/apks/install_verifier_bad/Android.bp core/tests/coretests/apks/install_verifier_good/Android.bp core/tests/coretests/apks/keyset/Android.bp core/tests/coretests/apks/locales/Android.bp core/tests/coretests/apks/overlay_config/Android.bp core/tests/coretests/apks/version/Android.bp core/tests/coretests/apks/version_nosys/Android.bp core/tests/featureflagtests/Android.bp core/tests/hdmitests/Android.bp core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp core/tests/hosttests/test-apps/NoLocTestApp/Android.bp core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp core/tests/hosttests/test-apps/SharedUid/32/Android.bp core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp core/tests/hosttests/test-apps/SharedUid/64/Android.bp core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp core/tests/hosttests/test-apps/SharedUid/dual/Android.bp core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp core/tests/hosttests/test-apps/SimpleTestApp/Android.bp core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp core/tests/mockingcoretests/Android.bp core/tests/notificationtests/Android.bp core/tests/overlaytests/device/Android.bp core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp core/tests/overlaytests/host/Android.bp core/tests/overlaytests/remount/Android.bp core/tests/overlaytests/remount/test-apps/Overlay/Android.bp core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp core/tests/overlaytests/remount/test-apps/Target/Android.bp core/tests/packagemanagertests/Android.bp core/tests/privacytests/Android.bp core/tests/screenshothelpertests/Android.bp core/tests/systemproperties/Android.bp core/tests/utillib/Android.bp core/tests/utiltests/Android.bp core/tests/utiltests/jni/Android.bp core/tests/uwbtests/Android.bp core/xsd/Android.bp core/xsd/vts/Android.bp data/etc/Android.bp data/etc/car/Android.bp data/fonts/Android.bp data/keyboards/Android.mk drm/jni/Android.bp errorprone/Android.bp graphics/proto/Android.bp keystore/Android.bp keystore/tests/Android.bp libs/WindowManager/Jetpack/Android.bp libs/WindowManager/Shell/Android.bp libs/WindowManager/Shell/tests/Android.bp libs/androidfw/Android.bp libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp libs/hostgraphics/Android.bp libs/incident/Android.bp libs/input/Android.bp libs/input/tests/Android.bp libs/protoutil/Android.bp libs/services/Android.bp libs/storage/Android.bp libs/usb/tests/AccessoryChat/Android.bp libs/usb/tests/AccessoryChat/accessorychat/Android.bp location/lib/Android.bp location/tests/Android.bp location/tests/locationtests/Android.bp lowpan/tests/Android.bp media/Android.bp media/java/Android.bp media/java/android/media/tv/tunerresourcemanager/Android.bp media/jni/Android.bp media/jni/audioeffect/Android.bp media/jni/soundpool/Android.bp media/jni/soundpool/tests/Android.bp media/lib/remotedisplay/Android.bp media/lib/signer/Android.bp media/lib/tvremote/Android.bp media/lib/tvremote/tests/Android.bp media/mca/filterfw/Android.bp media/mca/filterfw/native/Android.bp media/mca/filterpacks/Android.bp media/mca/samples/CameraEffectsRecordingSample/Android.bp media/mca/tests/Android.bp media/native/midi/Android.bp media/packages/BluetoothMidiService/Android.bp media/packages/BluetoothMidiService/tests/unit/Android.bp media/tests/AudioPolicyTest/Android.bp media/tests/CameraBrowser/Android.bp media/tests/EffectsTest/Android.bp media/tests/MediaDump/Android.bp media/tests/MediaFrameworkTest/Android.bp media/tests/MediaRouter/Android.bp media/tests/MtpTests/Android.bp media/tests/ScoAudioTest/Android.bp media/tests/SoundPoolTest/Android.bp media/tests/TunerTest/Android.bp media/tests/audiotests/Android.bp media/tests/players/Android.bp mime/Android.bp native/android/Android.bp native/graphics/jni/Android.bp native/webview/loader/Android.bp nfc-extras/Android.bp nfc-extras/tests/Android.bp packages/AppPredictionLib/Android.bp packages/BackupEncryption/Android.bp packages/BackupEncryption/test/robolectric-integration/Android.bp packages/BackupEncryption/test/robolectric/Android.bp packages/BackupEncryption/test/unittest/Android.bp packages/BackupRestoreConfirmation/Android.bp packages/CarSystemUI/Android.bp packages/CarrierDefaultApp/Android.bp packages/CarrierDefaultApp/tests/unit/Android.bp packages/CompanionDeviceManager/Android.bp packages/Connectivity/framework/Android.bp packages/Connectivity/service/Android.bp packages/CtsShim/Android.bp packages/CtsShim/build/Android.bp packages/CtsShim/build/jni/Android.bp packages/DynamicSystemInstallationService/Android.bp packages/DynamicSystemInstallationService/tests/Android.bp packages/EasterEgg/Android.bp packages/EncryptedLocalTransport/Android.bp packages/ExtShared/Android.bp packages/ExternalStorageProvider/Android.bp packages/ExternalStorageProvider/tests/Android.bp packages/FakeOemFeatures/Android.bp packages/FusedLocation/Android.bp packages/InputDevices/Android.bp packages/LocalTransport/Android.bp packages/PackageInstaller/Android.bp packages/PrintRecommendationService/Android.bp packages/PrintSpooler/Android.bp packages/PrintSpooler/jni/Android.bp packages/PrintSpooler/tests/outofprocess/Android.bp packages/SettingsLib/ActionBarShadow/Android.bp packages/SettingsLib/ActionButtonsPreference/Android.bp packages/SettingsLib/AdaptiveIcon/Android.bp packages/SettingsLib/Android.bp packages/SettingsLib/AppPreference/Android.bp packages/SettingsLib/BarChartPreference/Android.bp packages/SettingsLib/DisplayDensityUtils/Android.bp packages/SettingsLib/EntityHeaderWidgets/Android.bp packages/SettingsLib/HelpUtils/Android.bp packages/SettingsLib/LayoutPreference/Android.bp packages/SettingsLib/ProgressBar/Android.bp packages/SettingsLib/RadioButtonPreference/Android.bp packages/SettingsLib/RestrictedLockUtils/Android.bp packages/SettingsLib/SchedulesProvider/Android.bp packages/SettingsLib/SearchProvider/Android.bp packages/SettingsLib/SearchWidget/Android.bp packages/SettingsLib/SettingsSpinner/Android.bp packages/SettingsLib/SettingsTheme/Android.bp packages/SettingsLib/Tile/Android.bp packages/SettingsLib/Utils/Android.bp packages/SettingsLib/search/Android.bp packages/SettingsLib/tests/integ/Android.bp packages/SettingsLib/tests/robotests/Android.bp packages/SettingsProvider/Android.bp packages/SharedStorageBackup/Android.bp packages/Shell/Android.bp packages/Shell/tests/Android.bp packages/SimAppDialog/Android.bp packages/SoundPicker/Android.bp packages/StatementService/Android.bp packages/SystemUI/Android.bp packages/SystemUI/plugin/Android.bp packages/SystemUI/plugin/ExamplePlugin/Android.bp packages/SystemUI/plugin_core/Android.bp packages/SystemUI/shared/Android.bp packages/VpnDialogs/Android.bp packages/WAPPushManager/Android.bp packages/WAPPushManager/tests/Android.bp packages/WallpaperBackup/Android.bp packages/WallpaperCropper/Android.bp packages/overlays/Android.mk packages/overlays/tests/Android.bp packages/services/PacProcessor/Android.bp packages/services/PacProcessor/jni/Android.bp packages/services/Proxy/Android.bp proto/Android.bp rs/jni/Android.mk samples/demo/haptic-assessment/Android.bp sax/tests/saxtests/Android.bp services/Android.bp services/accessibility/Android.bp services/appprediction/Android.bp services/appwidget/Android.bp services/autofill/Android.bp services/backup/Android.bp services/backup/backuplib/Android.bp services/companion/Android.bp services/contentcapture/Android.bp services/contentsuggestions/Android.bp services/core/Android.bp services/core/java/com/android/server/vcn/Android.bp services/core/jni/Android.bp services/core/xsd/Android.bp services/core/xsd/vts/Android.bp services/coverage/Android.bp services/devicepolicy/Android.bp services/incremental/Android.bp services/midi/Android.bp services/net/Android.bp services/people/Android.bp services/print/Android.bp services/profcollect/Android.bp services/restrictions/Android.bp services/robotests/Android.bp services/robotests/backup/Android.bp services/systemcaptions/Android.bp services/tests/PackageManagerComponentOverrideTests/Android.bp services/tests/PackageManagerServiceTests/host/Android.bp services/tests/PackageManagerServiceTests/host/test-apps/Android.bp services/tests/mockingservicestests/Android.bp services/tests/rescueparty/Android.bp services/tests/servicestests/Android.bp services/tests/servicestests/aidl/Android.bp services/tests/servicestests/apks/Android.bp services/tests/servicestests/apks/install-split-base/Android.bp services/tests/servicestests/apks/install-split-feature-a/Android.bp services/tests/servicestests/apks/install_intent_filters/Android.bp services/tests/servicestests/apks/install_uses_sdk/Android.bp services/tests/servicestests/test-apps/ConnTestApp/Android.bp services/tests/servicestests/test-apps/JobTestApp/Android.bp services/tests/servicestests/test-apps/PackageParserApp/Android.bp services/tests/servicestests/test-apps/PackageParsingTestManifests/Android.bp services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp services/tests/servicestests/test-apps/SuspendTestApp/Android.bp services/tests/shortcutmanagerutils/Android.bp services/tests/uiservicestests/Android.bp services/tests/wmtests/Android.bp services/usage/Android.bp services/usb/Android.bp services/voiceinteraction/Android.bp services/wifi/Android.bp startop/apps/test/Android.bp startop/iorap/Android.bp startop/iorap/functional_tests/Android.bp startop/iorap/stress/Android.bp startop/iorap/tests/Android.bp startop/view_compiler/Android.bp startop/view_compiler/dex_builder_test/Android.bp test-base/hiddenapi/Android.bp test-mock/Android.bp test-runner/tests/Android.bp tests/AccessibilityEventsLogger/Android.bp tests/AccessoryDisplay/common/Android.bp tests/AccessoryDisplay/sink/Android.bp tests/AccessoryDisplay/source/Android.bp tests/ActivityManagerPerfTests/stub-app/Android.bp tests/ActivityManagerPerfTests/test-app/Android.bp tests/ActivityManagerPerfTests/tests/Android.bp tests/ActivityManagerPerfTests/utils/Android.bp tests/ActivityTests/Android.bp tests/ActivityViewTest/Android.bp tests/AmSlam/Android.bp tests/ApkVerityTest/Android.bp tests/ApkVerityTest/ApkVerityTestApp/Android.bp tests/ApkVerityTest/block_device_writer/Android.bp tests/AppLaunch/Android.bp tests/AppLaunchWear/Android.bp tests/AppResourcesLoaders/Android.bp tests/AppResourcesLoaders/Overlay/Android.bp tests/Assist/Android.bp tests/AutoVerify/app1/Android.bp tests/AutoVerify/app2/Android.bp tests/AutoVerify/app3/Android.bp tests/AutoVerify/app4/Android.bp tests/BackgroundDexOptServiceIntegrationTests/Android.bp tests/BandwidthTests/Android.bp tests/BatteryWaster/Android.bp tests/BiDiTests/Android.bp tests/BlobStoreTestUtils/Android.bp tests/BootImageProfileTest/Android.bp tests/BrowserPowerTest/Android.bp tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp tests/CameraPrewarmTest/Android.bp tests/Codegen/Android.bp tests/Compatibility/Android.bp tests/CoreTests/android/Android.bp tests/DataIdleTest/Android.bp tests/DozeTest/Android.bp tests/DpiTest/Android.bp tests/DynamicCodeLoggerIntegrationTests/Android.mk tests/FeatureSplit/base/Android.bp tests/FeatureSplit/feature1/Android.bp tests/FeatureSplit/feature2/Android.bp tests/FixVibrateSetting/Android.bp tests/FlickerTests/Android.bp tests/FlickerTests/test-apps/Android.bp tests/FlickerTests/test-apps/flickerapp/Android.bp tests/FrameworkPerf/Android.bp tests/GamePerformance/Android.bp tests/GridLayoutTest/Android.bp tests/HierarchyViewerTest/Android.bp tests/HugeBackup/Android.bp tests/HwAccelerationTest/Android.bp tests/Internal/Android.bp tests/JankBench/Android.bp tests/JobSchedulerPerfTests/Android.bp tests/JobSchedulerTestApp/Android.bp tests/LargeAssetTest/Android.bp tests/LegacyAssistant/Android.bp tests/LocalizationTest/Android.bp tests/LocationTracker/Android.bp tests/LotsOfApps/Android.bp tests/LowStorageTest/Android.bp tests/ManagedProfileLifecycleStressTest/Android.bp tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp tests/MemoryUsage/Android.bp tests/MirrorSurfaceTest/Android.bp tests/NativeProcessesMemoryTest/Android.bp tests/NetworkSecurityConfigTest/Android.bp tests/NullHomeTest/Android.bp tests/OdmApps/Android.bp tests/OdmApps/app/Android.bp tests/OdmApps/priv-app/Android.bp tests/OneMedia/Android.bp tests/PackageWatchdog/Android.bp tests/PlatformCompatGating/Android.bp tests/PlatformCompatGating/test-rules/Android.bp tests/ProtoInputStreamTests/Android.bp tests/RemoteDisplayProvider/Android.bp tests/RenderThreadTest/Android.bp tests/RollbackTest/Android.bp tests/SerialChat/Android.bp tests/ServiceCrashTest/Android.bp tests/SharedLibrary/client/Android.bp tests/SharedLibrary/lib/Android.bp tests/ShowWhenLockedApp/Android.bp tests/SmokeTest/Android.bp tests/SmokeTest/tests/Android.bp tests/SmokeTestApps/Android.bp tests/SoundTriggerTestApp/Android.bp tests/Split/Android.bp tests/StagedInstallTest/Android.bp tests/StatusBar/Android.bp tests/SurfaceComposition/Android.bp tests/SurfaceControlViewHostTest/Android.bp tests/SystemMemoryTest/device/Android.bp tests/SystemMemoryTest/host/Android.bp tests/SystemUIDemoModeController/Android.bp tests/TaskOrganizerTest/Android.bp tests/TelephonyCommonTests/Android.bp tests/TouchLatency/Android.bp tests/TransformTest/Android.bp tests/TtsTests/Android.bp tests/UiBench/Android.bp tests/UsageReportingTest/Android.bp tests/UsageStatsPerfTests/Android.bp tests/UsageStatsTest/Android.bp tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp tests/UsbManagerTests/Android.bp tests/UsbManagerTests/lib/Android.bp tests/UsbTests/Android.bp tests/UsesFeature2Test/Android.bp tests/VectorDrawableTest/Android.bp tests/VoiceEnrollment/Android.bp tests/VoiceInteraction/Android.bp tests/WallpaperTest/Android.bp tests/WindowAnimationJank/Android.bp tests/WindowInsetsTests/Android.bp tests/appwidgets/AppWidgetHostTest/Android.bp tests/appwidgets/AppWidgetProviderTest/Android.bp tests/backup/Android.mk tests/benchmarks/Android.bp tests/libs-permissions/Android.bp tests/net/Android.bp tests/net/common/Android.bp tests/net/deflake/Android.bp tests/net/integration/Android.bp tests/net/jni/Android.bp tests/net/smoketest/Android.bp tests/notification/Android.bp tests/permission/Android.bp tests/privapp-permissions/Android.bp tests/testables/Android.bp tests/testables/tests/Android.bp tests/utils/StubIME/Android.bp tests/utils/hostutils/Android.bp tests/utils/testutils/Android.bp tests/vcn/Android.bp tools/aapt/Android.bp tools/aapt2/Android.bp tools/aapt2/integration-tests/AutoVersionTest/Android.bp tools/aapt2/integration-tests/BasicTest/Android.bp tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk tools/aapt2/integration-tests/StaticLibTest/App/Android.bp tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp tools/aapt2/integration-tests/SymlinkTest/Android.bp tools/bit/Android.bp tools/codegen/Android.bp tools/dump-coverage/Android.bp tools/incident_report/Android.bp tools/incident_section_gen/Android.bp tools/lock_agent/Android.bp tools/locked_region_code_injection/Android.bp tools/obbtool/Android.bp tools/powermodel/Android.bp tools/preload-check/Android.bp tools/preload-check/device/Android.bp tools/preload/loadclass/Android.bp tools/processors/staledataclass/Android.bp tools/processors/view_inspector/Android.bp tools/protologtool/Android.bp tools/sdkparcelables/Android.bp tools/split-select/Android.bp tools/streaming_proto/Android.bp tools/validatekeymaps/Android.bp wifi/java/Android.bp wifi/tests/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD to: libs/hwui/Android.bp native/webview/plat_support/Android.bp obex/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD SPDX-license-identifier-CC-BY SPDX-license-identifier-CPL-1.0 SPDX-license-identifier-GPL SPDX-license-identifier-GPL-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS SPDX-license-identifier-W3C legacy_unencumbered to: Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_unencumbered to: core/java/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-CPL-1.0 to: test-base/Android.bp test-runner/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-GPL to: core/res/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-GPL-2.0 to: libs/usb/Android.bp libs/usb/tests/accessorytest/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT to: tools/preload/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS to: api/Android.bp boot/Android.bp cmds/device_config/Android.bp cmds/settings/Android.bp core/api/Android.bp core/tests/coretests/certs/Android.bp core/tests/overlaytests/remount/test-apps/certs/Android.bp core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp libs/tracingproxy/Android.bp services/startop/Android.bp test-legacy/Android.mk tests/ApkVerityTest/testdata/Android.bp tests/TransitionTests/Android.bp Bug: 68860345 Bug: 151177513 Bug: 151953481 Test: m all Exempt-From-Owner-Approval: janitorial work Change-Id: Ic44d662936d1ff0cae7fbe915932b37aa4e4869a Merged-in: I6e9103c3275cb2e6df5dc586588eccd7d2ab6b06 --- framework/Android.bp | 11 ++++++++++- service/Android.bp | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/framework/Android.bp b/framework/Android.bp index 8db8d7699a..3326ea9edd 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -15,6 +15,15 @@ // // TODO: use a java_library in the bootclasspath instead +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-connectivity-sources", srcs: [ @@ -26,4 +35,4 @@ filegroup { "//frameworks/base", "//packages/modules/Connectivity:__subpackages__", ], -} \ No newline at end of file +} diff --git a/service/Android.bp b/service/Android.bp index ed1716fad8..f20b89fb84 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libservice-connectivity", // TODO: build against the NDK (sdk_version: "30" for example) From 6e9ae2339b87ea6953beca8b0e552fd0b1e561eb Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Wed, 10 Feb 2021 14:26:13 -0800 Subject: [PATCH 042/343] Clean up T&C implementation Update the T&C variable names internally to user portal, to have a consistent naming. Bug: 162785447 Test: compiles - no logic changes Change-Id: Ie9b0a2630952c2d82606c1ecd089b2131edbcefc --- .../src/android/net/CaptivePortalData.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java index f4b46e9f11..eafda4d2d6 100644 --- a/framework/src/android/net/CaptivePortalData.java +++ b/framework/src/android/net/CaptivePortalData.java @@ -44,7 +44,7 @@ public final class CaptivePortalData implements Parcelable { private final boolean mCaptive; private final String mVenueFriendlyName; private final int mVenueInfoUrlSource; - private final int mTermsAndConditionsSource; + private final int mUserPortalUrlSource; /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -65,7 +65,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - String venueFriendlyName, int venueInfoUrlSource, int termsAndConditionsSource) { + String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -75,7 +75,7 @@ public final class CaptivePortalData implements Parcelable { mCaptive = captive; mVenueFriendlyName = venueFriendlyName; mVenueInfoUrlSource = venueInfoUrlSource; - mTermsAndConditionsSource = termsAndConditionsSource; + mUserPortalUrlSource = userPortalUrlSource; } private CaptivePortalData(Parcel p) { @@ -100,7 +100,7 @@ public final class CaptivePortalData implements Parcelable { dest.writeBoolean(mCaptive); dest.writeString(mVenueFriendlyName); dest.writeInt(mVenueInfoUrlSource); - dest.writeInt(mTermsAndConditionsSource); + dest.writeInt(mUserPortalUrlSource); } /** @@ -130,7 +130,7 @@ public final class CaptivePortalData implements Parcelable { public Builder(@Nullable CaptivePortalData data) { if (data == null) return; setRefreshTime(data.mRefreshTimeMillis) - .setUserPortalUrl(data.mUserPortalUrl, data.mTermsAndConditionsSource) + .setUserPortalUrl(data.mUserPortalUrl, data.mUserPortalUrlSource) .setVenueInfoUrl(data.mVenueInfoUrl, data.mVenueInfoUrlSource) .setSessionExtendable(data.mIsSessionExtendable) .setBytesRemaining(data.mByteLimit) @@ -314,7 +314,7 @@ public final class CaptivePortalData implements Parcelable { * @return The source that the user portal URL was obtained from */ public @CaptivePortalDataSource int getUserPortalUrlSource() { - return mTermsAndConditionsSource; + return mUserPortalUrlSource; } /** @@ -342,7 +342,7 @@ public final class CaptivePortalData implements Parcelable { public int hashCode() { return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName, - mVenueInfoUrlSource, mTermsAndConditionsSource); + mVenueInfoUrlSource, mUserPortalUrlSource); } @Override @@ -358,7 +358,7 @@ public final class CaptivePortalData implements Parcelable { && mCaptive == other.mCaptive && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName) && mVenueInfoUrlSource == other.mVenueInfoUrlSource - && mTermsAndConditionsSource == other.mTermsAndConditionsSource; + && mUserPortalUrlSource == other.mUserPortalUrlSource; } @Override @@ -373,7 +373,7 @@ public final class CaptivePortalData implements Parcelable { + ", captive: " + mCaptive + ", venueFriendlyName: " + mVenueFriendlyName + ", venueInfoUrlSource: " + mVenueInfoUrlSource - + ", termsAndConditionsSource: " + mTermsAndConditionsSource + + ", userPortalUrlSource: " + mUserPortalUrlSource + "}"; } } From 71ced8e08877ef1526ce3f6a3ce8b8b4257e8e7e Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Feb 2021 18:52:06 +0900 Subject: [PATCH 043/343] Do not depend on Tethering stubs in CM consts Tethering API stubs depend on connectivity stubs for classes like MacAddress or LinkAddress, so connectivity stubs cannot depend on Tethering stubs or there would be a circular dependency. This means ConnectivityManager API surface cannot reference Tethering API constants. Instead, use the literal in ConnectivityManager. This means that both ConnectivityManager and TetheringManager specify the constant value. An alternative considered was to have TetheringManager depend on the ConnectivityManager constants, but considering that ConnectivityManager only has some of the constants, this would be more confusing. Breaking the constants by mistake is unlikely as their values are part of the API surface, so will always be in sync. Bug: 171540887 Test: m Change-Id: I16b6e1912fffc5ff8b3b392901d2357ffd213c72 --- framework/src/android/net/ConnectivityManager.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 4213f8af95..c7bb2a75db 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -456,7 +456,7 @@ public class ConnectivityManager { * @hide */ @SystemApi - public static final int TETHERING_WIFI = TetheringManager.TETHERING_WIFI; + public static final int TETHERING_WIFI = 0; /** * USB tethering type. @@ -464,7 +464,7 @@ public class ConnectivityManager { * @hide */ @SystemApi - public static final int TETHERING_USB = TetheringManager.TETHERING_USB; + public static final int TETHERING_USB = 1; /** * Bluetooth tethering type. @@ -472,7 +472,7 @@ public class ConnectivityManager { * @hide */ @SystemApi - public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH; + public static final int TETHERING_BLUETOOTH = 2; /** * Wifi P2p tethering type. @@ -2799,7 +2799,7 @@ public class ConnectivityManager { */ @SystemApi @Deprecated - public static final int TETHER_ERROR_NO_ERROR = TetheringManager.TETHER_ERROR_NO_ERROR; + public static final int TETHER_ERROR_NO_ERROR = 0; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}. * {@hide} @@ -2875,8 +2875,7 @@ public class ConnectivityManager { */ @SystemApi @Deprecated - public static final int TETHER_ERROR_PROVISION_FAILED = - TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; + public static final int TETHER_ERROR_PROVISION_FAILED = 11; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}. * {@hide} @@ -2890,8 +2889,7 @@ public class ConnectivityManager { */ @SystemApi @Deprecated - public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = - TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; + public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; /** * Get a more detailed error code after a Tethering or Untethering From ad43ca6d4093c93d186160f62197562fb9866efb Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Feb 2021 20:16:28 +0900 Subject: [PATCH 044/343] Split parcelable .aidl files to aidl-export The one-line "parcelable X" files need to be imported by targets that do not build against SDK (the SDK has prebuilt definitions), so prepare a dedicated directory for them. This avoids having users of the classes include the whole src/ directory, which could contain definitions for classes that are not part of the public API, so should not be imported. Also move back to frameworks/base/core some .aidl definitions that were separated from their associated class. Bug: 171540887 Test: m Change-Id: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 --- framework/Android.bp | 26 +++++++++++++++++-- .../android/net/CaptivePortalData.aidl | 0 .../net/ConnectivityDiagnosticsManager.aidl | 0 .../android/net/DhcpInfo.aidl | 0 .../android/net/IpConfiguration.aidl | 0 .../android/net/IpPrefix.aidl | 0 .../android/net/KeepalivePacketData.aidl | 0 .../android/net/LinkAddress.aidl | 0 .../android/net/LinkProperties.aidl | 0 .../android/net/MacAddress.aidl | 0 .../android/net/Network.aidl | 0 .../android/net/NetworkAgentConfig.aidl | 0 .../android/net/NetworkCapabilities.aidl | 0 .../android/net/NetworkInfo.aidl | 0 .../android/net/NetworkRequest.aidl | 0 .../android/net/ProxyInfo.aidl | 0 .../android/net/RouteInfo.aidl | 0 .../android/net/StaticIpConfiguration.aidl | 0 .../android/net/TestNetworkInterface.aidl | 0 .../android/net/apf/ApfCapabilities.aidl | 0 .../android/net/ConnectivityMetricsEvent.aidl | 20 -------------- .../android/net/InterfaceConfiguration.aidl | 19 -------------- framework/src/android/net/UidRange.aidl | 24 ----------------- 23 files changed, 24 insertions(+), 65 deletions(-) rename framework/{src => aidl-export}/android/net/CaptivePortalData.aidl (100%) rename framework/{src => aidl-export}/android/net/ConnectivityDiagnosticsManager.aidl (100%) rename framework/{src => aidl-export}/android/net/DhcpInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/IpConfiguration.aidl (100%) rename framework/{src => aidl-export}/android/net/IpPrefix.aidl (100%) rename framework/{src => aidl-export}/android/net/KeepalivePacketData.aidl (100%) rename framework/{src => aidl-export}/android/net/LinkAddress.aidl (100%) rename framework/{src => aidl-export}/android/net/LinkProperties.aidl (100%) rename framework/{src => aidl-export}/android/net/MacAddress.aidl (100%) rename framework/{src => aidl-export}/android/net/Network.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkAgentConfig.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkCapabilities.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkRequest.aidl (100%) rename framework/{src => aidl-export}/android/net/ProxyInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/RouteInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/StaticIpConfiguration.aidl (100%) rename framework/{src => aidl-export}/android/net/TestNetworkInterface.aidl (100%) rename framework/{src => aidl-export}/android/net/apf/ApfCapabilities.aidl (100%) delete mode 100644 framework/src/android/net/ConnectivityMetricsEvent.aidl delete mode 100644 framework/src/android/net/InterfaceConfiguration.aidl delete mode 100644 framework/src/android/net/UidRange.aidl diff --git a/framework/Android.bp b/framework/Android.bp index 8db8d7699a..73e1511644 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -14,14 +14,36 @@ // limitations under the License. // -// TODO: use a java_library in the bootclasspath instead filegroup { - name: "framework-connectivity-sources", + name: "framework-connectivity-internal-sources", srcs: [ "src/**/*.java", "src/**/*.aidl", ], path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-aidl-export-sources", + srcs: [ + "aidl-export/**/*.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +// TODO: use a java_library in the bootclasspath instead +filegroup { + name: "framework-connectivity-sources", + srcs: [ + ":framework-connectivity-internal-sources", + ":framework-connectivity-aidl-export-sources", + ], visibility: [ "//frameworks/base", "//packages/modules/Connectivity:__subpackages__", diff --git a/framework/src/android/net/CaptivePortalData.aidl b/framework/aidl-export/android/net/CaptivePortalData.aidl similarity index 100% rename from framework/src/android/net/CaptivePortalData.aidl rename to framework/aidl-export/android/net/CaptivePortalData.aidl diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.aidl b/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl similarity index 100% rename from framework/src/android/net/ConnectivityDiagnosticsManager.aidl rename to framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl diff --git a/framework/src/android/net/DhcpInfo.aidl b/framework/aidl-export/android/net/DhcpInfo.aidl similarity index 100% rename from framework/src/android/net/DhcpInfo.aidl rename to framework/aidl-export/android/net/DhcpInfo.aidl diff --git a/framework/src/android/net/IpConfiguration.aidl b/framework/aidl-export/android/net/IpConfiguration.aidl similarity index 100% rename from framework/src/android/net/IpConfiguration.aidl rename to framework/aidl-export/android/net/IpConfiguration.aidl diff --git a/framework/src/android/net/IpPrefix.aidl b/framework/aidl-export/android/net/IpPrefix.aidl similarity index 100% rename from framework/src/android/net/IpPrefix.aidl rename to framework/aidl-export/android/net/IpPrefix.aidl diff --git a/framework/src/android/net/KeepalivePacketData.aidl b/framework/aidl-export/android/net/KeepalivePacketData.aidl similarity index 100% rename from framework/src/android/net/KeepalivePacketData.aidl rename to framework/aidl-export/android/net/KeepalivePacketData.aidl diff --git a/framework/src/android/net/LinkAddress.aidl b/framework/aidl-export/android/net/LinkAddress.aidl similarity index 100% rename from framework/src/android/net/LinkAddress.aidl rename to framework/aidl-export/android/net/LinkAddress.aidl diff --git a/framework/src/android/net/LinkProperties.aidl b/framework/aidl-export/android/net/LinkProperties.aidl similarity index 100% rename from framework/src/android/net/LinkProperties.aidl rename to framework/aidl-export/android/net/LinkProperties.aidl diff --git a/framework/src/android/net/MacAddress.aidl b/framework/aidl-export/android/net/MacAddress.aidl similarity index 100% rename from framework/src/android/net/MacAddress.aidl rename to framework/aidl-export/android/net/MacAddress.aidl diff --git a/framework/src/android/net/Network.aidl b/framework/aidl-export/android/net/Network.aidl similarity index 100% rename from framework/src/android/net/Network.aidl rename to framework/aidl-export/android/net/Network.aidl diff --git a/framework/src/android/net/NetworkAgentConfig.aidl b/framework/aidl-export/android/net/NetworkAgentConfig.aidl similarity index 100% rename from framework/src/android/net/NetworkAgentConfig.aidl rename to framework/aidl-export/android/net/NetworkAgentConfig.aidl diff --git a/framework/src/android/net/NetworkCapabilities.aidl b/framework/aidl-export/android/net/NetworkCapabilities.aidl similarity index 100% rename from framework/src/android/net/NetworkCapabilities.aidl rename to framework/aidl-export/android/net/NetworkCapabilities.aidl diff --git a/framework/src/android/net/NetworkInfo.aidl b/framework/aidl-export/android/net/NetworkInfo.aidl similarity index 100% rename from framework/src/android/net/NetworkInfo.aidl rename to framework/aidl-export/android/net/NetworkInfo.aidl diff --git a/framework/src/android/net/NetworkRequest.aidl b/framework/aidl-export/android/net/NetworkRequest.aidl similarity index 100% rename from framework/src/android/net/NetworkRequest.aidl rename to framework/aidl-export/android/net/NetworkRequest.aidl diff --git a/framework/src/android/net/ProxyInfo.aidl b/framework/aidl-export/android/net/ProxyInfo.aidl similarity index 100% rename from framework/src/android/net/ProxyInfo.aidl rename to framework/aidl-export/android/net/ProxyInfo.aidl diff --git a/framework/src/android/net/RouteInfo.aidl b/framework/aidl-export/android/net/RouteInfo.aidl similarity index 100% rename from framework/src/android/net/RouteInfo.aidl rename to framework/aidl-export/android/net/RouteInfo.aidl diff --git a/framework/src/android/net/StaticIpConfiguration.aidl b/framework/aidl-export/android/net/StaticIpConfiguration.aidl similarity index 100% rename from framework/src/android/net/StaticIpConfiguration.aidl rename to framework/aidl-export/android/net/StaticIpConfiguration.aidl diff --git a/framework/src/android/net/TestNetworkInterface.aidl b/framework/aidl-export/android/net/TestNetworkInterface.aidl similarity index 100% rename from framework/src/android/net/TestNetworkInterface.aidl rename to framework/aidl-export/android/net/TestNetworkInterface.aidl diff --git a/framework/src/android/net/apf/ApfCapabilities.aidl b/framework/aidl-export/android/net/apf/ApfCapabilities.aidl similarity index 100% rename from framework/src/android/net/apf/ApfCapabilities.aidl rename to framework/aidl-export/android/net/apf/ApfCapabilities.aidl diff --git a/framework/src/android/net/ConnectivityMetricsEvent.aidl b/framework/src/android/net/ConnectivityMetricsEvent.aidl deleted file mode 100644 index 1c541dc4c8..0000000000 --- a/framework/src/android/net/ConnectivityMetricsEvent.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** {@hide} */ -parcelable ConnectivityMetricsEvent; diff --git a/framework/src/android/net/InterfaceConfiguration.aidl b/framework/src/android/net/InterfaceConfiguration.aidl deleted file mode 100644 index 8aa5e34528..0000000000 --- a/framework/src/android/net/InterfaceConfiguration.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable InterfaceConfiguration; diff --git a/framework/src/android/net/UidRange.aidl b/framework/src/android/net/UidRange.aidl deleted file mode 100644 index f70fc8e2fe..0000000000 --- a/framework/src/android/net/UidRange.aidl +++ /dev/null @@ -1,24 +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. - */ - -package android.net; - -/** - * An inclusive range of UIDs. - * - * {@hide} - */ -parcelable UidRange; \ No newline at end of file From 6916d5194b3f24c1f0cb038a1f77b27e3a9c7257 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Feb 2021 20:16:28 +0900 Subject: [PATCH 045/343] Split parcelable .aidl files to aidl-export The one-line "parcelable X" files need to be imported by targets that do not build against SDK (the SDK has prebuilt definitions), so prepare a dedicated directory for them. This avoids having users of the classes include the whole src/ directory, which could contain definitions for classes that are not part of the public API, so should not be imported. Also move back to frameworks/base/core some .aidl definitions that were separated from their associated class. Bug: 171540887 Test: m Merged-In: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 Change-Id: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 --- framework/Android.bp | 27 +++++++++++++++++-- .../android/net/CaptivePortalData.aidl | 0 .../net/ConnectivityDiagnosticsManager.aidl | 0 .../android/net/DhcpInfo.aidl | 0 .../android/net/IpConfiguration.aidl | 0 .../android/net/IpPrefix.aidl | 0 .../android/net/KeepalivePacketData.aidl | 0 .../android/net/LinkAddress.aidl | 0 .../android/net/LinkProperties.aidl | 0 .../android/net/MacAddress.aidl | 0 .../android/net/Network.aidl | 0 .../android/net/NetworkAgentConfig.aidl | 0 .../android/net/NetworkCapabilities.aidl | 0 .../android/net/NetworkInfo.aidl | 0 .../android/net/NetworkRequest.aidl | 0 .../android/net/ProxyInfo.aidl | 0 .../android/net/RouteInfo.aidl | 0 .../android/net/StaticIpConfiguration.aidl | 0 .../android/net/TestNetworkInterface.aidl | 0 .../android/net/apf/ApfCapabilities.aidl | 0 .../android/net/ConnectivityMetricsEvent.aidl | 20 -------------- .../android/net/InterfaceConfiguration.aidl | 19 ------------- framework/src/android/net/UidRange.aidl | 24 ----------------- 23 files changed, 25 insertions(+), 65 deletions(-) rename framework/{src => aidl-export}/android/net/CaptivePortalData.aidl (100%) rename framework/{src => aidl-export}/android/net/ConnectivityDiagnosticsManager.aidl (100%) rename framework/{src => aidl-export}/android/net/DhcpInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/IpConfiguration.aidl (100%) rename framework/{src => aidl-export}/android/net/IpPrefix.aidl (100%) rename framework/{src => aidl-export}/android/net/KeepalivePacketData.aidl (100%) rename framework/{src => aidl-export}/android/net/LinkAddress.aidl (100%) rename framework/{src => aidl-export}/android/net/LinkProperties.aidl (100%) rename framework/{src => aidl-export}/android/net/MacAddress.aidl (100%) rename framework/{src => aidl-export}/android/net/Network.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkAgentConfig.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkCapabilities.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/NetworkRequest.aidl (100%) rename framework/{src => aidl-export}/android/net/ProxyInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/RouteInfo.aidl (100%) rename framework/{src => aidl-export}/android/net/StaticIpConfiguration.aidl (100%) rename framework/{src => aidl-export}/android/net/TestNetworkInterface.aidl (100%) rename framework/{src => aidl-export}/android/net/apf/ApfCapabilities.aidl (100%) delete mode 100644 framework/src/android/net/ConnectivityMetricsEvent.aidl delete mode 100644 framework/src/android/net/InterfaceConfiguration.aidl delete mode 100644 framework/src/android/net/UidRange.aidl diff --git a/framework/Android.bp b/framework/Android.bp index 3326ea9edd..ffca971430 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -14,7 +14,6 @@ // limitations under the License. // -// TODO: use a java_library in the bootclasspath instead package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import @@ -24,13 +23,37 @@ package { default_applicable_licenses: ["frameworks_base_license"], } +// TODO: use a java_library in the bootclasspath instead filegroup { - name: "framework-connectivity-sources", + name: "framework-connectivity-internal-sources", srcs: [ "src/**/*.java", "src/**/*.aidl", ], path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-aidl-export-sources", + srcs: [ + "aidl-export/**/*.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +// TODO: use a java_library in the bootclasspath instead +filegroup { + name: "framework-connectivity-sources", + srcs: [ + ":framework-connectivity-internal-sources", + ":framework-connectivity-aidl-export-sources", + ], visibility: [ "//frameworks/base", "//packages/modules/Connectivity:__subpackages__", diff --git a/framework/src/android/net/CaptivePortalData.aidl b/framework/aidl-export/android/net/CaptivePortalData.aidl similarity index 100% rename from framework/src/android/net/CaptivePortalData.aidl rename to framework/aidl-export/android/net/CaptivePortalData.aidl diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.aidl b/framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl similarity index 100% rename from framework/src/android/net/ConnectivityDiagnosticsManager.aidl rename to framework/aidl-export/android/net/ConnectivityDiagnosticsManager.aidl diff --git a/framework/src/android/net/DhcpInfo.aidl b/framework/aidl-export/android/net/DhcpInfo.aidl similarity index 100% rename from framework/src/android/net/DhcpInfo.aidl rename to framework/aidl-export/android/net/DhcpInfo.aidl diff --git a/framework/src/android/net/IpConfiguration.aidl b/framework/aidl-export/android/net/IpConfiguration.aidl similarity index 100% rename from framework/src/android/net/IpConfiguration.aidl rename to framework/aidl-export/android/net/IpConfiguration.aidl diff --git a/framework/src/android/net/IpPrefix.aidl b/framework/aidl-export/android/net/IpPrefix.aidl similarity index 100% rename from framework/src/android/net/IpPrefix.aidl rename to framework/aidl-export/android/net/IpPrefix.aidl diff --git a/framework/src/android/net/KeepalivePacketData.aidl b/framework/aidl-export/android/net/KeepalivePacketData.aidl similarity index 100% rename from framework/src/android/net/KeepalivePacketData.aidl rename to framework/aidl-export/android/net/KeepalivePacketData.aidl diff --git a/framework/src/android/net/LinkAddress.aidl b/framework/aidl-export/android/net/LinkAddress.aidl similarity index 100% rename from framework/src/android/net/LinkAddress.aidl rename to framework/aidl-export/android/net/LinkAddress.aidl diff --git a/framework/src/android/net/LinkProperties.aidl b/framework/aidl-export/android/net/LinkProperties.aidl similarity index 100% rename from framework/src/android/net/LinkProperties.aidl rename to framework/aidl-export/android/net/LinkProperties.aidl diff --git a/framework/src/android/net/MacAddress.aidl b/framework/aidl-export/android/net/MacAddress.aidl similarity index 100% rename from framework/src/android/net/MacAddress.aidl rename to framework/aidl-export/android/net/MacAddress.aidl diff --git a/framework/src/android/net/Network.aidl b/framework/aidl-export/android/net/Network.aidl similarity index 100% rename from framework/src/android/net/Network.aidl rename to framework/aidl-export/android/net/Network.aidl diff --git a/framework/src/android/net/NetworkAgentConfig.aidl b/framework/aidl-export/android/net/NetworkAgentConfig.aidl similarity index 100% rename from framework/src/android/net/NetworkAgentConfig.aidl rename to framework/aidl-export/android/net/NetworkAgentConfig.aidl diff --git a/framework/src/android/net/NetworkCapabilities.aidl b/framework/aidl-export/android/net/NetworkCapabilities.aidl similarity index 100% rename from framework/src/android/net/NetworkCapabilities.aidl rename to framework/aidl-export/android/net/NetworkCapabilities.aidl diff --git a/framework/src/android/net/NetworkInfo.aidl b/framework/aidl-export/android/net/NetworkInfo.aidl similarity index 100% rename from framework/src/android/net/NetworkInfo.aidl rename to framework/aidl-export/android/net/NetworkInfo.aidl diff --git a/framework/src/android/net/NetworkRequest.aidl b/framework/aidl-export/android/net/NetworkRequest.aidl similarity index 100% rename from framework/src/android/net/NetworkRequest.aidl rename to framework/aidl-export/android/net/NetworkRequest.aidl diff --git a/framework/src/android/net/ProxyInfo.aidl b/framework/aidl-export/android/net/ProxyInfo.aidl similarity index 100% rename from framework/src/android/net/ProxyInfo.aidl rename to framework/aidl-export/android/net/ProxyInfo.aidl diff --git a/framework/src/android/net/RouteInfo.aidl b/framework/aidl-export/android/net/RouteInfo.aidl similarity index 100% rename from framework/src/android/net/RouteInfo.aidl rename to framework/aidl-export/android/net/RouteInfo.aidl diff --git a/framework/src/android/net/StaticIpConfiguration.aidl b/framework/aidl-export/android/net/StaticIpConfiguration.aidl similarity index 100% rename from framework/src/android/net/StaticIpConfiguration.aidl rename to framework/aidl-export/android/net/StaticIpConfiguration.aidl diff --git a/framework/src/android/net/TestNetworkInterface.aidl b/framework/aidl-export/android/net/TestNetworkInterface.aidl similarity index 100% rename from framework/src/android/net/TestNetworkInterface.aidl rename to framework/aidl-export/android/net/TestNetworkInterface.aidl diff --git a/framework/src/android/net/apf/ApfCapabilities.aidl b/framework/aidl-export/android/net/apf/ApfCapabilities.aidl similarity index 100% rename from framework/src/android/net/apf/ApfCapabilities.aidl rename to framework/aidl-export/android/net/apf/ApfCapabilities.aidl diff --git a/framework/src/android/net/ConnectivityMetricsEvent.aidl b/framework/src/android/net/ConnectivityMetricsEvent.aidl deleted file mode 100644 index 1c541dc4c8..0000000000 --- a/framework/src/android/net/ConnectivityMetricsEvent.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** {@hide} */ -parcelable ConnectivityMetricsEvent; diff --git a/framework/src/android/net/InterfaceConfiguration.aidl b/framework/src/android/net/InterfaceConfiguration.aidl deleted file mode 100644 index 8aa5e34528..0000000000 --- a/framework/src/android/net/InterfaceConfiguration.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -parcelable InterfaceConfiguration; diff --git a/framework/src/android/net/UidRange.aidl b/framework/src/android/net/UidRange.aidl deleted file mode 100644 index f70fc8e2fe..0000000000 --- a/framework/src/android/net/UidRange.aidl +++ /dev/null @@ -1,24 +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. - */ - -package android.net; - -/** - * An inclusive range of UIDs. - * - * {@hide} - */ -parcelable UidRange; \ No newline at end of file From 709eb8461294937122682aa8a8f124b7508fcaea Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 21 Jan 2021 02:04:15 +0800 Subject: [PATCH 046/343] [IT4.6] Unbundle NMS out from ConnectivityManager ConnectivityService is no longer to update idle timer to NMS but send to INetd directly after this change. Replace the API implementation in ConnectivityManager to refer into ConnectivityService instead of NetworkManagementService to remove the dependency between CM and NMS for ConnectivityService mainline. Bug: 170598012 Test: atest FrameworksNetTests Change-Id: If0ac9a6427dba5a732a15b5d7ca1351b71b07b7b --- .../src/android/net/ConnectivityManager.java | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index c7bb2a75db..adab6e3fbc 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -50,7 +50,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.INetworkActivityListener; -import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.Messenger; @@ -835,7 +834,6 @@ public class ConnectivityManager { private final Context mContext; - private INetworkManagementService mNMService; private INetworkPolicyManager mNPManager; private final TetheringManager mTetheringManager; @@ -2211,17 +2209,6 @@ public class ConnectivityManager { void onNetworkActive(); } - private INetworkManagementService getNetworkManagementService() { - synchronized (this) { - if (mNMService != null) { - return mNMService; - } - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); - return mNMService; - } - } - private final ArrayMap mNetworkActivityListeners = new ArrayMap<>(); @@ -2246,7 +2233,7 @@ public class ConnectivityManager { }; try { - getNetworkManagementService().registerNetworkActivityListener(rl); + mService.registerNetworkActivityListener(rl); mNetworkActivityListeners.put(l, rl); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -2263,7 +2250,7 @@ public class ConnectivityManager { INetworkActivityListener rl = mNetworkActivityListeners.get(l); Preconditions.checkArgument(rl != null, "Listener was not registered."); try { - getNetworkManagementService().unregisterNetworkActivityListener(rl); + mService.registerNetworkActivityListener(rl); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2279,7 +2266,7 @@ public class ConnectivityManager { */ public boolean isDefaultNetworkActive() { try { - return getNetworkManagementService().isNetworkActive(); + return mService.isDefaultNetworkActive(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } From cea06a618b62143027920f6a2b5370ef6a9546db Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 4 Feb 2021 17:29:59 +0800 Subject: [PATCH 047/343] [IT06]Move INetworkActivityListener into connectivity module INetworkActivityListener is hidden and the only usage is inside the connectivity module. Thus, move this into module scope. Bug: 170598012 Test: atest FrameworksNetTests Change-Id: I0a75c440c1daa773217bbd362b212fda4d07ec64 --- .../src/android/net/ConnectivityManager.java | 1 - .../src/android/net/IConnectivityManager.aidl | 2 +- .../android/net/INetworkActivityListener.aidl | 24 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 framework/src/android/net/INetworkActivityListener.aidl diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index adab6e3fbc..f41a8cb14d 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -49,7 +49,6 @@ import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; -import android.os.INetworkActivityListener; import android.os.Looper; import android.os.Message; import android.os.Messenger; diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 6391802f33..160338d396 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -21,6 +21,7 @@ import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; import android.net.IOnSetOemNetworkPreferenceListener; +import android.net.INetworkActivityListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; import android.net.LinkProperties; @@ -36,7 +37,6 @@ import android.net.UidRange; import android.net.QosSocketInfo; import android.os.Bundle; import android.os.IBinder; -import android.os.INetworkActivityListener; import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; diff --git a/framework/src/android/net/INetworkActivityListener.aidl b/framework/src/android/net/INetworkActivityListener.aidl new file mode 100644 index 0000000000..79687dd3bf --- /dev/null +++ b/framework/src/android/net/INetworkActivityListener.aidl @@ -0,0 +1,24 @@ +/* Copyright 2013, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +/** + * @hide + */ +oneway interface INetworkActivityListener +{ + void onNetworkActive(); +} From 345c2dfcf046d74c6e0fd5335fab000ad6c6bbcb Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 3 Feb 2021 10:18:20 +0900 Subject: [PATCH 048/343] Use formal API for ActivityThread to set proxy Add setHttpProxyConfiguration to the public API, and use ConnectivityManager APIs from ActivityThread (instead of hidden APIs) to get/set the proxy for an app process. The default proxy is now initialized with getDefaultProxy instead of getProxyForNetwork(null); this should not make a difference, as nothing should have called bindProcessToNetwork at that point yet. Bug: 174436414 Test: m; device boots Merged-In: Ifb516194ecde1567cea4b6806946091cdcf2f015 Change-Id: I06b797eeae54609aecdc0afe1df4e6c602a17a69 --- .../src/android/net/ConnectivityManager.java | 2 +- framework/src/android/net/Proxy.java | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 4213f8af95..6b4e524410 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4608,7 +4608,7 @@ public class ConnectivityManager { // Set HTTP proxy system properties to match network. // TODO: Deprecate this static method and replace it with a non-static version. try { - Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy()); + Proxy.setHttpProxyConfiguration(getInstance().getDefaultProxy()); } catch (SecurityException e) { // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy. Log.e(TAG, "Can't set proxy properties", e); diff --git a/framework/src/android/net/Proxy.java b/framework/src/android/net/Proxy.java index 9cd7ab2c3e..77c8a4f457 100644 --- a/framework/src/android/net/Proxy.java +++ b/framework/src/android/net/Proxy.java @@ -16,8 +16,10 @@ package android.net; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; @@ -185,7 +187,19 @@ public final class Proxy { /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final void setHttpProxySystemProperty(ProxyInfo p) { + @Deprecated + public static void setHttpProxySystemProperty(ProxyInfo p) { + setHttpProxyConfiguration(p); + } + + /** + * Set HTTP proxy configuration for the process to match the provided ProxyInfo. + * + * If the provided ProxyInfo is null, the proxy configuration will be cleared. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static void setHttpProxyConfiguration(@Nullable ProxyInfo p) { String host = null; String port = null; String exclList = null; @@ -196,11 +210,11 @@ public final class Proxy { exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); pacFileUrl = p.getPacFileUrl(); } - setHttpProxySystemProperty(host, port, exclList, pacFileUrl); + setHttpProxyConfiguration(host, port, exclList, pacFileUrl); } /** @hide */ - public static final void setHttpProxySystemProperty(String host, String port, String exclList, + public static void setHttpProxyConfiguration(String host, String port, String exclList, Uri pacFileUrl) { if (exclList != null) exclList = exclList.replace(",", "|"); if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); From e849277786bf9ec0514cbd53e8b7ed9ef5c6af5f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 18 Feb 2021 01:17:36 +0900 Subject: [PATCH 049/343] Delete VPN methods in ConnectivityManager. 1. Stop using ConnectivityManager for VPNs in VpnDialogs. 2. Delete updateLockdownVpn, since all callers have been migrated to calling VpnManager directly. 3. Delete the call to VpnManager in factoryReset, since the only caller (ResetNetworkConfirm) has been updated to call into VpnManager directly. 4. Delete getVpnManager, since it is now unused. Test: m Bug: 173331190 Change-Id: I5d071281c0e36f6523fea10671a9abf994c66d66 --- .../src/android/net/ConnectivityManager.java | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index d3414a404d..071ec34b62 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1069,58 +1069,6 @@ public class ConnectivityManager { } } - /** - * Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { - return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage); - } - - /** - * Calls VpnManager#setAlwaysOnVpnPackageForUser. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List lockdownAllowlist) { - return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled, - lockdownAllowlist); - } - - /** - * Calls VpnManager#getAlwaysOnVpnPackageForUser. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public String getAlwaysOnVpnPackageForUser(int userId) { - return getVpnManager().getAlwaysOnVpnPackageForUser(userId); - } - - /** - * Calls VpnManager#isVpnLockdownEnabled. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean isVpnLockdownEnabled(int userId) { - return getVpnManager().isVpnLockdownEnabled(userId); - } - - /** - * Calls VpnManager#getVpnLockdownAllowlist. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public List getVpnLockdownAllowlist(int userId) { - return getVpnManager().getVpnLockdownAllowlist(userId); - } - /** * Adds or removes a requirement for given UID ranges to use the VPN. * @@ -3166,16 +3114,6 @@ public class ConnectivityManager { } } - /** - * Calls VpnManager#updateLockdownVpn. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean updateLockdownVpn() { - return getVpnManager().updateLockdownVpn(); - } - /** * Set sign in error notification to visible or invisible * @@ -4537,8 +4475,6 @@ public class ConnectivityManager { try { mService.factoryReset(); mTetheringManager.stopAllTethering(); - // TODO: Migrate callers to VpnManager#factoryReset. - getVpnManager().factoryReset(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4832,15 +4768,6 @@ public class ConnectivityManager { return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); } - /** - * Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a - * private final mVpnManager because ConnectivityManager is initialized before VpnManager. - * @hide TODO: remove. - */ - public VpnManager getVpnManager() { - return mContext.getSystemService(VpnManager.class); - } - /** @hide */ public ConnectivityDiagnosticsManager createDiagnosticsManager() { return new ConnectivityDiagnosticsManager(mContext, mService); From da6bc5ace2f63221e7cfe9c909af7e0a932415fb Mon Sep 17 00:00:00 2001 From: Nataniel Borges Date: Fri, 19 Feb 2021 15:25:33 +0000 Subject: [PATCH 050/343] Revert "Delete VPN methods in ConnectivityManager." This reverts commit e849277786bf9ec0514cbd53e8b7ed9ef5c6af5f. Bug: 180710918 Reason for revert: Broken build Change-Id: I6e6318b4c01ccab27ca3e9f16bb2194aa1d9ffd2 --- .../src/android/net/ConnectivityManager.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 071ec34b62..d3414a404d 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1069,6 +1069,58 @@ public class ConnectivityManager { } } + /** + * Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide + */ + @Deprecated + public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { + return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage); + } + + /** + * Calls VpnManager#setAlwaysOnVpnPackageForUser. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide + */ + @Deprecated + public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, + boolean lockdownEnabled, @Nullable List lockdownAllowlist) { + return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled, + lockdownAllowlist); + } + + /** + * Calls VpnManager#getAlwaysOnVpnPackageForUser. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide + */ + @Deprecated + public String getAlwaysOnVpnPackageForUser(int userId) { + return getVpnManager().getAlwaysOnVpnPackageForUser(userId); + } + + /** + * Calls VpnManager#isVpnLockdownEnabled. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide + */ + @Deprecated + public boolean isVpnLockdownEnabled(int userId) { + return getVpnManager().isVpnLockdownEnabled(userId); + } + + /** + * Calls VpnManager#getVpnLockdownAllowlist. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide + */ + @Deprecated + public List getVpnLockdownAllowlist(int userId) { + return getVpnManager().getVpnLockdownAllowlist(userId); + } + /** * Adds or removes a requirement for given UID ranges to use the VPN. * @@ -3114,6 +3166,16 @@ public class ConnectivityManager { } } + /** + * Calls VpnManager#updateLockdownVpn. + * @deprecated TODO: remove when callers have migrated to VpnManager. + * @hide + */ + @Deprecated + public boolean updateLockdownVpn() { + return getVpnManager().updateLockdownVpn(); + } + /** * Set sign in error notification to visible or invisible * @@ -4475,6 +4537,8 @@ public class ConnectivityManager { try { mService.factoryReset(); mTetheringManager.stopAllTethering(); + // TODO: Migrate callers to VpnManager#factoryReset. + getVpnManager().factoryReset(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4768,6 +4832,15 @@ public class ConnectivityManager { return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); } + /** + * Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a + * private final mVpnManager because ConnectivityManager is initialized before VpnManager. + * @hide TODO: remove. + */ + public VpnManager getVpnManager() { + return mContext.getSystemService(VpnManager.class); + } + /** @hide */ public ConnectivityDiagnosticsManager createDiagnosticsManager() { return new ConnectivityDiagnosticsManager(mContext, mService); From 727b672919bf964d1ae2ba03d8be830619f3e869 Mon Sep 17 00:00:00 2001 From: Bob Badour Date: Fri, 12 Feb 2021 17:07:05 -0800 Subject: [PATCH 051/343] [LSC] Add LOCAL_LICENSE_KINDS to frameworks/base Added SPDX-license-identifier-Apache-2.0 to: apct-tests/perftests/autofill/Android.bp apct-tests/perftests/blobstore/Android.bp apct-tests/perftests/core/Android.bp apct-tests/perftests/core/apps/overlay/Android.bp apct-tests/perftests/core/apps/reources_manager/Android.bp apct-tests/perftests/core/jni/Android.bp apct-tests/perftests/multiuser/Android.bp apct-tests/perftests/multiuser/apps/dummyapp/Android.bp apct-tests/perftests/packagemanager/Android.bp apct-tests/perftests/packagemanager/apps/query-all/Android.bp apct-tests/perftests/textclassifier/Android.bp apct-tests/perftests/utils/Android.bp apct-tests/perftests/windowmanager/Android.bp apex/Android.bp apex/blobstore/framework/Android.bp apex/blobstore/service/Android.bp apex/jobscheduler/framework/Android.bp apex/jobscheduler/service/Android.bp apex/media/Android.bp apex/media/aidl/Android.bp apex/media/framework/Android.bp cmds/am/Android.bp cmds/app_process/Android.bp cmds/appops/Android.bp cmds/appwidget/Android.bp cmds/backup/Android.bp cmds/bmgr/Android.bp cmds/bootanimation/Android.bp cmds/bu/Android.bp cmds/content/Android.bp cmds/dpm/Android.bp cmds/hid/Android.bp cmds/hid/jni/Android.bp cmds/idmap2/Android.bp cmds/ime/Android.bp cmds/incident/Android.bp cmds/incident_helper/Android.bp cmds/incidentd/Android.bp cmds/input/Android.bp cmds/interrupter/Android.bp cmds/locksettings/Android.bp cmds/pm/Android.bp cmds/requestsync/Android.bp cmds/screencap/Android.bp cmds/sm/Android.bp cmds/svc/Android.bp cmds/telecom/Android.bp cmds/uiautomator/Android.bp cmds/uiautomator/cmds/uiautomator/Android.bp cmds/uiautomator/instrumentation/Android.bp cmds/uiautomator/library/Android.bp cmds/vr/Android.bp cmds/wm/Android.bp config/Android.bp core/java/android/service/wallpaper/Android.bp core/jni/Android.bp core/sysprop/Android.bp core/tests/BroadcastRadioTests/Android.bp core/tests/ConnectivityManagerTest/Android.bp core/tests/PackageInstallerSessions/Android.bp core/tests/PlatformCompatFramework/Android.bp core/tests/bandwidthtests/Android.bp core/tests/benchmarks/Android.bp core/tests/bluetoothtests/Android.bp core/tests/bugreports/Android.bp core/tests/coretests/Android.bp core/tests/coretests/BinderDeathRecipientHelperApp/Android.bp core/tests/coretests/BinderProxyCountingTestApp/Android.bp core/tests/coretests/BinderProxyCountingTestService/Android.bp core/tests/coretests/BstatsTestApp/Android.bp core/tests/coretests/DisabledTestApp/Android.bp core/tests/coretests/EnabledTestApp/Android.bp core/tests/coretests/aidl/Android.bp core/tests/coretests/apks/Android.bp core/tests/coretests/apks/install/Android.bp core/tests/coretests/apks/install_bad_dex/Android.bp core/tests/coretests/apks/install_complete_package_info/Android.bp core/tests/coretests/apks/install_decl_perm/Android.bp core/tests/coretests/apks/install_jni_lib/Android.bp core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.bp core/tests/coretests/apks/install_loc_auto/Android.bp core/tests/coretests/apks/install_loc_internal/Android.bp core/tests/coretests/apks/install_loc_sdcard/Android.bp core/tests/coretests/apks/install_loc_unspecified/Android.bp core/tests/coretests/apks/install_use_perm_good/Android.bp core/tests/coretests/apks/install_uses_feature/Android.bp core/tests/coretests/apks/install_verifier_bad/Android.bp core/tests/coretests/apks/install_verifier_good/Android.bp core/tests/coretests/apks/keyset/Android.bp core/tests/coretests/apks/locales/Android.bp core/tests/coretests/apks/overlay_config/Android.bp core/tests/coretests/apks/version/Android.bp core/tests/coretests/apks/version_nosys/Android.bp core/tests/featureflagtests/Android.bp core/tests/hdmitests/Android.bp core/tests/hosttests/test-apps/AutoLocTestApp/Android.bp core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v1/Android.bp core/tests/hosttests/test-apps/AutoLocVersionedTestApp_v2/Android.bp core/tests/hosttests/test-apps/ExternalLocAllPermsTestApp/Android.bp core/tests/hosttests/test-apps/ExternalLocPermsFLTestApp/Android.bp core/tests/hosttests/test-apps/ExternalLocTestApp/Android.bp core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v1/Android.bp core/tests/hosttests/test-apps/ExternalLocVersionedTestApp_v2/Android.bp core/tests/hosttests/test-apps/ExternalSharedPerms/Android.bp core/tests/hosttests/test-apps/ExternalSharedPermsBT/Android.bp core/tests/hosttests/test-apps/ExternalSharedPermsDiffKey/Android.bp core/tests/hosttests/test-apps/ExternalSharedPermsFL/Android.bp core/tests/hosttests/test-apps/InternalLocTestApp/Android.bp core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests/Android.bp core/tests/hosttests/test-apps/NoLocTestApp/Android.bp core/tests/hosttests/test-apps/NoLocVersionedTestApp_v1/Android.bp core/tests/hosttests/test-apps/NoLocVersionedTestApp_v2/Android.bp core/tests/hosttests/test-apps/SharedUid/32/Android.bp core/tests/hosttests/test-apps/SharedUid/32/jni/Android.bp core/tests/hosttests/test-apps/SharedUid/64/Android.bp core/tests/hosttests/test-apps/SharedUid/64/jni/Android.bp core/tests/hosttests/test-apps/SharedUid/dual/Android.bp core/tests/hosttests/test-apps/SharedUid/dual/jni/Android.bp core/tests/hosttests/test-apps/SharedUid/java_only/Android.bp core/tests/hosttests/test-apps/SimpleTestApp/Android.bp core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v1_ext/Android.bp core/tests/hosttests/test-apps/UpdateExtToIntLocTestApp_v2_int/Android.bp core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v1_ext/Android.bp core/tests/hosttests/test-apps/UpdateExternalLocTestApp_v2_none/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_Auto/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_External/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_Internal/Android.bp core/tests/hosttests/test-apps/VersatileTestApp_None/Android.bp core/tests/mockingcoretests/Android.bp core/tests/notificationtests/Android.bp core/tests/overlaytests/device/Android.bp core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.bp core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.bp core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.bp core/tests/overlaytests/host/Android.bp core/tests/overlaytests/remount/Android.bp core/tests/overlaytests/remount/test-apps/Overlay/Android.bp core/tests/overlaytests/remount/test-apps/SharedLibrary/Android.bp core/tests/overlaytests/remount/test-apps/SharedLibraryOverlay/Android.bp core/tests/overlaytests/remount/test-apps/Target/Android.bp core/tests/packagemanagertests/Android.bp core/tests/privacytests/Android.bp core/tests/screenshothelpertests/Android.bp core/tests/systemproperties/Android.bp core/tests/utillib/Android.bp core/tests/utiltests/Android.bp core/tests/utiltests/jni/Android.bp core/tests/uwbtests/Android.bp core/xsd/Android.bp core/xsd/vts/Android.bp data/etc/Android.bp data/etc/car/Android.bp data/fonts/Android.bp data/keyboards/Android.mk drm/jni/Android.bp errorprone/Android.bp graphics/proto/Android.bp keystore/Android.bp keystore/tests/Android.bp libs/WindowManager/Jetpack/Android.bp libs/WindowManager/Shell/Android.bp libs/WindowManager/Shell/tests/Android.bp libs/androidfw/Android.bp libs/androidfw/fuzz/resourcefile_fuzzer/Android.bp libs/hostgraphics/Android.bp libs/incident/Android.bp libs/input/Android.bp libs/input/tests/Android.bp libs/protoutil/Android.bp libs/services/Android.bp libs/storage/Android.bp libs/usb/tests/AccessoryChat/Android.bp libs/usb/tests/AccessoryChat/accessorychat/Android.bp location/lib/Android.bp location/tests/Android.bp location/tests/locationtests/Android.bp lowpan/tests/Android.bp media/Android.bp media/java/Android.bp media/java/android/media/tv/tunerresourcemanager/Android.bp media/jni/Android.bp media/jni/audioeffect/Android.bp media/jni/soundpool/Android.bp media/jni/soundpool/tests/Android.bp media/lib/remotedisplay/Android.bp media/lib/signer/Android.bp media/lib/tvremote/Android.bp media/lib/tvremote/tests/Android.bp media/mca/filterfw/Android.bp media/mca/filterfw/native/Android.bp media/mca/filterpacks/Android.bp media/mca/samples/CameraEffectsRecordingSample/Android.bp media/mca/tests/Android.bp media/native/midi/Android.bp media/packages/BluetoothMidiService/Android.bp media/packages/BluetoothMidiService/tests/unit/Android.bp media/tests/AudioPolicyTest/Android.bp media/tests/CameraBrowser/Android.bp media/tests/EffectsTest/Android.bp media/tests/MediaDump/Android.bp media/tests/MediaFrameworkTest/Android.bp media/tests/MediaRouter/Android.bp media/tests/MtpTests/Android.bp media/tests/ScoAudioTest/Android.bp media/tests/SoundPoolTest/Android.bp media/tests/TunerTest/Android.bp media/tests/audiotests/Android.bp media/tests/players/Android.bp mime/Android.bp native/android/Android.bp native/graphics/jni/Android.bp native/webview/loader/Android.bp nfc-extras/Android.bp nfc-extras/tests/Android.bp packages/AppPredictionLib/Android.bp packages/BackupEncryption/Android.bp packages/BackupEncryption/test/robolectric-integration/Android.bp packages/BackupEncryption/test/robolectric/Android.bp packages/BackupEncryption/test/unittest/Android.bp packages/BackupRestoreConfirmation/Android.bp packages/CarSystemUI/Android.bp packages/CarrierDefaultApp/Android.bp packages/CarrierDefaultApp/tests/unit/Android.bp packages/CompanionDeviceManager/Android.bp packages/Connectivity/framework/Android.bp packages/Connectivity/service/Android.bp packages/CtsShim/Android.bp packages/CtsShim/build/Android.bp packages/CtsShim/build/jni/Android.bp packages/DynamicSystemInstallationService/Android.bp packages/DynamicSystemInstallationService/tests/Android.bp packages/EasterEgg/Android.bp packages/EncryptedLocalTransport/Android.bp packages/ExtShared/Android.bp packages/ExternalStorageProvider/Android.bp packages/ExternalStorageProvider/tests/Android.bp packages/FakeOemFeatures/Android.bp packages/FusedLocation/Android.bp packages/InputDevices/Android.bp packages/LocalTransport/Android.bp packages/PackageInstaller/Android.bp packages/PrintRecommendationService/Android.bp packages/PrintSpooler/Android.bp packages/PrintSpooler/jni/Android.bp packages/PrintSpooler/tests/outofprocess/Android.bp packages/SettingsLib/ActionBarShadow/Android.bp packages/SettingsLib/ActionButtonsPreference/Android.bp packages/SettingsLib/AdaptiveIcon/Android.bp packages/SettingsLib/Android.bp packages/SettingsLib/AppPreference/Android.bp packages/SettingsLib/BarChartPreference/Android.bp packages/SettingsLib/DisplayDensityUtils/Android.bp packages/SettingsLib/EntityHeaderWidgets/Android.bp packages/SettingsLib/HelpUtils/Android.bp packages/SettingsLib/LayoutPreference/Android.bp packages/SettingsLib/ProgressBar/Android.bp packages/SettingsLib/RadioButtonPreference/Android.bp packages/SettingsLib/RestrictedLockUtils/Android.bp packages/SettingsLib/SchedulesProvider/Android.bp packages/SettingsLib/SearchProvider/Android.bp packages/SettingsLib/SearchWidget/Android.bp packages/SettingsLib/SettingsSpinner/Android.bp packages/SettingsLib/SettingsTheme/Android.bp packages/SettingsLib/Tile/Android.bp packages/SettingsLib/Utils/Android.bp packages/SettingsLib/search/Android.bp packages/SettingsLib/tests/integ/Android.bp packages/SettingsLib/tests/robotests/Android.bp packages/SettingsProvider/Android.bp packages/SharedStorageBackup/Android.bp packages/Shell/Android.bp packages/Shell/tests/Android.bp packages/SimAppDialog/Android.bp packages/SoundPicker/Android.bp packages/StatementService/Android.bp packages/SystemUI/Android.bp packages/SystemUI/plugin/Android.bp packages/SystemUI/plugin/ExamplePlugin/Android.bp packages/SystemUI/plugin_core/Android.bp packages/SystemUI/shared/Android.bp packages/VpnDialogs/Android.bp packages/WAPPushManager/Android.bp packages/WAPPushManager/tests/Android.bp packages/WallpaperBackup/Android.bp packages/WallpaperCropper/Android.bp packages/overlays/Android.mk packages/overlays/tests/Android.bp packages/services/PacProcessor/Android.bp packages/services/PacProcessor/jni/Android.bp packages/services/Proxy/Android.bp proto/Android.bp rs/jni/Android.mk samples/demo/haptic-assessment/Android.bp sax/tests/saxtests/Android.bp services/Android.bp services/accessibility/Android.bp services/appprediction/Android.bp services/appwidget/Android.bp services/autofill/Android.bp services/backup/Android.bp services/backup/backuplib/Android.bp services/companion/Android.bp services/contentcapture/Android.bp services/contentsuggestions/Android.bp services/core/Android.bp services/core/java/com/android/server/vcn/Android.bp services/core/jni/Android.bp services/core/xsd/Android.bp services/core/xsd/vts/Android.bp services/coverage/Android.bp services/devicepolicy/Android.bp services/incremental/Android.bp services/midi/Android.bp services/net/Android.bp services/people/Android.bp services/print/Android.bp services/profcollect/Android.bp services/restrictions/Android.bp services/robotests/Android.bp services/robotests/backup/Android.bp services/systemcaptions/Android.bp services/tests/PackageManagerComponentOverrideTests/Android.bp services/tests/PackageManagerServiceTests/host/Android.bp services/tests/PackageManagerServiceTests/host/test-apps/Android.bp services/tests/mockingservicestests/Android.bp services/tests/rescueparty/Android.bp services/tests/servicestests/Android.bp services/tests/servicestests/aidl/Android.bp services/tests/servicestests/apks/Android.bp services/tests/servicestests/apks/install-split-base/Android.bp services/tests/servicestests/apks/install-split-feature-a/Android.bp services/tests/servicestests/apks/install_intent_filters/Android.bp services/tests/servicestests/apks/install_uses_sdk/Android.bp services/tests/servicestests/test-apps/ConnTestApp/Android.bp services/tests/servicestests/test-apps/JobTestApp/Android.bp services/tests/servicestests/test-apps/PackageParserApp/Android.bp services/tests/servicestests/test-apps/PackageParsingTestManifests/Android.bp services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp services/tests/servicestests/test-apps/SuspendTestApp/Android.bp services/tests/shortcutmanagerutils/Android.bp services/tests/uiservicestests/Android.bp services/tests/wmtests/Android.bp services/usage/Android.bp services/usb/Android.bp services/voiceinteraction/Android.bp services/wifi/Android.bp startop/apps/test/Android.bp startop/iorap/Android.bp startop/iorap/functional_tests/Android.bp startop/iorap/stress/Android.bp startop/iorap/tests/Android.bp startop/view_compiler/Android.bp startop/view_compiler/dex_builder_test/Android.bp test-base/hiddenapi/Android.bp test-mock/Android.bp test-runner/tests/Android.bp tests/AccessibilityEventsLogger/Android.bp tests/AccessoryDisplay/common/Android.bp tests/AccessoryDisplay/sink/Android.bp tests/AccessoryDisplay/source/Android.bp tests/ActivityManagerPerfTests/stub-app/Android.bp tests/ActivityManagerPerfTests/test-app/Android.bp tests/ActivityManagerPerfTests/tests/Android.bp tests/ActivityManagerPerfTests/utils/Android.bp tests/ActivityTests/Android.bp tests/ActivityViewTest/Android.bp tests/AmSlam/Android.bp tests/ApkVerityTest/Android.bp tests/ApkVerityTest/ApkVerityTestApp/Android.bp tests/ApkVerityTest/block_device_writer/Android.bp tests/AppLaunch/Android.bp tests/AppLaunchWear/Android.bp tests/AppResourcesLoaders/Android.bp tests/AppResourcesLoaders/Overlay/Android.bp tests/Assist/Android.bp tests/AutoVerify/app1/Android.bp tests/AutoVerify/app2/Android.bp tests/AutoVerify/app3/Android.bp tests/AutoVerify/app4/Android.bp tests/BackgroundDexOptServiceIntegrationTests/Android.bp tests/BandwidthTests/Android.bp tests/BatteryWaster/Android.bp tests/BiDiTests/Android.bp tests/BlobStoreTestUtils/Android.bp tests/BootImageProfileTest/Android.bp tests/BrowserPowerTest/Android.bp tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp tests/CameraPrewarmTest/Android.bp tests/Codegen/Android.bp tests/Compatibility/Android.bp tests/CoreTests/android/Android.bp tests/DataIdleTest/Android.bp tests/DozeTest/Android.bp tests/DpiTest/Android.bp tests/DynamicCodeLoggerIntegrationTests/Android.mk tests/FeatureSplit/base/Android.bp tests/FeatureSplit/feature1/Android.bp tests/FeatureSplit/feature2/Android.bp tests/FixVibrateSetting/Android.bp tests/FlickerTests/Android.bp tests/FlickerTests/test-apps/Android.bp tests/FlickerTests/test-apps/flickerapp/Android.bp tests/FrameworkPerf/Android.bp tests/GamePerformance/Android.bp tests/GridLayoutTest/Android.bp tests/HierarchyViewerTest/Android.bp tests/HugeBackup/Android.bp tests/HwAccelerationTest/Android.bp tests/Internal/Android.bp tests/JankBench/Android.bp tests/JobSchedulerPerfTests/Android.bp tests/JobSchedulerTestApp/Android.bp tests/LargeAssetTest/Android.bp tests/LegacyAssistant/Android.bp tests/LocalizationTest/Android.bp tests/LocationTracker/Android.bp tests/LotsOfApps/Android.bp tests/LowStorageTest/Android.bp tests/ManagedProfileLifecycleStressTest/Android.bp tests/ManagedProfileLifecycleStressTest/app/DummyDPC/Android.bp tests/MemoryUsage/Android.bp tests/MirrorSurfaceTest/Android.bp tests/NativeProcessesMemoryTest/Android.bp tests/NetworkSecurityConfigTest/Android.bp tests/NullHomeTest/Android.bp tests/OdmApps/Android.bp tests/OdmApps/app/Android.bp tests/OdmApps/priv-app/Android.bp tests/OneMedia/Android.bp tests/PackageWatchdog/Android.bp tests/PlatformCompatGating/Android.bp tests/PlatformCompatGating/test-rules/Android.bp tests/ProtoInputStreamTests/Android.bp tests/RemoteDisplayProvider/Android.bp tests/RenderThreadTest/Android.bp tests/RollbackTest/Android.bp tests/SerialChat/Android.bp tests/ServiceCrashTest/Android.bp tests/SharedLibrary/client/Android.bp tests/SharedLibrary/lib/Android.bp tests/ShowWhenLockedApp/Android.bp tests/SmokeTest/Android.bp tests/SmokeTest/tests/Android.bp tests/SmokeTestApps/Android.bp tests/SoundTriggerTestApp/Android.bp tests/Split/Android.bp tests/StagedInstallTest/Android.bp tests/StatusBar/Android.bp tests/SurfaceComposition/Android.bp tests/SurfaceControlViewHostTest/Android.bp tests/SystemMemoryTest/device/Android.bp tests/SystemMemoryTest/host/Android.bp tests/SystemUIDemoModeController/Android.bp tests/TaskOrganizerTest/Android.bp tests/TelephonyCommonTests/Android.bp tests/TouchLatency/Android.bp tests/TransformTest/Android.bp tests/TtsTests/Android.bp tests/UiBench/Android.bp tests/UsageReportingTest/Android.bp tests/UsageStatsPerfTests/Android.bp tests/UsageStatsTest/Android.bp tests/UsbHostExternalManagmentTest/AoapTestDevice/Android.bp tests/UsbHostExternalManagmentTest/AoapTestHost/Android.bp tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/Android.bp tests/UsbManagerTests/Android.bp tests/UsbManagerTests/lib/Android.bp tests/UsbTests/Android.bp tests/UsesFeature2Test/Android.bp tests/VectorDrawableTest/Android.bp tests/VoiceEnrollment/Android.bp tests/VoiceInteraction/Android.bp tests/WallpaperTest/Android.bp tests/WindowAnimationJank/Android.bp tests/WindowInsetsTests/Android.bp tests/appwidgets/AppWidgetHostTest/Android.bp tests/appwidgets/AppWidgetProviderTest/Android.bp tests/backup/Android.mk tests/benchmarks/Android.bp tests/libs-permissions/Android.bp tests/net/Android.bp tests/net/common/Android.bp tests/net/deflake/Android.bp tests/net/integration/Android.bp tests/net/jni/Android.bp tests/net/smoketest/Android.bp tests/notification/Android.bp tests/permission/Android.bp tests/privapp-permissions/Android.bp tests/testables/Android.bp tests/testables/tests/Android.bp tests/utils/StubIME/Android.bp tests/utils/hostutils/Android.bp tests/utils/testutils/Android.bp tests/vcn/Android.bp tools/aapt/Android.bp tools/aapt2/Android.bp tools/aapt2/integration-tests/AutoVersionTest/Android.bp tools/aapt2/integration-tests/BasicTest/Android.bp tools/aapt2/integration-tests/MergeOnlyTest/LeafLib/Android.mk tools/aapt2/integration-tests/MergeOnlyTest/LocalLib/Android.mk tools/aapt2/integration-tests/NamespaceTest/LibOne/Android.mk tools/aapt2/integration-tests/NamespaceTest/LibTwo/Android.mk tools/aapt2/integration-tests/StaticLibTest/App/Android.bp tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp tools/aapt2/integration-tests/SymlinkTest/Android.bp tools/bit/Android.bp tools/codegen/Android.bp tools/dump-coverage/Android.bp tools/incident_report/Android.bp tools/incident_section_gen/Android.bp tools/lock_agent/Android.bp tools/locked_region_code_injection/Android.bp tools/obbtool/Android.bp tools/powermodel/Android.bp tools/preload-check/Android.bp tools/preload-check/device/Android.bp tools/preload/loadclass/Android.bp tools/processors/staledataclass/Android.bp tools/processors/view_inspector/Android.bp tools/protologtool/Android.bp tools/sdkparcelables/Android.bp tools/split-select/Android.bp tools/streaming_proto/Android.bp tools/validatekeymaps/Android.bp wifi/java/Android.bp wifi/tests/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD to: libs/hwui/Android.bp native/webview/plat_support/Android.bp obex/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD SPDX-license-identifier-CC-BY SPDX-license-identifier-CPL-1.0 SPDX-license-identifier-GPL SPDX-license-identifier-GPL-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS SPDX-license-identifier-W3C legacy_unencumbered to: Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-BSD legacy_unencumbered to: core/java/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-CPL-1.0 to: test-base/Android.bp test-runner/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-GPL to: core/res/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-GPL-2.0 to: libs/usb/Android.bp libs/usb/tests/accessorytest/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT to: tools/preload/Android.bp Added SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-Unicode-DFS to: api/Android.bp boot/Android.bp cmds/device_config/Android.bp cmds/settings/Android.bp core/api/Android.bp core/tests/coretests/certs/Android.bp core/tests/overlaytests/remount/test-apps/certs/Android.bp core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp libs/tracingproxy/Android.bp services/startop/Android.bp test-legacy/Android.mk tests/ApkVerityTest/testdata/Android.bp tests/TransitionTests/Android.bp Bug: 68860345 Bug: 151177513 Bug: 151953481 Test: m all Exempt-From-Owner-Approval: janitorial work Change-Id: Ib9737d8fb5ef5b90a2c14fe71f1a571079edcf02 Merged-In: Ib9737d8fb5ef5b90a2c14fe71f1a571079edcf02 --- framework/Android.bp | 11 ++++++++++- service/Android.bp | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/framework/Android.bp b/framework/Android.bp index 73e1511644..c7e261c936 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + filegroup { name: "framework-connectivity-internal-sources", srcs: [ @@ -48,4 +57,4 @@ filegroup { "//frameworks/base", "//packages/modules/Connectivity:__subpackages__", ], -} \ No newline at end of file +} diff --git a/service/Android.bp b/service/Android.bp index ed1716fad8..f20b89fb84 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -14,6 +14,15 @@ // limitations under the License. // +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + cc_library_shared { name: "libservice-connectivity", // TODO: build against the NDK (sdk_version: "30" for example) From b2966facbb3be5aa7a6f6dbcf18c3275ae9375fd Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 13 Jan 2021 18:13:11 +0800 Subject: [PATCH 052/343] [VCN07] Bypass VCN for non-internet app accessible cellular services Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities and user intention, which includes: 1. For the requests that don't have anything besides VCN_SUPPORTED_CAPABILITIES, add the NOT_VCN_MANAGED to allow the callers automatically utilize VCN networks if available. 2. For the requests that explicitly add or remove NOT_VCN_MANAGED, do not alter them to allow user fire request that suits their need. Test: atest NetworkRequestTest#testBypassingVcnForNonInternetRequest Bug: 175662146 Change-Id: I2876264cee14b624c89ba3b380027a8b521ad8ea (cherry-picked from aosp/1549817) --- framework/src/android/net/NetworkRequest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4e3085f470..b4a651c060 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -16,6 +16,22 @@ package android.net; +import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; +import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +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_RESTRICTED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; +import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -30,6 +46,8 @@ import android.os.Process; import android.text.TextUtils; import android.util.proto.ProtoOutputStream; +import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -154,8 +172,30 @@ public class NetworkRequest implements Parcelable { * needed in terms of {@link NetworkCapabilities} features */ public static class Builder { + /** + * Capabilities that are currently compatible with VCN networks. + */ + private static final List VCN_SUPPORTED_CAPABILITIES = Arrays.asList( + NET_CAPABILITY_CAPTIVE_PORTAL, + NET_CAPABILITY_DUN, + NET_CAPABILITY_FOREGROUND, + NET_CAPABILITY_INTERNET, + NET_CAPABILITY_NOT_CONGESTED, + NET_CAPABILITY_NOT_METERED, + NET_CAPABILITY_NOT_RESTRICTED, + NET_CAPABILITY_NOT_ROAMING, + NET_CAPABILITY_NOT_SUSPENDED, + NET_CAPABILITY_NOT_VPN, + NET_CAPABILITY_PARTIAL_CONNECTIVITY, + NET_CAPABILITY_TEMPORARILY_NOT_METERED, + NET_CAPABILITY_TRUSTED, + NET_CAPABILITY_VALIDATED); + private final NetworkCapabilities mNetworkCapabilities; + // A boolean that represents the user modified NOT_VCN_MANAGED capability. + private boolean mModifiedNotVcnManaged = false; + /** * Default constructor for Builder. */ @@ -177,6 +217,7 @@ public class NetworkRequest implements Parcelable { // maybeMarkCapabilitiesRestricted() doesn't add back. final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); nc.maybeMarkCapabilitiesRestricted(); + deduceNotVcnManagedCapability(nc); return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, ConnectivityManager.REQUEST_ID_UNSET, Type.NONE); } @@ -193,6 +234,9 @@ public class NetworkRequest implements Parcelable { */ public Builder addCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addCapability(capability); + if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { + mModifiedNotVcnManaged = true; + } return this; } @@ -204,6 +248,9 @@ public class NetworkRequest implements Parcelable { */ public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.removeCapability(capability); + if (capability == NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED) { + mModifiedNotVcnManaged = true; + } return this; } @@ -261,6 +308,9 @@ public class NetworkRequest implements Parcelable { @NonNull public Builder clearCapabilities() { mNetworkCapabilities.clearAll(); + // If the caller explicitly clear all capabilities, the NOT_VCN_MANAGED capabilities + // should not be add back later. + mModifiedNotVcnManaged = true; return this; } @@ -380,6 +430,25 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.setSignalStrength(signalStrength); return this; } + + /** + * Deduce the NET_CAPABILITY_NOT_VCN_MANAGED capability from other capabilities + * and user intention, which includes: + * 1. For the requests that don't have anything besides + * {@link #VCN_SUPPORTED_CAPABILITIES}, add the NET_CAPABILITY_NOT_VCN_MANAGED to + * allow the callers automatically utilize VCN networks if available. + * 2. For the requests that explicitly add or remove NET_CAPABILITY_NOT_VCN_MANAGED, + * do not alter them to allow user fire request that suits their need. + * + * @hide + */ + private void deduceNotVcnManagedCapability(final NetworkCapabilities nc) { + if (mModifiedNotVcnManaged) return; + for (final int cap : nc.getCapabilities()) { + if (!VCN_SUPPORTED_CAPABILITIES.contains(cap)) return; + } + nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); + } } // implement the Parcelable interface From a7f938e4aa7a06e25318c317c420c89b1d57fba6 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 22 Feb 2021 03:18:42 +0000 Subject: [PATCH 053/343] Revert "Revert "Delete VPN methods in ConnectivityManager."" 1. Stop using ConnectivityManager for VPNs in VpnDialogs. 2. Delete updateLockdownVpn, since all callers have been migrated to calling VpnManager directly. 3. Delete the call to VpnManager in factoryReset, since the only caller (ResetNetworkConfirm) has been updated to call into VpnManager directly. 4. Delete getVpnManager, since it is now unused. This reverts commit da6bc5ace2f63221e7cfe9c909af7e0a932415fb. Reason for revert: should be safe to submit now that aosp/1596096 is merged Bug: 173331190 Test: treehugger Change-Id: Ife3607c024006ce4fe46c981e9742170becb6331 --- .../src/android/net/ConnectivityManager.java | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index d3414a404d..071ec34b62 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1069,58 +1069,6 @@ public class ConnectivityManager { } } - /** - * Calls VpnManager#isAlwaysOnVpnPackageSupportedForUser. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean isAlwaysOnVpnPackageSupportedForUser(int userId, @Nullable String vpnPackage) { - return getVpnManager().isAlwaysOnVpnPackageSupportedForUser(userId, vpnPackage); - } - - /** - * Calls VpnManager#setAlwaysOnVpnPackageForUser. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage, - boolean lockdownEnabled, @Nullable List lockdownAllowlist) { - return getVpnManager().setAlwaysOnVpnPackageForUser(userId, vpnPackage, lockdownEnabled, - lockdownAllowlist); - } - - /** - * Calls VpnManager#getAlwaysOnVpnPackageForUser. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public String getAlwaysOnVpnPackageForUser(int userId) { - return getVpnManager().getAlwaysOnVpnPackageForUser(userId); - } - - /** - * Calls VpnManager#isVpnLockdownEnabled. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean isVpnLockdownEnabled(int userId) { - return getVpnManager().isVpnLockdownEnabled(userId); - } - - /** - * Calls VpnManager#getVpnLockdownAllowlist. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public List getVpnLockdownAllowlist(int userId) { - return getVpnManager().getVpnLockdownAllowlist(userId); - } - /** * Adds or removes a requirement for given UID ranges to use the VPN. * @@ -3166,16 +3114,6 @@ public class ConnectivityManager { } } - /** - * Calls VpnManager#updateLockdownVpn. - * @deprecated TODO: remove when callers have migrated to VpnManager. - * @hide - */ - @Deprecated - public boolean updateLockdownVpn() { - return getVpnManager().updateLockdownVpn(); - } - /** * Set sign in error notification to visible or invisible * @@ -4537,8 +4475,6 @@ public class ConnectivityManager { try { mService.factoryReset(); mTetheringManager.stopAllTethering(); - // TODO: Migrate callers to VpnManager#factoryReset. - getVpnManager().factoryReset(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4832,15 +4768,6 @@ public class ConnectivityManager { return new TestNetworkManager(ITestNetworkManager.Stub.asInterface(tnBinder)); } - /** - * Temporary hack to shim calls from ConnectivityManager to VpnManager. We cannot store a - * private final mVpnManager because ConnectivityManager is initialized before VpnManager. - * @hide TODO: remove. - */ - public VpnManager getVpnManager() { - return mContext.getSystemService(VpnManager.class); - } - /** @hide */ public ConnectivityDiagnosticsManager createDiagnosticsManager() { return new ConnectivityDiagnosticsManager(mContext, mService); From 4aad90f1b15fe2b34c93e5753fd362154e6faae9 Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 2 Feb 2021 22:31:30 +0800 Subject: [PATCH 054/343] Use alternative PhoneStateListener formal API MultinetworkPolicyTracker is part of Connectivity mainline module which cannot call @hide API to register PhoneStateListener. Thus, replace it to formal API. Bug: 171183530 Test: atest FrameworksNetTests Change-Id: Ib02790623e82726aaada33f559226020d1e0019b --- .../net/util/MultinetworkPolicyTracker.java | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java index 85e3fa3048..43fffd733e 100644 --- a/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -40,6 +40,8 @@ import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; /** * A class to encapsulate management of the "Smart Networking" capability of @@ -73,6 +75,32 @@ public class MultinetworkPolicyTracker { private volatile int mMeteredMultipathPreference; private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + // Mainline module can't use internal HandlerExecutor, so add an identical executor here. + private static class HandlerExecutor implements Executor { + @NonNull + private final Handler mHandler; + + HandlerExecutor(@NonNull Handler handler) { + mHandler = handler; + } + @Override + public void execute(Runnable command) { + if (!mHandler.post(command)) { + throw new RejectedExecutionException(mHandler + " is shutting down"); + } + } + } + + @VisibleForTesting + protected class ActiveDataSubscriptionIdChangedListener extends PhoneStateListener + implements PhoneStateListener.ActiveDataSubscriptionIdChangedListener { + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + mActiveSubId = subId; + reevaluateInternal(); + } + } + public MultinetworkPolicyTracker(Context ctx, Handler handler) { this(ctx, handler, null); } @@ -93,14 +121,8 @@ public class MultinetworkPolicyTracker { } }; - ctx.getSystemService(TelephonyManager.class).listen( - new PhoneStateListener(handler.getLooper()) { - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - mActiveSubId = subId; - reevaluateInternal(); - } - }, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); + ctx.getSystemService(TelephonyManager.class).registerPhoneStateListener( + new HandlerExecutor(handler), new ActiveDataSubscriptionIdChangedListener()); updateAvoidBadWifi(); updateMeteredMultipathPreference(); From e7ec282eee199b1e8fdda685e66e87e68a13a917 Mon Sep 17 00:00:00 2001 From: Sarah Chin Date: Wed, 3 Feb 2021 12:00:20 -0800 Subject: [PATCH 055/343] APIs for 5G slicing Create TrafficDescriptor class Create new APN ENTERPRISE Update setupDataCall and DataCallResponse to take TrafficDescriptor and matchAllRuleAllowed Move ApnTypes from Annotation to ApnSetting Bug: 179312227 Test: atest FrameworksTelephonyTests Change-Id: I7433976bfe25bcb2af85ffb9338959cbcc9f42f3 --- .../src/android/net/NetworkCapabilities.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 26d14cbfaa..cd76f409b0 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -205,6 +205,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_OEM_PRIVATE, NET_CAPABILITY_VEHICLE_INTERNAL, NET_CAPABILITY_NOT_VCN_MANAGED, + NET_CAPABILITY_ENTERPRISE, }) public @interface NetCapability { } @@ -415,8 +416,17 @@ public final class NetworkCapabilities implements Parcelable { @SystemApi public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; + /** + * Indicates that this network is intended for enterprise use. + *

+ * 5G URSP rules may indicate that all data should use a connection dedicated for enterprise + * use. If the enterprise capability is requested, all enterprise traffic will be routed over + * the connection with this capability. + */ + public static final int NET_CAPABILITY_ENTERPRISE = 29; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VCN_MANAGED; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_ENTERPRISE; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -474,7 +484,8 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_MCX) | (1 << NET_CAPABILITY_RCS) | (1 << NET_CAPABILITY_VEHICLE_INTERNAL) - | (1 << NET_CAPABILITY_XCAP); + | (1 << NET_CAPABILITY_XCAP) + | (1 << NET_CAPABILITY_ENTERPRISE); /** * Capabilities that force network to be restricted. @@ -2028,8 +2039,9 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; case NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE"; - case NET_CAPABILITY_VEHICLE_INTERNAL: return "NET_CAPABILITY_VEHICLE_INTERNAL"; + case NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL"; case NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED"; + case NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE"; default: return Integer.toString(capability); } } From 3ba84e60f9548f398b4bb46b9f8b282bca7a159e Mon Sep 17 00:00:00 2001 From: paulhu Date: Mon, 22 Feb 2021 15:40:43 +0800 Subject: [PATCH 056/343] Implement Settings#checkAndNoteChangeNetworkStateOperation on CS Connectivity is becoming a mainline module in S and ConnectivityManager#enforceChangePermission is using Settings#checkAndNoteChangeNetworkStateOperation for performing a strict and comprehensive check of whether a calling package is allowed to change the state of network. However, Mainline modules are not allowed to use non-formal APIs, fortunately CS is the only caller of this ConnectivityManager#enforceChangePermission. Thus, implement the Settings API on ConnectivityService and remove the ConnectivityManager#enforceChangePermission and Settings#checkAndNoteChangeNetworkStateOperation. Bug: 178565313 Test: atest FrameworksNetTests Change-Id: I6f03398c1735b89470ad5bdbe3a036929daeb53c --- .../src/android/net/ConnectivityManager.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 4ddae533bb..de4c5474c4 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -2297,31 +2297,6 @@ public class ConnectivityManager { } } - /* TODO: These permissions checks don't belong in client-side code. Move them to - * services.jar, possibly in com.android.server.net. */ - - /** {@hide} */ - public static final void enforceChangePermission(Context context, - String callingPkg, String callingAttributionTag) { - int uid = Binder.getCallingUid(); - checkAndNoteChangeNetworkStateOperation(context, uid, callingPkg, - callingAttributionTag, true /* throwException */); - } - - /** - * Check if the package is a allowed to change the network state. This also accounts that such - * an access happened. - * - * @return {@code true} iff the package is allowed to change the network state. - */ - // TODO: Remove method and replace with direct call once R code is pushed to AOSP - private static boolean checkAndNoteChangeNetworkStateOperation(@NonNull Context context, - int uid, @NonNull String callingPackage, @Nullable String callingAttributionTag, - boolean throwException) { - return Settings.checkAndNoteChangeNetworkStateOperation(context, uid, callingPackage, - callingAttributionTag, throwException); - } - /** * Check if the package is a allowed to write settings. This also accounts that such an access * happened. From bb0277e7e60639e4b015cc008f790c6850b772e6 Mon Sep 17 00:00:00 2001 From: paulhu Date: Mon, 22 Feb 2021 15:40:43 +0800 Subject: [PATCH 057/343] Implement Settings#checkAndNoteChangeNetworkStateOperation on CS Connectivity is becoming a mainline module in S and ConnectivityManager#enforceChangePermission is using Settings#checkAndNoteChangeNetworkStateOperation for performing a strict and comprehensive check of whether a calling package is allowed to change the state of network. However, Mainline modules are not allowed to use non-formal APIs, fortunately CS is the only caller of this ConnectivityManager#enforceChangePermission. Thus, implement the Settings API on ConnectivityService and remove the ConnectivityManager#enforceChangePermission and Settings#checkAndNoteChangeNetworkStateOperation. Bug: 178565313 Test: atest FrameworksNetTests Change-Id: I6f03398c1735b89470ad5bdbe3a036929daeb53c Merged-In: I6f03398c1735b89470ad5bdbe3a036929daeb53c --- .../src/android/net/ConnectivityManager.java | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 6273f4bb57..66e7da43cb 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -2245,31 +2245,6 @@ public class ConnectivityManager { } } - /* TODO: These permissions checks don't belong in client-side code. Move them to - * services.jar, possibly in com.android.server.net. */ - - /** {@hide} */ - public static final void enforceChangePermission(Context context, - String callingPkg, String callingAttributionTag) { - int uid = Binder.getCallingUid(); - checkAndNoteChangeNetworkStateOperation(context, uid, callingPkg, - callingAttributionTag, true /* throwException */); - } - - /** - * Check if the package is a allowed to change the network state. This also accounts that such - * an access happened. - * - * @return {@code true} iff the package is allowed to change the network state. - */ - // TODO: Remove method and replace with direct call once R code is pushed to AOSP - private static boolean checkAndNoteChangeNetworkStateOperation(@NonNull Context context, - int uid, @NonNull String callingPackage, @Nullable String callingAttributionTag, - boolean throwException) { - return Settings.checkAndNoteChangeNetworkStateOperation(context, uid, callingPackage, - throwException); - } - /** * Check if the package is a allowed to write settings. This also accounts that such an access * happened. From 5b1411c6366861984b66c0decd862ef57585cd34 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 24 Feb 2021 14:45:39 +0900 Subject: [PATCH 058/343] Add public alternative for protectFromVpn The method is called directly by VpnService#protect. Bug: 171540887 Test: m Change-Id: I7cbb1ef1301dcf8d27b2cc39c0431a0156fe3442 --- framework/src/android/net/NetworkUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java index 9ccb04a44a..b5e8a614b8 100644 --- a/framework/src/android/net/NetworkUtils.java +++ b/framework/src/android/net/NetworkUtils.java @@ -91,7 +91,8 @@ public class NetworkUtils { * this socket will go directly to the underlying network, so its traffic will not be * forwarded through the VPN. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553, + publicAlternatives = "Use {@link android.net.VpnService#protect} instead.") public static native boolean protectFromVpn(FileDescriptor fd); /** From 11b5a5cc71bd087699a59704680fa57df6d3b621 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 28 Jan 2021 13:37:03 +0900 Subject: [PATCH 059/343] Split out the connectivity API surface Split out connectivity APIs to connectivity module directories. This prepares future move of the connectivity code into a mainline module, but still keeps it implemented by framework-minus-apex for now: the API stubs are moved to framework-connectivity.stubs, but the implementation on device remains in the same place. This allows moving the connectivity code in/out of APEX with minimal changes. BYPASS_INCLUSIVE_LANGUAGE_REASON=Moving files, can't modify released API Bug: 171540887 Test: device boots, connectivity working Change-Id: I21c42f032efa6c10e36c749df3183ce9679303a7 --- framework/Android.bp | 25 ++ framework/api/current.txt | 470 +++++++++++++++++++++++++ framework/api/lint-baseline.txt | 4 + framework/api/module-lib-current.txt | 66 ++++ framework/api/module-lib-removed.txt | 1 + framework/api/removed.txt | 11 + framework/api/system-current.txt | 407 +++++++++++++++++++++ framework/api/system-lint-baseline.txt | 1 + framework/api/system-removed.txt | 1 + 9 files changed, 986 insertions(+) create mode 100644 framework/api/current.txt create mode 100644 framework/api/lint-baseline.txt create mode 100644 framework/api/module-lib-current.txt create mode 100644 framework/api/module-lib-removed.txt create mode 100644 framework/api/removed.txt create mode 100644 framework/api/system-current.txt create mode 100644 framework/api/system-lint-baseline.txt create mode 100644 framework/api/system-removed.txt diff --git a/framework/Android.bp b/framework/Android.bp index c7e261c936..86b85e8398 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -58,3 +58,28 @@ filegroup { "//packages/modules/Connectivity:__subpackages__", ], } + +java_sdk_library { + name: "framework-connectivity", + api_only: true, + defaults: ["framework-module-defaults"], + // TODO: build against module API + platform_apis: true, + srcs: [ + ":framework-connectivity-sources", + ], + aidl: { + include_dirs: [ + // Include directories for parcelables that are part of the stable API, and need a + // one-line "parcelable X" .aidl declaration to be used in AIDL interfaces. + // TODO(b/180293679): remove these dependencies as they should not be necessary once + // the module builds against API (the parcelable declarations exist in framework.aidl) + "frameworks/base/core/java", // For framework parcelables + "frameworks/native/aidl/binder", // For PersistableBundle.aidl + ], + }, + libs: [ + "unsupportedappusage", + ], + permitted_packages: ["android.net", "com.android.connectivity.aidl"], +} diff --git a/framework/api/current.txt b/framework/api/current.txt new file mode 100644 index 0000000000..31b8fc8ae5 --- /dev/null +++ b/framework/api/current.txt @@ -0,0 +1,470 @@ +// Signature format: 2.0 +package android.net { + + public class CaptivePortal implements android.os.Parcelable { + method public int describeContents(); + method public void ignoreNetwork(); + method public void reportCaptivePortalDismissed(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class ConnectivityDiagnosticsManager { + method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback); + method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback); + } + + public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback { + ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback(); + method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport); + method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport); + method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean); + } + + public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable { + ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle); + method public int describeContents(); + method @NonNull public android.os.PersistableBundle getAdditionalInfo(); + method @NonNull public android.net.LinkProperties getLinkProperties(); + method @NonNull public android.net.Network getNetwork(); + method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); + method public long getReportTimestamp(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttempted"; + field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded"; + field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult"; + field public static final int NETWORK_PROBE_DNS = 4; // 0x4 + field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20 + field public static final int NETWORK_PROBE_HTTP = 8; // 0x8 + field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10 + field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40 + field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0 + field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2 + field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3 + field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1 + } + + public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable { + ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle); + method public int describeContents(); + method public int getDetectionMethod(); + method @NonNull public android.net.LinkProperties getLinkProperties(); + method @NonNull public android.net.Network getNetwork(); + method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); + method public long getReportTimestamp(); + method @NonNull public android.os.PersistableBundle getStallDetails(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1 + field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2 + field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts"; + field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis"; + field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate"; + } + + public class ConnectivityManager { + method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); + method public boolean bindProcessToNetwork(@Nullable android.net.Network); + method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork(); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo(); + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo(); + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks(); + method @Deprecated public boolean getBackgroundDataSetting(); + method @Nullable public android.net.Network getBoundNetworkForProcess(); + method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress); + method @Nullable public android.net.ProxyInfo getDefaultProxy(); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network); + method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference(); + method @Nullable public byte[] getNetworkWatchlistConfigHash(); + method @Deprecated @Nullable public static android.net.Network getProcessDefaultNetwork(); + method public int getRestrictBackgroundStatus(); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered(); + method public boolean isDefaultNetworkActive(); + method @Deprecated public static boolean isNetworkTypeValid(int); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent); + method public void releaseNetworkRequest(@NonNull android.app.PendingIntent); + method public void removeDefaultNetworkActiveListener(@NonNull android.net.ConnectivityManager.OnNetworkActiveListener); + method @Deprecated public void reportBadNetwork(@Nullable android.net.Network); + method public void reportNetworkConnectivity(@Nullable android.net.Network, boolean); + method public boolean requestBandwidthUpdate(@NonNull android.net.Network); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler, int); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent); + method @Deprecated public void setNetworkPreference(int); + method @Deprecated public static boolean setProcessDefaultNetwork(@Nullable android.net.Network); + method public void unregisterNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); + method public void unregisterNetworkCallback(@NonNull android.app.PendingIntent); + field @Deprecated public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; + field public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL"; + field public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED"; + field @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + field @Deprecated public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1 + field public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; + field public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; + field @Deprecated public static final String EXTRA_EXTRA_INFO = "extraInfo"; + field @Deprecated public static final String EXTRA_IS_FAILOVER = "isFailover"; + field public static final String EXTRA_NETWORK = "android.net.extra.NETWORK"; + field @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo"; + field public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST"; + field @Deprecated public static final String EXTRA_NETWORK_TYPE = "networkType"; + field public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity"; + field @Deprecated public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork"; + field public static final String EXTRA_REASON = "reason"; + field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1 + field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4 + field public static final int MULTIPATH_PREFERENCE_RELIABILITY = 2; // 0x2 + field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1 + field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3 + field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2 + field @Deprecated public static final int TYPE_BLUETOOTH = 7; // 0x7 + field @Deprecated public static final int TYPE_DUMMY = 8; // 0x8 + field @Deprecated public static final int TYPE_ETHERNET = 9; // 0x9 + field @Deprecated public static final int TYPE_MOBILE = 0; // 0x0 + field @Deprecated public static final int TYPE_MOBILE_DUN = 4; // 0x4 + field @Deprecated public static final int TYPE_MOBILE_HIPRI = 5; // 0x5 + field @Deprecated public static final int TYPE_MOBILE_MMS = 2; // 0x2 + field @Deprecated public static final int TYPE_MOBILE_SUPL = 3; // 0x3 + field @Deprecated public static final int TYPE_VPN = 17; // 0x11 + field @Deprecated public static final int TYPE_WIFI = 1; // 0x1 + field @Deprecated public static final int TYPE_WIMAX = 6; // 0x6 + } + + public static class ConnectivityManager.NetworkCallback { + ctor public ConnectivityManager.NetworkCallback(); + method public void onAvailable(@NonNull android.net.Network); + method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); + method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities); + method public void onLinkPropertiesChanged(@NonNull android.net.Network, @NonNull android.net.LinkProperties); + method public void onLosing(@NonNull android.net.Network, int); + method public void onLost(@NonNull android.net.Network); + method public void onUnavailable(); + } + + public static interface ConnectivityManager.OnNetworkActiveListener { + method public void onNetworkActive(); + } + + public class DhcpInfo implements android.os.Parcelable { + ctor public DhcpInfo(); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public int dns1; + field public int dns2; + field public int gateway; + field public int ipAddress; + field public int leaseDuration; + field public int netmask; + field public int serverAddress; + } + + public final class DnsResolver { + method @NonNull public static android.net.DnsResolver getInstance(); + method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback>); + method public void query(@Nullable android.net.Network, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback>); + method public void rawQuery(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback); + method public void rawQuery(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback); + field public static final int CLASS_IN = 1; // 0x1 + field public static final int ERROR_PARSE = 0; // 0x0 + field public static final int ERROR_SYSTEM = 1; // 0x1 + field public static final int FLAG_EMPTY = 0; // 0x0 + field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4 + field public static final int FLAG_NO_CACHE_STORE = 2; // 0x2 + field public static final int FLAG_NO_RETRY = 1; // 0x1 + field public static final int TYPE_A = 1; // 0x1 + field public static final int TYPE_AAAA = 28; // 0x1c + } + + public static interface DnsResolver.Callback { + method public void onAnswer(@NonNull T, int); + method public void onError(@NonNull android.net.DnsResolver.DnsException); + } + + public static class DnsResolver.DnsException extends java.lang.Exception { + field public final int code; + } + + public class InetAddresses { + method public static boolean isNumericAddress(@NonNull String); + method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String); + } + + public final class IpPrefix implements android.os.Parcelable { + method public boolean contains(@NonNull java.net.InetAddress); + method public int describeContents(); + method @NonNull public java.net.InetAddress getAddress(); + method @IntRange(from=0, to=128) public int getPrefixLength(); + method @NonNull public byte[] getRawAddress(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class LinkAddress implements android.os.Parcelable { + method public int describeContents(); + method public java.net.InetAddress getAddress(); + method public int getFlags(); + method @IntRange(from=0, to=128) public int getPrefixLength(); + method public int getScope(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class LinkProperties implements android.os.Parcelable { + ctor public LinkProperties(); + method public boolean addRoute(@NonNull android.net.RouteInfo); + method public void clear(); + method public int describeContents(); + method @Nullable public java.net.Inet4Address getDhcpServerAddress(); + method @NonNull public java.util.List getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public android.net.ProxyInfo getHttpProxy(); + method @Nullable public String getInterfaceName(); + method @NonNull public java.util.List getLinkAddresses(); + method public int getMtu(); + method @Nullable public android.net.IpPrefix getNat64Prefix(); + method @Nullable public String getPrivateDnsServerName(); + method @NonNull public java.util.List getRoutes(); + method public boolean isPrivateDnsActive(); + method public boolean isWakeOnLanSupported(); + method public void setDhcpServerAddress(@Nullable java.net.Inet4Address); + method public void setDnsServers(@NonNull java.util.Collection); + method public void setDomains(@Nullable String); + method public void setHttpProxy(@Nullable android.net.ProxyInfo); + method public void setInterfaceName(@Nullable String); + method public void setLinkAddresses(@NonNull java.util.Collection); + method public void setMtu(int); + method public void setNat64Prefix(@Nullable android.net.IpPrefix); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class MacAddress implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]); + method @NonNull public static android.net.MacAddress fromString(@NonNull String); + method public int getAddressType(); + method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac(); + method public boolean isLocallyAssigned(); + method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress); + method @NonNull public byte[] toByteArray(); + method @NonNull public String toOuiString(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.net.MacAddress BROADCAST_ADDRESS; + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int TYPE_BROADCAST = 3; // 0x3 + field public static final int TYPE_MULTICAST = 2; // 0x2 + field public static final int TYPE_UNICAST = 1; // 0x1 + } + + public class Network implements android.os.Parcelable { + method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException; + method public void bindSocket(java.net.Socket) throws java.io.IOException; + method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException; + method public int describeContents(); + method public static android.net.Network fromNetworkHandle(long); + method public java.net.InetAddress[] getAllByName(String) throws java.net.UnknownHostException; + method public java.net.InetAddress getByName(String) throws java.net.UnknownHostException; + method public long getNetworkHandle(); + method public javax.net.SocketFactory getSocketFactory(); + method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException; + method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException; + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(); + ctor public NetworkCapabilities(android.net.NetworkCapabilities); + method public int describeContents(); + method public int getLinkDownstreamBandwidthKbps(); + method public int getLinkUpstreamBandwidthKbps(); + method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); + method public int getOwnerUid(); + method public int getSignalStrength(); + method @Nullable public android.net.TransportInfo getTransportInfo(); + method public boolean hasCapability(int); + method public boolean hasTransport(int); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11 + field public static final int NET_CAPABILITY_CBS = 5; // 0x5 + field public static final int NET_CAPABILITY_DUN = 2; // 0x2 + field public static final int NET_CAPABILITY_EIMS = 10; // 0xa + field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d + field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13 + field public static final int NET_CAPABILITY_FOTA = 3; // 0x3 + field public static final int NET_CAPABILITY_IA = 7; // 0x7 + field public static final int NET_CAPABILITY_IMS = 4; // 0x4 + field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc + field public static final int NET_CAPABILITY_MCX = 23; // 0x17 + field public static final int NET_CAPABILITY_MMS = 0; // 0x0 + field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14 + field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb + field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd + field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12 + field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15 + field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf + field public static final int NET_CAPABILITY_RCS = 8; // 0x8 + field public static final int NET_CAPABILITY_SUPL = 1; // 0x1 + field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19 + field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe + field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10 + field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 + field public static final int NET_CAPABILITY_XCAP = 9; // 0x9 + field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000 + field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2 + field public static final int TRANSPORT_CELLULAR = 0; // 0x0 + field public static final int TRANSPORT_ETHERNET = 3; // 0x3 + field public static final int TRANSPORT_LOWPAN = 6; // 0x6 + field public static final int TRANSPORT_VPN = 4; // 0x4 + field public static final int TRANSPORT_WIFI = 1; // 0x1 + field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5 + } + + @Deprecated public class NetworkInfo implements android.os.Parcelable { + ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String); + method @Deprecated public int describeContents(); + method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState(); + method @Deprecated public String getExtraInfo(); + method @Deprecated public String getReason(); + method @Deprecated public android.net.NetworkInfo.State getState(); + method @Deprecated public int getSubtype(); + method @Deprecated public String getSubtypeName(); + method @Deprecated public int getType(); + method @Deprecated public String getTypeName(); + method @Deprecated public boolean isAvailable(); + method @Deprecated public boolean isConnected(); + method @Deprecated public boolean isConnectedOrConnecting(); + method @Deprecated public boolean isFailover(); + method @Deprecated public boolean isRoaming(); + method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String); + method @Deprecated public void writeToParcel(android.os.Parcel, int); + field @Deprecated @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + @Deprecated public enum NetworkInfo.DetailedState { + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState AUTHENTICATING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState BLOCKED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState FAILED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState IDLE; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SCANNING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SUSPENDED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK; + } + + @Deprecated public enum NetworkInfo.State { + enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.State SUSPENDED; + enum_constant @Deprecated public static final android.net.NetworkInfo.State UNKNOWN; + } + + public class NetworkRequest implements android.os.Parcelable { + method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities); + method public int describeContents(); + method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); + method public boolean hasCapability(int); + method public boolean hasTransport(int); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static class NetworkRequest.Builder { + ctor public NetworkRequest.Builder(); + method public android.net.NetworkRequest.Builder addCapability(int); + method public android.net.NetworkRequest.Builder addTransportType(int); + method public android.net.NetworkRequest build(); + method @NonNull public android.net.NetworkRequest.Builder clearCapabilities(); + method public android.net.NetworkRequest.Builder removeCapability(int); + method public android.net.NetworkRequest.Builder removeTransportType(int); + method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String); + method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); + } + + public final class Proxy { + ctor public Proxy(); + method @Deprecated public static String getDefaultHost(); + method @Deprecated public static int getDefaultPort(); + method @Deprecated public static String getHost(android.content.Context); + method @Deprecated public static int getPort(android.content.Context); + field @Deprecated public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + field public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; + } + + public class ProxyInfo implements android.os.Parcelable { + ctor public ProxyInfo(@Nullable android.net.ProxyInfo); + method public static android.net.ProxyInfo buildDirectProxy(String, int); + method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List); + method public static android.net.ProxyInfo buildPacProxy(android.net.Uri); + method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int); + method public int describeContents(); + method public String[] getExclusionList(); + method public String getHost(); + method public android.net.Uri getPacFileUrl(); + method public int getPort(); + method public boolean isValid(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class RouteInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.IpPrefix getDestination(); + method @Nullable public java.net.InetAddress getGateway(); + method @Nullable public String getInterface(); + method public boolean hasGateway(); + method public boolean isDefaultRoute(); + method public boolean matches(java.net.InetAddress); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public abstract class SocketKeepalive implements java.lang.AutoCloseable { + method public final void close(); + method public final void start(@IntRange(from=0xa, to=0xe10) int); + method public final void stop(); + field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1 + field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0 + field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8 + field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb + field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 + field public static final int ERROR_INVALID_NETWORK = -20; // 0xffffffec + field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea + field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7 + field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6 + field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2 + } + + public static class SocketKeepalive.Callback { + ctor public SocketKeepalive.Callback(); + method public void onDataReceived(); + method public void onError(int); + method public void onStarted(); + method public void onStopped(); + } + + public interface TransportInfo { + } + +} + diff --git a/framework/api/lint-baseline.txt b/framework/api/lint-baseline.txt new file mode 100644 index 0000000000..2f4004ab72 --- /dev/null +++ b/framework/api/lint-baseline.txt @@ -0,0 +1,4 @@ +// Baseline format: 1.0 +VisiblySynchronized: android.net.NetworkInfo#toString(): + Internal locks must not be exposed (synchronizing on this or class is still + externally observable): method android.net.NetworkInfo.toString() diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt new file mode 100644 index 0000000000..3af855ec1e --- /dev/null +++ b/framework/api/module-lib-current.txt @@ -0,0 +1,66 @@ +// Signature format: 2.0 +package android.net { + + public final class ConnectivityFrameworkInitializer { + method public static void registerServiceWrappers(); + } + + public class ConnectivityManager { + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + } + + public final class NetworkAgentConfig implements android.os.Parcelable { + method @Nullable public String getSubscriberId(); + } + + public static final class NetworkAgentConfig.Builder { + method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); + } + + public final class NetworkCapabilities implements android.os.Parcelable { + field public static final int TRANSPORT_TEST = 7; // 0x7 + } + + public final class Proxy { + method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo); + } + + public final class TcpRepairWindow { + ctor public TcpRepairWindow(int, int, int, int, int, int); + field public final int maxWindow; + field public final int rcvWnd; + field public final int rcvWndScale; + field public final int rcvWup; + field public final int sndWl1; + field public final int sndWnd; + } + + public final class TestNetworkInterface implements android.os.Parcelable { + ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String); + method public int describeContents(); + method @NonNull public android.os.ParcelFileDescriptor getFileDescriptor(); + method @NonNull public String getInterfaceName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class TestNetworkManager { + method @NonNull public android.net.TestNetworkInterface createTapInterface(); + method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection); + method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder); + method public void teardownTestNetwork(@NonNull android.net.Network); + field public static final String TEST_TAP_PREFIX = "testtap"; + } + + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { + ctor public VpnTransportInfo(int); + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public final int type; + } + +} + diff --git a/framework/api/module-lib-removed.txt b/framework/api/module-lib-removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/framework/api/module-lib-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/framework/api/removed.txt b/framework/api/removed.txt new file mode 100644 index 0000000000..303a1e6173 --- /dev/null +++ b/framework/api/removed.txt @@ -0,0 +1,11 @@ +// Signature format: 2.0 +package android.net { + + public class ConnectivityManager { + method @Deprecated public boolean requestRouteToHost(int, int); + method @Deprecated public int startUsingNetworkFeature(int, String); + method @Deprecated public int stopUsingNetworkFeature(int, String); + } + +} + diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt new file mode 100644 index 0000000000..41ebc5774f --- /dev/null +++ b/framework/api/system-current.txt @@ -0,0 +1,407 @@ +// Signature format: 2.0 +package android.net { + + public class CaptivePortal implements android.os.Parcelable { + method public void logEvent(int, @NonNull String); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork(); + method public void useNetwork(); + field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64 + field public static final int APP_RETURN_DISMISSED = 0; // 0x0 + field public static final int APP_RETURN_UNWANTED = 1; // 0x1 + field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2 + } + + public final class CaptivePortalData implements android.os.Parcelable { + method public int describeContents(); + method public long getByteLimit(); + method public long getExpiryTimeMillis(); + method public long getRefreshTimeMillis(); + method @Nullable public android.net.Uri getUserPortalUrl(); + method public int getUserPortalUrlSource(); + method @Nullable public String getVenueFriendlyName(); + method @Nullable public android.net.Uri getVenueInfoUrl(); + method public int getVenueInfoUrlSource(); + method public boolean isCaptive(); + method public boolean isSessionExtendable(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0 + field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1 + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static class CaptivePortalData.Builder { + ctor public CaptivePortalData.Builder(); + ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData); + method @NonNull public android.net.CaptivePortalData build(); + method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long); + method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean); + method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long); + method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long); + method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); + method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); + method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); + method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); + method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); + method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); + } + + public class ConnectivityManager { + method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl(); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider); + method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull android.net.QosCallback, @NonNull java.util.concurrent.Executor); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); + method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider); + method public void unregisterQosCallback(@NonNull android.net.QosCallback); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback); + field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; + field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + field public static final int TETHERING_BLUETOOTH = 2; // 0x2 + field public static final int TETHERING_USB = 1; // 0x1 + field public static final int TETHERING_WIFI = 0; // 0x0 + field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd + field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0 + field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb + field public static final int TYPE_NONE = -1; // 0xffffffff + field @Deprecated public static final int TYPE_PROXY = 16; // 0x10 + field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd + } + + public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener { + method public void onComplete(); + } + + @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { + ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); + method @Deprecated public void onTetheringFailed(); + method @Deprecated public void onTetheringStarted(); + } + + @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener { + method @Deprecated public void onTetheringEntitlementResult(int); + } + + @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback { + ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback(); + method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network); + } + + public final class InvalidPacketException extends java.lang.Exception { + ctor public InvalidPacketException(int); + method public int getError(); + field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb + field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 + field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea + } + + public final class IpConfiguration implements android.os.Parcelable { + ctor public IpConfiguration(); + ctor public IpConfiguration(@NonNull android.net.IpConfiguration); + method public int describeContents(); + method @Nullable public android.net.ProxyInfo getHttpProxy(); + method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment(); + method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings(); + method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration(); + method public void setHttpProxy(@Nullable android.net.ProxyInfo); + method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment); + method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings); + method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public enum IpConfiguration.IpAssignment { + enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP; + enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC; + enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED; + } + + public enum IpConfiguration.ProxySettings { + enum_constant public static final android.net.IpConfiguration.ProxySettings NONE; + enum_constant public static final android.net.IpConfiguration.ProxySettings PAC; + enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC; + enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED; + } + + public final class IpPrefix implements android.os.Parcelable { + ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); + ctor public IpPrefix(@NonNull String); + } + + public class KeepalivePacketData { + ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException; + method @NonNull public java.net.InetAddress getDstAddress(); + method public int getDstPort(); + method @NonNull public byte[] getPacket(); + method @NonNull public java.net.InetAddress getSrcAddress(); + method public int getSrcPort(); + } + + public class LinkAddress implements android.os.Parcelable { + ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int); + ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long); + ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); + ctor public LinkAddress(@NonNull String); + ctor public LinkAddress(@NonNull String, int, int); + method public long getDeprecationTime(); + method public long getExpirationTime(); + method public boolean isGlobalPreferred(); + method public boolean isIpv4(); + method public boolean isIpv6(); + method public boolean isSameAddressAs(@Nullable android.net.LinkAddress); + field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL + field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL + } + + public final class LinkProperties implements android.os.Parcelable { + ctor public LinkProperties(@Nullable android.net.LinkProperties); + ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean); + method public boolean addDnsServer(@NonNull java.net.InetAddress); + method public boolean addLinkAddress(@NonNull android.net.LinkAddress); + method public boolean addPcscfServer(@NonNull java.net.InetAddress); + method @NonNull public java.util.List getAddresses(); + method @NonNull public java.util.List getAllInterfaceNames(); + method @NonNull public java.util.List getAllLinkAddresses(); + method @NonNull public java.util.List getAllRoutes(); + method @Nullable public android.net.Uri getCaptivePortalApiUrl(); + method @Nullable public android.net.CaptivePortalData getCaptivePortalData(); + method @NonNull public java.util.List getPcscfServers(); + method @Nullable public String getTcpBufferSizes(); + method @NonNull public java.util.List getValidatedPrivateDnsServers(); + method public boolean hasGlobalIpv6Address(); + method public boolean hasIpv4Address(); + method public boolean hasIpv4DefaultRoute(); + method public boolean hasIpv4DnsServer(); + method public boolean hasIpv6DefaultRoute(); + method public boolean hasIpv6DnsServer(); + method public boolean isIpv4Provisioned(); + method public boolean isIpv6Provisioned(); + method public boolean isProvisioned(); + method public boolean isReachable(@NonNull java.net.InetAddress); + method public boolean removeDnsServer(@NonNull java.net.InetAddress); + method public boolean removeLinkAddress(@NonNull android.net.LinkAddress); + method public boolean removeRoute(@NonNull android.net.RouteInfo); + method public void setCaptivePortalApiUrl(@Nullable android.net.Uri); + method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData); + method public void setPcscfServers(@NonNull java.util.Collection); + method public void setPrivateDnsServerName(@Nullable String); + method public void setTcpBufferSizes(@Nullable String); + method public void setUsePrivateDns(boolean); + method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection); + } + + public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable { + ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException; + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class Network implements android.os.Parcelable { + ctor public Network(@NonNull android.net.Network); + method public int getNetId(); + method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); + } + + public abstract class NetworkAgent { + ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); + method @Nullable public android.net.Network getNetwork(); + method public void markConnected(); + method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData); + method public void onAutomaticReconnectDisabled(); + method public void onNetworkUnwanted(); + method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter); + method public void onQosCallbackUnregistered(int); + method public void onRemoveKeepalivePacketFilter(int); + method public void onSaveAcceptUnvalidated(boolean); + method public void onSignalStrengthThresholdsUpdated(@NonNull int[]); + method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData); + method public void onStopSocketKeepalive(int); + method public void onValidationStatus(int, @Nullable android.net.Uri); + method @NonNull public android.net.Network register(); + method public final void sendLinkProperties(@NonNull android.net.LinkProperties); + method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); + method public final void sendNetworkScore(@IntRange(from=0, to=99) int); + method public final void sendQosCallbackError(int, int); + method public final void sendQosSessionAvailable(int, int, @NonNull android.telephony.data.EpsBearerQosSessionAttributes); + method public final void sendQosSessionLost(int, int); + method public final void sendSocketKeepaliveEvent(int, int); + method public final void setUnderlyingNetworks(@Nullable java.util.List); + method public void unregister(); + field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 + field public static final int VALIDATION_STATUS_VALID = 1; // 0x1 + } + + public final class NetworkAgentConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getLegacyType(); + method @NonNull public String getLegacyTypeName(); + method public boolean isExplicitlySelected(); + method public boolean isPartialConnectivityAcceptable(); + method public boolean isUnvalidatedConnectivityAcceptable(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class NetworkAgentConfig.Builder { + ctor public NetworkAgentConfig.Builder(); + method @NonNull public android.net.NetworkAgentConfig build(); + method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String); + method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean); + method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean); + } + + public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); + method @NonNull public int[] getAdministratorUids(); + method @Nullable public String getSsid(); + method @NonNull public int[] getTransportTypes(); + method public boolean isPrivateDnsBroken(); + method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); + field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c + field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 + field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a + field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 + field public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; // 0x1b + } + + public static final class NetworkCapabilities.Builder { + ctor public NetworkCapabilities.Builder(); + ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); + method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); + method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder clearAll(); + method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + } + + public class NetworkProvider { + ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String); + method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest); + method public int getProviderId(); + method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest); + method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int); + field public static final int ID_NONE = -1; // 0xffffffff + } + + public class NetworkRequest implements android.os.Parcelable { + method @Nullable public String getRequestorPackageName(); + method public int getRequestorUid(); + } + + public static class NetworkRequest.Builder { + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); + } + + public final class RouteInfo implements android.os.Parcelable { + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int); + method public int getMtu(); + method public int getType(); + field public static final int RTN_THROW = 9; // 0x9 + field public static final int RTN_UNICAST = 1; // 0x1 + field public static final int RTN_UNREACHABLE = 7; // 0x7 + } + + public abstract class SocketKeepalive implements java.lang.AutoCloseable { + field public static final int SUCCESS = 0; // 0x0 + } + + public final class StaticIpConfiguration implements android.os.Parcelable { + ctor public StaticIpConfiguration(); + ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + method public void addDnsServer(@NonNull java.net.InetAddress); + method public void clear(); + method public int describeContents(); + method @NonNull public java.util.List getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public java.net.InetAddress getGateway(); + method @Nullable public android.net.LinkAddress getIpAddress(); + method @NonNull public java.util.List getRoutes(@Nullable String); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class StaticIpConfiguration.Builder { + ctor public StaticIpConfiguration.Builder(); + method @NonNull public android.net.StaticIpConfiguration build(); + method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable); + method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String); + method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress); + method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress); + } + + public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable { + ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException; + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public final int ipTos; + field public final int ipTtl; + field public final int tcpAck; + field public final int tcpSeq; + field public final int tcpWindow; + field public final int tcpWindowScale; + } + + public interface TransportInfo { + method public default boolean hasLocationSensitiveFields(); + method @NonNull public default android.net.TransportInfo makeCopy(boolean); + } + +} + +package android.net.apf { + + public final class ApfCapabilities implements android.os.Parcelable { + ctor public ApfCapabilities(int, int, int); + method public int describeContents(); + method public static boolean getApfDrop8023Frames(); + method @NonNull public static int[] getApfEtherTypeBlackList(); + method public boolean hasDataAccess(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public final int apfPacketFormat; + field public final int apfVersionSupported; + field public final int maximumApfProgramSize; + } + +} + +package android.net.util { + + public final class SocketUtils { + method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException; + method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; + method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); + } + +} + diff --git a/framework/api/system-lint-baseline.txt b/framework/api/system-lint-baseline.txt new file mode 100644 index 0000000000..9a97707763 --- /dev/null +++ b/framework/api/system-lint-baseline.txt @@ -0,0 +1 @@ +// Baseline format: 1.0 diff --git a/framework/api/system-removed.txt b/framework/api/system-removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/framework/api/system-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 From 5f658cbb9b808f097017ca1b98e6075e1cf475ad Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 25 Feb 2021 09:12:04 +0800 Subject: [PATCH 060/343] Fix copyright license of VpnTransportInfo Test: TH Bug: None Change-Id: Id1fe2c62a0fd60b9833d8b00d2fa2ddc2f031004 --- framework/src/android/net/VpnTransportInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/android/net/VpnTransportInfo.java b/framework/src/android/net/VpnTransportInfo.java index 0242ba0874..340141b78a 100644 --- a/framework/src/android/net/VpnTransportInfo.java +++ b/framework/src/android/net/VpnTransportInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From f15fc7f9a80f9214e6656d8dbdd01559348a2adf Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 28 Jan 2021 13:37:03 +0900 Subject: [PATCH 061/343] Split out the connectivity API surface Split out connectivity APIs to connectivity module directories. This prepares future move of the connectivity code into a mainline module, but still keeps it implemented by framework-minus-apex for now: the API stubs are moved to framework-connectivity.stubs, but the implementation on device remains in the same place. This allows moving the connectivity code in/out of APEX with minimal changes. BYPASS_INCLUSIVE_LANGUAGE_REASON=Moving files, can't modify released API Bug: 171540887 Test: device boots, connectivity working Merged-In: I21c42f032efa6c10e36c749df3183ce9679303a7 (cherry-pick from internal branch with API files conflicts) Change-Id: I21c42f032efa6c10e36c749df3183ce9679303a7 --- framework/Android.bp | 25 ++ framework/api/current.txt | 469 +++++++++++++++++++++++++ framework/api/lint-baseline.txt | 4 + framework/api/module-lib-current.txt | 66 ++++ framework/api/module-lib-removed.txt | 1 + framework/api/removed.txt | 11 + framework/api/system-current.txt | 407 +++++++++++++++++++++ framework/api/system-lint-baseline.txt | 1 + framework/api/system-removed.txt | 1 + 9 files changed, 985 insertions(+) create mode 100644 framework/api/current.txt create mode 100644 framework/api/lint-baseline.txt create mode 100644 framework/api/module-lib-current.txt create mode 100644 framework/api/module-lib-removed.txt create mode 100644 framework/api/removed.txt create mode 100644 framework/api/system-current.txt create mode 100644 framework/api/system-lint-baseline.txt create mode 100644 framework/api/system-removed.txt diff --git a/framework/Android.bp b/framework/Android.bp index ffca971430..9da27d2711 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -59,3 +59,28 @@ filegroup { "//packages/modules/Connectivity:__subpackages__", ], } + +java_sdk_library { + name: "framework-connectivity", + api_only: true, + defaults: ["framework-module-defaults"], + // TODO: build against module API + platform_apis: true, + srcs: [ + ":framework-connectivity-sources", + ], + aidl: { + include_dirs: [ + // Include directories for parcelables that are part of the stable API, and need a + // one-line "parcelable X" .aidl declaration to be used in AIDL interfaces. + // TODO(b/180293679): remove these dependencies as they should not be necessary once + // the module builds against API (the parcelable declarations exist in framework.aidl) + "frameworks/base/core/java", // For framework parcelables + "frameworks/native/aidl/binder", // For PersistableBundle.aidl + ], + }, + libs: [ + "unsupportedappusage", + ], + permitted_packages: ["android.net", "com.android.connectivity.aidl"], +} diff --git a/framework/api/current.txt b/framework/api/current.txt new file mode 100644 index 0000000000..d4262a807a --- /dev/null +++ b/framework/api/current.txt @@ -0,0 +1,469 @@ +// Signature format: 2.0 +package android.net { + + public class CaptivePortal implements android.os.Parcelable { + method public int describeContents(); + method public void ignoreNetwork(); + method public void reportCaptivePortalDismissed(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class ConnectivityDiagnosticsManager { + method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback); + method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback); + } + + public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback { + ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback(); + method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport); + method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport); + method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean); + } + + public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable { + ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle); + method public int describeContents(); + method @NonNull public android.os.PersistableBundle getAdditionalInfo(); + method @NonNull public android.net.LinkProperties getLinkProperties(); + method @NonNull public android.net.Network getNetwork(); + method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); + method public long getReportTimestamp(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttempted"; + field public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded"; + field public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult"; + field public static final int NETWORK_PROBE_DNS = 4; // 0x4 + field public static final int NETWORK_PROBE_FALLBACK = 32; // 0x20 + field public static final int NETWORK_PROBE_HTTP = 8; // 0x8 + field public static final int NETWORK_PROBE_HTTPS = 16; // 0x10 + field public static final int NETWORK_PROBE_PRIVATE_DNS = 64; // 0x40 + field public static final int NETWORK_VALIDATION_RESULT_INVALID = 0; // 0x0 + field public static final int NETWORK_VALIDATION_RESULT_PARTIALLY_VALID = 2; // 0x2 + field public static final int NETWORK_VALIDATION_RESULT_SKIPPED = 3; // 0x3 + field public static final int NETWORK_VALIDATION_RESULT_VALID = 1; // 0x1 + } + + public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable { + ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle); + method public int describeContents(); + method public int getDetectionMethod(); + method @NonNull public android.net.LinkProperties getLinkProperties(); + method @NonNull public android.net.Network getNetwork(); + method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities(); + method public long getReportTimestamp(); + method @NonNull public android.os.PersistableBundle getStallDetails(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1 + field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2 + field public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts"; + field public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS = "tcpMetricsCollectionPeriodMillis"; + field public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate"; + } + + public class ConnectivityManager { + method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); + method public boolean bindProcessToNetwork(@Nullable android.net.Network); + method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork(); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo(); + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo(); + method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks(); + method @Deprecated public boolean getBackgroundDataSetting(); + method @Nullable public android.net.Network getBoundNetworkForProcess(); + method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress); + method @Nullable public android.net.ProxyInfo getDefaultProxy(); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network); + method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int); + method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network); + method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference(); + method @Nullable public byte[] getNetworkWatchlistConfigHash(); + method @Deprecated @Nullable public static android.net.Network getProcessDefaultNetwork(); + method public int getRestrictBackgroundStatus(); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered(); + method public boolean isDefaultNetworkActive(); + method @Deprecated public static boolean isNetworkTypeValid(int); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent); + method public void releaseNetworkRequest(@NonNull android.app.PendingIntent); + method public void removeDefaultNetworkActiveListener(@NonNull android.net.ConnectivityManager.OnNetworkActiveListener); + method @Deprecated public void reportBadNetwork(@Nullable android.net.Network); + method public void reportNetworkConnectivity(@Nullable android.net.Network, boolean); + method public boolean requestBandwidthUpdate(@NonNull android.net.Network); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler, int); + method public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.app.PendingIntent); + method @Deprecated public void setNetworkPreference(int); + method @Deprecated public static boolean setProcessDefaultNetwork(@Nullable android.net.Network); + method public void unregisterNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); + method public void unregisterNetworkCallback(@NonNull android.app.PendingIntent); + field @Deprecated public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; + field public static final String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL"; + field public static final String ACTION_RESTRICT_BACKGROUND_CHANGED = "android.net.conn.RESTRICT_BACKGROUND_CHANGED"; + field @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + field @Deprecated public static final int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1 + field public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL"; + field public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL"; + field @Deprecated public static final String EXTRA_EXTRA_INFO = "extraInfo"; + field @Deprecated public static final String EXTRA_IS_FAILOVER = "isFailover"; + field public static final String EXTRA_NETWORK = "android.net.extra.NETWORK"; + field @Deprecated public static final String EXTRA_NETWORK_INFO = "networkInfo"; + field public static final String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST"; + field @Deprecated public static final String EXTRA_NETWORK_TYPE = "networkType"; + field public static final String EXTRA_NO_CONNECTIVITY = "noConnectivity"; + field @Deprecated public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork"; + field public static final String EXTRA_REASON = "reason"; + field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1 + field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4 + field public static final int MULTIPATH_PREFERENCE_RELIABILITY = 2; // 0x2 + field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1 + field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3 + field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2 + field @Deprecated public static final int TYPE_BLUETOOTH = 7; // 0x7 + field @Deprecated public static final int TYPE_DUMMY = 8; // 0x8 + field @Deprecated public static final int TYPE_ETHERNET = 9; // 0x9 + field @Deprecated public static final int TYPE_MOBILE = 0; // 0x0 + field @Deprecated public static final int TYPE_MOBILE_DUN = 4; // 0x4 + field @Deprecated public static final int TYPE_MOBILE_HIPRI = 5; // 0x5 + field @Deprecated public static final int TYPE_MOBILE_MMS = 2; // 0x2 + field @Deprecated public static final int TYPE_MOBILE_SUPL = 3; // 0x3 + field @Deprecated public static final int TYPE_VPN = 17; // 0x11 + field @Deprecated public static final int TYPE_WIFI = 1; // 0x1 + field @Deprecated public static final int TYPE_WIMAX = 6; // 0x6 + } + + public static class ConnectivityManager.NetworkCallback { + ctor public ConnectivityManager.NetworkCallback(); + method public void onAvailable(@NonNull android.net.Network); + method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); + method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities); + method public void onLinkPropertiesChanged(@NonNull android.net.Network, @NonNull android.net.LinkProperties); + method public void onLosing(@NonNull android.net.Network, int); + method public void onLost(@NonNull android.net.Network); + method public void onUnavailable(); + } + + public static interface ConnectivityManager.OnNetworkActiveListener { + method public void onNetworkActive(); + } + + public class DhcpInfo implements android.os.Parcelable { + ctor public DhcpInfo(); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public int dns1; + field public int dns2; + field public int gateway; + field public int ipAddress; + field public int leaseDuration; + field public int netmask; + field public int serverAddress; + } + + public final class DnsResolver { + method @NonNull public static android.net.DnsResolver getInstance(); + method public void query(@Nullable android.net.Network, @NonNull String, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback>); + method public void query(@Nullable android.net.Network, @NonNull String, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback>); + method public void rawQuery(@Nullable android.net.Network, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback); + method public void rawQuery(@Nullable android.net.Network, @NonNull String, int, int, int, @NonNull java.util.concurrent.Executor, @Nullable android.os.CancellationSignal, @NonNull android.net.DnsResolver.Callback); + field public static final int CLASS_IN = 1; // 0x1 + field public static final int ERROR_PARSE = 0; // 0x0 + field public static final int ERROR_SYSTEM = 1; // 0x1 + field public static final int FLAG_EMPTY = 0; // 0x0 + field public static final int FLAG_NO_CACHE_LOOKUP = 4; // 0x4 + field public static final int FLAG_NO_CACHE_STORE = 2; // 0x2 + field public static final int FLAG_NO_RETRY = 1; // 0x1 + field public static final int TYPE_A = 1; // 0x1 + field public static final int TYPE_AAAA = 28; // 0x1c + } + + public static interface DnsResolver.Callback { + method public void onAnswer(@NonNull T, int); + method public void onError(@NonNull android.net.DnsResolver.DnsException); + } + + public static class DnsResolver.DnsException extends java.lang.Exception { + field public final int code; + } + + public class InetAddresses { + method public static boolean isNumericAddress(@NonNull String); + method @NonNull public static java.net.InetAddress parseNumericAddress(@NonNull String); + } + + public final class IpPrefix implements android.os.Parcelable { + method public boolean contains(@NonNull java.net.InetAddress); + method public int describeContents(); + method @NonNull public java.net.InetAddress getAddress(); + method @IntRange(from=0, to=128) public int getPrefixLength(); + method @NonNull public byte[] getRawAddress(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class LinkAddress implements android.os.Parcelable { + method public int describeContents(); + method public java.net.InetAddress getAddress(); + method public int getFlags(); + method @IntRange(from=0, to=128) public int getPrefixLength(); + method public int getScope(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class LinkProperties implements android.os.Parcelable { + ctor public LinkProperties(); + method public boolean addRoute(@NonNull android.net.RouteInfo); + method public void clear(); + method public int describeContents(); + method @Nullable public java.net.Inet4Address getDhcpServerAddress(); + method @NonNull public java.util.List getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public android.net.ProxyInfo getHttpProxy(); + method @Nullable public String getInterfaceName(); + method @NonNull public java.util.List getLinkAddresses(); + method public int getMtu(); + method @Nullable public android.net.IpPrefix getNat64Prefix(); + method @Nullable public String getPrivateDnsServerName(); + method @NonNull public java.util.List getRoutes(); + method public boolean isPrivateDnsActive(); + method public boolean isWakeOnLanSupported(); + method public void setDhcpServerAddress(@Nullable java.net.Inet4Address); + method public void setDnsServers(@NonNull java.util.Collection); + method public void setDomains(@Nullable String); + method public void setHttpProxy(@Nullable android.net.ProxyInfo); + method public void setInterfaceName(@Nullable String); + method public void setLinkAddresses(@NonNull java.util.Collection); + method public void setMtu(int); + method public void setNat64Prefix(@Nullable android.net.IpPrefix); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class MacAddress implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public static android.net.MacAddress fromBytes(@NonNull byte[]); + method @NonNull public static android.net.MacAddress fromString(@NonNull String); + method public int getAddressType(); + method @Nullable public java.net.Inet6Address getLinkLocalIpv6FromEui48Mac(); + method public boolean isLocallyAssigned(); + method public boolean matches(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress); + method @NonNull public byte[] toByteArray(); + method @NonNull public String toOuiString(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.net.MacAddress BROADCAST_ADDRESS; + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int TYPE_BROADCAST = 3; // 0x3 + field public static final int TYPE_MULTICAST = 2; // 0x2 + field public static final int TYPE_UNICAST = 1; // 0x1 + } + + public class Network implements android.os.Parcelable { + method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException; + method public void bindSocket(java.net.Socket) throws java.io.IOException; + method public void bindSocket(java.io.FileDescriptor) throws java.io.IOException; + method public int describeContents(); + method public static android.net.Network fromNetworkHandle(long); + method public java.net.InetAddress[] getAllByName(String) throws java.net.UnknownHostException; + method public java.net.InetAddress getByName(String) throws java.net.UnknownHostException; + method public long getNetworkHandle(); + method public javax.net.SocketFactory getSocketFactory(); + method public java.net.URLConnection openConnection(java.net.URL) throws java.io.IOException; + method public java.net.URLConnection openConnection(java.net.URL, java.net.Proxy) throws java.io.IOException; + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(); + ctor public NetworkCapabilities(android.net.NetworkCapabilities); + method public int describeContents(); + method public int getLinkDownstreamBandwidthKbps(); + method public int getLinkUpstreamBandwidthKbps(); + method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); + method public int getOwnerUid(); + method public int getSignalStrength(); + method @Nullable public android.net.TransportInfo getTransportInfo(); + method public boolean hasCapability(int); + method public boolean hasTransport(int); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11 + field public static final int NET_CAPABILITY_CBS = 5; // 0x5 + field public static final int NET_CAPABILITY_DUN = 2; // 0x2 + field public static final int NET_CAPABILITY_EIMS = 10; // 0xa + field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13 + field public static final int NET_CAPABILITY_FOTA = 3; // 0x3 + field public static final int NET_CAPABILITY_IA = 7; // 0x7 + field public static final int NET_CAPABILITY_IMS = 4; // 0x4 + field public static final int NET_CAPABILITY_INTERNET = 12; // 0xc + field public static final int NET_CAPABILITY_MCX = 23; // 0x17 + field public static final int NET_CAPABILITY_MMS = 0; // 0x0 + field public static final int NET_CAPABILITY_NOT_CONGESTED = 20; // 0x14 + field public static final int NET_CAPABILITY_NOT_METERED = 11; // 0xb + field public static final int NET_CAPABILITY_NOT_RESTRICTED = 13; // 0xd + field public static final int NET_CAPABILITY_NOT_ROAMING = 18; // 0x12 + field public static final int NET_CAPABILITY_NOT_SUSPENDED = 21; // 0x15 + field public static final int NET_CAPABILITY_NOT_VPN = 15; // 0xf + field public static final int NET_CAPABILITY_RCS = 8; // 0x8 + field public static final int NET_CAPABILITY_SUPL = 1; // 0x1 + field public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; // 0x19 + field public static final int NET_CAPABILITY_TRUSTED = 14; // 0xe + field public static final int NET_CAPABILITY_VALIDATED = 16; // 0x10 + field public static final int NET_CAPABILITY_WIFI_P2P = 6; // 0x6 + field public static final int NET_CAPABILITY_XCAP = 9; // 0x9 + field public static final int SIGNAL_STRENGTH_UNSPECIFIED = -2147483648; // 0x80000000 + field public static final int TRANSPORT_BLUETOOTH = 2; // 0x2 + field public static final int TRANSPORT_CELLULAR = 0; // 0x0 + field public static final int TRANSPORT_ETHERNET = 3; // 0x3 + field public static final int TRANSPORT_LOWPAN = 6; // 0x6 + field public static final int TRANSPORT_VPN = 4; // 0x4 + field public static final int TRANSPORT_WIFI = 1; // 0x1 + field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5 + } + + @Deprecated public class NetworkInfo implements android.os.Parcelable { + ctor @Deprecated public NetworkInfo(int, int, @Nullable String, @Nullable String); + method @Deprecated public int describeContents(); + method @Deprecated @NonNull public android.net.NetworkInfo.DetailedState getDetailedState(); + method @Deprecated public String getExtraInfo(); + method @Deprecated public String getReason(); + method @Deprecated public android.net.NetworkInfo.State getState(); + method @Deprecated public int getSubtype(); + method @Deprecated public String getSubtypeName(); + method @Deprecated public int getType(); + method @Deprecated public String getTypeName(); + method @Deprecated public boolean isAvailable(); + method @Deprecated public boolean isConnected(); + method @Deprecated public boolean isConnectedOrConnecting(); + method @Deprecated public boolean isFailover(); + method @Deprecated public boolean isRoaming(); + method @Deprecated public void setDetailedState(@NonNull android.net.NetworkInfo.DetailedState, @Nullable String, @Nullable String); + method @Deprecated public void writeToParcel(android.os.Parcel, int); + field @Deprecated @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + @Deprecated public enum NetworkInfo.DetailedState { + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState AUTHENTICATING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState BLOCKED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState CONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState DISCONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState FAILED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState IDLE; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState OBTAINING_IPADDR; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SCANNING; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState SUSPENDED; + enum_constant @Deprecated public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK; + } + + @Deprecated public enum NetworkInfo.State { + enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.State CONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTED; + enum_constant @Deprecated public static final android.net.NetworkInfo.State DISCONNECTING; + enum_constant @Deprecated public static final android.net.NetworkInfo.State SUSPENDED; + enum_constant @Deprecated public static final android.net.NetworkInfo.State UNKNOWN; + } + + public class NetworkRequest implements android.os.Parcelable { + method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities); + method public int describeContents(); + method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); + method public boolean hasCapability(int); + method public boolean hasTransport(int); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static class NetworkRequest.Builder { + ctor public NetworkRequest.Builder(); + method public android.net.NetworkRequest.Builder addCapability(int); + method public android.net.NetworkRequest.Builder addTransportType(int); + method public android.net.NetworkRequest build(); + method @NonNull public android.net.NetworkRequest.Builder clearCapabilities(); + method public android.net.NetworkRequest.Builder removeCapability(int); + method public android.net.NetworkRequest.Builder removeTransportType(int); + method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String); + method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); + } + + public final class Proxy { + ctor public Proxy(); + method @Deprecated public static String getDefaultHost(); + method @Deprecated public static int getDefaultPort(); + method @Deprecated public static String getHost(android.content.Context); + method @Deprecated public static int getPort(android.content.Context); + field @Deprecated public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; + field public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; + } + + public class ProxyInfo implements android.os.Parcelable { + ctor public ProxyInfo(@Nullable android.net.ProxyInfo); + method public static android.net.ProxyInfo buildDirectProxy(String, int); + method public static android.net.ProxyInfo buildDirectProxy(String, int, java.util.List); + method public static android.net.ProxyInfo buildPacProxy(android.net.Uri); + method @NonNull public static android.net.ProxyInfo buildPacProxy(@NonNull android.net.Uri, int); + method public int describeContents(); + method public String[] getExclusionList(); + method public String getHost(); + method public android.net.Uri getPacFileUrl(); + method public int getPort(); + method public boolean isValid(); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public final class RouteInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.net.IpPrefix getDestination(); + method @Nullable public java.net.InetAddress getGateway(); + method @Nullable public String getInterface(); + method public boolean hasGateway(); + method public boolean isDefaultRoute(); + method public boolean matches(java.net.InetAddress); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public abstract class SocketKeepalive implements java.lang.AutoCloseable { + method public final void close(); + method public final void start(@IntRange(from=0xa, to=0xe10) int); + method public final void stop(); + field public static final int ERROR_HARDWARE_ERROR = -31; // 0xffffffe1 + field public static final int ERROR_INSUFFICIENT_RESOURCES = -32; // 0xffffffe0 + field public static final int ERROR_INVALID_INTERVAL = -24; // 0xffffffe8 + field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb + field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 + field public static final int ERROR_INVALID_NETWORK = -20; // 0xffffffec + field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea + field public static final int ERROR_INVALID_SOCKET = -25; // 0xffffffe7 + field public static final int ERROR_SOCKET_NOT_IDLE = -26; // 0xffffffe6 + field public static final int ERROR_UNSUPPORTED = -30; // 0xffffffe2 + } + + public static class SocketKeepalive.Callback { + ctor public SocketKeepalive.Callback(); + method public void onDataReceived(); + method public void onError(int); + method public void onStarted(); + method public void onStopped(); + } + + public interface TransportInfo { + } + +} + diff --git a/framework/api/lint-baseline.txt b/framework/api/lint-baseline.txt new file mode 100644 index 0000000000..2f4004ab72 --- /dev/null +++ b/framework/api/lint-baseline.txt @@ -0,0 +1,4 @@ +// Baseline format: 1.0 +VisiblySynchronized: android.net.NetworkInfo#toString(): + Internal locks must not be exposed (synchronizing on this or class is still + externally observable): method android.net.NetworkInfo.toString() diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt new file mode 100644 index 0000000000..3af855ec1e --- /dev/null +++ b/framework/api/module-lib-current.txt @@ -0,0 +1,66 @@ +// Signature format: 2.0 +package android.net { + + public final class ConnectivityFrameworkInitializer { + method public static void registerServiceWrappers(); + } + + public class ConnectivityManager { + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + } + + public final class NetworkAgentConfig implements android.os.Parcelable { + method @Nullable public String getSubscriberId(); + } + + public static final class NetworkAgentConfig.Builder { + method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); + } + + public final class NetworkCapabilities implements android.os.Parcelable { + field public static final int TRANSPORT_TEST = 7; // 0x7 + } + + public final class Proxy { + method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo); + } + + public final class TcpRepairWindow { + ctor public TcpRepairWindow(int, int, int, int, int, int); + field public final int maxWindow; + field public final int rcvWnd; + field public final int rcvWndScale; + field public final int rcvWup; + field public final int sndWl1; + field public final int sndWnd; + } + + public final class TestNetworkInterface implements android.os.Parcelable { + ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String); + method public int describeContents(); + method @NonNull public android.os.ParcelFileDescriptor getFileDescriptor(); + method @NonNull public String getInterfaceName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class TestNetworkManager { + method @NonNull public android.net.TestNetworkInterface createTapInterface(); + method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection); + method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder); + method public void teardownTestNetwork(@NonNull android.net.Network); + field public static final String TEST_TAP_PREFIX = "testtap"; + } + + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { + ctor public VpnTransportInfo(int); + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public final int type; + } + +} + diff --git a/framework/api/module-lib-removed.txt b/framework/api/module-lib-removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/framework/api/module-lib-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/framework/api/removed.txt b/framework/api/removed.txt new file mode 100644 index 0000000000..303a1e6173 --- /dev/null +++ b/framework/api/removed.txt @@ -0,0 +1,11 @@ +// Signature format: 2.0 +package android.net { + + public class ConnectivityManager { + method @Deprecated public boolean requestRouteToHost(int, int); + method @Deprecated public int startUsingNetworkFeature(int, String); + method @Deprecated public int stopUsingNetworkFeature(int, String); + } + +} + diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt new file mode 100644 index 0000000000..41ebc5774f --- /dev/null +++ b/framework/api/system-current.txt @@ -0,0 +1,407 @@ +// Signature format: 2.0 +package android.net { + + public class CaptivePortal implements android.os.Parcelable { + method public void logEvent(int, @NonNull String); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork(); + method public void useNetwork(); + field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64 + field public static final int APP_RETURN_DISMISSED = 0; // 0x0 + field public static final int APP_RETURN_UNWANTED = 1; // 0x1 + field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2 + } + + public final class CaptivePortalData implements android.os.Parcelable { + method public int describeContents(); + method public long getByteLimit(); + method public long getExpiryTimeMillis(); + method public long getRefreshTimeMillis(); + method @Nullable public android.net.Uri getUserPortalUrl(); + method public int getUserPortalUrlSource(); + method @Nullable public String getVenueFriendlyName(); + method @Nullable public android.net.Uri getVenueInfoUrl(); + method public int getVenueInfoUrlSource(); + method public boolean isCaptive(); + method public boolean isSessionExtendable(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0; // 0x0 + field public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1; // 0x1 + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static class CaptivePortalData.Builder { + ctor public CaptivePortalData.Builder(); + ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData); + method @NonNull public android.net.CaptivePortalData build(); + method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long); + method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean); + method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long); + method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long); + method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); + method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); + method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); + method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); + method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); + method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); + } + + public class ConnectivityManager { + method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback); + method @Deprecated @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl(); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider); + method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull android.net.QosCallback, @NonNull java.util.concurrent.Executor); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); + method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); + method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider); + method public void unregisterQosCallback(@NonNull android.net.QosCallback); + method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback); + field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; + field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + field public static final int TETHERING_BLUETOOTH = 2; // 0x2 + field public static final int TETHERING_USB = 1; // 0x1 + field public static final int TETHERING_WIFI = 0; // 0x0 + field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd + field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0 + field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb + field public static final int TYPE_NONE = -1; // 0xffffffff + field @Deprecated public static final int TYPE_PROXY = 16; // 0x10 + field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd + } + + public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener { + method public void onComplete(); + } + + @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { + ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); + method @Deprecated public void onTetheringFailed(); + method @Deprecated public void onTetheringStarted(); + } + + @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener { + method @Deprecated public void onTetheringEntitlementResult(int); + } + + @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback { + ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback(); + method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network); + } + + public final class InvalidPacketException extends java.lang.Exception { + ctor public InvalidPacketException(int); + method public int getError(); + field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb + field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 + field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea + } + + public final class IpConfiguration implements android.os.Parcelable { + ctor public IpConfiguration(); + ctor public IpConfiguration(@NonNull android.net.IpConfiguration); + method public int describeContents(); + method @Nullable public android.net.ProxyInfo getHttpProxy(); + method @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment(); + method @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings(); + method @Nullable public android.net.StaticIpConfiguration getStaticIpConfiguration(); + method public void setHttpProxy(@Nullable android.net.ProxyInfo); + method public void setIpAssignment(@NonNull android.net.IpConfiguration.IpAssignment); + method public void setProxySettings(@NonNull android.net.IpConfiguration.ProxySettings); + method public void setStaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public enum IpConfiguration.IpAssignment { + enum_constant public static final android.net.IpConfiguration.IpAssignment DHCP; + enum_constant public static final android.net.IpConfiguration.IpAssignment STATIC; + enum_constant public static final android.net.IpConfiguration.IpAssignment UNASSIGNED; + } + + public enum IpConfiguration.ProxySettings { + enum_constant public static final android.net.IpConfiguration.ProxySettings NONE; + enum_constant public static final android.net.IpConfiguration.ProxySettings PAC; + enum_constant public static final android.net.IpConfiguration.ProxySettings STATIC; + enum_constant public static final android.net.IpConfiguration.ProxySettings UNASSIGNED; + } + + public final class IpPrefix implements android.os.Parcelable { + ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); + ctor public IpPrefix(@NonNull String); + } + + public class KeepalivePacketData { + ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException; + method @NonNull public java.net.InetAddress getDstAddress(); + method public int getDstPort(); + method @NonNull public byte[] getPacket(); + method @NonNull public java.net.InetAddress getSrcAddress(); + method public int getSrcPort(); + } + + public class LinkAddress implements android.os.Parcelable { + ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int); + ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long); + ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int); + ctor public LinkAddress(@NonNull String); + ctor public LinkAddress(@NonNull String, int, int); + method public long getDeprecationTime(); + method public long getExpirationTime(); + method public boolean isGlobalPreferred(); + method public boolean isIpv4(); + method public boolean isIpv6(); + method public boolean isSameAddressAs(@Nullable android.net.LinkAddress); + field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL + field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL + } + + public final class LinkProperties implements android.os.Parcelable { + ctor public LinkProperties(@Nullable android.net.LinkProperties); + ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean); + method public boolean addDnsServer(@NonNull java.net.InetAddress); + method public boolean addLinkAddress(@NonNull android.net.LinkAddress); + method public boolean addPcscfServer(@NonNull java.net.InetAddress); + method @NonNull public java.util.List getAddresses(); + method @NonNull public java.util.List getAllInterfaceNames(); + method @NonNull public java.util.List getAllLinkAddresses(); + method @NonNull public java.util.List getAllRoutes(); + method @Nullable public android.net.Uri getCaptivePortalApiUrl(); + method @Nullable public android.net.CaptivePortalData getCaptivePortalData(); + method @NonNull public java.util.List getPcscfServers(); + method @Nullable public String getTcpBufferSizes(); + method @NonNull public java.util.List getValidatedPrivateDnsServers(); + method public boolean hasGlobalIpv6Address(); + method public boolean hasIpv4Address(); + method public boolean hasIpv4DefaultRoute(); + method public boolean hasIpv4DnsServer(); + method public boolean hasIpv6DefaultRoute(); + method public boolean hasIpv6DnsServer(); + method public boolean isIpv4Provisioned(); + method public boolean isIpv6Provisioned(); + method public boolean isProvisioned(); + method public boolean isReachable(@NonNull java.net.InetAddress); + method public boolean removeDnsServer(@NonNull java.net.InetAddress); + method public boolean removeLinkAddress(@NonNull android.net.LinkAddress); + method public boolean removeRoute(@NonNull android.net.RouteInfo); + method public void setCaptivePortalApiUrl(@Nullable android.net.Uri); + method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData); + method public void setPcscfServers(@NonNull java.util.Collection); + method public void setPrivateDnsServerName(@Nullable String); + method public void setTcpBufferSizes(@Nullable String); + method public void setUsePrivateDns(boolean); + method public void setValidatedPrivateDnsServers(@NonNull java.util.Collection); + } + + public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable { + ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException; + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public class Network implements android.os.Parcelable { + ctor public Network(@NonNull android.net.Network); + method public int getNetId(); + method @NonNull public android.net.Network getPrivateDnsBypassingCopy(); + } + + public abstract class NetworkAgent { + ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider); + method @Nullable public android.net.Network getNetwork(); + method public void markConnected(); + method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData); + method public void onAutomaticReconnectDisabled(); + method public void onNetworkUnwanted(); + method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter); + method public void onQosCallbackUnregistered(int); + method public void onRemoveKeepalivePacketFilter(int); + method public void onSaveAcceptUnvalidated(boolean); + method public void onSignalStrengthThresholdsUpdated(@NonNull int[]); + method public void onStartSocketKeepalive(int, @NonNull java.time.Duration, @NonNull android.net.KeepalivePacketData); + method public void onStopSocketKeepalive(int); + method public void onValidationStatus(int, @Nullable android.net.Uri); + method @NonNull public android.net.Network register(); + method public final void sendLinkProperties(@NonNull android.net.LinkProperties); + method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); + method public final void sendNetworkScore(@IntRange(from=0, to=99) int); + method public final void sendQosCallbackError(int, int); + method public final void sendQosSessionAvailable(int, int, @NonNull android.telephony.data.EpsBearerQosSessionAttributes); + method public final void sendQosSessionLost(int, int); + method public final void sendSocketKeepaliveEvent(int, int); + method public final void setUnderlyingNetworks(@Nullable java.util.List); + method public void unregister(); + field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 + field public static final int VALIDATION_STATUS_VALID = 1; // 0x1 + } + + public final class NetworkAgentConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getLegacyType(); + method @NonNull public String getLegacyTypeName(); + method public boolean isExplicitlySelected(); + method public boolean isPartialConnectivityAcceptable(); + method public boolean isUnvalidatedConnectivityAcceptable(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class NetworkAgentConfig.Builder { + ctor public NetworkAgentConfig.Builder(); + method @NonNull public android.net.NetworkAgentConfig build(); + method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String); + method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean); + method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean); + } + + public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); + method @NonNull public int[] getAdministratorUids(); + method @Nullable public String getSsid(); + method @NonNull public int[] getTransportTypes(); + method public boolean isPrivateDnsBroken(); + method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); + field public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; // 0x1c + field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 + field public static final int NET_CAPABILITY_OEM_PRIVATE = 26; // 0x1a + field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 + field public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27; // 0x1b + } + + public static final class NetworkCapabilities.Builder { + ctor public NetworkCapabilities.Builder(); + ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); + method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); + method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder clearAll(); + method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + } + + public class NetworkProvider { + ctor public NetworkProvider(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String); + method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void declareNetworkRequestUnfulfillable(@NonNull android.net.NetworkRequest); + method public int getProviderId(); + method public void onNetworkRequestWithdrawn(@NonNull android.net.NetworkRequest); + method public void onNetworkRequested(@NonNull android.net.NetworkRequest, @IntRange(from=0, to=99) int, int); + field public static final int ID_NONE = -1; // 0xffffffff + } + + public class NetworkRequest implements android.os.Parcelable { + method @Nullable public String getRequestorPackageName(); + method public int getRequestorUid(); + } + + public static class NetworkRequest.Builder { + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); + } + + public final class RouteInfo implements android.os.Parcelable { + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); + ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int); + method public int getMtu(); + method public int getType(); + field public static final int RTN_THROW = 9; // 0x9 + field public static final int RTN_UNICAST = 1; // 0x1 + field public static final int RTN_UNREACHABLE = 7; // 0x7 + } + + public abstract class SocketKeepalive implements java.lang.AutoCloseable { + field public static final int SUCCESS = 0; // 0x0 + } + + public final class StaticIpConfiguration implements android.os.Parcelable { + ctor public StaticIpConfiguration(); + ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); + method public void addDnsServer(@NonNull java.net.InetAddress); + method public void clear(); + method public int describeContents(); + method @NonNull public java.util.List getDnsServers(); + method @Nullable public String getDomains(); + method @Nullable public java.net.InetAddress getGateway(); + method @Nullable public android.net.LinkAddress getIpAddress(); + method @NonNull public java.util.List getRoutes(@Nullable String); + method public void writeToParcel(android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + + public static final class StaticIpConfiguration.Builder { + ctor public StaticIpConfiguration.Builder(); + method @NonNull public android.net.StaticIpConfiguration build(); + method @NonNull public android.net.StaticIpConfiguration.Builder setDnsServers(@NonNull Iterable); + method @NonNull public android.net.StaticIpConfiguration.Builder setDomains(@Nullable String); + method @NonNull public android.net.StaticIpConfiguration.Builder setGateway(@Nullable java.net.InetAddress); + method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress); + } + + public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable { + ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException; + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public final int ipTos; + field public final int ipTtl; + field public final int tcpAck; + field public final int tcpSeq; + field public final int tcpWindow; + field public final int tcpWindowScale; + } + + public interface TransportInfo { + method public default boolean hasLocationSensitiveFields(); + method @NonNull public default android.net.TransportInfo makeCopy(boolean); + } + +} + +package android.net.apf { + + public final class ApfCapabilities implements android.os.Parcelable { + ctor public ApfCapabilities(int, int, int); + method public int describeContents(); + method public static boolean getApfDrop8023Frames(); + method @NonNull public static int[] getApfEtherTypeBlackList(); + method public boolean hasDataAccess(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + field public final int apfPacketFormat; + field public final int apfVersionSupported; + field public final int maximumApfProgramSize; + } + +} + +package android.net.util { + + public final class SocketUtils { + method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException; + method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; + method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); + method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); + method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); + } + +} + diff --git a/framework/api/system-lint-baseline.txt b/framework/api/system-lint-baseline.txt new file mode 100644 index 0000000000..9a97707763 --- /dev/null +++ b/framework/api/system-lint-baseline.txt @@ -0,0 +1 @@ +// Baseline format: 1.0 diff --git a/framework/api/system-removed.txt b/framework/api/system-removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/framework/api/system-removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 From 1e290800373818b96361d0fe6beb99f2966dcf83 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Feb 2021 00:03:53 +0900 Subject: [PATCH 062/343] Move SocketUtils out of the connectivity module SocketUtils contains system APIs for modules to interact for sockets, wrapping internal APIs. It should be part of the platform to keep access to the internal APIs. This involves splitting NetworkUtils.protectVpn to NetworkUtilsInternal, since SocketUtils and VpnService are the only users of that method. The @UnsupportedAppUsage NetworkUtils.protectVpn has low usage count, and is already available through VpnService.protect. Bug: 181512874 Test: boots, VPN working Change-Id: I7028d334975f7536c06afac7a22200c33db707ac --- framework/api/system-current.txt | 13 -- framework/src/android/net/NetworkUtils.java | 16 --- .../src/android/net/util/SocketUtils.java | 121 ------------------ 3 files changed, 150 deletions(-) delete mode 100644 framework/src/android/net/util/SocketUtils.java diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 41ebc5774f..b541e5238f 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -392,16 +392,3 @@ package android.net.apf { } -package android.net.util { - - public final class SocketUtils { - method public static void bindSocketToInterface(@NonNull java.io.FileDescriptor, @NonNull String) throws android.system.ErrnoException; - method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException; - method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int); - method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]); - method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]); - } - -} - diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java index b5e8a614b8..9e42bbecbe 100644 --- a/framework/src/android/net/NetworkUtils.java +++ b/framework/src/android/net/NetworkUtils.java @@ -86,22 +86,6 @@ public class NetworkUtils { */ public static native int bindSocketToNetwork(FileDescriptor fd, int netId); - /** - * Protect {@code fd} from VPN connections. After protecting, data sent through - * this socket will go directly to the underlying network, so its traffic will not be - * forwarded through the VPN. - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553, - publicAlternatives = "Use {@link android.net.VpnService#protect} instead.") - public static native boolean protectFromVpn(FileDescriptor fd); - - /** - * Protect {@code socketfd} from VPN connections. After protecting, data sent through - * this socket will go directly to the underlying network, so its traffic will not be - * forwarded through the VPN. - */ - public native static boolean protectFromVpn(int socketfd); - /** * Determine if {@code uid} can access network designated by {@code netId}. * @return {@code true} if {@code uid} can access network, {@code false} otherwise. diff --git a/framework/src/android/net/util/SocketUtils.java b/framework/src/android/net/util/SocketUtils.java deleted file mode 100644 index e64060f1b2..0000000000 --- a/framework/src/android/net/util/SocketUtils.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.util; - -import static android.system.OsConstants.SOL_SOCKET; -import static android.system.OsConstants.SO_BINDTODEVICE; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.net.NetworkUtils; -import android.system.ErrnoException; -import android.system.NetlinkSocketAddress; -import android.system.Os; -import android.system.PacketSocketAddress; - -import libcore.io.IoBridge; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.net.SocketAddress; - -/** - * Collection of utilities to interact with raw sockets. - * @hide - */ -@SystemApi -public final class SocketUtils { - /** - * Create a raw datagram socket that is bound to an interface. - * - *

Data sent through the socket will go directly to the underlying network, ignoring VPNs. - */ - public static void bindSocketToInterface(@NonNull FileDescriptor socket, @NonNull String iface) - throws ErrnoException { - // SO_BINDTODEVICE actually takes a string. This works because the first member - // of struct ifreq is a NULL-terminated interface name. - // TODO: add a setsockoptString() - Os.setsockoptIfreq(socket, SOL_SOCKET, SO_BINDTODEVICE, iface); - NetworkUtils.protectFromVpn(socket); - } - - /** - * Make a socket address to communicate with netlink. - */ - @NonNull - public static SocketAddress makeNetlinkSocketAddress(int portId, int groupsMask) { - return new NetlinkSocketAddress(portId, groupsMask); - } - - /** - * Make socket address that packet sockets can bind to. - * - * @param protocol the layer 2 protocol of the packets to receive. One of the {@code ETH_P_*} - * constants in {@link android.system.OsConstants}. - * @param ifIndex the interface index on which packets will be received. - */ - @NonNull - public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex) { - return new PacketSocketAddress( - protocol /* sll_protocol */, - ifIndex /* sll_ifindex */, - null /* sll_addr */); - } - - /** - * Make a socket address that packet socket can send packets to. - * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead. - * - * @param ifIndex the interface index on which packets will be sent. - * @param hwAddr the hardware address to which packets will be sent. - */ - @Deprecated - @NonNull - public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) { - return new PacketSocketAddress( - 0 /* sll_protocol */, - ifIndex /* sll_ifindex */, - hwAddr /* sll_addr */); - } - - /** - * Make a socket address that a packet socket can send packets to. - * - * @param protocol the layer 2 protocol of the packets to send. One of the {@code ETH_P_*} - * constants in {@link android.system.OsConstants}. - * @param ifIndex the interface index on which packets will be sent. - * @param hwAddr the hardware address to which packets will be sent. - */ - @NonNull - public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex, - @NonNull byte[] hwAddr) { - return new PacketSocketAddress( - protocol /* sll_protocol */, - ifIndex /* sll_ifindex */, - hwAddr /* sll_addr */); - } - - /** - * @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor) - */ - public static void closeSocket(@Nullable FileDescriptor fd) throws IOException { - IoBridge.closeAndSignalBlockedThreads(fd); - } - - private SocketUtils() {} -} From 070ff8bb9cd9931e69a3793081339a7121da7e33 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 1 Mar 2021 17:53:45 +0900 Subject: [PATCH 063/343] Move QoS API classes to Connectivity The classes were added in S and are used to back ConnectivityManager APIs. Add them to the connectivity boundary as they belong together with ConnectivityManager. Bug: 181512874 Test: m Change-Id: I03b5978949b200a72813d1ebc4812d851fe3df37 --- .../android/net/QosFilterParcelable.aidl | 21 +++ .../aidl-export/android/net/QosSession.aidl | 21 +++ .../android/net/QosSocketInfo.aidl | 21 +++ framework/api/system-current.txt | 50 ++++++ framework/src/android/net/IQosCallback.aidl | 34 ++++ .../android/net/NetworkReleasedException.java | 32 ++++ framework/src/android/net/QosCallback.java | 91 ++++++++++ .../android/net/QosCallbackConnection.java | 128 ++++++++++++++ .../src/android/net/QosCallbackException.java | 110 ++++++++++++ framework/src/android/net/QosFilter.java | 75 ++++++++ .../src/android/net/QosFilterParcelable.java | 113 ++++++++++++ framework/src/android/net/QosSession.java | 136 ++++++++++++++ .../src/android/net/QosSessionAttributes.java | 30 ++++ .../src/android/net/QosSocketFilter.java | 166 ++++++++++++++++++ framework/src/android/net/QosSocketInfo.java | 154 ++++++++++++++++ .../SocketLocalAddressChangedException.java | 32 ++++ .../android/net/SocketNotBoundException.java | 32 ++++ 17 files changed, 1246 insertions(+) create mode 100644 framework/aidl-export/android/net/QosFilterParcelable.aidl create mode 100644 framework/aidl-export/android/net/QosSession.aidl create mode 100644 framework/aidl-export/android/net/QosSocketInfo.aidl create mode 100644 framework/src/android/net/IQosCallback.aidl create mode 100644 framework/src/android/net/NetworkReleasedException.java create mode 100644 framework/src/android/net/QosCallback.java create mode 100644 framework/src/android/net/QosCallbackConnection.java create mode 100644 framework/src/android/net/QosCallbackException.java create mode 100644 framework/src/android/net/QosFilter.java create mode 100644 framework/src/android/net/QosFilterParcelable.java create mode 100644 framework/src/android/net/QosSession.java create mode 100644 framework/src/android/net/QosSessionAttributes.java create mode 100644 framework/src/android/net/QosSocketFilter.java create mode 100644 framework/src/android/net/QosSocketInfo.java create mode 100644 framework/src/android/net/SocketLocalAddressChangedException.java create mode 100644 framework/src/android/net/SocketNotBoundException.java diff --git a/framework/aidl-export/android/net/QosFilterParcelable.aidl b/framework/aidl-export/android/net/QosFilterParcelable.aidl new file mode 100644 index 0000000000..312d6352ee --- /dev/null +++ b/framework/aidl-export/android/net/QosFilterParcelable.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright (C) 2020 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +parcelable QosFilterParcelable; + diff --git a/framework/aidl-export/android/net/QosSession.aidl b/framework/aidl-export/android/net/QosSession.aidl new file mode 100644 index 0000000000..c2cf36624b --- /dev/null +++ b/framework/aidl-export/android/net/QosSession.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright (C) 2020 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +parcelable QosSession; + diff --git a/framework/aidl-export/android/net/QosSocketInfo.aidl b/framework/aidl-export/android/net/QosSocketInfo.aidl new file mode 100644 index 0000000000..476c0900e2 --- /dev/null +++ b/framework/aidl-export/android/net/QosSocketInfo.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright (C) 2020 The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.net; + +parcelable QosSocketInfo; + diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 41ebc5774f..40c2cd10ba 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -308,6 +308,9 @@ package android.net { field public static final int ID_NONE = -1; // 0xffffffff } + public class NetworkReleasedException extends java.lang.Exception { + } + public class NetworkRequest implements android.os.Parcelable { method @Nullable public String getRequestorPackageName(); method public int getRequestorUid(); @@ -317,6 +320,47 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); } + public abstract class QosCallback { + ctor public QosCallback(); + method public void onError(@NonNull android.net.QosCallbackException); + method public void onQosSessionAvailable(@NonNull android.net.QosSession, @NonNull android.net.QosSessionAttributes); + method public void onQosSessionLost(@NonNull android.net.QosSession); + } + + public static class QosCallback.QosCallbackRegistrationException extends java.lang.RuntimeException { + } + + public final class QosCallbackException extends java.lang.Exception { + } + + public abstract class QosFilter { + method @NonNull public abstract android.net.Network getNetwork(); + method public abstract boolean matchesLocalAddress(@NonNull java.net.InetAddress, int, int); + } + + public final class QosSession implements android.os.Parcelable { + ctor public QosSession(int, int); + method public int describeContents(); + method public int getSessionId(); + method public int getSessionType(); + method public long getUniqueId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int TYPE_EPS_BEARER = 1; // 0x1 + } + + public interface QosSessionAttributes { + } + + public final class QosSocketInfo implements android.os.Parcelable { + ctor public QosSocketInfo(@NonNull android.net.Network, @NonNull java.net.Socket) throws java.io.IOException; + method public int describeContents(); + method @NonNull public java.net.InetSocketAddress getLocalSocketAddress(); + method @NonNull public android.net.Network getNetwork(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + public final class RouteInfo implements android.os.Parcelable { ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int); ctor public RouteInfo(@Nullable android.net.IpPrefix, @Nullable java.net.InetAddress, @Nullable String, int, int); @@ -331,6 +375,12 @@ package android.net { field public static final int SUCCESS = 0; // 0x0 } + public class SocketLocalAddressChangedException extends java.lang.Exception { + } + + public class SocketNotBoundException extends java.lang.Exception { + } + public final class StaticIpConfiguration implements android.os.Parcelable { ctor public StaticIpConfiguration(); ctor public StaticIpConfiguration(@Nullable android.net.StaticIpConfiguration); diff --git a/framework/src/android/net/IQosCallback.aidl b/framework/src/android/net/IQosCallback.aidl new file mode 100644 index 0000000000..91c75759f8 --- /dev/null +++ b/framework/src/android/net/IQosCallback.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.Bundle; +import android.net.QosSession; +import android.telephony.data.EpsBearerQosSessionAttributes; + +/** + * AIDL interface for QosCallback + * + * @hide + */ +oneway interface IQosCallback +{ + void onQosEpsBearerSessionAvailable(in QosSession session, + in EpsBearerQosSessionAttributes attributes); + void onQosSessionLost(in QosSession session); + void onError(in int type); +} diff --git a/framework/src/android/net/NetworkReleasedException.java b/framework/src/android/net/NetworkReleasedException.java new file mode 100644 index 0000000000..0629b7563a --- /dev/null +++ b/framework/src/android/net/NetworkReleasedException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; + +/** + * Indicates that the {@link Network} was released and is no longer available. + * + * @hide + */ +@SystemApi +public class NetworkReleasedException extends Exception { + /** @hide */ + public NetworkReleasedException() { + super("The network was released and is no longer available"); + } +} diff --git a/framework/src/android/net/QosCallback.java b/framework/src/android/net/QosCallback.java new file mode 100644 index 0000000000..22f06bc0e6 --- /dev/null +++ b/framework/src/android/net/QosCallback.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.SystemApi; + +import java.util.concurrent.Executor; + +/** + * Receives Qos information given a {@link Network}. The callback is registered with + * {@link ConnectivityManager#registerQosCallback}. + * + *

+ *
+ * The callback will no longer receive calls if any of the following takes place: + *

    + *
  1. {@link ConnectivityManager#unregisterQosCallback(QosCallback)} is called with the same + * callback instance.
  2. + *
  3. {@link QosCallback#onError(QosCallbackException)} is called.
  4. + *
  5. A network specific issue occurs. eg. Congestion on a carrier network.
  6. + *
  7. The network registered with the callback has no associated QoS providers
  8. + * + * {@hide} + */ +@SystemApi +public abstract class QosCallback { + /** + * Invoked after an error occurs on a registered callback. Once called, the callback is + * automatically unregistered and the callback will no longer receive calls. + * + *

    The underlying exception can either be a runtime exception or a custom exception made for + * {@link QosCallback}. see: {@link QosCallbackException}. + * + * @param exception wraps the underlying cause + */ + public void onError(@NonNull final QosCallbackException exception) { + } + + /** + * Called when a Qos Session first becomes available to the callback or if its attributes have + * changed. + *

    + * Note: The callback may be called multiple times with the same attributes. + * + * @param session the available session + * @param sessionAttributes the attributes of the session + */ + public void onQosSessionAvailable(@NonNull final QosSession session, + @NonNull final QosSessionAttributes sessionAttributes) { + } + + /** + * Called after a Qos Session is lost. + *

    + * At least one call to + * {@link QosCallback#onQosSessionAvailable(QosSession, QosSessionAttributes)} + * with the same {@link QosSession} will precede a call to lost. + * + * @param session the lost session + */ + public void onQosSessionLost(@NonNull final QosSession session) { + } + + /** + * Thrown when there is a problem registering {@link QosCallback} with + * {@link ConnectivityManager#registerQosCallback(QosSocketInfo, QosCallback, Executor)}. + */ + public static class QosCallbackRegistrationException extends RuntimeException { + /** + * @hide + */ + public QosCallbackRegistrationException() { + super(); + } + } +} diff --git a/framework/src/android/net/QosCallbackConnection.java b/framework/src/android/net/QosCallbackConnection.java new file mode 100644 index 0000000000..bdb4ad68cd --- /dev/null +++ b/framework/src/android/net/QosCallbackConnection.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.telephony.data.EpsBearerQosSessionAttributes; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.Objects; +import java.util.concurrent.Executor; + +/** + * Sends messages from {@link com.android.server.ConnectivityService} to the registered + * {@link QosCallback}. + *

    + * This is a satellite class of {@link ConnectivityManager} and not meant + * to be used in other contexts. + * + * @hide + */ +class QosCallbackConnection extends android.net.IQosCallback.Stub { + + @NonNull private final ConnectivityManager mConnectivityManager; + @Nullable private volatile QosCallback mCallback; + @NonNull private final Executor mExecutor; + + @VisibleForTesting + @Nullable + public QosCallback getCallback() { + return mCallback; + } + + /** + * The constructor for the connection + * + * @param connectivityManager the mgr that created this connection + * @param callback the callback to send messages back to + * @param executor The executor on which the callback will be invoked. The provided + * {@link Executor} must run callback sequentially, otherwise the order of + * callbacks cannot be guaranteed. + */ + QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager, + @NonNull final QosCallback callback, + @NonNull final Executor executor) { + mConnectivityManager = Objects.requireNonNull(connectivityManager, + "connectivityManager must be non-null"); + mCallback = Objects.requireNonNull(callback, "callback must be non-null"); + mExecutor = Objects.requireNonNull(executor, "executor must be non-null"); + } + + /** + * Called when either the {@link EpsBearerQosSessionAttributes} has changed or on the first time + * the attributes have become available. + * + * @param session the session that is now available + * @param attributes the corresponding attributes of session + */ + @Override + public void onQosEpsBearerSessionAvailable(@NonNull final QosSession session, + @NonNull final EpsBearerQosSessionAttributes attributes) { + + mExecutor.execute(() -> { + final QosCallback callback = mCallback; + if (callback != null) { + callback.onQosSessionAvailable(session, attributes); + } + }); + } + + /** + * Called when the session is lost. + * + * @param session the session that was lost + */ + @Override + public void onQosSessionLost(@NonNull final QosSession session) { + mExecutor.execute(() -> { + final QosCallback callback = mCallback; + if (callback != null) { + callback.onQosSessionLost(session); + } + }); + } + + /** + * Called when there is an error on the registered callback. + * + * @param errorType the type of error + */ + @Override + public void onError(@QosCallbackException.ExceptionType final int errorType) { + mExecutor.execute(() -> { + final QosCallback callback = mCallback; + if (callback != null) { + // Messages no longer need to be received since there was an error. + stopReceivingMessages(); + mConnectivityManager.unregisterQosCallback(callback); + callback.onError(QosCallbackException.createException(errorType)); + } + }); + } + + /** + * The callback will stop receiving messages. + *

    + * There are no synchronization guarantees on exactly when the callback will stop receiving + * messages. + */ + void stopReceivingMessages() { + mCallback = null; + } +} diff --git a/framework/src/android/net/QosCallbackException.java b/framework/src/android/net/QosCallbackException.java new file mode 100644 index 0000000000..7fd9a527e2 --- /dev/null +++ b/framework/src/android/net/QosCallbackException.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.util.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This is the exception type passed back through the onError method on {@link QosCallback}. + * {@link QosCallbackException#getCause()} contains the actual error that caused this exception. + * + * The possible exception types as causes are: + * 1. {@link NetworkReleasedException} + * 2. {@link SocketNotBoundException} + * 3. {@link UnsupportedOperationException} + * 4. {@link SocketLocalAddressChangedException} + * + * @hide + */ +@SystemApi +public final class QosCallbackException extends Exception { + + /** @hide */ + @IntDef(prefix = {"EX_TYPE_"}, value = { + EX_TYPE_FILTER_NONE, + EX_TYPE_FILTER_NETWORK_RELEASED, + EX_TYPE_FILTER_SOCKET_NOT_BOUND, + EX_TYPE_FILTER_NOT_SUPPORTED, + EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ExceptionType {} + + private static final String TAG = "QosCallbackException"; + + // Types of exceptions supported // + /** {@hide} */ + public static final int EX_TYPE_FILTER_NONE = 0; + + /** {@hide} */ + public static final int EX_TYPE_FILTER_NETWORK_RELEASED = 1; + + /** {@hide} */ + public static final int EX_TYPE_FILTER_SOCKET_NOT_BOUND = 2; + + /** {@hide} */ + public static final int EX_TYPE_FILTER_NOT_SUPPORTED = 3; + + /** {@hide} */ + public static final int EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED = 4; + + /** + * Creates exception based off of a type and message. Not all types of exceptions accept a + * custom message. + * + * {@hide} + */ + @NonNull + static QosCallbackException createException(@ExceptionType final int type) { + switch (type) { + case EX_TYPE_FILTER_NETWORK_RELEASED: + return new QosCallbackException(new NetworkReleasedException()); + case EX_TYPE_FILTER_SOCKET_NOT_BOUND: + return new QosCallbackException(new SocketNotBoundException()); + case EX_TYPE_FILTER_NOT_SUPPORTED: + return new QosCallbackException(new UnsupportedOperationException( + "This device does not support the specified filter")); + case EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED: + return new QosCallbackException( + new SocketLocalAddressChangedException()); + default: + Log.wtf(TAG, "create: No case setup for exception type: '" + type + "'"); + return new QosCallbackException( + new RuntimeException("Unknown exception code: " + type)); + } + } + + /** + * @hide + */ + public QosCallbackException(@NonNull final String message) { + super(message); + } + + /** + * @hide + */ + public QosCallbackException(@NonNull final Throwable cause) { + super(cause); + } +} diff --git a/framework/src/android/net/QosFilter.java b/framework/src/android/net/QosFilter.java new file mode 100644 index 0000000000..ab55002e02 --- /dev/null +++ b/framework/src/android/net/QosFilter.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.SystemApi; + +import java.net.InetAddress; + +/** + * Provides the related filtering logic to the {@link NetworkAgent} to match {@link QosSession}s + * to their related {@link QosCallback}. + * + * Used by the {@link com.android.server.ConnectivityService} to validate a {@link QosCallback} + * is still able to receive a {@link QosSession}. + * + * @hide + */ +@SystemApi +public abstract class QosFilter { + + /** + * The constructor is kept hidden from outside this package to ensure that all derived types + * are known and properly handled when being passed to and from {@link NetworkAgent}. + * + * @hide + */ + QosFilter() { + } + + /** + * The network used with this filter. + * + * @return the registered {@link Network} + */ + @NonNull + public abstract Network getNetwork(); + + /** + * Validates that conditions have not changed such that no further {@link QosSession}s should + * be passed back to the {@link QosCallback} associated to this filter. + * + * @return the error code when present, otherwise the filter is valid + * + * @hide + */ + @QosCallbackException.ExceptionType + public abstract int validate(); + + /** + * Determines whether or not the parameters is a match for the filter. + * + * @param address the local address + * @param startPort the start of the port range + * @param endPort the end of the port range + * @return whether the parameters match the local address of the filter + */ + public abstract boolean matchesLocalAddress(@NonNull InetAddress address, + int startPort, int endPort); +} + diff --git a/framework/src/android/net/QosFilterParcelable.java b/framework/src/android/net/QosFilterParcelable.java new file mode 100644 index 0000000000..da3b2cf8ff --- /dev/null +++ b/framework/src/android/net/QosFilterParcelable.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.util.Objects; + +/** + * Aware of how to parcel different types of {@link QosFilter}s. Any new type of qos filter must + * have a specialized case written here. + *

    + * Specifically leveraged when transferring {@link QosFilter} from + * {@link com.android.server.ConnectivityService} to {@link NetworkAgent} when the filter is first + * registered. + *

    + * This is not meant to be used in other contexts. + * + * @hide + */ +public final class QosFilterParcelable implements Parcelable { + + private static final String LOG_TAG = QosFilterParcelable.class.getSimpleName(); + + // Indicates that the filter was not successfully written to the parcel. + private static final int NO_FILTER_PRESENT = 0; + + // The parcel is of type qos socket filter. + private static final int QOS_SOCKET_FILTER = 1; + + private final QosFilter mQosFilter; + + /** + * The underlying qos filter. + *

    + * Null only in the case parceling failed. + */ + @Nullable + public QosFilter getQosFilter() { + return mQosFilter; + } + + public QosFilterParcelable(@NonNull final QosFilter qosFilter) { + Objects.requireNonNull(qosFilter, "qosFilter must be non-null"); + + // NOTE: Normally a type check would belong here, but doing so breaks unit tests that rely + // on mocking qos filter. + mQosFilter = qosFilter; + } + + private QosFilterParcelable(final Parcel in) { + final int filterParcelType = in.readInt(); + + switch (filterParcelType) { + case QOS_SOCKET_FILTER: { + mQosFilter = new QosSocketFilter(QosSocketInfo.CREATOR.createFromParcel(in)); + break; + } + + case NO_FILTER_PRESENT: + default: { + mQosFilter = null; + } + } + } + + public static final Creator CREATOR = new Creator() { + @Override + public QosFilterParcelable createFromParcel(final Parcel in) { + return new QosFilterParcelable(in); + } + + @Override + public QosFilterParcelable[] newArray(final int size) { + return new QosFilterParcelable[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(final Parcel dest, final int flags) { + if (mQosFilter instanceof QosSocketFilter) { + dest.writeInt(QOS_SOCKET_FILTER); + final QosSocketFilter qosSocketFilter = (QosSocketFilter) mQosFilter; + qosSocketFilter.getQosSocketInfo().writeToParcel(dest, 0); + return; + } + dest.writeInt(NO_FILTER_PRESENT); + Log.e(LOG_TAG, "Parceling failed, unknown type of filter present: " + mQosFilter); + } +} diff --git a/framework/src/android/net/QosSession.java b/framework/src/android/net/QosSession.java new file mode 100644 index 0000000000..4f3bb77c58 --- /dev/null +++ b/framework/src/android/net/QosSession.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Provides identifying information of a QoS session. Sent to an application through + * {@link QosCallback}. + * + * @hide + */ +@SystemApi +public final class QosSession implements Parcelable { + + /** + * The {@link QosSession} is a LTE EPS Session. + */ + public static final int TYPE_EPS_BEARER = 1; + + private final int mSessionId; + + private final int mSessionType; + + /** + * Gets the unique id of the session that is used to differentiate sessions across different + * types. + *

    + * Note: Different qos sessions can be provided by different actors. + * + * @return the unique id + */ + public long getUniqueId() { + return (long) mSessionType << 32 | mSessionId; + } + + /** + * Gets the session id that is unique within that type. + *

    + * Note: The session id is set by the actor providing the qos. It can be either manufactured by + * the actor, but also may have a particular meaning within that type. For example, using the + * bearer id as the session id for {@link android.telephony.data.EpsBearerQosSessionAttributes} + * is a straight forward way to keep the sessions unique from one another within that type. + * + * @return the id of the session + */ + public int getSessionId() { + return mSessionId; + } + + /** + * Gets the type of session. + */ + @QosSessionType + public int getSessionType() { + return mSessionType; + } + + /** + * Creates a {@link QosSession}. + * + * @param sessionId uniquely identifies the session across all sessions of the same type + * @param sessionType the type of session + */ + public QosSession(final int sessionId, @QosSessionType final int sessionType) { + //Ensures the session id is unique across types of sessions + mSessionId = sessionId; + mSessionType = sessionType; + } + + + @Override + public String toString() { + return "QosSession{" + + "mSessionId=" + mSessionId + + ", mSessionType=" + mSessionType + + '}'; + } + + /** + * Annotations for types of qos sessions. + */ + @IntDef(value = { + TYPE_EPS_BEARER, + }) + @interface QosSessionType {} + + private QosSession(final Parcel in) { + mSessionId = in.readInt(); + mSessionType = in.readInt(); + } + + @NonNull + public static final Creator CREATOR = new Creator() { + @NonNull + @Override + public QosSession createFromParcel(@NonNull final Parcel in) { + return new QosSession(in); + } + + @NonNull + @Override + public QosSession[] newArray(final int size) { + return new QosSession[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull final Parcel dest, final int flags) { + dest.writeInt(mSessionId); + dest.writeInt(mSessionType); + } +} diff --git a/framework/src/android/net/QosSessionAttributes.java b/framework/src/android/net/QosSessionAttributes.java new file mode 100644 index 0000000000..7a885942d1 --- /dev/null +++ b/framework/src/android/net/QosSessionAttributes.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; + +/** + * Implemented by classes that encapsulate Qos related attributes that describe a Qos Session. + * + * Use the instanceof keyword to determine the underlying type. + * + * @hide + */ +@SystemApi +public interface QosSessionAttributes { +} diff --git a/framework/src/android/net/QosSocketFilter.java b/framework/src/android/net/QosSocketFilter.java new file mode 100644 index 0000000000..2080e68f5f --- /dev/null +++ b/framework/src/android/net/QosSocketFilter.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.net.QosCallbackException.EX_TYPE_FILTER_NONE; +import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.ParcelFileDescriptor; +import android.system.ErrnoException; +import android.system.Os; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +import java.io.FileDescriptor; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.util.Objects; + +/** + * Filters a {@link QosSession} according to the binding on the provided {@link Socket}. + * + * @hide + */ +public class QosSocketFilter extends QosFilter { + + private static final String TAG = QosSocketFilter.class.getSimpleName(); + + @NonNull + private final QosSocketInfo mQosSocketInfo; + + /** + * Creates a {@link QosSocketFilter} based off of {@link QosSocketInfo}. + * + * @param qosSocketInfo the information required to filter and validate + */ + public QosSocketFilter(@NonNull final QosSocketInfo qosSocketInfo) { + Objects.requireNonNull(qosSocketInfo, "qosSocketInfo must be non-null"); + mQosSocketInfo = qosSocketInfo; + } + + /** + * Gets the parcelable qos socket info that was used to create the filter. + */ + @NonNull + public QosSocketInfo getQosSocketInfo() { + return mQosSocketInfo; + } + + /** + * Performs two validations: + * 1. If the socket is not bound, then return + * {@link QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND}. This is detected + * by checking the local address on the filter which becomes null when the socket is no + * longer bound. + * 2. In the scenario that the socket is now bound to a different local address, which can + * happen in the case of UDP, then + * {@link QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED} is returned. + * @return validation error code + */ + @Override + public int validate() { + final InetSocketAddress sa = getAddressFromFileDescriptor(); + if (sa == null) { + return QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND; + } + + if (!sa.equals(mQosSocketInfo.getLocalSocketAddress())) { + return EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED; + } + + return EX_TYPE_FILTER_NONE; + } + + /** + * The local address of the socket's binding. + * + * Note: If the socket is no longer bound, null is returned. + * + * @return the local address + */ + @Nullable + private InetSocketAddress getAddressFromFileDescriptor() { + final ParcelFileDescriptor parcelFileDescriptor = mQosSocketInfo.getParcelFileDescriptor(); + if (parcelFileDescriptor == null) return null; + + final FileDescriptor fd = parcelFileDescriptor.getFileDescriptor(); + if (fd == null) return null; + + final SocketAddress address; + try { + address = Os.getsockname(fd); + } catch (final ErrnoException e) { + Log.e(TAG, "getAddressFromFileDescriptor: getLocalAddress exception", e); + return null; + } + if (address instanceof InetSocketAddress) { + return (InetSocketAddress) address; + } + return null; + } + + /** + * The network used with this filter. + * + * @return the registered {@link Network} + */ + @NonNull + @Override + public Network getNetwork() { + return mQosSocketInfo.getNetwork(); + } + + /** + * @inheritDoc + */ + @Override + public boolean matchesLocalAddress(@NonNull final InetAddress address, final int startPort, + final int endPort) { + if (mQosSocketInfo.getLocalSocketAddress() == null) { + return false; + } + + return matchesLocalAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort, + endPort); + } + + /** + * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} with the + * filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}. + *

    + * This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked + * due to being final. + * + * @param filterSocketAddress the socket address of the filter + * @param address the address to compare the filterSocketAddressWith + * @param startPort the start of the port range to check + * @param endPort the end of the port range to check + */ + @VisibleForTesting + public static boolean matchesLocalAddress(@NonNull final InetSocketAddress filterSocketAddress, + @NonNull final InetAddress address, + final int startPort, final int endPort) { + return startPort <= filterSocketAddress.getPort() + && endPort >= filterSocketAddress.getPort() + && filterSocketAddress.getAddress().equals(address); + } +} diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java new file mode 100644 index 0000000000..d37c4691dd --- /dev/null +++ b/framework/src/android/net/QosSocketInfo.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Objects; + +/** + * Used in conjunction with + * {@link ConnectivityManager#registerQosCallback} + * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}. + * + * @hide + */ +@SystemApi +public final class QosSocketInfo implements Parcelable { + + @NonNull + private final Network mNetwork; + + @NonNull + private final ParcelFileDescriptor mParcelFileDescriptor; + + @NonNull + private final InetSocketAddress mLocalSocketAddress; + + /** + * The {@link Network} the socket is on. + * + * @return the registered {@link Network} + */ + @NonNull + public Network getNetwork() { + return mNetwork; + } + + /** + * The parcel file descriptor wrapped around the socket's file descriptor. + * + * @return the parcel file descriptor of the socket + */ + @NonNull + ParcelFileDescriptor getParcelFileDescriptor() { + return mParcelFileDescriptor; + } + + /** + * The local address of the socket passed into {@link QosSocketInfo(Network, Socket)}. + * The value does not reflect any changes that occur to the socket after it is first set + * in the constructor. + * + * @return the local address of the socket + */ + @NonNull + public InetSocketAddress getLocalSocketAddress() { + return mLocalSocketAddress; + } + + /** + * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The + * {@link Socket} must remain bound in order to receive {@link QosSession}s. + * + * @param network the network + * @param socket the bound {@link Socket} + */ + public QosSocketInfo(@NonNull final Network network, @NonNull final Socket socket) + throws IOException { + Objects.requireNonNull(socket, "socket cannot be null"); + + mNetwork = Objects.requireNonNull(network, "network cannot be null"); + mParcelFileDescriptor = ParcelFileDescriptor.dup(socket.getFileDescriptor$()); + mLocalSocketAddress = + new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()); + } + + /* Parcelable methods */ + private QosSocketInfo(final Parcel in) { + mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in)); + mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in); + + final int addressLength = in.readInt(); + mLocalSocketAddress = readSocketAddress(in, addressLength); + } + + private InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) { + final byte[] address = new byte[addressLength]; + in.readByteArray(address); + final int port = in.readInt(); + + try { + return new InetSocketAddress(InetAddress.getByAddress(address), port); + } catch (final UnknownHostException e) { + /* The catch block was purposely left empty. UnknownHostException will never be thrown + since the address provided is numeric and non-null. */ + } + return new InetSocketAddress(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull final Parcel dest, final int flags) { + mNetwork.writeToParcel(dest, 0); + mParcelFileDescriptor.writeToParcel(dest, 0); + + final byte[] address = mLocalSocketAddress.getAddress().getAddress(); + dest.writeInt(address.length); + dest.writeByteArray(address); + dest.writeInt(mLocalSocketAddress.getPort()); + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @NonNull + @Override + public QosSocketInfo createFromParcel(final Parcel in) { + return new QosSocketInfo(in); + } + + @NonNull + @Override + public QosSocketInfo[] newArray(final int size) { + return new QosSocketInfo[size]; + } + }; +} diff --git a/framework/src/android/net/SocketLocalAddressChangedException.java b/framework/src/android/net/SocketLocalAddressChangedException.java new file mode 100644 index 0000000000..9daad83fd1 --- /dev/null +++ b/framework/src/android/net/SocketLocalAddressChangedException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; + +/** + * Thrown when the local address of the socket has changed. + * + * @hide + */ +@SystemApi +public class SocketLocalAddressChangedException extends Exception { + /** @hide */ + public SocketLocalAddressChangedException() { + super("The local address of the socket changed"); + } +} diff --git a/framework/src/android/net/SocketNotBoundException.java b/framework/src/android/net/SocketNotBoundException.java new file mode 100644 index 0000000000..b1d7026ac9 --- /dev/null +++ b/framework/src/android/net/SocketNotBoundException.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; + +/** + * Thrown when a previously bound socket becomes unbound. + * + * @hide + */ +@SystemApi +public class SocketNotBoundException extends Exception { + /** @hide */ + public SocketNotBoundException() { + super("The socket is unbound"); + } +} From a1433566fec43bce09844aed6f9a36d4028a5e71 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 22 Feb 2021 07:28:12 +0000 Subject: [PATCH 064/343] Move Proxy, PacProxySelector out of Connectivity PacProxySelector is tied to IProxyService, which does not have a formal API. Proxy is the interface with ConnectivityService, and all its methods are public or module API. Bug: 171540887 Test: m Change-Id: I8ceba961a81661c3e11d8179955b594d3cab6ff7 --- framework/api/current.txt | 10 - framework/api/module-lib-current.txt | 4 - .../src/android/net/PacProxySelector.java | 138 ---------- framework/src/android/net/Proxy.java | 248 ------------------ 4 files changed, 400 deletions(-) delete mode 100644 framework/src/android/net/PacProxySelector.java delete mode 100644 framework/src/android/net/Proxy.java diff --git a/framework/api/current.txt b/framework/api/current.txt index d4262a807a..4bfcda3826 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -400,16 +400,6 @@ package android.net { method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); } - public final class Proxy { - ctor public Proxy(); - method @Deprecated public static String getDefaultHost(); - method @Deprecated public static int getDefaultPort(); - method @Deprecated public static String getHost(android.content.Context); - method @Deprecated public static int getPort(android.content.Context); - field @Deprecated public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; - field public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; - } - public class ProxyInfo implements android.os.Parcelable { ctor public ProxyInfo(@Nullable android.net.ProxyInfo); method public static android.net.ProxyInfo buildDirectProxy(String, int); diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 3af855ec1e..a9fd6f2485 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -23,10 +23,6 @@ package android.net { field public static final int TRANSPORT_TEST = 7; // 0x7 } - public final class Proxy { - method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo); - } - public final class TcpRepairWindow { ctor public TcpRepairWindow(int, int, int, int, int, int); field public final int maxWindow; diff --git a/framework/src/android/net/PacProxySelector.java b/framework/src/android/net/PacProxySelector.java deleted file mode 100644 index 326943a27d..0000000000 --- a/framework/src/android/net/PacProxySelector.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.os.ServiceManager; -import android.util.Log; - -import com.android.net.IProxyService; - -import com.google.android.collect.Lists; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.Proxy; -import java.net.Proxy.Type; -import java.net.ProxySelector; -import java.net.SocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.List; - -/** - * @hide - */ -public class PacProxySelector extends ProxySelector { - private static final String TAG = "PacProxySelector"; - public static final String PROXY_SERVICE = "com.android.net.IProxyService"; - private static final String SOCKS = "SOCKS "; - private static final String PROXY = "PROXY "; - - private IProxyService mProxyService; - private final List mDefaultList; - - public PacProxySelector() { - mProxyService = IProxyService.Stub.asInterface( - ServiceManager.getService(PROXY_SERVICE)); - if (mProxyService == null) { - // Added because of b10267814 where mako is restarting. - Log.e(TAG, "PacProxyInstaller: no proxy service"); - } - mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY); - } - - @Override - public List select(URI uri) { - if (mProxyService == null) { - mProxyService = IProxyService.Stub.asInterface( - ServiceManager.getService(PROXY_SERVICE)); - } - if (mProxyService == null) { - Log.e(TAG, "select: no proxy service return NO_PROXY"); - return Lists.newArrayList(java.net.Proxy.NO_PROXY); - } - String response = null; - String urlString; - try { - // Strip path and username/password from URI so it's not visible to PAC script. The - // path often contains credentials the app does not want exposed to a potentially - // malicious PAC script. - if (!"http".equalsIgnoreCase(uri.getScheme())) { - uri = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), "/", null, null); - } - urlString = uri.toURL().toString(); - } catch (URISyntaxException e) { - urlString = uri.getHost(); - } catch (MalformedURLException e) { - urlString = uri.getHost(); - } - try { - response = mProxyService.resolvePacFile(uri.getHost(), urlString); - } catch (Exception e) { - Log.e(TAG, "Error resolving PAC File", e); - } - if (response == null) { - return mDefaultList; - } - - return parseResponse(response); - } - - private static List parseResponse(String response) { - String[] split = response.split(";"); - List ret = Lists.newArrayList(); - for (String s : split) { - String trimmed = s.trim(); - if (trimmed.equals("DIRECT")) { - ret.add(java.net.Proxy.NO_PROXY); - } else if (trimmed.startsWith(PROXY)) { - Proxy proxy = proxyFromHostPort(Type.HTTP, trimmed.substring(PROXY.length())); - if (proxy != null) { - ret.add(proxy); - } - } else if (trimmed.startsWith(SOCKS)) { - Proxy proxy = proxyFromHostPort(Type.SOCKS, trimmed.substring(SOCKS.length())); - if (proxy != null) { - ret.add(proxy); - } - } - } - if (ret.size() == 0) { - ret.add(java.net.Proxy.NO_PROXY); - } - return ret; - } - - private static Proxy proxyFromHostPort(Proxy.Type type, String hostPortString) { - try { - String[] hostPort = hostPortString.split(":"); - String host = hostPort[0]; - int port = Integer.parseInt(hostPort[1]); - return new Proxy(type, InetSocketAddress.createUnresolved(host, port)); - } catch (NumberFormatException|ArrayIndexOutOfBoundsException e) { - Log.d(TAG, "Unable to parse proxy " + hostPortString + " " + e); - return null; - } - } - - @Override - public void connectFailed(URI uri, SocketAddress address, IOException failure) { - - } - -} diff --git a/framework/src/android/net/Proxy.java b/framework/src/android/net/Proxy.java deleted file mode 100644 index 77c8a4f457..0000000000 --- a/framework/src/android/net/Proxy.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.annotation.Nullable; -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; -import android.annotation.SystemApi; -import android.compat.annotation.UnsupportedAppUsage; -import android.content.Context; -import android.os.Build; -import android.text.TextUtils; -import android.util.Log; - -import com.android.net.module.util.ProxyUtils; - -import java.net.InetSocketAddress; -import java.net.ProxySelector; -import java.net.URI; -import java.util.List; - -/** - * A convenience class for accessing the user and default proxy - * settings. - */ -public final class Proxy { - - private static final String TAG = "Proxy"; - - private static final ProxySelector sDefaultProxySelector; - - /** - * Used to notify an app that's caching the proxy that either the default - * connection has changed or any connection's proxy has changed. The new - * proxy should be queried using {@link ConnectivityManager#getDefaultProxy()}. - * - *

    This is a protected intent that can only be sent by the system - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE"; - /** - * Intent extra included with {@link #PROXY_CHANGE_ACTION} intents. - * It describes the new proxy being used (as a {@link ProxyInfo} object). - * @deprecated Because {@code PROXY_CHANGE_ACTION} is sent whenever the proxy - * for any network on the system changes, applications should always use - * {@link ConnectivityManager#getDefaultProxy()} or - * {@link ConnectivityManager#getLinkProperties(Network)}.{@link LinkProperties#getHttpProxy()} - * to get the proxy for the Network(s) they are using. - */ - @Deprecated - public static final String EXTRA_PROXY_INFO = "android.intent.extra.PROXY_INFO"; - - private static ConnectivityManager sConnectivityManager = null; - - static { - sDefaultProxySelector = ProxySelector.getDefault(); - } - - /** - * Return the proxy object to be used for the URL given as parameter. - * @param ctx A Context used to get the settings for the proxy host. - * @param url A URL to be accessed. Used to evaluate exclusion list. - * @return Proxy (java.net) object containing the host name. If the - * user did not set a hostname it returns the default host. - * A null value means that no host is to be used. - * {@hide} - */ - @UnsupportedAppUsage - public static final java.net.Proxy getProxy(Context ctx, String url) { - String host = ""; - if ((url != null) && !isLocalHost(host)) { - URI uri = URI.create(url); - ProxySelector proxySelector = ProxySelector.getDefault(); - - List proxyList = proxySelector.select(uri); - - if (proxyList.size() > 0) { - return proxyList.get(0); - } - } - return java.net.Proxy.NO_PROXY; - } - - - /** - * Return the proxy host set by the user. - * @param ctx A Context used to get the settings for the proxy host. - * @return String containing the host name. If the user did not set a host - * name it returns the default host. A null value means that no - * host is to be used. - * @deprecated Use standard java vm proxy values to find the host, port - * and exclusion list. This call ignores the exclusion list. - */ - @Deprecated - public static final String getHost(Context ctx) { - java.net.Proxy proxy = getProxy(ctx, null); - if (proxy == java.net.Proxy.NO_PROXY) return null; - try { - return ((InetSocketAddress)(proxy.address())).getHostName(); - } catch (Exception e) { - return null; - } - } - - /** - * Return the proxy port set by the user. - * @param ctx A Context used to get the settings for the proxy port. - * @return The port number to use or -1 if no proxy is to be used. - * @deprecated Use standard java vm proxy values to find the host, port - * and exclusion list. This call ignores the exclusion list. - */ - @Deprecated - public static final int getPort(Context ctx) { - java.net.Proxy proxy = getProxy(ctx, null); - if (proxy == java.net.Proxy.NO_PROXY) return -1; - try { - return ((InetSocketAddress)(proxy.address())).getPort(); - } catch (Exception e) { - return -1; - } - } - - /** - * Return the default proxy host specified by the carrier. - * @return String containing the host name or null if there is no proxy for - * this carrier. - * @deprecated Use standard java vm proxy values to find the host, port and - * exclusion list. This call ignores the exclusion list and no - * longer reports only mobile-data apn-based proxy values. - */ - @Deprecated - public static final String getDefaultHost() { - String host = System.getProperty("http.proxyHost"); - if (TextUtils.isEmpty(host)) return null; - return host; - } - - /** - * Return the default proxy port specified by the carrier. - * @return The port number to be used with the proxy host or -1 if there is - * no proxy for this carrier. - * @deprecated Use standard java vm proxy values to find the host, port and - * exclusion list. This call ignores the exclusion list and no - * longer reports only mobile-data apn-based proxy values. - */ - @Deprecated - public static final int getDefaultPort() { - if (getDefaultHost() == null) return -1; - try { - return Integer.parseInt(System.getProperty("http.proxyPort")); - } catch (NumberFormatException e) { - return -1; - } - } - - private static final boolean isLocalHost(String host) { - if (host == null) { - return false; - } - try { - if (host != null) { - if (host.equalsIgnoreCase("localhost")) { - return true; - } - if (InetAddresses.parseNumericAddress(host).isLoopbackAddress()) { - return true; - } - } - } catch (IllegalArgumentException iex) { - } - return false; - } - - /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @Deprecated - public static void setHttpProxySystemProperty(ProxyInfo p) { - setHttpProxyConfiguration(p); - } - - /** - * Set HTTP proxy configuration for the process to match the provided ProxyInfo. - * - * If the provided ProxyInfo is null, the proxy configuration will be cleared. - * @hide - */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public static void setHttpProxyConfiguration(@Nullable ProxyInfo p) { - String host = null; - String port = null; - String exclList = null; - Uri pacFileUrl = Uri.EMPTY; - if (p != null) { - host = p.getHost(); - port = Integer.toString(p.getPort()); - exclList = ProxyUtils.exclusionListAsString(p.getExclusionList()); - pacFileUrl = p.getPacFileUrl(); - } - setHttpProxyConfiguration(host, port, exclList, pacFileUrl); - } - - /** @hide */ - public static void setHttpProxyConfiguration(String host, String port, String exclList, - Uri pacFileUrl) { - if (exclList != null) exclList = exclList.replace(",", "|"); - if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList); - if (host != null) { - System.setProperty("http.proxyHost", host); - System.setProperty("https.proxyHost", host); - } else { - System.clearProperty("http.proxyHost"); - System.clearProperty("https.proxyHost"); - } - if (port != null) { - System.setProperty("http.proxyPort", port); - System.setProperty("https.proxyPort", port); - } else { - System.clearProperty("http.proxyPort"); - System.clearProperty("https.proxyPort"); - } - if (exclList != null) { - System.setProperty("http.nonProxyHosts", exclList); - System.setProperty("https.nonProxyHosts", exclList); - } else { - System.clearProperty("http.nonProxyHosts"); - System.clearProperty("https.nonProxyHosts"); - } - if (!Uri.EMPTY.equals(pacFileUrl)) { - ProxySelector.setDefault(new PacProxySelector()); - } else { - ProxySelector.setDefault(sDefaultProxySelector); - } - } -} From 96a931b5b25874aa040a66599034dafe88233195 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 2 Mar 2021 03:28:50 +0000 Subject: [PATCH 065/343] Add modules-utils-os to service-connectivity service-connectivity needs the library so that module utilities are statically linked, not picked up from the framework jar as hidden symbols. Bug: 170598012 Change-Id: I1045b3784a4bdb902f44d848ccddb304986631c3 Test: m --- service/Android.bp | 1 + service/jarjar-rules.txt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/service/Android.bp b/service/Android.bp index f20b89fb84..e65b7b423b 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -63,6 +63,7 @@ java_library { "unsupportedappusage", ], static_libs: [ + "modules-utils-os", "net-utils-device-common", "net-utils-framework-common", "netd-client", diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index ef53ebb43c..d8205bf780 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -1 +1,2 @@ -rule com.android.net.module.util.** com.android.connectivity.util.@1 \ No newline at end of file +rule com.android.net.module.util.** com.android.connectivity.net-utils.@1 +rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 \ No newline at end of file From 24d950ce5a7d8c4018556583fa23c5b7f02d13fb Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 2 Mar 2021 13:56:38 +0900 Subject: [PATCH 066/343] Move OemNetworkPreferences aidl to connectivity Move the IOnSetOemNetworkPreferenceListener aidl definition to framework-connectivity. The interface is an internal implementation detail of framework-connectivity, so it should be built inside the jar. Bug: 181512874 Test: m Change-Id: I898049b50fc620ee629587a9303f058e0a6d0272 --- .../IOnSetOemNetworkPreferenceListener.aidl | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl diff --git a/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl new file mode 100644 index 0000000000..7979afc54f --- /dev/null +++ b/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl @@ -0,0 +1,23 @@ +/** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +oneway interface IOnSetOemNetworkPreferenceListener { + void onComplete(); +} From 5115480e8f5d0bdf4d82d0809cdc5ccf0f1f78e7 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 2 Mar 2021 12:12:49 +0900 Subject: [PATCH 067/343] Move UidRange to connectivity UidRange is a data class that is an implementation detail of Connectivity. Move it to the connectivity boundary. Remaining usages of UidRange outside of Connectivity (in VPN) should be migrated to other classes, like Range or UidRangeParcel. Bug: 181512874 Test: m Change-Id: I6f2e3685ad1c07171dd90480d1e546329de8732d --- framework/src/android/net/UidRange.aidl | 24 ++++ framework/src/android/net/UidRange.java | 152 ++++++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 framework/src/android/net/UidRange.aidl create mode 100644 framework/src/android/net/UidRange.java diff --git a/framework/src/android/net/UidRange.aidl b/framework/src/android/net/UidRange.aidl new file mode 100644 index 0000000000..f70fc8e2fe --- /dev/null +++ b/framework/src/android/net/UidRange.aidl @@ -0,0 +1,24 @@ +/* + * 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. + */ + +package android.net; + +/** + * An inclusive range of UIDs. + * + * {@hide} + */ +parcelable UidRange; \ No newline at end of file diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java new file mode 100644 index 0000000000..26518d32ed --- /dev/null +++ b/framework/src/android/net/UidRange.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; + +import java.util.Collection; + +/** + * An inclusive range of UIDs. + * + * @hide + */ +public final class UidRange implements Parcelable { + public final int start; + public final int stop; + + public UidRange(int startUid, int stopUid) { + if (startUid < 0) throw new IllegalArgumentException("Invalid start UID."); + if (stopUid < 0) throw new IllegalArgumentException("Invalid stop UID."); + if (startUid > stopUid) throw new IllegalArgumentException("Invalid UID range."); + start = startUid; + stop = stopUid; + } + + /** Creates a UidRange for the specified user. */ + public static UidRange createForUser(UserHandle user) { + final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1); + final int start = UserHandle.getUid(user, 0 /* appId */); + final int end = UserHandle.getUid(nextUser, 0) - 1; + return new UidRange(start, end); + } + + /** Returns the smallest user Id which is contained in this UidRange */ + public int getStartUser() { + return UserHandle.getUserHandleForUid(start).getIdentifier(); + } + + /** Returns the largest user Id which is contained in this UidRange */ + public int getEndUser() { + return UserHandle.getUserHandleForUid(stop).getIdentifier(); + } + + /** Returns whether the UidRange contains the specified UID. */ + public boolean contains(int uid) { + return start <= uid && uid <= stop; + } + + /** + * Returns the count of UIDs in this range. + */ + public int count() { + return 1 + stop - start; + } + + /** + * @return {@code true} if this range contains every UID contained by the {@code other} range. + */ + public boolean containsRange(UidRange other) { + return start <= other.start && other.stop <= stop; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + start; + result = 31 * result + stop; + return result; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o instanceof UidRange) { + UidRange other = (UidRange) o; + return start == other.start && stop == other.stop; + } + return false; + } + + @Override + public String toString() { + return start + "-" + stop; + } + + // Implement the Parcelable interface + // TODO: Consider making this class no longer parcelable, since all users are likely in the + // system server. + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(start); + dest.writeInt(stop); + } + + public static final @android.annotation.NonNull Creator CREATOR = + new Creator() { + @Override + public UidRange createFromParcel(Parcel in) { + int start = in.readInt(); + int stop = in.readInt(); + + return new UidRange(start, stop); + } + @Override + public UidRange[] newArray(int size) { + return new UidRange[size]; + } + }; + + /** + * Returns whether any of the UidRange in the collection contains the specified uid + * + * @param ranges The collection of UidRange to check + * @param uid the uid in question + * @return {@code true} if the uid is contained within the ranges, {@code false} otherwise + * + * @see UidRange#contains(int) + */ + public static boolean containsUid(Collection ranges, int uid) { + if (ranges == null) return false; + for (UidRange range : ranges) { + if (range.contains(uid)) { + return true; + } + } + return false; + } +} From ae9a64d7daf28cbeb871c669a979bc142d24bd46 Mon Sep 17 00:00:00 2001 From: Sarah Chin Date: Wed, 3 Feb 2021 12:00:20 -0800 Subject: [PATCH 068/343] APIs for 5G slicing Create TrafficDescriptor class Create new APN ENTERPRISE Update setupDataCall and DataCallResponse to take TrafficDescriptor and matchAllRuleAllowed Move ApnTypes from Annotation to ApnSetting Bug: 179312227 Test: atest FrameworksTelephonyTests Change-Id: I7433976bfe25bcb2af85ffb9338959cbcc9f42f3 Merged-In: I7433976bfe25bcb2af85ffb9338959cbcc9f42f3 --- framework/api/current.txt | 1 + .../src/android/net/NetworkCapabilities.java | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index 4bfcda3826..a8f1a4d2a7 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -302,6 +302,7 @@ package android.net { field public static final int NET_CAPABILITY_CBS = 5; // 0x5 field public static final int NET_CAPABILITY_DUN = 2; // 0x2 field public static final int NET_CAPABILITY_EIMS = 10; // 0xa + field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13 field public static final int NET_CAPABILITY_FOTA = 3; // 0x3 field public static final int NET_CAPABILITY_IA = 7; // 0x7 diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 26d14cbfaa..cd76f409b0 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -205,6 +205,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_OEM_PRIVATE, NET_CAPABILITY_VEHICLE_INTERNAL, NET_CAPABILITY_NOT_VCN_MANAGED, + NET_CAPABILITY_ENTERPRISE, }) public @interface NetCapability { } @@ -415,8 +416,17 @@ public final class NetworkCapabilities implements Parcelable { @SystemApi public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28; + /** + * Indicates that this network is intended for enterprise use. + *

    + * 5G URSP rules may indicate that all data should use a connection dedicated for enterprise + * use. If the enterprise capability is requested, all enterprise traffic will be routed over + * the connection with this capability. + */ + public static final int NET_CAPABILITY_ENTERPRISE = 29; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VCN_MANAGED; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_ENTERPRISE; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -474,7 +484,8 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_MCX) | (1 << NET_CAPABILITY_RCS) | (1 << NET_CAPABILITY_VEHICLE_INTERNAL) - | (1 << NET_CAPABILITY_XCAP); + | (1 << NET_CAPABILITY_XCAP) + | (1 << NET_CAPABILITY_ENTERPRISE); /** * Capabilities that force network to be restricted. @@ -2028,8 +2039,9 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; case NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE"; - case NET_CAPABILITY_VEHICLE_INTERNAL: return "NET_CAPABILITY_VEHICLE_INTERNAL"; + case NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL"; case NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED"; + case NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE"; default: return Integer.toString(capability); } } From 68d60cdb1aaff3a47b5f371e3af65d255c4c251c Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 22 Feb 2021 21:03:44 +0800 Subject: [PATCH 069/343] [Telephony] Use TelephonyCallback instead of PhoneStateListener part1 Since the redesign of PhoneStateListener, use TelephonyCallback to get the callback of EVENT_* Bug: 167684594 Test: make Change-Id: Ia3b777b12142b104b5798804f50b34748f9bf28c --- .../android/net/util/MultinetworkPolicyTracker.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java index 43fffd733e..739ddada50 100644 --- a/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -30,8 +30,8 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.provider.Settings; -import android.telephony.PhoneStateListener; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; @@ -92,8 +92,8 @@ public class MultinetworkPolicyTracker { } @VisibleForTesting - protected class ActiveDataSubscriptionIdChangedListener extends PhoneStateListener - implements PhoneStateListener.ActiveDataSubscriptionIdChangedListener { + protected class ActiveDataSubscriptionIdListener extends TelephonyCallback + implements TelephonyCallback.ActiveDataSubscriptionIdListener { @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveSubId = subId; @@ -121,8 +121,8 @@ public class MultinetworkPolicyTracker { } }; - ctx.getSystemService(TelephonyManager.class).registerPhoneStateListener( - new HandlerExecutor(handler), new ActiveDataSubscriptionIdChangedListener()); + ctx.getSystemService(TelephonyManager.class).registerTelephonyCallback( + new HandlerExecutor(handler), new ActiveDataSubscriptionIdListener()); updateAvoidBadWifi(); updateMeteredMultipathPreference(); From 1c7789742b5cf0a9d56e27b95bd0c49bb3fbd590 Mon Sep 17 00:00:00 2001 From: lifr Date: Tue, 2 Mar 2021 17:12:27 +0800 Subject: [PATCH 070/343] [CS05]Remove the hidden API usage of MetricsLogger Legacy metrics are unused and deprecated, so they are being removed. Therefore, delete the usage of the hidden MetricsLogger API. Bug: 157966864 Test: atest CtsNetTestCases atest CaptivePortalTest atest ConnectivityServiceTest Change-Id: I51241f5d50ec580015882c84dd917b015c700c7c --- framework/api/system-current.txt | 2 +- framework/src/android/net/CaptivePortal.java | 7 +++---- framework/src/android/net/ICaptivePortal.aidl | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 373fa3c240..f5972fa340 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -2,7 +2,7 @@ package android.net { public class CaptivePortal implements android.os.Parcelable { - method public void logEvent(int, @NonNull String); + method @Deprecated public void logEvent(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork(); method public void useNetwork(); field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64 diff --git a/framework/src/android/net/CaptivePortal.java b/framework/src/android/net/CaptivePortal.java index 269bbf20c8..4a7b601642 100644 --- a/framework/src/android/net/CaptivePortal.java +++ b/framework/src/android/net/CaptivePortal.java @@ -160,12 +160,11 @@ public class CaptivePortal implements Parcelable { * @param eventId one of the CAPTIVE_PORTAL_LOGIN_* constants in metrics_constants.proto. * @param packageName captive portal application package name. * @hide + * @deprecated The event will not be logged in Android S and above. The + * caller is migrating to statsd. */ + @Deprecated @SystemApi public void logEvent(int eventId, @NonNull String packageName) { - try { - ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName); - } catch (RemoteException e) { - } } } diff --git a/framework/src/android/net/ICaptivePortal.aidl b/framework/src/android/net/ICaptivePortal.aidl index fe21905c70..e35f8d46af 100644 --- a/framework/src/android/net/ICaptivePortal.aidl +++ b/framework/src/android/net/ICaptivePortal.aidl @@ -23,5 +23,4 @@ package android.net; oneway interface ICaptivePortal { void appRequest(int request); void appResponse(int response); - void logEvent(int eventId, String packageName); } From d9264b1fa3b64b719ef1245983b593e7bbdaf46a Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 4 Mar 2021 09:29:30 +0800 Subject: [PATCH 071/343] Use ArraySet#add() instead of ArraySet#append() ArraySet#append() is a hidden API which is not accessible for mainline module, use public one - ArraySet#add() instead. Bug: 170598012 Test: atest FrameworksNetTests Change-Id: I0742e2ec7aff008141b1de6d10eeca2910df71b1 --- framework/src/android/net/NetworkCapabilities.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index cd76f409b0..fa0e914d2c 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -1864,7 +1864,7 @@ public final class NetworkCapabilities implements Parcelable { final ArraySet result = new ArraySet<>(size); for (int i = 0; i < size; i++) { final T value = in.readParcelable(loader); - result.append(value); + result.add(value); } return result; } From eaff72d5449671fdf5a89f8b5007e78eb91eacec Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 4 Mar 2021 09:38:21 +0800 Subject: [PATCH 072/343] Replace withCleanCallingIdentity with [clear|restore]CallingIdentity To prevent using @hide method - withCleanCallingIdentity() from mainline module, use clearCallingIdentity() & restoreCallingIdentity() instead. Bug: 172183305 Test: FrameworksNetTests, CtsNetTestCasesLatestSdk Change-Id: I8221bb8717ba6809c5087ea2808cd4ccef948cfd --- framework/src/android/net/ConnectivityManager.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 66e7da43cb..1f2975c8a3 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -2886,10 +2886,14 @@ public class ConnectivityManager { ResultReceiver wrappedListener = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { - Binder.withCleanCallingIdentity(() -> - executor.execute(() -> { - listener.onTetheringEntitlementResult(resultCode); - })); + final long token = Binder.clearCallingIdentity(); + try { + executor.execute(() -> { + listener.onTetheringEntitlementResult(resultCode); + }); + } finally { + Binder.restoreCallingIdentity(token); + } } }; From b12113700c3ed569821557ef657c40244c1fb803 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 3 Mar 2021 12:09:05 +0800 Subject: [PATCH 073/343] [FUI22] Support getAllNetworkStateSnapshot Currently, ConnectivityService has getAllNetworkState but it is not ideal to expose as system API since the plan is to get rid of NetworkState. Thus, create a new one that returns NetworkStateSnapshot to fulfill the needs. Note the original getAllNetworkState cannot be deleted now since it has @UnsupportedAppUsage annotation. Test: atest FrameworksNetTests Bug: 174123988 Change-Id: Icddd434552b0e9ecbc8299e7242ec88cf3145aca --- framework/api/module-lib-current.txt | 1 + .../src/android/net/ConnectivityManager.java | 19 +++++++++++++++++++ .../src/android/net/IConnectivityManager.aidl | 3 +++ 3 files changed, 23 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index a9fd6f2485..d2ed73ef82 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -6,6 +6,7 @@ package android.net { } public class ConnectivityManager { + method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 66e7da43cb..a6dc9ce051 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1258,6 +1258,25 @@ public class ConnectivityManager { } } + /** + * Return a list of {@link NetworkStateSnapshot}s, one for each network that is currently + * connected. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + @NonNull + public List getAllNetworkStateSnapshot() { + try { + return mService.getAllNetworkStateSnapshot(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Returns the {@link Network} object currently serving a given type, or * null if the given type is not connected. diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 160338d396..cd49258d1c 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -31,6 +31,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.NetworkState; +import android.net.NetworkStateSnapshot; import android.net.OemNetworkPreferences; import android.net.ProxyInfo; import android.net.UidRange; @@ -79,6 +80,8 @@ interface IConnectivityManager @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) NetworkState[] getAllNetworkState(); + List getAllNetworkStateSnapshot(); + boolean isActiveNetworkMetered(); boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, From 919a491443ff4ef41e851c048656af17abc467da Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 5 Mar 2021 08:53:36 +0900 Subject: [PATCH 074/343] Move NetworkState to Connectivity NetworkState is becoming an internal implementation class, with NetworkStateSnapshot replacing it as a proper API. Considering this it belongs inside Connectivity. Bug: 174123988 Test: m Change-Id: I201f1a07c50d9da31e33f5c207875da8863ef57c --- framework/src/android/net/NetworkState.java | 130 ++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 framework/src/android/net/NetworkState.java diff --git a/framework/src/android/net/NetworkState.java b/framework/src/android/net/NetworkState.java new file mode 100644 index 0000000000..d01026566c --- /dev/null +++ b/framework/src/android/net/NetworkState.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Slog; + +/** + * Snapshot of network state. + * + * @hide + */ +public class NetworkState implements Parcelable { + private static final boolean VALIDATE_ROAMING_STATE = false; + + // TODO: remove and make members @NonNull. + public static final NetworkState EMPTY = new NetworkState(); + + public final NetworkInfo networkInfo; + public final LinkProperties linkProperties; + public final NetworkCapabilities networkCapabilities; + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + public final Network network; + public final String subscriberId; + public final int legacyNetworkType; + + private NetworkState() { + networkInfo = null; + linkProperties = null; + networkCapabilities = null; + network = null; + subscriberId = null; + legacyNetworkType = 0; + } + + public NetworkState(int legacyNetworkType, @NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, + @Nullable String subscriberId) { + this(legacyNetworkType, new NetworkInfo(legacyNetworkType, 0, null, null), linkProperties, + networkCapabilities, network, subscriberId); + } + + // Constructor that used internally in ConnectivityService mainline module. + public NetworkState(@NonNull NetworkInfo networkInfo, @NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, + @Nullable String subscriberId) { + this(networkInfo.getType(), networkInfo, linkProperties, + networkCapabilities, network, subscriberId); + } + + public NetworkState(int legacyNetworkType, @NonNull NetworkInfo networkInfo, + @NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, + @Nullable String subscriberId) { + this.networkInfo = networkInfo; + this.linkProperties = linkProperties; + this.networkCapabilities = networkCapabilities; + this.network = network; + this.subscriberId = subscriberId; + this.legacyNetworkType = legacyNetworkType; + + // This object is an atomic view of a network, so the various components + // should always agree on roaming state. + if (VALIDATE_ROAMING_STATE && networkInfo != null && networkCapabilities != null) { + if (networkInfo.isRoaming() == networkCapabilities + .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) { + Slog.wtf("NetworkState", "Roaming state disagreement between " + networkInfo + + " and " + networkCapabilities); + } + } + } + + @UnsupportedAppUsage + public NetworkState(Parcel in) { + networkInfo = in.readParcelable(null); + linkProperties = in.readParcelable(null); + networkCapabilities = in.readParcelable(null); + network = in.readParcelable(null); + subscriberId = in.readString(); + legacyNetworkType = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(networkInfo, flags); + out.writeParcelable(linkProperties, flags); + out.writeParcelable(networkCapabilities, flags); + out.writeParcelable(network, flags); + out.writeString(subscriberId); + out.writeInt(legacyNetworkType); + } + + @UnsupportedAppUsage + @NonNull + public static final Creator CREATOR = new Creator() { + @Override + public NetworkState createFromParcel(Parcel in) { + return new NetworkState(in); + } + + @Override + public NetworkState[] newArray(int size) { + return new NetworkState[size]; + } + }; +} From 43042a95cd0acea9f1c722a14359d836539540aa Mon Sep 17 00:00:00 2001 From: David Su Date: Fri, 5 Mar 2021 01:21:21 +0000 Subject: [PATCH 075/343] Emphasize possibility of multiple networks with same transport Bug: 180125982 Test: compiles Change-Id: I70d312c29b7d7b773ebb8d70043f239a6c1aae15 --- framework/src/android/net/NetworkCapabilities.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index cd76f409b0..0b87ba197b 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -2291,7 +2291,8 @@ public final class NetworkCapabilities implements Parcelable { * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network * to be selected. This is logically different than - * {@code NetworkCapabilities.NET_CAPABILITY_*}. + * {@code NetworkCapabilities.NET_CAPABILITY_*}. Also note that multiple networks with the + * same transport type may be active concurrently. * * @param transportType the transport type to be added or removed. * @return this builder From bc736ce82f3e3a8552ce2fafd40eab88df5ff8f4 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 8 Jan 2021 18:32:00 +0800 Subject: [PATCH 076/343] Create a service-connectivity-pre-jarjar library This is needed for FrameworksNetTests because it inculdes service-connectivity. Without this library, the service-connectivity is already jarjar-ed which will cause the util classes couldn't be found when running the tests. So let the tests inculde the pre-jarjar version and service-connectivity applies the jarjar to this library. Bug: 177046265 Test: FrameworksNetTests Change-Id: I1acd95ff9bec99b918646e8ec3a57f3ef156e2ca --- service/Android.bp | 18 +++++++++++++++--- service/jarjar-rules.txt | 13 ++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/service/Android.bp b/service/Android.bp index e65b7b423b..2fb9f72fea 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -50,12 +50,11 @@ cc_library_shared { } java_library { - name: "service-connectivity", + name: "service-connectivity-pre-jarjar", srcs: [ + ":framework-connectivity-shared-srcs", ":connectivity-service-srcs", ], - installable: true, - jarjar_rules: "jarjar-rules.txt", libs: [ "android.net.ipsec.ike", "services.core", @@ -73,3 +72,16 @@ java_library { "com.android.tethering", ], } + +java_library { + name: "service-connectivity", + installable: true, + static_libs:[ + "service-connectivity-pre-jarjar", + ], + jarjar_rules: "jarjar-rules.txt", + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], +} diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index d8205bf780..d8c60a428e 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -1,2 +1,13 @@ rule com.android.net.module.util.** com.android.connectivity.net-utils.@1 -rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 \ No newline at end of file +rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 + +# internal util classes +# Exclude AsyncChannel. TODO: remove AsyncChannel usage in ConnectivityService +rule com.android.internal.util.AsyncChannel* @0 +# Exclude LocationPermissionChecker. This is going to be moved to libs/net +rule com.android.internal.util.LocationPermissionChecker* @0 +rule android.util.LocalLog* com.android.connectivity.util.LocalLog@1 +# android.util.IndentingPrintWriter* should use a different package name from +# the one in com.android.internal.util +rule android.util.IndentingPrintWriter* android.connectivity.util.IndentingPrintWriter@1 +rule com.android.internal.util.** com.android.connectivity.util.@1 From 991f65f1644b158ff6b113fb5a59a2e4b70042ce Mon Sep 17 00:00:00 2001 From: lifr Date: Thu, 4 Mar 2021 14:08:08 +0800 Subject: [PATCH 077/343] [CS10]Remove the hidden API usage of BitUtils The connection service will become the main line module. It is difficult to include BitUtils in the module. and so Move the hidden API needed in BitUtils to NetworkCapabilitiesUtils. Bug: 170598012 Test: atest ConnectivityServiceTest atest NetworkCapabilitiesTest atest DnsUtilsTest Change-Id: Ibc81827e25a54fc3ff94f78d810fe4f5073e3a98 --- .../src/android/net/NetworkCapabilities.java | 22 ++++++++++--------- framework/src/android/net/util/DnsUtils.java | 4 +--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index cd76f409b0..ab58f1b41a 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -34,9 +34,9 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.NetworkCapabilitiesUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -610,7 +610,7 @@ public final class NetworkCapabilities implements Parcelable { */ @UnsupportedAppUsage public @NetCapability int[] getCapabilities() { - return BitUtils.unpackBits(mNetworkCapabilities); + return NetworkCapabilitiesUtils.unpackBits(mNetworkCapabilities); } /** @@ -620,7 +620,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NetCapability int[] getUnwantedCapabilities() { - return BitUtils.unpackBits(mUnwantedNetworkCapabilities); + return NetworkCapabilitiesUtils.unpackBits(mUnwantedNetworkCapabilities); } @@ -632,8 +632,8 @@ public final class NetworkCapabilities implements Parcelable { */ public void setCapabilities(@NetCapability int[] capabilities, @NetCapability int[] unwantedCapabilities) { - mNetworkCapabilities = BitUtils.packBits(capabilities); - mUnwantedNetworkCapabilities = BitUtils.packBits(unwantedCapabilities); + mNetworkCapabilities = NetworkCapabilitiesUtils.packBits(capabilities); + mUnwantedNetworkCapabilities = NetworkCapabilitiesUtils.packBits(unwantedCapabilities); } /** @@ -688,7 +688,7 @@ public final class NetworkCapabilities implements Parcelable { & NON_REQUESTABLE_CAPABILITIES; if (nonRequestable != 0) { - return capabilityNameOf(BitUtils.unpackBits(nonRequestable)[0]); + return capabilityNameOf(NetworkCapabilitiesUtils.unpackBits(nonRequestable)[0]); } if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth"; if (hasSignalStrength()) return "signalStrength"; @@ -946,7 +946,7 @@ public final class NetworkCapabilities implements Parcelable { */ @SystemApi @NonNull public @Transport int[] getTransportTypes() { - return BitUtils.unpackBits(mTransportTypes); + return NetworkCapabilitiesUtils.unpackBits(mTransportTypes); } /** @@ -956,7 +956,7 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void setTransportTypes(@Transport int[] transportTypes) { - mTransportTypes = BitUtils.packBits(transportTypes); + mTransportTypes = NetworkCapabilitiesUtils.packBits(transportTypes); } /** @@ -1721,8 +1721,10 @@ public final class NetworkCapabilities implements Parcelable { long oldImmutableCapabilities = this.mNetworkCapabilities & mask; long newImmutableCapabilities = that.mNetworkCapabilities & mask; if (oldImmutableCapabilities != newImmutableCapabilities) { - String before = capabilityNamesOf(BitUtils.unpackBits(oldImmutableCapabilities)); - String after = capabilityNamesOf(BitUtils.unpackBits(newImmutableCapabilities)); + String before = capabilityNamesOf(NetworkCapabilitiesUtils.unpackBits( + oldImmutableCapabilities)); + String after = capabilityNamesOf(NetworkCapabilitiesUtils.unpackBits( + newImmutableCapabilities)); joiner.add(String.format("immutable capabilities changed: %s -> %s", before, after)); } diff --git a/framework/src/android/net/util/DnsUtils.java b/framework/src/android/net/util/DnsUtils.java index 7908353eed..3fe245edb9 100644 --- a/framework/src/android/net/util/DnsUtils.java +++ b/framework/src/android/net/util/DnsUtils.java @@ -29,8 +29,6 @@ import android.system.ErrnoException; import android.system.Os; import android.util.Log; -import com.android.internal.util.BitUtils; - import libcore.io.IoUtils; import java.io.FileDescriptor; @@ -332,7 +330,7 @@ public class DnsUtils { if (srcByte[i] == dstByte[i]) { continue; } - int x = BitUtils.uint8(srcByte[i]) ^ BitUtils.uint8(dstByte[i]); + int x = (srcByte[i] & 0xff) ^ (dstByte[i] & 0xff); return i * CHAR_BIT + (Integer.numberOfLeadingZeros(x) - 24); // Java ints are 32 bits } return dstByte.length * CHAR_BIT; From c5e54d4c37f0f7081bdafcb66517a948ca9388e2 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sat, 6 Mar 2021 00:43:09 +0900 Subject: [PATCH 078/343] Move OemNetworkPreferences to Connectivity The data class supports a ConnectivityManager API, so it should be together with the ConnectivityManager API surface. Bug: 181512874 Test: m Change-Id: I5642486ea0febcb08cadcbd4cd3f0c6056deae0e --- .../android/net/OemNetworkPreferences.aidl | 19 ++ framework/api/system-current.txt | 20 ++ .../android/net/OemNetworkPreferences.java | 239 ++++++++++++++++++ 3 files changed, 278 insertions(+) create mode 100644 framework/aidl-export/android/net/OemNetworkPreferences.aidl create mode 100644 framework/src/android/net/OemNetworkPreferences.java diff --git a/framework/aidl-export/android/net/OemNetworkPreferences.aidl b/framework/aidl-export/android/net/OemNetworkPreferences.aidl new file mode 100644 index 0000000000..2b6a4ceef5 --- /dev/null +++ b/framework/aidl-export/android/net/OemNetworkPreferences.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable OemNetworkPreferences; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index f5972fa340..a732430e6a 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -320,6 +320,26 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); } + public final class OemNetworkPreferences implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.Map getNetworkPreferences(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; // 0x1 + field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; // 0x2 + field public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; // 0x3 + field public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; // 0x4 + field public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; // 0x0 + } + + public static final class OemNetworkPreferences.Builder { + ctor public OemNetworkPreferences.Builder(); + ctor public OemNetworkPreferences.Builder(@NonNull android.net.OemNetworkPreferences); + method @NonNull public android.net.OemNetworkPreferences.Builder addNetworkPreference(@NonNull String, int); + method @NonNull public android.net.OemNetworkPreferences build(); + method @NonNull public android.net.OemNetworkPreferences.Builder clearNetworkPreference(@NonNull String); + } + public abstract class QosCallback { ctor public QosCallback(); method public void onError(@NonNull android.net.QosCallbackException); diff --git a/framework/src/android/net/OemNetworkPreferences.java b/framework/src/android/net/OemNetworkPreferences.java new file mode 100644 index 0000000000..48bd29769f --- /dev/null +++ b/framework/src/android/net/OemNetworkPreferences.java @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Bundle; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Network preferences to set the default active network on a per-application basis as per a given + * {@link OemNetworkPreference}. An example of this would be to set an application's network + * preference to {@link #OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK} which would have the default + * network for that application set to an unmetered network first if available and if not, it then + * set that application's default network to an OEM managed network if available. + * + * @hide + */ +@SystemApi +public final class OemNetworkPreferences implements Parcelable { + /** + * Default in case this value is not set. Using it will result in an error. + */ + public static final int OEM_NETWORK_PREFERENCE_UNINITIALIZED = 0; + + /** + * If an unmetered network is available, use it. + * Otherwise, if a network with the OEM_PAID capability is available, use it. + * Otherwise, use the general default network. + */ + public static final int OEM_NETWORK_PREFERENCE_OEM_PAID = 1; + + /** + * If an unmetered network is available, use it. + * Otherwise, if a network with the OEM_PAID capability is available, use it. + * Otherwise, the app doesn't get a default network. + */ + public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK = 2; + + /** + * Use only NET_CAPABILITY_OEM_PAID networks. + */ + public static final int OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY = 3; + + /** + * Use only NET_CAPABILITY_OEM_PRIVATE networks. + */ + public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4; + + @NonNull + private final Bundle mNetworkMappings; + + /** + * Return the currently built application package name to {@link OemNetworkPreference} mappings. + * @return the current network preferences map. + */ + @NonNull + public Map getNetworkPreferences() { + return convertToUnmodifiableMap(mNetworkMappings); + } + + private OemNetworkPreferences(@NonNull final Bundle networkMappings) { + Objects.requireNonNull(networkMappings); + mNetworkMappings = (Bundle) networkMappings.clone(); + } + + @Override + public String toString() { + return "OemNetworkPreferences{" + "mNetworkMappings=" + mNetworkMappings + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OemNetworkPreferences that = (OemNetworkPreferences) o; + + return mNetworkMappings.size() == that.mNetworkMappings.size() + && mNetworkMappings.toString().equals(that.mNetworkMappings.toString()); + } + + @Override + public int hashCode() { + return Objects.hash(mNetworkMappings); + } + + /** + * Builder used to create {@link OemNetworkPreferences} objects. Specify the preferred Network + * to package name mappings. + */ + public static final class Builder { + private final Bundle mNetworkMappings; + + public Builder() { + mNetworkMappings = new Bundle(); + } + + /** + * Constructor to populate the builder's values with an already built + * {@link OemNetworkPreferences}. + * @param preferences the {@link OemNetworkPreferences} to populate with. + */ + public Builder(@NonNull final OemNetworkPreferences preferences) { + Objects.requireNonNull(preferences); + mNetworkMappings = (Bundle) preferences.mNetworkMappings.clone(); + } + + /** + * Add a network preference for a given package. Previously stored values for the given + * package will be overwritten. + * + * @param packageName full package name (e.g.: "com.google.apps.contacts") of the app + * to use the given preference + * @param preference the desired network preference to use + * @return The builder to facilitate chaining. + */ + @NonNull + public Builder addNetworkPreference(@NonNull final String packageName, + @OemNetworkPreference final int preference) { + Objects.requireNonNull(packageName); + mNetworkMappings.putInt(packageName, preference); + return this; + } + + /** + * Remove a network preference for a given package. + * + * @param packageName full package name (e.g.: "com.google.apps.contacts") of the app to + * remove a preference for. + * @return The builder to facilitate chaining. + */ + @NonNull + public Builder clearNetworkPreference(@NonNull final String packageName) { + Objects.requireNonNull(packageName); + mNetworkMappings.remove(packageName); + return this; + } + + /** + * Build {@link OemNetworkPreferences} return the current OEM network preferences. + */ + @NonNull + public OemNetworkPreferences build() { + return new OemNetworkPreferences(mNetworkMappings); + } + } + + private static Map convertToUnmodifiableMap(@NonNull final Bundle bundle) { + final Map networkPreferences = new HashMap<>(); + for (final String key : bundle.keySet()) { + networkPreferences.put(key, bundle.getInt(key)); + } + return Collections.unmodifiableMap(networkPreferences); + } + + /** @hide */ + @IntDef(prefix = "OEM_NETWORK_PREFERENCE_", value = { + OEM_NETWORK_PREFERENCE_UNINITIALIZED, + OEM_NETWORK_PREFERENCE_OEM_PAID, + OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK, + OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY, + OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY + }) + @Retention(RetentionPolicy.SOURCE) + public @interface OemNetworkPreference {} + + /** + * Return the string value for OemNetworkPreference + * + * @param value int value of OemNetworkPreference + * @return string version of OemNetworkPreference + * + * @hide + */ + @NonNull + public static String oemNetworkPreferenceToString(@OemNetworkPreference int value) { + switch (value) { + case OEM_NETWORK_PREFERENCE_UNINITIALIZED: + return "OEM_NETWORK_PREFERENCE_UNINITIALIZED"; + case OEM_NETWORK_PREFERENCE_OEM_PAID: + return "OEM_NETWORK_PREFERENCE_OEM_PAID"; + case OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK: + return "OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK"; + case OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY: + return "OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY"; + case OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY: + return "OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY"; + default: + return Integer.toHexString(value); + } + } + + @Override + public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { + dest.writeBundle(mNetworkMappings); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public OemNetworkPreferences[] newArray(int size) { + return new OemNetworkPreferences[size]; + } + + @Override + public OemNetworkPreferences createFromParcel(@NonNull android.os.Parcel in) { + return new OemNetworkPreferences( + in.readBundle(getClass().getClassLoader())); + } + }; +} From a20cf48c1b3c885b16d3880ea41332a26ea753fa Mon Sep 17 00:00:00 2001 From: paulhu Date: Thu, 4 Mar 2021 10:53:27 +0800 Subject: [PATCH 079/343] Replace Inet[4|6]Address#ANY Connectivity is becoming a mainline module in S but mainline modules are not allowed to use non-formal APIs. Thus, replace non-formal API Inet[4|6]Address#ANY to NetworkStackConstants#IPV[4|6]_ADDR_ANY. Bug: 181756157 Test: FrameworksNetTests Change-Id: Id4d2fc551c1384f549a586e87ab68356ba05b995 --- framework/src/android/net/RouteInfo.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/RouteInfo.java b/framework/src/android/net/RouteInfo.java index 5b6684ace0..fad3144a4b 100644 --- a/framework/src/android/net/RouteInfo.java +++ b/framework/src/android/net/RouteInfo.java @@ -26,6 +26,7 @@ import android.os.Parcel; import android.os.Parcelable; import com.android.net.module.util.NetUtils; +import com.android.net.module.util.NetworkStackConstants; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -181,9 +182,9 @@ public final class RouteInfo implements Parcelable { if (destination == null) { if (gateway != null) { if (gateway instanceof Inet4Address) { - destination = new IpPrefix(Inet4Address.ANY, 0); + destination = new IpPrefix(NetworkStackConstants.IPV4_ADDR_ANY, 0); } else { - destination = new IpPrefix(Inet6Address.ANY, 0); + destination = new IpPrefix(NetworkStackConstants.IPV6_ADDR_ANY, 0); } } else { // no destination, no gateway. invalid. @@ -196,9 +197,9 @@ public final class RouteInfo implements Parcelable { // ConnectivityService) to stop doing things like r.getGateway().equals(), ... . if (gateway == null) { if (destination.getAddress() instanceof Inet4Address) { - gateway = Inet4Address.ANY; + gateway = NetworkStackConstants.IPV4_ADDR_ANY; } else { - gateway = Inet6Address.ANY; + gateway = NetworkStackConstants.IPV6_ADDR_ANY; } } mHasGateway = (!gateway.isAnyLocalAddress()); From a3b96dc5818fd48926566563ad328213fd7bbbbe Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 22 Feb 2021 21:03:44 +0800 Subject: [PATCH 080/343] [Telephony] Use TelephonyCallback instead of PhoneStateListener part1 Since the redesign of PhoneStateListener, use TelephonyCallback to get the callback of EVENT_* Bug: 167684594 Test: make Change-Id: Ia3b777b12142b104b5798804f50b34748f9bf28c Merged-In: Ia3b777b12142b104b5798804f50b34748f9bf28c --- .../android/net/util/MultinetworkPolicyTracker.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java index 43fffd733e..739ddada50 100644 --- a/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -30,8 +30,8 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.provider.Settings; -import android.telephony.PhoneStateListener; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; @@ -92,8 +92,8 @@ public class MultinetworkPolicyTracker { } @VisibleForTesting - protected class ActiveDataSubscriptionIdChangedListener extends PhoneStateListener - implements PhoneStateListener.ActiveDataSubscriptionIdChangedListener { + protected class ActiveDataSubscriptionIdListener extends TelephonyCallback + implements TelephonyCallback.ActiveDataSubscriptionIdListener { @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveSubId = subId; @@ -121,8 +121,8 @@ public class MultinetworkPolicyTracker { } }; - ctx.getSystemService(TelephonyManager.class).registerPhoneStateListener( - new HandlerExecutor(handler), new ActiveDataSubscriptionIdChangedListener()); + ctx.getSystemService(TelephonyManager.class).registerTelephonyCallback( + new HandlerExecutor(handler), new ActiveDataSubscriptionIdListener()); updateAvoidBadWifi(); updateMeteredMultipathPreference(); From 32288186bb714df7b65b31f82a47a8ea73867783 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 14:20:19 +0900 Subject: [PATCH 081/343] Add Ethernet, TestNetworkSpecifier API Rename StringNetworkSpecifier to EthernetNetworkSpecifier (its only production user), and make it module-lib API. The original StringNetworkSpecifier file is actually kept to satisfy some invalid dependencies; it will be removed separately. This allows specifying an Ethernet interface with a non-deprecated API: until this change the only way to do so would be to use NetworkRequest#setSpecifier(String), which is deprecated. Similarly, add the TestNetworkSpecifier API for TestNetworkManager, to replace previous usage of StringNetworkSpecifier. TestNetworkManager is module API, so TestNetworkSpecifier should be module API too. This allows tests to request the test interface specifically, without using the deprecated NetworkRequest#setSpecifier(String). Bug: 179329291 Test: m Change-Id: Iee569f5c8bbdc4bc979610e1191308281f3d4620 --- framework/api/module-lib-current.txt | 8 ++ framework/src/android/net/NetworkRequest.java | 17 +++- .../src/android/net/TestNetworkSpecifier.java | 97 +++++++++++++++++++ 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 framework/src/android/net/TestNetworkSpecifier.java diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index a9fd6f2485..284a55885c 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -50,6 +50,14 @@ package android.net { field public static final String TEST_TAP_PREFIX = "testtap"; } + public final class TestNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { + ctor public TestNetworkSpecifier(@NonNull String); + method public int describeContents(); + method @Nullable public String getInterfaceName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { ctor public VpnTransportInfo(int); method public int describeContents(); diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index b4a651c060..17a8ee1720 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -31,6 +31,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVIT import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; @@ -382,11 +383,17 @@ public class NetworkRequest implements Parcelable { return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() .setSubscriptionId(subId).build()); } catch (NumberFormatException nfe) { - // A StringNetworkSpecifier does not accept null or empty ("") strings. When network - // specifiers were strings a null string and an empty string were considered - // equivalent. Hence no meaning is attached to a null or empty ("") string. - return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null - : new StringNetworkSpecifier(networkSpecifier)); + // An EthernetNetworkSpecifier or TestNetworkSpecifier does not accept null or empty + // ("") strings. When network specifiers were strings a null string and an empty + // string were considered equivalent. Hence no meaning is attached to a null or + // empty ("") string. + if (TextUtils.isEmpty(networkSpecifier)) { + return setNetworkSpecifier((NetworkSpecifier) null); + } else if (mNetworkCapabilities.hasTransport(TRANSPORT_TEST)) { + return setNetworkSpecifier(new TestNetworkSpecifier(networkSpecifier)); + } else { + return setNetworkSpecifier(new EthernetNetworkSpecifier(networkSpecifier)); + } } } diff --git a/framework/src/android/net/TestNetworkSpecifier.java b/framework/src/android/net/TestNetworkSpecifier.java new file mode 100644 index 0000000000..b7470a591d --- /dev/null +++ b/framework/src/android/net/TestNetworkSpecifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A {@link NetworkSpecifier} used to identify test interfaces. + * + * @see TestNetworkManager + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class TestNetworkSpecifier extends NetworkSpecifier implements Parcelable { + + /** + * Name of the network interface. + */ + @NonNull + private final String mInterfaceName; + + public TestNetworkSpecifier(@NonNull String interfaceName) { + Preconditions.checkStringNotEmpty(interfaceName); + mInterfaceName = interfaceName; + } + + // This may be null in the future to support specifiers based on data other than the interface + // name. + @Nullable + public String getInterfaceName() { + return mInterfaceName; + } + + @Override + public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof TestNetworkSpecifier)) return false; + return TextUtils.equals(mInterfaceName, ((TestNetworkSpecifier) o).mInterfaceName); + } + + @Override + public int hashCode() { + return Objects.hashCode(mInterfaceName); + } + + @Override + public String toString() { + return "TestNetworkSpecifier (" + mInterfaceName + ")"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInterfaceName); + } + + public static final @NonNull Creator CREATOR = + new Creator() { + public TestNetworkSpecifier createFromParcel(Parcel in) { + return new TestNetworkSpecifier(in.readString()); + } + public TestNetworkSpecifier[] newArray(int size) { + return new TestNetworkSpecifier[size]; + } + }; +} From 56520566cea5340963f23dce447c708b980b3f03 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 8 Mar 2021 22:05:03 +0900 Subject: [PATCH 082/343] Create ServiceConnectivityResources Create the ServiceConnectivityResources package, which contains resources Connectivity unbundled from platform resources. Migrate the first few resources from ConnectivityService that have no RRO in AOSP. To avoid boot time impact, avoid loading the resources in the ConnectivityService constructor. Bug: 182125649 Test: atest FrameworksNetTests Change-Id: I77ac6f4303c54acc96f16e18ef02add30298ff3d --- service/Android.bp | 1 + .../ServiceConnectivityResources/Android.bp | 35 +++++++++++++++ .../AndroidManifest.xml | 37 +++++++++++++++ .../res/values/config.xml | 45 +++++++++++++++++++ .../res/values/overlayable.xml | 27 +++++++++++ .../res/values/strings.xml | 22 +++++++++ 6 files changed, 167 insertions(+) create mode 100644 service/ServiceConnectivityResources/Android.bp create mode 100644 service/ServiceConnectivityResources/AndroidManifest.xml create mode 100644 service/ServiceConnectivityResources/res/values/config.xml create mode 100644 service/ServiceConnectivityResources/res/values/overlayable.xml create mode 100644 service/ServiceConnectivityResources/res/values/strings.xml diff --git a/service/Android.bp b/service/Android.bp index e65b7b423b..5392f8451a 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -61,6 +61,7 @@ java_library { "services.core", "services.net", "unsupportedappusage", + "ServiceConnectivityResources", ], static_libs: [ "modules-utils-os", diff --git a/service/ServiceConnectivityResources/Android.bp b/service/ServiceConnectivityResources/Android.bp new file mode 100644 index 0000000000..f2446b7f7e --- /dev/null +++ b/service/ServiceConnectivityResources/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// APK to hold all the wifi overlayable resources. +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_app { + name: "ServiceConnectivityResources", + sdk_version: "system_current", + resource_dirs: [ + "res", + ], + privileged: true, + export_package_resources: true, + apex_available: [ + "com.android.tethering", + ], + // TODO: use a dedicated cert once generated + certificate: "platform", +} diff --git a/service/ServiceConnectivityResources/AndroidManifest.xml b/service/ServiceConnectivityResources/AndroidManifest.xml new file mode 100644 index 0000000000..2c30302615 --- /dev/null +++ b/service/ServiceConnectivityResources/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml new file mode 100644 index 0000000000..7d98c76a40 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + 60000 + + + + + + + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml new file mode 100644 index 0000000000..00ec2df0e6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/service/ServiceConnectivityResources/res/values/strings.xml b/service/ServiceConnectivityResources/res/values/strings.xml new file mode 100644 index 0000000000..2c7b992650 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values/strings.xml @@ -0,0 +1,22 @@ + + + + + System Connectivity Resources + \ No newline at end of file From 61c0b1a6f5f342db1a1971806075149fa31375b2 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 9 Mar 2021 23:53:55 +0000 Subject: [PATCH 083/343] Use ParcelDescriptor.fromSocket instead of getFileDescriptor Socket.getFileDescriptor$ is a hidden API. Instead, replace it with ParcelDescriptor.fromSocket, which was created to handle such use-cases. Bug: 170598012 Change-Id: I9e218e4ec29d2b7fe5d2faeb1c2e1cafc63dc923 Test: m --- framework/src/android/net/QosSocketInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java index d37c4691dd..3bf700b4d2 100644 --- a/framework/src/android/net/QosSocketInfo.java +++ b/framework/src/android/net/QosSocketInfo.java @@ -92,7 +92,7 @@ public final class QosSocketInfo implements Parcelable { Objects.requireNonNull(socket, "socket cannot be null"); mNetwork = Objects.requireNonNull(network, "network cannot be null"); - mParcelFileDescriptor = ParcelFileDescriptor.dup(socket.getFileDescriptor$()); + mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket); mLocalSocketAddress = new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()); } From 63338848da3044989c4ce1fe671a0a0c6f32f3ca Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 8 Jan 2021 18:32:00 +0800 Subject: [PATCH 084/343] Create a service-connectivity-pre-jarjar library This is needed for FrameworksNetTests because it inculdes service-connectivity. Without this library, the service-connectivity is already jarjar-ed which will cause the util classes couldn't be found when running the tests. So let the tests inculde the pre-jarjar version and service-connectivity applies the jarjar to this library. Bug: 177046265 Test: FrameworksNetTests Change-Id: I1acd95ff9bec99b918646e8ec3a57f3ef156e2ca Merged-In: I1acd95ff9bec99b918646e8ec3a57f3ef156e2ca --- service/Android.bp | 18 +++++++++++++++--- service/jarjar-rules.txt | 13 ++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/service/Android.bp b/service/Android.bp index e65b7b423b..2fb9f72fea 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -50,12 +50,11 @@ cc_library_shared { } java_library { - name: "service-connectivity", + name: "service-connectivity-pre-jarjar", srcs: [ + ":framework-connectivity-shared-srcs", ":connectivity-service-srcs", ], - installable: true, - jarjar_rules: "jarjar-rules.txt", libs: [ "android.net.ipsec.ike", "services.core", @@ -73,3 +72,16 @@ java_library { "com.android.tethering", ], } + +java_library { + name: "service-connectivity", + installable: true, + static_libs:[ + "service-connectivity-pre-jarjar", + ], + jarjar_rules: "jarjar-rules.txt", + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], +} diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index d8205bf780..d8c60a428e 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -1,2 +1,13 @@ rule com.android.net.module.util.** com.android.connectivity.net-utils.@1 -rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 \ No newline at end of file +rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 + +# internal util classes +# Exclude AsyncChannel. TODO: remove AsyncChannel usage in ConnectivityService +rule com.android.internal.util.AsyncChannel* @0 +# Exclude LocationPermissionChecker. This is going to be moved to libs/net +rule com.android.internal.util.LocationPermissionChecker* @0 +rule android.util.LocalLog* com.android.connectivity.util.LocalLog@1 +# android.util.IndentingPrintWriter* should use a different package name from +# the one in com.android.internal.util +rule android.util.IndentingPrintWriter* android.connectivity.util.IndentingPrintWriter@1 +rule com.android.internal.util.** com.android.connectivity.util.@1 From 764e506248573c47e59fe0faa3a31704d4a5ca0e Mon Sep 17 00:00:00 2001 From: lifr Date: Thu, 11 Mar 2021 03:17:17 +0800 Subject: [PATCH 085/343] [CS15]Do not use hidden API of PlatformProperties ConnectivityService is going to become a mainline module, and it will not able to use hidden method anymore. Using PlatformProperties as a static library instead of hidden API. Bug: 170917042 Test: atest FrameworksNetTests Merged-In: I3a3deca5d2e0f690db8c0061de2db2217376d268 Change-Id: I3a3deca5d2e0f690db8c0061de2db2217376d268 --- service/Android.bp | 3 ++- service/jarjar-rules.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/service/Android.bp b/service/Android.bp index 2fb9f72fea..856f3b8533 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -66,6 +66,7 @@ java_library { "net-utils-device-common", "net-utils-framework-common", "netd-client", + "PlatformProperties", ], apex_available: [ "//apex_available:platform", @@ -76,7 +77,7 @@ java_library { java_library { name: "service-connectivity", installable: true, - static_libs:[ + static_libs: [ "service-connectivity-pre-jarjar", ], jarjar_rules: "jarjar-rules.txt", diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index d8c60a428e..a7b419b020 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -1,3 +1,4 @@ +rule android.sysprop.** com.android.connectivity.sysprop.@1 rule com.android.net.module.util.** com.android.connectivity.net-utils.@1 rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 From 07051bcd834ce0325134b6518d80bb7569d5e821 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 07:43:37 +0000 Subject: [PATCH 086/343] Remove usage of hidden InetSocketAddress constructor The constructor is a hidden API, and used in a code path that can never happen. Replace it with a thrown exception (which should never be thrown either). Bug: 170598012 Change-Id: Ie2c671c1a75accb8e94b08de9901d14b72caaf7e Test: m --- framework/src/android/net/QosSocketInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java index d37c4691dd..c345a9d77d 100644 --- a/framework/src/android/net/QosSocketInfo.java +++ b/framework/src/android/net/QosSocketInfo.java @@ -114,10 +114,10 @@ public final class QosSocketInfo implements Parcelable { try { return new InetSocketAddress(InetAddress.getByAddress(address), port); } catch (final UnknownHostException e) { - /* The catch block was purposely left empty. UnknownHostException will never be thrown + /* This can never happen. UnknownHostException will never be thrown since the address provided is numeric and non-null. */ + throw new RuntimeException("UnknownHostException on numeric address", e); } - return new InetSocketAddress(); } @Override From 5a4c7353b24a33de222dfc01eb5adae2ff861e35 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 17:19:18 +0900 Subject: [PATCH 087/343] Move ParseException to Connectivity ParseException is a public API class used to support Connectivity APIs, so it should be in the same API surface as connectivity. Bug: 181512874 Test: m Change-Id: Ie1213de0d0facc8f409f7b4c2553abb382e4afbf --- framework/api/current.txt | 4 ++ framework/src/android/net/ParseException.java | 37 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 framework/src/android/net/ParseException.java diff --git a/framework/api/current.txt b/framework/api/current.txt index a8f1a4d2a7..ab5d969f5d 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -401,6 +401,10 @@ package android.net { method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); } + public class ParseException extends java.lang.RuntimeException { + field public String response; + } + public class ProxyInfo implements android.os.Parcelable { ctor public ProxyInfo(@Nullable android.net.ProxyInfo); method public static android.net.ProxyInfo buildDirectProxy(String, int); diff --git a/framework/src/android/net/ParseException.java b/framework/src/android/net/ParseException.java new file mode 100644 index 0000000000..bcfdd7ef09 --- /dev/null +++ b/framework/src/android/net/ParseException.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; + +/** + * Thrown when parsing failed. + */ +// See non-public class {@link WebAddress}. +public class ParseException extends RuntimeException { + public String response; + + ParseException(@NonNull String response) { + super(response); + this.response = response; + } + + ParseException(@NonNull String response, @NonNull Throwable cause) { + super(response, cause); + this.response = response; + } +} From a29be5c0f74c66507e26af85a09a22b60690c258 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 10:56:49 +0000 Subject: [PATCH 088/343] Remove hidden INVALID_RESOURCE_ID in unused param INVALID_RESOURCE_ID is a hidden API so its usage should be avoided. The current usage is for an unused parameter, so just use a literal instead. Bug: 182451544 Change-Id: I066d9c34f735434adee4ee72e8a7fe1ceb900c3c Test: m --- framework/src/android/net/ConnectivityManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 45ed3179d7..77e67bac8a 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -16,7 +16,6 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; -import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.REQUEST; @@ -1996,7 +1995,7 @@ public class ConnectivityManager { dup = createInvalidFd(); } return new NattSocketKeepalive(mService, network, dup, - INVALID_RESOURCE_ID /* Unused */, source, destination, executor, callback); + -1 /* Unused */, source, destination, executor, callback); } /** From 2d4413f8e3ecb83a46f3615ae7ae795df83fc9fa Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 20:29:10 +0900 Subject: [PATCH 089/343] Remove hidden @NetworkType in NetworkInfo The NetworkType annotation is a hidden telephony symbol, and should be kept hidden as annotations are disallowed by API guidelines. Remove its usage in NetworkInfo as users of annotated constants that build against API stubs are expected not to use the annotation. Bug: 182451544 Test: m Change-Id: I6658c1faa147c527c989b87d67f1af166c488dde --- framework/src/android/net/NetworkInfo.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/android/net/NetworkInfo.java b/framework/src/android/net/NetworkInfo.java index d752901e2e..bb23494593 100644 --- a/framework/src/android/net/NetworkInfo.java +++ b/framework/src/android/net/NetworkInfo.java @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.Annotation.NetworkType; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; @@ -164,7 +163,7 @@ public class NetworkInfo implements Parcelable { * @param typeName a human-readable string for the network type, or an empty string or null. * @param subtypeName a human-readable string for the subtype, or an empty string or null. */ - public NetworkInfo(int type, @NetworkType int subtype, + public NetworkInfo(int type, int subtype, @Nullable String typeName, @Nullable String subtypeName) { if (!ConnectivityManager.isNetworkTypeValid(type) && type != ConnectivityManager.TYPE_NONE) { From fa5eacc89f19bf96ed7de600a1a81b90454132f7 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 20:49:13 +0900 Subject: [PATCH 090/343] Remove connectivity dependency on Preconditions Preconditions.checkNotNull is deprecated to be replaced by Objects.requireNonNull, and other methods can easily be replaced by inline checks. Preconditions is an internal API class that should not be used by unbundled jars. Bug: 177046265 Test: m Change-Id: If14a75439ff332c927dc4114ae0eecb89f53c6c7 --- .../net/ConnectivityDiagnosticsManager.java | 5 +-- .../src/android/net/ConnectivityManager.java | 44 +++++++++++-------- framework/src/android/net/MacAddress.java | 10 ++--- .../src/android/net/NetworkCapabilities.java | 11 ++--- .../android/net/StaticIpConfiguration.java | 3 +- .../src/android/net/TestNetworkManager.java | 7 ++- 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.java b/framework/src/android/net/ConnectivityDiagnosticsManager.java index 5234494973..3598ebc701 100644 --- a/framework/src/android/net/ConnectivityDiagnosticsManager.java +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.java @@ -28,7 +28,6 @@ import android.os.PersistableBundle; import android.os.RemoteException; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -70,8 +69,8 @@ public class ConnectivityDiagnosticsManager { /** @hide */ public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) { - mContext = Preconditions.checkNotNull(context, "missing context"); - mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mContext = Objects.requireNonNull(context, "missing context"); + mService = Objects.requireNonNull(service, "missing IConnectivityManager"); } /** @hide */ diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 45ed3179d7..e463a7cd31 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -69,7 +69,6 @@ import android.util.SparseIntArray; import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; import libcore.net.event.NetworkEventDispatcher; @@ -1733,7 +1732,9 @@ public class ConnectivityManager { // Map from type to transports. final int NOT_FOUND = -1; final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND); - Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type); + if (transport == NOT_FOUND) { + throw new IllegalArgumentException("unknown legacy type: " + type); + } nc.addTransportType(transport); // Map from type to capabilities. @@ -1838,8 +1839,8 @@ public class ConnectivityManager { } private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { - Preconditions.checkNotNull(network, "network cannot be null"); - Preconditions.checkNotNull(callback, "callback cannot be null"); + Objects.requireNonNull(network, "network cannot be null"); + Objects.requireNonNull(callback, "callback cannot be null"); mNetwork = network; mExecutor = Executors.newSingleThreadExecutor(); mCallback = new ISocketKeepaliveCallback.Stub() { @@ -2214,7 +2215,9 @@ public class ConnectivityManager { */ public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) { INetworkActivityListener rl = mNetworkActivityListeners.get(l); - Preconditions.checkArgument(rl != null, "Listener was not registered."); + if (rl == null) { + throw new IllegalArgumentException("Listener was not registered."); + } try { mService.registerNetworkActivityListener(rl); } catch (RemoteException e) { @@ -2242,8 +2245,8 @@ public class ConnectivityManager { * {@hide} */ public ConnectivityManager(Context context, IConnectivityManager service) { - mContext = Preconditions.checkNotNull(context, "missing context"); - mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mContext = Objects.requireNonNull(context, "missing context"); + mService = Objects.requireNonNull(service, "missing IConnectivityManager"); mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); sInstance = this; } @@ -2510,7 +2513,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { - Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); + Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null."); final Executor executor = new Executor() { @Override @@ -2603,7 +2606,7 @@ public class ConnectivityManager { public void registerTetheringEventCallback( @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEventCallback callback) { - Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); + Objects.requireNonNull(callback, "OnTetheringEventCallback cannot be null."); final TetheringEventCallback tetherCallback = new TetheringEventCallback() { @@ -2901,7 +2904,7 @@ public class ConnectivityManager { public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEntitlementResultListener listener) { - Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null."); + Objects.requireNonNull(listener, "TetheringEntitlementResultListener cannot be null."); ResultReceiver wrappedListener = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -3525,7 +3528,7 @@ public class ConnectivityManager { } CallbackHandler(Handler handler) { - this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper()); + this(Objects.requireNonNull(handler, "Handler cannot be null.").getLooper()); } @Override @@ -3623,9 +3626,9 @@ public class ConnectivityManager { int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { printStackTrace(); checkCallbackNotNull(callback); - Preconditions.checkArgument( - reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null, - "null NetworkCapabilities"); + if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) { + throw new IllegalArgumentException("null NetworkCapabilities"); + } final NetworkRequest request; final String callingPackageName = mContext.getOpPackageName(); try { @@ -3971,15 +3974,17 @@ public class ConnectivityManager { } private static void checkPendingIntentNotNull(PendingIntent intent) { - Preconditions.checkNotNull(intent, "PendingIntent cannot be null."); + Objects.requireNonNull(intent, "PendingIntent cannot be null."); } private static void checkCallbackNotNull(NetworkCallback callback) { - Preconditions.checkNotNull(callback, "null NetworkCallback"); + Objects.requireNonNull(callback, "null NetworkCallback"); } private static void checkTimeout(int timeoutMs) { - Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive."); + if (timeoutMs <= 0) { + throw new IllegalArgumentException("timeoutMs must be strictly positive."); + } } /** @@ -4229,8 +4234,9 @@ public class ConnectivityManager { // Find all requests associated to this callback and stop callback triggers immediately. // Callback is reusable immediately. http://b/20701525, http://b/35921499. synchronized (sCallbacks) { - Preconditions.checkArgument(networkCallback.networkRequest != null, - "NetworkCallback was not registered"); + if (networkCallback.networkRequest == null) { + throw new IllegalArgumentException("NetworkCallback was not registered"); + } if (networkCallback.networkRequest == ALREADY_UNREGISTERED) { Log.d(TAG, "NetworkCallback was already unregistered"); return; diff --git a/framework/src/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java index c83c23a4b6..26a504a29c 100644 --- a/framework/src/android/net/MacAddress.java +++ b/framework/src/android/net/MacAddress.java @@ -25,7 +25,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; @@ -34,6 +33,7 @@ import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Arrays; +import java.util.Objects; /** * Representation of a MAC address. @@ -229,7 +229,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static @NonNull byte[] byteAddrFromStringAddr(String addr) { - Preconditions.checkNotNull(addr); + Objects.requireNonNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -275,7 +275,7 @@ public final class MacAddress implements Parcelable { // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) // that avoids the allocation of an intermediary byte[]. private static long longAddrFromStringAddr(String addr) { - Preconditions.checkNotNull(addr); + Objects.requireNonNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -364,8 +364,8 @@ public final class MacAddress implements Parcelable { * */ public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) { - Preconditions.checkNotNull(baseAddress); - Preconditions.checkNotNull(mask); + Objects.requireNonNull(baseAddress); + Objects.requireNonNull(mask); return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index c82cd3b4f3..7a693444e6 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -34,7 +34,6 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; @@ -2073,8 +2072,9 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidTransportType(@Transport int transport) { - Preconditions.checkArgument( - isValidTransport(transport), "Invalid TransportType " + transport); + if (!isValidTransport(transport)) { + throw new IllegalArgumentException("Invalid TransportType " + transport); + } } private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { @@ -2082,8 +2082,9 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { - Preconditions.checkArgument(isValidCapability(capability), - "NetworkCapability " + capability + "out of range"); + if (!isValidCapability(capability)) { + throw new IllegalArgumentException("NetworkCapability " + capability + "out of range"); + } } /** diff --git a/framework/src/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java index ce545974f5..7904f7a4ec 100644 --- a/framework/src/android/net/StaticIpConfiguration.java +++ b/framework/src/android/net/StaticIpConfiguration.java @@ -24,7 +24,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; import com.android.net.module.util.InetAddressUtils; import java.net.InetAddress; @@ -153,7 +152,7 @@ public final class StaticIpConfiguration implements Parcelable { * @return The {@link Builder} for chaining. */ public @NonNull Builder setDnsServers(@NonNull Iterable dnsServers) { - Preconditions.checkNotNull(dnsServers); + Objects.requireNonNull(dnsServers); mDnsServers = dnsServers; return this; } diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java index a174a7be85..a7a62351e5 100644 --- a/framework/src/android/net/TestNetworkManager.java +++ b/framework/src/android/net/TestNetworkManager.java @@ -21,10 +21,9 @@ import android.annotation.SystemApi; import android.os.IBinder; import android.os.RemoteException; -import com.android.internal.util.Preconditions; - import java.util.Arrays; import java.util.Collection; +import java.util.Objects; /** * Class that allows creation and management of per-app, test-only networks @@ -50,7 +49,7 @@ public class TestNetworkManager { /** @hide */ public TestNetworkManager(@NonNull ITestNetworkManager service) { - mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager"); + mService = Objects.requireNonNull(service, "missing ITestNetworkManager"); } /** @@ -93,7 +92,7 @@ public class TestNetworkManager { */ public void setupTestNetwork( @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { - Preconditions.checkNotNull(lp, "Invalid LinkProperties"); + Objects.requireNonNull(lp, "Invalid LinkProperties"); setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); } From c7bf00636e2e39110497ac09dcb09ef216aa1b1e Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 21:01:30 +0900 Subject: [PATCH 091/343] Remove Slog usage in NetworkState Slog should not be used in unbundled jars as it is a hidden API; use the standard Log utility instead. Bug: 172050541 Test: m Change-Id: I54b2b99b2aedbb5194e9ec24068d2f2ce46d67fc --- framework/src/android/net/NetworkState.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/android/net/NetworkState.java b/framework/src/android/net/NetworkState.java index d01026566c..9b69674728 100644 --- a/framework/src/android/net/NetworkState.java +++ b/framework/src/android/net/NetworkState.java @@ -22,7 +22,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import android.util.Slog; +import android.util.Log; /** * Snapshot of network state. @@ -83,7 +83,7 @@ public class NetworkState implements Parcelable { if (VALIDATE_ROAMING_STATE && networkInfo != null && networkCapabilities != null) { if (networkInfo.isRoaming() == networkCapabilities .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) { - Slog.wtf("NetworkState", "Roaming state disagreement between " + networkInfo + Log.wtf("NetworkState", "Roaming state disagreement between " + networkInfo + " and " + networkCapabilities); } } From 5a5c99b84e1c3af1e710684f75919c39b4198343 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 5 Mar 2021 15:51:17 +0800 Subject: [PATCH 092/343] [VCN10] Add new API to listen for highest score network Test: atest ConnectivityServiceTest#testRegisterBestMatchingNetworkCallback Bug: 175662146 Change-Id: Ifa411c7b53da789c74fff7e1a95f9c9ebf5bd05c --- framework/src/android/net/ConnectivityManager.java | 13 +++++++++++++ framework/src/android/net/NetworkRequest.java | 5 +++++ 2 files changed, 18 insertions(+) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 45ed3179d7..3d1da91cf3 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -20,6 +20,7 @@ import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.REQUEST; +import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; @@ -4189,6 +4190,18 @@ public class ConnectivityManager { TRACK_SYSTEM_DEFAULT, TYPE_NONE, cbHandler); } + /** + * @hide + */ + // TODO: Make it public api. + @SuppressLint("ExecutorRegistration") + public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, + @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { + final NetworkCapabilities nc = request.networkCapabilities; + final CallbackHandler cbHandler = new CallbackHandler(handler); + sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler); + } + /** * Requests bandwidth update for a given {@link Network} and returns whether the update request * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index b4a651c060..59b539af39 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -113,6 +113,10 @@ public class NetworkRequest implements Parcelable { * for the network (if any) that satisfies the default Internet * request. * + * - TRACK_BEST, which causes the framework to send callbacks about + * the single, highest scoring current network (if any) that matches + * the specified NetworkCapabilities. + * * - BACKGROUND_REQUEST, like REQUEST but does not cause any networks * to retain the NET_CAPABILITY_FOREGROUND capability. A network with * no foreground requests is in the background. A network that has @@ -135,6 +139,7 @@ public class NetworkRequest implements Parcelable { REQUEST, BACKGROUND_REQUEST, TRACK_SYSTEM_DEFAULT, + TRACK_BEST, }; /** From dbb7046923f7a3752242e98800dc3574adaf8265 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 9 Mar 2021 20:49:48 +0800 Subject: [PATCH 093/343] [VCN11] Make requestBackgroundNetwork requires handler Test: atest FrameworksNetTests android.net.cts.ConnectivityManagerTest Bug: 175662146 Change-Id: Iac9487e8de8bfdd87fc7a0153b228ae2a7ba4e19 --- framework/api/module-lib-current.txt | 2 +- framework/src/android/net/ConnectivityManager.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index d2ed73ef82..65a44f05cc 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -8,7 +8,7 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); - method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); } diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 3d1da91cf3..adf22da5be 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4992,10 +4992,10 @@ public class ConnectivityManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK }) public void requestBackgroundNetwork(@NonNull NetworkRequest request, - @Nullable Handler handler, @NonNull NetworkCallback networkCallback) { + @NonNull Handler handler, @NonNull NetworkCallback networkCallback) { final NetworkCapabilities nc = request.networkCapabilities; sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST, - TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler)); + TYPE_NONE, new CallbackHandler(handler)); } /** From ea33ac97f6ddc3d8350b4bdf030354c02309ce03 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 14:20:19 +0900 Subject: [PATCH 094/343] Add Ethernet, TestNetworkSpecifier API Rename StringNetworkSpecifier to EthernetNetworkSpecifier (its only production user), and make it module-lib API. The original StringNetworkSpecifier file is actually kept to satisfy some invalid dependencies; it will be removed separately. This allows specifying an Ethernet interface with a non-deprecated API: until this change the only way to do so would be to use NetworkRequest#setSpecifier(String), which is deprecated. Similarly, add the TestNetworkSpecifier API for TestNetworkManager, to replace previous usage of StringNetworkSpecifier. TestNetworkManager is module API, so TestNetworkSpecifier should be module API too. This allows tests to request the test interface specifically, without using the deprecated NetworkRequest#setSpecifier(String). Bug: 179329291 Test: m Merged-In: Iee569f5c8bbdc4bc979610e1191308281f3d4620 Change-Id: Iee569f5c8bbdc4bc979610e1191308281f3d4620 --- framework/api/module-lib-current.txt | 8 ++ framework/src/android/net/NetworkRequest.java | 17 +++- .../src/android/net/TestNetworkSpecifier.java | 97 +++++++++++++++++++ 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 framework/src/android/net/TestNetworkSpecifier.java diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index d2ed73ef82..6df57c1323 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -51,6 +51,14 @@ package android.net { field public static final String TEST_TAP_PREFIX = "testtap"; } + public final class TestNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { + ctor public TestNetworkSpecifier(@NonNull String); + method public int describeContents(); + method @Nullable public String getInterfaceName(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { ctor public VpnTransportInfo(int); method public int describeContents(); diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index b4a651c060..17a8ee1720 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -31,6 +31,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVIT import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; @@ -382,11 +383,17 @@ public class NetworkRequest implements Parcelable { return setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder() .setSubscriptionId(subId).build()); } catch (NumberFormatException nfe) { - // A StringNetworkSpecifier does not accept null or empty ("") strings. When network - // specifiers were strings a null string and an empty string were considered - // equivalent. Hence no meaning is attached to a null or empty ("") string. - return setNetworkSpecifier(TextUtils.isEmpty(networkSpecifier) ? null - : new StringNetworkSpecifier(networkSpecifier)); + // An EthernetNetworkSpecifier or TestNetworkSpecifier does not accept null or empty + // ("") strings. When network specifiers were strings a null string and an empty + // string were considered equivalent. Hence no meaning is attached to a null or + // empty ("") string. + if (TextUtils.isEmpty(networkSpecifier)) { + return setNetworkSpecifier((NetworkSpecifier) null); + } else if (mNetworkCapabilities.hasTransport(TRANSPORT_TEST)) { + return setNetworkSpecifier(new TestNetworkSpecifier(networkSpecifier)); + } else { + return setNetworkSpecifier(new EthernetNetworkSpecifier(networkSpecifier)); + } } } diff --git a/framework/src/android/net/TestNetworkSpecifier.java b/framework/src/android/net/TestNetworkSpecifier.java new file mode 100644 index 0000000000..b7470a591d --- /dev/null +++ b/framework/src/android/net/TestNetworkSpecifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A {@link NetworkSpecifier} used to identify test interfaces. + * + * @see TestNetworkManager + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class TestNetworkSpecifier extends NetworkSpecifier implements Parcelable { + + /** + * Name of the network interface. + */ + @NonNull + private final String mInterfaceName; + + public TestNetworkSpecifier(@NonNull String interfaceName) { + Preconditions.checkStringNotEmpty(interfaceName); + mInterfaceName = interfaceName; + } + + // This may be null in the future to support specifiers based on data other than the interface + // name. + @Nullable + public String getInterfaceName() { + return mInterfaceName; + } + + @Override + public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof TestNetworkSpecifier)) return false; + return TextUtils.equals(mInterfaceName, ((TestNetworkSpecifier) o).mInterfaceName); + } + + @Override + public int hashCode() { + return Objects.hashCode(mInterfaceName); + } + + @Override + public String toString() { + return "TestNetworkSpecifier (" + mInterfaceName + ")"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInterfaceName); + } + + public static final @NonNull Creator CREATOR = + new Creator() { + public TestNetworkSpecifier createFromParcel(Parcel in) { + return new TestNetworkSpecifier(in.readString()); + } + public TestNetworkSpecifier[] newArray(int size) { + return new TestNetworkSpecifier[size]; + } + }; +} From 697b459ad9e4347ea02ba1fa74c6b7484c2f38d0 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 24 Dec 2020 19:14:36 +0800 Subject: [PATCH 095/343] [VCN04] Add Subscription Id set into NetworkCapabilities This is a generic way to request networks that has different subId but belongs to the same carrier. For example, cellular networks with different SIM card, or carrier Wifi that provided by the operator. Test: atest NetworkCapabilitiesTest#testSubIds Test: m doc-comment-check-docs -j Test: atest CtsNetTestCases Bug: 175662146 Change-Id: Ifca766f5acc73c285948d6251ec31506d9bb0bcb --- .../src/android/net/NetworkCapabilities.java | 101 +++++++++++++++++- framework/src/android/net/NetworkRequest.java | 17 +++ 2 files changed, 113 insertions(+), 5 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index c82cd3b4f3..73fbd614cb 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -131,6 +131,7 @@ public final class NetworkCapabilities implements Parcelable { mPrivateDnsBroken = false; mRequestorUid = Process.INVALID_UID; mRequestorPackageName = null; + mSubIds = new ArraySet<>(); } /** @@ -159,6 +160,7 @@ public final class NetworkCapabilities implements Parcelable { mPrivateDnsBroken = nc.mPrivateDnsBroken; mRequestorUid = nc.mRequestorUid; mRequestorPackageName = nc.mRequestorPackageName; + mSubIds = new ArraySet<>(nc.mSubIds); } /** @@ -1655,6 +1657,7 @@ public final class NetworkCapabilities implements Parcelable { combineSSIDs(nc); combineRequestor(nc); combineAdministratorUids(nc); + combineSubIds(nc); } /** @@ -1674,8 +1677,9 @@ public final class NetworkCapabilities implements Parcelable { && satisfiedBySpecifier(nc) && (onlyImmutable || satisfiedBySignalStrength(nc)) && (onlyImmutable || satisfiedByUids(nc)) - && (onlyImmutable || satisfiedBySSID(nc))) - && (onlyImmutable || satisfiedByRequestor(nc)); + && (onlyImmutable || satisfiedBySSID(nc)) + && (onlyImmutable || satisfiedByRequestor(nc)) + && (onlyImmutable || satisfiedBySubIds(nc))); } /** @@ -1771,7 +1775,8 @@ public final class NetworkCapabilities implements Parcelable { && equalsOwnerUid(that) && equalsPrivateDnsBroken(that) && equalsRequestor(that) - && equalsAdministratorUids(that); + && equalsAdministratorUids(that) + && equalsSubIds(that); } @Override @@ -1793,7 +1798,8 @@ public final class NetworkCapabilities implements Parcelable { + Objects.hashCode(mPrivateDnsBroken) * 47 + Objects.hashCode(mRequestorUid) * 53 + Objects.hashCode(mRequestorPackageName) * 59 - + Arrays.hashCode(mAdministratorUids) * 61; + + Arrays.hashCode(mAdministratorUids) * 61 + + Objects.hashCode(mSubIds) * 67; } @Override @@ -1827,6 +1833,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeInt(mOwnerUid); dest.writeInt(mRequestorUid); dest.writeString(mRequestorPackageName); + dest.writeIntArray(CollectionUtils.toIntArray(mSubIds)); } public static final @android.annotation.NonNull Creator CREATOR = @@ -1850,6 +1857,11 @@ public final class NetworkCapabilities implements Parcelable { netCap.mOwnerUid = in.readInt(); netCap.mRequestorUid = in.readInt(); netCap.mRequestorPackageName = in.readString(); + netCap.mSubIds = new ArraySet<>(); + final int[] subIdInts = Objects.requireNonNull(in.createIntArray()); + for (int i = 0; i < subIdInts.length; i++) { + netCap.mSubIds.add(subIdInts[i]); + } return netCap; } @Override @@ -1933,11 +1945,14 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" SSID: ").append(mSSID); } - if (mPrivateDnsBroken) { sb.append(" PrivateDnsBroken"); } + if (!mSubIds.isEmpty()) { + sb.append(" SubscriptionIds: ").append(mSubIds); + } + sb.append("]"); return sb.toString(); } @@ -2250,6 +2265,68 @@ public final class NetworkCapabilities implements Parcelable { && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); } + /** + * Set of the subscription IDs that identifies the network or request, empty if none. + */ + @NonNull + private ArraySet mSubIds = new ArraySet<>(); + + /** + * Sets the subscription ID set that associated to this network or request. + * + * @hide + */ + @NonNull + public NetworkCapabilities setSubIds(@NonNull Set subIds) { + mSubIds = new ArraySet(Objects.requireNonNull(subIds)); + return this; + } + + /** + * Gets the subscription ID set that associated to this network or request. + * @hide + * @return + */ + @NonNull + public Set getSubIds() { + return new ArraySet<>(mSubIds); + } + + /** + * Tests if the subscription ID set of this network is the same as that of the passed one. + */ + private boolean equalsSubIds(@NonNull NetworkCapabilities nc) { + return Objects.equals(mSubIds, nc.mSubIds); + } + + /** + * Check if the subscription ID set requirements of this object are matched by the passed one. + * If specified in the request, the passed one need to have at least one subId and at least + * one of them needs to be in the request set. + */ + private boolean satisfiedBySubIds(@NonNull NetworkCapabilities nc) { + if (mSubIds.isEmpty()) return true; + if (nc.mSubIds.isEmpty()) return false; + for (final Integer subId : nc.mSubIds) { + if (mSubIds.contains(subId)) return true; + } + return false; + } + + /** + * Combine subscription ID set of the capabilities. + * + *

    This is only legal if the subscription Ids are equal. + * + *

    If both subscription IDs are not equal, they belong to different subscription + * (or no subscription). In this case, it would not make sense to add them together. + */ + private void combineSubIds(@NonNull NetworkCapabilities nc) { + if (!Objects.equals(mSubIds, nc.mSubIds)) { + throw new IllegalStateException("Can't combine two subscription ID sets"); + } + } + /** * Builder class for NetworkCapabilities. * @@ -2555,6 +2632,20 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Set the subscription ID set. + * + * @param subIds a set that represent the subscription IDs. Empty if clean up. + * @return this builder. + * + * @hide + */ + @NonNull + public Builder setSubIds(@NonNull final Set subIds) { + mCaps.setSubIds(subIds); + return this; + } + /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 17a8ee1720..65ca1b2f7d 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -456,6 +456,23 @@ public class NetworkRequest implements Parcelable { } nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED); } + + /** + * Sets the optional subscription ID set. + *

    + * This specify the subscription IDs requirement. + * A network will satisfy this request only if it matches one of the subIds in this set. + * An empty set matches all networks, including those without a subId. + * + * @param subIds A {@code Set} that represents subscription IDs. + * + * @hide + */ + @NonNull + public Builder setSubIds(@NonNull Set subIds) { + mNetworkCapabilities.setSubIds(subIds); + return this; + } } // implement the Parcelable interface From e1b65bdbfe4aef6b4367d9a5c3346eadb4a105c7 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 11 Mar 2021 20:20:19 +0800 Subject: [PATCH 096/343] [VCN12] Expose setSubIds/getSubIds APIs Test: atest NetworkCapabilitiesTest Bug: 175662146 Change-Id: Ia4b98bc6c5fcefee44233f3b7fbb6517a0e8870e --- framework/api/current.txt | 2 ++ framework/api/system-current.txt | 1 + framework/src/android/net/NetworkCapabilities.java | 3 --- framework/src/android/net/NetworkRequest.java | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index a8f1a4d2a7..61ffaca5df 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -293,6 +293,7 @@ package android.net { method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); method public int getOwnerUid(); method public int getSignalStrength(); + method @NonNull public java.util.Set getSubIds(); method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); method public boolean hasTransport(int); @@ -399,6 +400,7 @@ package android.net { method public android.net.NetworkRequest.Builder removeTransportType(int); method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String); method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); + method @NonNull public android.net.NetworkRequest.Builder setSubIds(@NonNull java.util.Set); } public class ProxyInfo implements android.os.Parcelable { diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index a732430e6a..a98f14ea94 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -296,6 +296,7 @@ package android.net { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setSubIds(@NonNull java.util.Set); method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 73fbd614cb..4e1fd1c8a7 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -2284,7 +2284,6 @@ public final class NetworkCapabilities implements Parcelable { /** * Gets the subscription ID set that associated to this network or request. - * @hide * @return */ @NonNull @@ -2637,8 +2636,6 @@ public final class NetworkCapabilities implements Parcelable { * * @param subIds a set that represent the subscription IDs. Empty if clean up. * @return this builder. - * - * @hide */ @NonNull public Builder setSubIds(@NonNull final Set subIds) { diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 65ca1b2f7d..960d967275 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -465,8 +465,6 @@ public class NetworkRequest implements Parcelable { * An empty set matches all networks, including those without a subId. * * @param subIds A {@code Set} that represents subscription IDs. - * - * @hide */ @NonNull public Builder setSubIds(@NonNull Set subIds) { From 5cdbcfb7faffa474689a23eeb28cf3bf2e5c52fb Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 12 Mar 2021 00:46:33 +0800 Subject: [PATCH 097/343] Add a new API to get the network ID range of IPSec tunnel interface - Add a new API to get the network ID range of IPSec tunnel interface. - Use the new API in IpSecServiceTest to make sure the result is the same. Follow-up commit will change the logic in IpSecService#reserveNetId(), the modified test can ensure the correctness of the new change. Bug: 172183305 Test: atest FrameworksNetTests:IpSecServiceTest Change-Id: Ic605e48941fc9d6482cdcd01a8adcdc9b6d586a6 --- framework/api/module-lib-current.txt | 1 + .../src/android/net/ConnectivityManager.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index d2ed73ef82..a55ed6f113 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -7,6 +7,7 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); + method @NonNull public static android.util.Range getIpSecNetIdRange(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 45ed3179d7..a2fcdd64a0 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5040,4 +5040,21 @@ public class ConnectivityManager { throw e.rethrowFromSystemServer(); } } + + // The first network ID of IPSec tunnel interface. + private static final int TUN_INTF_NETID_START = 0xFC00; + // The network ID range of IPSec tunnel interface. + private static final int TUN_INTF_NETID_RANGE = 0x0400; + + /** + * Get the network ID range reserved for IPSec tunnel interfaces. + * + * @return A Range which indicates the network ID range of IPSec tunnel interface. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @NonNull + public static Range getIpSecNetIdRange() { + return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1); + } } From 686d5d2c3dd56f56326b02e09ee1ac90f44c9fda Mon Sep 17 00:00:00 2001 From: Daniel Bright Date: Wed, 10 Mar 2021 11:51:50 -0800 Subject: [PATCH 098/343] Swap parameters in QosCallback#registerQosCallback Bug: 181551395 Test: unit tests Change-Id: I9f3f7e7a1bbb19629a2607b82ce316768c4143df --- framework/api/system-current.txt | 2 +- framework/src/android/net/ConnectivityManager.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index a732430e6a..39b9c7d031 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -52,7 +52,7 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported(); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull android.net.NetworkProvider); - method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull android.net.QosCallback, @NonNull java.util.concurrent.Executor); + method public void registerQosCallback(@NonNull android.net.QosSocketInfo, @NonNull java.util.concurrent.Executor, @NonNull android.net.QosCallback); method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index a6dc9ce051..34d95c7978 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4804,20 +4804,20 @@ public class ConnectivityManager { * {@link QosCallback#onError(QosCallbackException)}. see: {@link QosCallbackException}. * * @param socketInfo the socket information used to match QoS events - * @param callback receives qos events that satisfy socketInfo * @param executor The executor on which the callback will be invoked. The provided * {@link Executor} must run callback sequentially, otherwise the order of - * callbacks cannot be guaranteed. + * callbacks cannot be guaranteed.onQosCallbackRegistered + * @param callback receives qos events that satisfy socketInfo * * @hide */ @SystemApi public void registerQosCallback(@NonNull final QosSocketInfo socketInfo, - @NonNull final QosCallback callback, - @CallbackExecutor @NonNull final Executor executor) { + @CallbackExecutor @NonNull final Executor executor, + @NonNull final QosCallback callback) { Objects.requireNonNull(socketInfo, "socketInfo must be non-null"); - Objects.requireNonNull(callback, "callback must be non-null"); Objects.requireNonNull(executor, "executor must be non-null"); + Objects.requireNonNull(callback, "callback must be non-null"); try { synchronized (mQosCallbackConnections) { From e08bc1803cd04936aa8933d467a05066c432a2ed Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 22 Dec 2020 15:10:42 -0800 Subject: [PATCH 099/343] ConnectivityManager: Provide API's to include location sensitive info Existing NetworkCallback users will get NetworkCapabilities with location sensitive data removed (except for ownerUid which will be added for existing apps for backwards compatibility). Apps have to opt-in to receive location sensitive data. Note: This was chosen because WifiInfo is the only TransportInfo tha has location sensitive info & that was added only in Android 12. If we choose to default to true, all existings apps retrieving NetworkCapabilities for wifi networks will be blamed for location access unnecessarily. Changes: i) Add a flag in NetworkCallback creation to retrieve NetworkCapabilities with location sensitive info in their callback. (More flags are being planned for NetworkCallback for throttling callback frequency, etc) ii) For NetworkCapabilities.getOwnerUid(), we will continue to send the data for apps targeting older SDK (since this is an existing field and the new flag defaults location sensitive data to off). Bug: 156867433 Test: atest android.net Test: atest com.android.server Change-Id: If70b5ea6f5c8885f0c353c8df08a826d55fe7f7a --- framework/api/current.txt | 2 + .../src/android/net/ConnectivityManager.java | 83 ++++++++++++++++--- .../src/android/net/IConnectivityManager.aidl | 4 +- .../src/android/net/NetworkCapabilities.java | 11 +++ 4 files changed, 86 insertions(+), 14 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index a8f1a4d2a7..8a7ed47286 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -143,6 +143,7 @@ package android.net { public static class ConnectivityManager.NetworkCallback { ctor public ConnectivityManager.NetworkCallback(); + ctor public ConnectivityManager.NetworkCallback(int); method public void onAvailable(@NonNull android.net.Network); method public void onBlockedStatusChanged(@NonNull android.net.Network, boolean); method public void onCapabilitiesChanged(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities); @@ -150,6 +151,7 @@ package android.net { method public void onLosing(@NonNull android.net.Network, int); method public void onLost(@NonNull android.net.Network); method public void onUnavailable(); + field public static final int FLAG_INCLUDE_LOCATION_INFO = 1; // 0x1 } public static interface ConnectivityManager.OnNetworkActiveListener { diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index adf22da5be..c160d82375 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -44,6 +44,7 @@ import android.net.SocketKeepalive.Callback; import android.net.TetheringManager.StartTetheringCallback; import android.net.TetheringManager.TetheringEventCallback; import android.net.TetheringManager.TetheringRequest; +import android.net.wifi.WifiNetworkSuggestion; import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; @@ -1315,7 +1316,7 @@ public class ConnectivityManager { } /** - * Returns an array of {@link android.net.NetworkCapabilities} objects, representing + * Returns an array of {@link NetworkCapabilities} objects, representing * the Networks that applications run by the given user will use by default. * @hide */ @@ -1395,11 +1396,19 @@ public class ConnectivityManager { } /** - * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This + * Get the {@link NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. * + * This will remove any location sensitive data in {@link TransportInfo} embedded in + * {@link NetworkCapabilities#getTransportInfo()}. Some transport info instances like + * {@link android.net.wifi.WifiInfo} contain location sensitive information. Retrieving + * this location sensitive information (subject to app's location permissions) will be + * noted by system. To include any location sensitive data in {@link TransportInfo}, + * use a {@link NetworkCallback} with + * {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} flag. + * * @param network The {@link Network} object identifying the network in question. - * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. + * @return The {@link NetworkCapabilities} for the network, or {@code null}. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable @@ -3244,6 +3253,54 @@ public class ConnectivityManager { * A {@code NetworkCallback} that has been unregistered can be registered again. */ public static class NetworkCallback { + /** + * No flags associated with this callback. + * @hide + */ + public static final int FLAG_NONE = 0; + /** + * Use this flag to include any location sensitive data in {@link NetworkCapabilities} sent + * via {@link #onCapabilitiesChanged(Network, NetworkCapabilities)}. + *

    + * These include: + *

  9. Some transport info instances (retrieved via + * {@link NetworkCapabilities#getTransportInfo()}) like {@link android.net.wifi.WifiInfo} + * contain location sensitive information. + *
  10. OwnerUid (retrieved via {@link NetworkCapabilities#getOwnerUid()} is location + * sensitive for wifi suggestor apps (i.e using {@link WifiNetworkSuggestion}).
  11. + *

    + *

    + * Note: + *

  12. Retrieving this location sensitive information (subject to app's location + * permissions) will be noted by system.
  13. + *
  14. Without this flag any {@link NetworkCapabilities} provided via the callback does + * not include location sensitive info. + *

    + */ + public static final int FLAG_INCLUDE_LOCATION_INFO = 1 << 0; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "FLAG_", value = { + FLAG_NONE, + FLAG_INCLUDE_LOCATION_INFO + }) + public @interface Flag { } + + /** + * All the valid flags for error checking. + */ + private static final int VALID_FLAGS = FLAG_INCLUDE_LOCATION_INFO; + + public NetworkCallback() { + this(FLAG_NONE); + } + + public NetworkCallback(@Flag int flags) { + Preconditions.checkArgument((flags & VALID_FLAGS) == flags); + mFlags = flags; + } + /** * Called when the framework connects to a new network to evaluate whether it satisfies this * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable} @@ -3381,7 +3438,7 @@ public class ConnectivityManager { * calling these methods while in a callback may return an outdated or even a null object. * * @param network The {@link Network} whose capabilities have changed. - * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this + * @param networkCapabilities The new {@link NetworkCapabilities} for this * network. */ public void onCapabilitiesChanged(@NonNull Network network, @@ -3450,6 +3507,7 @@ public class ConnectivityManager { public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {} private NetworkRequest networkRequest; + private final int mFlags; } /** @@ -3639,14 +3697,15 @@ public class ConnectivityManager { } Messenger messenger = new Messenger(handler); Binder binder = new Binder(); + final int callbackFlags = callback.mFlags; if (reqType == LISTEN) { request = mService.listenForNetwork( - need, messenger, binder, callingPackageName, + need, messenger, binder, callbackFlags, callingPackageName, getAttributionTag()); } else { request = mService.requestNetwork( need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType, - callingPackageName, getAttributionTag()); + callbackFlags, callingPackageName, getAttributionTag()); } if (request != null) { sCallbacks.put(request, callback); @@ -3693,7 +3752,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * *

    This method will attempt to find the best network that matches the passed * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the @@ -3777,7 +3836,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * This method behaves identically to {@link #requestNetwork(NetworkRequest, NetworkCallback)} * but runs all the callbacks on the passed Handler. @@ -3799,7 +3858,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link NetworkCapabilities}, limited * by a timeout. * * This function behaves identically to the non-timed-out version @@ -3834,7 +3893,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link NetworkCapabilities}, limited * by a timeout. * * This method behaves identically to @@ -3879,7 +3938,7 @@ public class ConnectivityManager { /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. + * Request a network to satisfy a set of {@link NetworkCapabilities}. * * This function behaves identically to the version that takes a NetworkCallback, but instead * of {@link NetworkCallback} a {@link PendingIntent} is used. This means @@ -4911,7 +4970,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, but + * Request a network to satisfy a set of {@link NetworkCapabilities}, but * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can * be used to request that the system provide a network without causing the network to be * in the foreground. diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index cd49258d1c..f9393e315b 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -143,7 +143,7 @@ interface IConnectivityManager NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, - String callingPackageName, String callingAttributionTag); + int callbackFlags, String callingPackageName, String callingAttributionTag); NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, in PendingIntent operation, String callingPackageName, String callingAttributionTag); @@ -151,7 +151,7 @@ interface IConnectivityManager void releasePendingNetworkRequest(in PendingIntent operation); NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, in IBinder binder, String callingPackageName, + in Messenger messenger, in IBinder binder, int callbackFlags, String callingPackageName, String callingAttributionTag); void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index c82cd3b4f3..7fe4794745 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -25,6 +25,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; +import android.net.wifi.WifiNetworkSuggestion; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -1048,6 +1049,16 @@ public final class NetworkCapabilities implements Parcelable { * * Instances of NetworkCapabilities sent to apps without the appropriate permissions will have * this field cleared out. + * + *

    + * This field will only be populated for VPN and wifi network suggestor apps (i.e using + * {@link WifiNetworkSuggestion}), and only for the network they own. + * In the case of wifi network suggestors apps, this field is also location sensitive, so the + * app needs to hold {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. If the + * app targets SDK version greater than or equal to {@link Build.VERSION_CODES#S}, then they + * also need to use {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} to get the info in their + * callback. The app will be blamed for location access if this field is included. + *

    */ public int getOwnerUid() { return mOwnerUid; From 907ebd4f90df2aa9ffc0044de5a777361c01f86b Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 8 Mar 2021 22:05:03 +0900 Subject: [PATCH 100/343] Create ServiceConnectivityResources Create the ServiceConnectivityResources package, which contains resources Connectivity unbundled from platform resources. Migrate the first few resources from ConnectivityService that have no RRO in AOSP. To avoid boot time impact, avoid loading the resources in the ConnectivityService constructor. Bug: 182125649 Test: atest FrameworksNetTests Merged-In: I77ac6f4303c54acc96f16e18ef02add30298ff3d Change-Id: I77ac6f4303c54acc96f16e18ef02add30298ff3d --- service/Android.bp | 1 + .../ServiceConnectivityResources/Android.bp | 35 +++++++++++++++ .../AndroidManifest.xml | 37 +++++++++++++++ .../res/values/config.xml | 45 +++++++++++++++++++ .../res/values/overlayable.xml | 27 +++++++++++ .../res/values/strings.xml | 22 +++++++++ 6 files changed, 167 insertions(+) create mode 100644 service/ServiceConnectivityResources/Android.bp create mode 100644 service/ServiceConnectivityResources/AndroidManifest.xml create mode 100644 service/ServiceConnectivityResources/res/values/config.xml create mode 100644 service/ServiceConnectivityResources/res/values/overlayable.xml create mode 100644 service/ServiceConnectivityResources/res/values/strings.xml diff --git a/service/Android.bp b/service/Android.bp index e65b7b423b..5392f8451a 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -61,6 +61,7 @@ java_library { "services.core", "services.net", "unsupportedappusage", + "ServiceConnectivityResources", ], static_libs: [ "modules-utils-os", diff --git a/service/ServiceConnectivityResources/Android.bp b/service/ServiceConnectivityResources/Android.bp new file mode 100644 index 0000000000..f2446b7f7e --- /dev/null +++ b/service/ServiceConnectivityResources/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// APK to hold all the wifi overlayable resources. +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_app { + name: "ServiceConnectivityResources", + sdk_version: "system_current", + resource_dirs: [ + "res", + ], + privileged: true, + export_package_resources: true, + apex_available: [ + "com.android.tethering", + ], + // TODO: use a dedicated cert once generated + certificate: "platform", +} diff --git a/service/ServiceConnectivityResources/AndroidManifest.xml b/service/ServiceConnectivityResources/AndroidManifest.xml new file mode 100644 index 0000000000..2c30302615 --- /dev/null +++ b/service/ServiceConnectivityResources/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml new file mode 100644 index 0000000000..7d98c76a40 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + 60000 + + + + + + + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml new file mode 100644 index 0000000000..00ec2df0e6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/service/ServiceConnectivityResources/res/values/strings.xml b/service/ServiceConnectivityResources/res/values/strings.xml new file mode 100644 index 0000000000..2c7b992650 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values/strings.xml @@ -0,0 +1,22 @@ + + + + + System Connectivity Resources + \ No newline at end of file From 180f44f0f27fb486a9b3774c37b5f0beafbc951b Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 12 Mar 2021 16:11:27 +0800 Subject: [PATCH 101/343] Have a new API to get private DNS mode - Expose PRIVATE_DNS_MODE_OFF, PRIVATE_DNS_MODE_OPPORTUNISTIC and PRIVATE_DNS_MODE_PROVIDER_HOSTNAME for external users. - Since PRIVATE_DNS_DEFAULT_MODE_FALLBACK might be changed from release to release, so it cannot be exposed as a system API. Remove PRIVATE_DNS_DEFAULT_MODE_FALLBACK and have a new API - getPrivateDnsMode() for users to get the private DNS mode instead. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCases Test: atest com.android.cts.devicepolicy.DeviceOwnerTest#testPrivateDnsPolicy Change-Id: I02a1e91b4eafb5f5df3eada1c07b99849a050c3c --- framework/api/module-lib-current.txt | 4 ++ .../src/android/net/ConnectivityManager.java | 46 +++++++++++++++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 4b3336644e..a04571496c 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -8,9 +8,13 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); method @NonNull public static android.util.Range getIpSecNetIdRange(); + method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + field public static final String PRIVATE_DNS_MODE_OFF = "off"; + field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; + field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; } public final class NetworkAgentConfig implements android.os.Parcelable { diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index f69468a6cd..3fb95d9f21 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -24,6 +24,8 @@ import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; +import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; +import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -32,11 +34,13 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.StringDef; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.IpSecManager.UdpEncapsulationSocket; @@ -64,6 +68,7 @@ import android.os.ServiceSpecificException; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Range; @@ -803,24 +808,27 @@ public class ConnectivityManager { /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_OFF = "off"; /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; - /** - * The default Private DNS mode. - * - * This may change from release to release or may become dependent upon - * the capabilities of the underlying platform. - * - * @hide - */ - public static final String PRIVATE_DNS_DEFAULT_MODE_FALLBACK = PRIVATE_DNS_MODE_OPPORTUNISTIC; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(value = { + PRIVATE_DNS_MODE_OFF, + PRIVATE_DNS_MODE_OPPORTUNISTIC, + PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, + }) + public @interface PrivateDnsMode {} @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private final IConnectivityManager mService; @@ -5129,4 +5137,24 @@ public class ConnectivityManager { public static Range getIpSecNetIdRange() { return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1); } + + /** + * Get private DNS mode from settings. + * + * @param cr The ContentResolver to query private DNS mode from settings. + * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @NonNull + @PrivateDnsMode + public static String getPrivateDnsMode(@NonNull ContentResolver cr) { + String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); + if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); + // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose + // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode. + if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_MODE_OPPORTUNISTIC; + return mode; + } } From 9b47fcca83587f52d568a999fa3b550efe49e845 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 12 Mar 2021 18:30:30 +0900 Subject: [PATCH 102/343] Remove VpnType usage in VpnTransportInfo The VpnType annotation is a hidden symbol, and should be kept hidden as annotations are disallowed by API guidelines. Remove its usage in VpnTransportInfo as users of annotated constants that build against API stubs are expected not to use the annotation. Bug: 173331190 Test: m Change-Id: I171fa57f6279defad081c3cd16265d58ec55e57d --- framework/src/android/net/VpnTransportInfo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/android/net/VpnTransportInfo.java b/framework/src/android/net/VpnTransportInfo.java index 340141b78a..c510079489 100644 --- a/framework/src/android/net/VpnTransportInfo.java +++ b/framework/src/android/net/VpnTransportInfo.java @@ -42,9 +42,9 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"}); /** Type of this VPN. */ - @VpnManager.VpnType public final int type; + public final int type; - public VpnTransportInfo(@VpnManager.VpnType int type) { + public VpnTransportInfo(int type) { this.type = type; } From 889dcda9c41bd84fe0d7350d850a6ff37cf57c5d Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 12 Mar 2021 17:56:09 +0800 Subject: [PATCH 103/343] Have a new API to get private DNS mode - Expose PRIVATE_DNS_MODE_OFF, PRIVATE_DNS_MODE_OPPORTUNISTIC and PRIVATE_DNS_MODE_PROVIDER_HOSTNAME for external users. - Since PRIVATE_DNS_DEFAULT_MODE_FALLBACK might be changed from release to release, so it cannot be exposed as a system API. Remove PRIVATE_DNS_DEFAULT_MODE_FALLBACK and have a new API - getPrivateDnsMode() for users to get the private DNS mode instead. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: I02a1e91b4eafb5f5df3eada1c07b99849a050c3c Merged-In: I02a1e91b4eafb5f5df3eada1c07b99849a050c3c --- framework/api/module-lib-current.txt | 4 ++ .../src/android/net/ConnectivityManager.java | 46 +++++++++++++++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 4b3336644e..a04571496c 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -8,9 +8,13 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); method @NonNull public static android.util.Range getIpSecNetIdRange(); + method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + field public static final String PRIVATE_DNS_MODE_OFF = "off"; + field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; + field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; } public final class NetworkAgentConfig implements android.os.Parcelable { diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index e9107b67e4..d74efd5751 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -24,6 +24,8 @@ import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; +import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; +import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import android.annotation.CallbackExecutor; import android.annotation.IntDef; @@ -32,11 +34,13 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.StringDef; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.net.IpSecManager.UdpEncapsulationSocket; @@ -64,6 +68,7 @@ import android.os.ServiceSpecificException; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Range; @@ -803,24 +808,27 @@ public class ConnectivityManager { /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_OFF = "off"; /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; /** * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; - /** - * The default Private DNS mode. - * - * This may change from release to release or may become dependent upon - * the capabilities of the underlying platform. - * - * @hide - */ - public static final String PRIVATE_DNS_DEFAULT_MODE_FALLBACK = PRIVATE_DNS_MODE_OPPORTUNISTIC; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(value = { + PRIVATE_DNS_MODE_OFF, + PRIVATE_DNS_MODE_OPPORTUNISTIC, + PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, + }) + public @interface PrivateDnsMode {} @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private final IConnectivityManager mService; @@ -5129,4 +5137,24 @@ public class ConnectivityManager { public static Range getIpSecNetIdRange() { return new Range(TUN_INTF_NETID_START, TUN_INTF_NETID_START + TUN_INTF_NETID_RANGE - 1); } + + /** + * Get private DNS mode from settings. + * + * @param cr The ContentResolver to query private DNS mode from settings. + * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @NonNull + @PrivateDnsMode + public static String getPrivateDnsMode(@NonNull ContentResolver cr) { + String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); + if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); + // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose + // PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode. + if (TextUtils.isEmpty(mode)) mode = PRIVATE_DNS_MODE_OPPORTUNISTIC; + return mode; + } } From 0494b85ffb5e32ed6321c4af5dbb964a5c97ed7b Mon Sep 17 00:00:00 2001 From: paulhu Date: Wed, 3 Mar 2021 22:15:11 +0800 Subject: [PATCH 104/343] Replace InetAddress#parseNumericAddress -Connectivity is becoming a mainline module in S but mainline modules are not allowed to use non-formal APIs. Thus, replace non-formal API InetAddress#parseNumericAddress to InetAddresses#parseNumericAddress. - Add deprecated method legacyParseIpAndMask() for IpPrefix and LinkAddress. Because InetAddresses#parseNumericAddress has a little different behavior in some case, but these two classes should keep working as before. So these two classes will use the new deprecated method. Bug: 181756157 Test: FrameworksNetTests Change-Id: I1c96b75f0b8d5e93304a39b4a8c8849964e5e810 --- framework/src/android/net/IpPrefix.java | 2 +- framework/src/android/net/LinkAddress.java | 2 +- framework/src/android/net/NetworkUtils.java | 47 ++++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/framework/src/android/net/IpPrefix.java b/framework/src/android/net/IpPrefix.java index d2ee7d13b0..bf4481afc5 100644 --- a/framework/src/android/net/IpPrefix.java +++ b/framework/src/android/net/IpPrefix.java @@ -113,7 +113,7 @@ public final class IpPrefix implements Parcelable { // first statement in constructor". We could factor out setting the member variables to an // init() method, but if we did, then we'd have to make the members non-final, or "error: // cannot assign a value to final variable address". So we just duplicate the code here. - Pair ipAndMask = NetworkUtils.parseIpAndMask(prefix); + Pair ipAndMask = NetworkUtils.legacyParseIpAndMask(prefix); this.address = ipAndMask.first.getAddress(); this.prefixLength = ipAndMask.second; checkAndMaskAddressAndPrefixLength(); diff --git a/framework/src/android/net/LinkAddress.java b/framework/src/android/net/LinkAddress.java index d1bdaa078c..d48b8c71f4 100644 --- a/framework/src/android/net/LinkAddress.java +++ b/framework/src/android/net/LinkAddress.java @@ -325,7 +325,7 @@ public class LinkAddress implements Parcelable { public LinkAddress(@NonNull String address, int flags, int scope) { // This may throw an IllegalArgumentException; catching it is the caller's responsibility. // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24". - Pair ipAndMask = NetworkUtils.parseIpAndMask(address); + Pair ipAndMask = NetworkUtils.legacyParseIpAndMask(address); init(ipAndMask.first, ipAndMask.second, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); } diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java index 9e42bbecbe..c0f262815b 100644 --- a/framework/src/android/net/NetworkUtils.java +++ b/framework/src/android/net/NetworkUtils.java @@ -27,8 +27,10 @@ import com.android.net.module.util.Inet4AddressUtils; import java.io.FileDescriptor; import java.math.BigInteger; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.SocketException; +import java.net.UnknownHostException; import java.util.Locale; import java.util.TreeSet; @@ -212,7 +214,7 @@ public class NetworkUtils { @Deprecated public static InetAddress numericToInetAddress(String addrString) throws IllegalArgumentException { - return InetAddress.parseNumericAddress(addrString); + return InetAddresses.parseNumericAddress(addrString); } /** @@ -234,7 +236,7 @@ public class NetworkUtils { try { String[] pieces = ipAndMaskString.split("/", 2); prefixLength = Integer.parseInt(pieces[1]); - address = InetAddress.parseNumericAddress(pieces[0]); + address = InetAddresses.parseNumericAddress(pieces[0]); } catch (NullPointerException e) { // Null string. } catch (ArrayIndexOutOfBoundsException e) { // No prefix length. } catch (NumberFormatException e) { // Non-numeric prefix. @@ -248,6 +250,47 @@ public class NetworkUtils { return new Pair(address, prefixLength); } + /** + * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64". + * @hide + * + * @deprecated This method is used only for IpPrefix and LinkAddress. Since Android S, use + * {@link #parseIpAndMask(String)}, if possible. + */ + @Deprecated + public static Pair legacyParseIpAndMask(String ipAndMaskString) { + InetAddress address = null; + int prefixLength = -1; + try { + String[] pieces = ipAndMaskString.split("/", 2); + prefixLength = Integer.parseInt(pieces[1]); + if (pieces[0] == null || pieces[0].isEmpty()) { + final byte[] bytes = new byte[16]; + bytes[15] = 1; + return new Pair(Inet6Address.getByAddress( + "ip6-localhost"/* host */, bytes, 0 /* scope_id */), prefixLength); + } + + if (pieces[0].startsWith("[") + && pieces[0].endsWith("]") + && pieces[0].indexOf(':') != -1) { + pieces[0] = pieces[0].substring(1, pieces[0].length() - 1); + } + address = InetAddresses.parseNumericAddress(pieces[0]); + } catch (NullPointerException e) { // Null string. + } catch (ArrayIndexOutOfBoundsException e) { // No prefix length. + } catch (NumberFormatException e) { // Non-numeric prefix. + } catch (IllegalArgumentException e) { // Invalid IP address. + } catch (UnknownHostException e) { // IP address length is illegal + } + + if (address == null || prefixLength == -1) { + throw new IllegalArgumentException("Invalid IP address and mask " + ipAndMaskString); + } + + return new Pair(address, prefixLength); + } + /** * Convert a 32 char hex string into a Inet6Address. * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be From 3a87589ff6e9b2256911049b167b6073a6bed7d2 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 14 Mar 2021 15:41:15 +0900 Subject: [PATCH 105/343] Remove MessageUtils usage in VpnTransportInfo MessageUtils is a hidden utility, and including a jarjared copy in framework-connectivity would add complexity. It is only used in VpnTransportInfo, where it would parse VPN constants when the class is loaded in each process. Considering the performance and maintenance cost using numerical type codes in toString() seems to be a better tradeoff. Bug: 177046265 Test: m Change-Id: Ie71cc816f86e020b44ed1c86349b5c9204dee3cf --- framework/src/android/net/VpnTransportInfo.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/framework/src/android/net/VpnTransportInfo.java b/framework/src/android/net/VpnTransportInfo.java index c510079489..cd8f4c06de 100644 --- a/framework/src/android/net/VpnTransportInfo.java +++ b/framework/src/android/net/VpnTransportInfo.java @@ -22,9 +22,6 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.util.SparseArray; - -import com.android.internal.util.MessageUtils; import java.util.Objects; @@ -38,9 +35,6 @@ import java.util.Objects; */ @SystemApi(client = MODULE_LIBRARIES) public final class VpnTransportInfo implements TransportInfo, Parcelable { - private static final SparseArray sTypeToString = - MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"}); - /** Type of this VPN. */ public final int type; @@ -63,8 +57,7 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable { @Override public String toString() { - final String typeString = sTypeToString.get(type, "VPN_TYPE_???"); - return String.format("VpnTransportInfo{%s}", typeString); + return String.format("VpnTransportInfo{type=%d}", type); } @Override From 25dcabf72d3c67be515bafcc7f94bc5e7911bcc7 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Mar 2021 10:20:40 +0900 Subject: [PATCH 106/343] Add ParseException constructors to API ParseException constructors are used by both platform and mainline module code, so they can't be package-private. Removing dependencies on either side is not possible as the class itself is part of the public API, and supports APIs on both sides. Having the constructors part of the API makes the class usable by both sides. Fixes: 182705505 Test: CtsNetTestCases for APIs using the exception Change-Id: Ia396ab2fa3afaed3cf474c8e60f72fc7f3f4fded --- framework/api/module-lib-current.txt | 5 +++++ framework/src/android/net/ParseException.java | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 4b3336644e..b04e248ca6 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -25,6 +25,11 @@ package android.net { field public static final int TRANSPORT_TEST = 7; // 0x7 } + public class ParseException extends java.lang.RuntimeException { + ctor public ParseException(@NonNull String); + ctor public ParseException(@NonNull String, @NonNull Throwable); + } + public final class TcpRepairWindow { ctor public TcpRepairWindow(int, int, int, int, int, int); field public final int maxWindow; diff --git a/framework/src/android/net/ParseException.java b/framework/src/android/net/ParseException.java index bcfdd7ef09..ca6d012dfe 100644 --- a/framework/src/android/net/ParseException.java +++ b/framework/src/android/net/ParseException.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; /** * Thrown when parsing failed. @@ -25,12 +26,16 @@ import android.annotation.NonNull; public class ParseException extends RuntimeException { public String response; - ParseException(@NonNull String response) { + /** @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public ParseException(@NonNull String response) { super(response); this.response = response; } - ParseException(@NonNull String response, @NonNull Throwable cause) { + /** @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public ParseException(@NonNull String response, @NonNull Throwable cause) { super(response, cause); this.response = response; } From c0d25c19b383b7523d76457b4fee729eddd604ef Mon Sep 17 00:00:00 2001 From: lifr Date: Tue, 9 Mar 2021 17:24:46 +0800 Subject: [PATCH 107/343] [CS15]Do not use hidden API of PlatformProperties ConnectivityService is going to become a mainline module, and it will not able to use hidden method anymore. Using PlatformProperties as a static library instead of hidden API. Bug: 170917042 Test: atest FrameworksNetTests Merged-In: I3a3deca5d2e0f690db8c0061de2db2217376d268 Change-Id: I3a3deca5d2e0f690db8c0061de2db2217376d268 --- service/Android.bp | 3 ++- service/jarjar-rules.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/service/Android.bp b/service/Android.bp index 2fb9f72fea..856f3b8533 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -66,6 +66,7 @@ java_library { "net-utils-device-common", "net-utils-framework-common", "netd-client", + "PlatformProperties", ], apex_available: [ "//apex_available:platform", @@ -76,7 +77,7 @@ java_library { java_library { name: "service-connectivity", installable: true, - static_libs:[ + static_libs: [ "service-connectivity-pre-jarjar", ], jarjar_rules: "jarjar-rules.txt", diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index d8c60a428e..a7b419b020 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -1,3 +1,4 @@ +rule android.sysprop.** com.android.connectivity.sysprop.@1 rule com.android.net.module.util.** com.android.connectivity.net-utils.@1 rule com.android.modules.utils.** com.android.connectivity.modules-utils.@1 From ed0fe3ecd38d25a86b1e68fd52d0a60dfab2e907 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 18 Jan 2021 15:28:01 +0800 Subject: [PATCH 108/343] Make PacProxyService be a system service PacProxyInstaller class is running a thread all the time and is listening to intent ACTION_PAC_REFRESH so it would be better to make it be a system service with a manager class PacProxyManager which is obtained with getSystemService(PacProxyManager.class). Besides, rename PacProxyInstaller to PacProxyService will be easier to know it's the service for PacProxyManager. ConnectivityService is going to be a mainline module and it needs constructor of PacProxyService to be SystemApi. However, in current design, it needs to pass a handler and an int arguments to the constructor which would be difficult to maintain if just expose the constructor directly. So, define a listener for the event that the current PAC proxy has been installed so that the handler and the int arguments can be removed from the constructor. Bug: 177035719 Test: FrameworksNetTests Change-Id: I2abff75ec59a17628ef006aad348c53fadbed076 --- framework/src/android/net/ProxyInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/android/net/ProxyInfo.java b/framework/src/android/net/ProxyInfo.java index 229db0d717..745e20f154 100644 --- a/framework/src/android/net/ProxyInfo.java +++ b/framework/src/android/net/ProxyInfo.java @@ -129,7 +129,7 @@ public class ProxyInfo implements Parcelable { } /** - * Only used in PacProxyInstaller after Local Proxy is bound. + * Only used in PacProxyService after Local Proxy is bound. * @hide */ public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) { From 3f0e7dd4e78aefb59361ceeb65f447f6ddd7a8e9 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Mar 2021 07:27:44 +0000 Subject: [PATCH 109/343] Revert "Remove connectivity dependency on Preconditions" This reverts commit fa5eacc89f19bf96ed7de600a1a81b90454132f7. Reason for revert: Build broken: b/182721112 Change-Id: Ibc84ec6d7900fdcf0bc14cd7036f9c08287711db --- .../net/ConnectivityDiagnosticsManager.java | 5 ++- .../src/android/net/ConnectivityManager.java | 44 ++++++++----------- framework/src/android/net/MacAddress.java | 10 ++--- .../src/android/net/NetworkCapabilities.java | 11 +++-- .../android/net/StaticIpConfiguration.java | 3 +- .../src/android/net/TestNetworkManager.java | 7 +-- 6 files changed, 38 insertions(+), 42 deletions(-) diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.java b/framework/src/android/net/ConnectivityDiagnosticsManager.java index 3598ebc701..5234494973 100644 --- a/framework/src/android/net/ConnectivityDiagnosticsManager.java +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.java @@ -28,6 +28,7 @@ import android.os.PersistableBundle; import android.os.RemoteException; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -69,8 +70,8 @@ public class ConnectivityDiagnosticsManager { /** @hide */ public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) { - mContext = Objects.requireNonNull(context, "missing context"); - mService = Objects.requireNonNull(service, "missing IConnectivityManager"); + mContext = Preconditions.checkNotNull(context, "missing context"); + mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); } /** @hide */ diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index e463a7cd31..45ed3179d7 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -69,6 +69,7 @@ import android.util.SparseIntArray; import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; import libcore.net.event.NetworkEventDispatcher; @@ -1732,9 +1733,7 @@ public class ConnectivityManager { // Map from type to transports. final int NOT_FOUND = -1; final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND); - if (transport == NOT_FOUND) { - throw new IllegalArgumentException("unknown legacy type: " + type); - } + Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type); nc.addTransportType(transport); // Map from type to capabilities. @@ -1839,8 +1838,8 @@ public class ConnectivityManager { } private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { - Objects.requireNonNull(network, "network cannot be null"); - Objects.requireNonNull(callback, "callback cannot be null"); + Preconditions.checkNotNull(network, "network cannot be null"); + Preconditions.checkNotNull(callback, "callback cannot be null"); mNetwork = network; mExecutor = Executors.newSingleThreadExecutor(); mCallback = new ISocketKeepaliveCallback.Stub() { @@ -2215,9 +2214,7 @@ public class ConnectivityManager { */ public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) { INetworkActivityListener rl = mNetworkActivityListeners.get(l); - if (rl == null) { - throw new IllegalArgumentException("Listener was not registered."); - } + Preconditions.checkArgument(rl != null, "Listener was not registered."); try { mService.registerNetworkActivityListener(rl); } catch (RemoteException e) { @@ -2245,8 +2242,8 @@ public class ConnectivityManager { * {@hide} */ public ConnectivityManager(Context context, IConnectivityManager service) { - mContext = Objects.requireNonNull(context, "missing context"); - mService = Objects.requireNonNull(service, "missing IConnectivityManager"); + mContext = Preconditions.checkNotNull(context, "missing context"); + mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); sInstance = this; } @@ -2513,7 +2510,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { - Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null."); + Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); final Executor executor = new Executor() { @Override @@ -2606,7 +2603,7 @@ public class ConnectivityManager { public void registerTetheringEventCallback( @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEventCallback callback) { - Objects.requireNonNull(callback, "OnTetheringEventCallback cannot be null."); + Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); final TetheringEventCallback tetherCallback = new TetheringEventCallback() { @@ -2904,7 +2901,7 @@ public class ConnectivityManager { public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEntitlementResultListener listener) { - Objects.requireNonNull(listener, "TetheringEntitlementResultListener cannot be null."); + Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null."); ResultReceiver wrappedListener = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -3528,7 +3525,7 @@ public class ConnectivityManager { } CallbackHandler(Handler handler) { - this(Objects.requireNonNull(handler, "Handler cannot be null.").getLooper()); + this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper()); } @Override @@ -3626,9 +3623,9 @@ public class ConnectivityManager { int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { printStackTrace(); checkCallbackNotNull(callback); - if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) { - throw new IllegalArgumentException("null NetworkCapabilities"); - } + Preconditions.checkArgument( + reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null, + "null NetworkCapabilities"); final NetworkRequest request; final String callingPackageName = mContext.getOpPackageName(); try { @@ -3974,17 +3971,15 @@ public class ConnectivityManager { } private static void checkPendingIntentNotNull(PendingIntent intent) { - Objects.requireNonNull(intent, "PendingIntent cannot be null."); + Preconditions.checkNotNull(intent, "PendingIntent cannot be null."); } private static void checkCallbackNotNull(NetworkCallback callback) { - Objects.requireNonNull(callback, "null NetworkCallback"); + Preconditions.checkNotNull(callback, "null NetworkCallback"); } private static void checkTimeout(int timeoutMs) { - if (timeoutMs <= 0) { - throw new IllegalArgumentException("timeoutMs must be strictly positive."); - } + Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive."); } /** @@ -4234,9 +4229,8 @@ public class ConnectivityManager { // Find all requests associated to this callback and stop callback triggers immediately. // Callback is reusable immediately. http://b/20701525, http://b/35921499. synchronized (sCallbacks) { - if (networkCallback.networkRequest == null) { - throw new IllegalArgumentException("NetworkCallback was not registered"); - } + Preconditions.checkArgument(networkCallback.networkRequest != null, + "NetworkCallback was not registered"); if (networkCallback.networkRequest == ALREADY_UNREGISTERED) { Log.d(TAG, "NetworkCallback was already unregistered"); return; diff --git a/framework/src/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java index 26a504a29c..c83c23a4b6 100644 --- a/framework/src/android/net/MacAddress.java +++ b/framework/src/android/net/MacAddress.java @@ -25,6 +25,7 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; @@ -33,7 +34,6 @@ import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Arrays; -import java.util.Objects; /** * Representation of a MAC address. @@ -229,7 +229,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static @NonNull byte[] byteAddrFromStringAddr(String addr) { - Objects.requireNonNull(addr); + Preconditions.checkNotNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -275,7 +275,7 @@ public final class MacAddress implements Parcelable { // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) // that avoids the allocation of an intermediary byte[]. private static long longAddrFromStringAddr(String addr) { - Objects.requireNonNull(addr); + Preconditions.checkNotNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -364,8 +364,8 @@ public final class MacAddress implements Parcelable { * */ public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) { - Objects.requireNonNull(baseAddress); - Objects.requireNonNull(mask); + Preconditions.checkNotNull(baseAddress); + Preconditions.checkNotNull(mask); return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 7a693444e6..c82cd3b4f3 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -34,6 +34,7 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; @@ -2072,9 +2073,8 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidTransportType(@Transport int transport) { - if (!isValidTransport(transport)) { - throw new IllegalArgumentException("Invalid TransportType " + transport); - } + Preconditions.checkArgument( + isValidTransport(transport), "Invalid TransportType " + transport); } private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { @@ -2082,9 +2082,8 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { - if (!isValidCapability(capability)) { - throw new IllegalArgumentException("NetworkCapability " + capability + "out of range"); - } + Preconditions.checkArgument(isValidCapability(capability), + "NetworkCapability " + capability + "out of range"); } /** diff --git a/framework/src/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java index 7904f7a4ec..ce545974f5 100644 --- a/framework/src/android/net/StaticIpConfiguration.java +++ b/framework/src/android/net/StaticIpConfiguration.java @@ -24,6 +24,7 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; import com.android.net.module.util.InetAddressUtils; import java.net.InetAddress; @@ -152,7 +153,7 @@ public final class StaticIpConfiguration implements Parcelable { * @return The {@link Builder} for chaining. */ public @NonNull Builder setDnsServers(@NonNull Iterable dnsServers) { - Objects.requireNonNull(dnsServers); + Preconditions.checkNotNull(dnsServers); mDnsServers = dnsServers; return this; } diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java index a7a62351e5..a174a7be85 100644 --- a/framework/src/android/net/TestNetworkManager.java +++ b/framework/src/android/net/TestNetworkManager.java @@ -21,9 +21,10 @@ import android.annotation.SystemApi; import android.os.IBinder; import android.os.RemoteException; +import com.android.internal.util.Preconditions; + import java.util.Arrays; import java.util.Collection; -import java.util.Objects; /** * Class that allows creation and management of per-app, test-only networks @@ -49,7 +50,7 @@ public class TestNetworkManager { /** @hide */ public TestNetworkManager(@NonNull ITestNetworkManager service) { - mService = Objects.requireNonNull(service, "missing ITestNetworkManager"); + mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager"); } /** @@ -92,7 +93,7 @@ public class TestNetworkManager { */ public void setupTestNetwork( @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { - Objects.requireNonNull(lp, "Invalid LinkProperties"); + Preconditions.checkNotNull(lp, "Invalid LinkProperties"); setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); } From d637272b9cdcc5e363424e4fd6ace587a994c796 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 21 Dec 2020 18:36:52 +0900 Subject: [PATCH 110/343] [NS01] Add NetworkScore As attested by numerous TODOs in the code, a new way of representing network quality and policy is needed instead of an int. An int representing the quality of the network requires all parties using it to know how all other parties are using it, and implementation details about the decision algorithm. For all intents and purposes, the selection is left to individual network factories who try to achieve a desired result while piecing together all possible states of the system. As the number of such cases and desires increases, this becomes both intractable and unmaintainable. Indeed, at this time in the codebase nobody can really predict exactly how a given change in score will affect selection across the board, and it is essentially impossible to figure out the behavior of network selection by inspecting the code because the moving parts are scattered throughout the entire codebase. Having an object encapsulating policy and quality values will let us centralize the selection and make it again possible to maintain without knowledge of all behaviors of all network factories. It will also provide better guarantees of respecting policy, and allow bugfixes that were not possible before because they'd touch too many parts of the code. Test: FrameworksNetTests FrameworksWifiTests NetworkStackTests Change-Id: I3185a6412b9b659798faf0c6882699e9c63cc115 --- .../src/android/net/ConnectivityManager.java | 20 +-------- .../src/android/net/IConnectivityManager.aidl | 3 +- framework/src/android/net/NetworkAgent.java | 42 ++++++++++++++----- .../aidl/INetworkAgentRegistry.aidl | 5 ++- 4 files changed, 38 insertions(+), 32 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 8c66db9a20..aec6b0a6ca 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -3205,10 +3205,6 @@ public class ConnectivityManager { } } - // TODO : remove this method. It is a stopgap measure to help sheperding a number - // of dependent changes that would conflict throughout the automerger graph. Having this - // temporarily helps with the process of going through with all these dependent changes across - // the entire tree. /** * @hide * Register a NetworkAgent with ConnectivityService. @@ -3218,20 +3214,8 @@ public class ConnectivityManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_FACTORY}) public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkAgentConfig config) { - return registerNetworkAgent(na, ni, lp, nc, score, config, NetworkProvider.ID_NONE); - } - - /** - * @hide - * Register a NetworkAgent with ConnectivityService. - * @return Network corresponding to NetworkAgent. - */ - @RequiresPermission(anyOf = { - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_FACTORY}) - public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { + NetworkCapabilities nc, @NonNull NetworkScore score, NetworkAgentConfig config, + int providerId) { try { return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index f9393e315b..1bbf1a95fc 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -30,6 +30,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkState; import android.net.NetworkStateSnapshot; import android.net.OemNetworkPreferences; @@ -138,7 +139,7 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, int score, in NetworkAgentConfig config, + in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index 27aa15d1e1..b3ab0ee8bd 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -371,6 +371,14 @@ public abstract class NetworkAgent { return ni; } + // Temporary backward compatibility constructor + public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + this(context, looper, logTag, nc, lp, + new NetworkScore.Builder().setLegacyInt(score).build(), config, provider); + } + /** * Create a new network agent. * @param context a {@link Context} to get system services from. @@ -382,10 +390,12 @@ public abstract class NetworkAgent { * @param score the initial score of this network. Update with sendNetworkScore. * @param config an immutable {@link NetworkAgentConfig} for this agent. * @param provider the {@link NetworkProvider} managing this agent. + * @hide TODO : unhide when impl is complete */ public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, + @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), getLegacyNetworkInfo(config)); @@ -395,12 +405,12 @@ public abstract class NetworkAgent { public final Context context; public final NetworkCapabilities capabilities; public final LinkProperties properties; - public final int score; + public final NetworkScore score; public final NetworkAgentConfig config; public final NetworkInfo info; InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, - @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, - @NonNull NetworkInfo info) { + @NonNull LinkProperties properties, @NonNull NetworkScore score, + @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { this.context = context; this.capabilities = capabilities; this.properties = properties; @@ -412,8 +422,9 @@ public abstract class NetworkAgent { private volatile InitialConfiguration mInitialConfiguration; private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, + @NonNull NetworkInfo ni) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; mNetworkInfo = new NetworkInfo(ni); @@ -872,16 +883,25 @@ public abstract class NetworkAgent { queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); } + /** + * Must be called by the agent to update the score of this network. + * + * @param score the new score. + * @hide TODO : unhide when impl is complete + */ + public final void sendNetworkScore(@NonNull NetworkScore score) { + Objects.requireNonNull(score); + queueOrSendMessage(reg -> reg.sendScore(score)); + } + /** * Must be called by the agent to update the score of this network. * * @param score the new score, between 0 and 99. + * deprecated use sendNetworkScore(NetworkScore) TODO : remove in S. */ public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { - if (score < 0) { - throw new IllegalArgumentException("Score must be >= 0"); - } - queueOrSendMessage(reg -> reg.sendScore(score)); + sendNetworkScore(new NetworkScore.Builder().setLegacyInt(score).build()); } /** diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl index f0193db5c2..18d26a7e4b 100644 --- a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl +++ b/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl @@ -19,11 +19,12 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; +import android.net.NetworkScore; import android.net.QosSession; import android.telephony.data.EpsBearerQosSessionAttributes; /** - * Interface for NetworkAgents to send network network properties. + * Interface for NetworkAgents to send network properties. * @hide */ oneway interface INetworkAgentRegistry { @@ -31,7 +32,7 @@ oneway interface INetworkAgentRegistry { void sendLinkProperties(in LinkProperties lp); // TODO: consider replacing this by "markConnected()" and removing void sendNetworkInfo(in NetworkInfo info); - void sendScore(int score); + void sendScore(in NetworkScore score); void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial); void sendSocketKeepaliveEvent(int slot, int reason); void sendUnderlyingNetworks(in @nullable List networks); From c296fccca186165e3d9b14123d2b34a96a1dffd2 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Mon, 15 Mar 2021 17:24:12 +0800 Subject: [PATCH 111/343] Add comments to describe the value of converting hex to decimal Bug: 172183305 Test: N/A Change-Id: Id274295d6c8c97d3014214f875168ff968f79bb6 --- framework/src/android/net/ConnectivityManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index e9107b67e4..0d4489c7e8 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5114,9 +5114,9 @@ public class ConnectivityManager { } // The first network ID of IPSec tunnel interface. - private static final int TUN_INTF_NETID_START = 0xFC00; + private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512 // The network ID range of IPSec tunnel interface. - private static final int TUN_INTF_NETID_RANGE = 0x0400; + private static final int TUN_INTF_NETID_RANGE = 0x0400; // 0x0400 = 1024 /** * Get the network ID range reserved for IPSec tunnel interfaces. From ffc407733390c798587e87b03666c3248a88107e Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 9 Mar 2021 16:12:48 +0800 Subject: [PATCH 112/343] Replace interal okhttp APIs Connectivity is becoming a mainline module in S but mainline modules are not allowed to use non-formal APIs. Thus, replace internal okhttp APIs to stable libcore APIs which are created for using HttpURLConnectionFactory. Bug: 182238821 Test: atest FrameworksNetTests Change-Id: I56ba1b9e6e94f9c6519c3f1c8f0c5993fccbe185 --- framework/src/android/net/Network.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java index 46141e0d0c..7245db3b17 100644 --- a/framework/src/android/net/Network.java +++ b/framework/src/android/net/Network.java @@ -30,10 +30,10 @@ import android.system.OsConstants; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; -import com.android.okhttp.internalandroidapi.Dns; -import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory; import libcore.io.IoUtils; +import libcore.net.http.Dns; +import libcore.net.http.HttpURLConnectionFactory; import java.io.FileDescriptor; import java.io.IOException; @@ -299,7 +299,7 @@ public class Network implements Parcelable { // Set configuration on the HttpURLConnectionFactory that will be good for all // connections created by this Network. Configuration that might vary is left // until openConnection() and passed as arguments. - HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory(); + HttpURLConnectionFactory urlConnectionFactory = HttpURLConnectionFactory.createInstance(); urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup // A private connection pool just for this Network. urlConnectionFactory.setNewConnectionPool(httpMaxConnections, From 5f161d22cd878b817cc7b7cb65216f7bc4e7ff8b Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 9 Mar 2021 13:35:25 +0900 Subject: [PATCH 113/343] Remove usage of networkAttributes networkAttributes is a legacy configuration that is now only used to configure which legacy type networks are supported, and what the restore timer is for that network type, for the deprecated startUsingNetworkFeature API. Use a dedicated resource for the restore timers, and build supported legacy network types using hasSystemFeature for wifi, wifi p2p, bluetooth, proxy types, and TelephonyManager.isDataCapable for the mobile types. Bug: 146206136 Test: atest FrameworksNetTests Change-Id: I3a771d3de6c5e912f18d2834e3a50af797ac4991 --- .../ServiceConnectivityResources/res/values/config.xml | 10 ++++++++++ .../res/values/overlayable.xml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml index 7d98c76a40..06c81921fd 100644 --- a/service/ServiceConnectivityResources/res/values/config.xml +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -42,4 +42,14 @@ --> + + 2,60000 + 3,60000 + 4,60000 + 5,60000 + 10,60000 + 11,60000 + 12,60000 + + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml index 00ec2df0e6..da8aee5627 100644 --- a/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -17,11 +17,11 @@ + - From 2a4c17c3b334f9b247253473761653d6cb9ce8eb Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 16 Mar 2021 17:11:14 +0800 Subject: [PATCH 114/343] Change the parameter type from ContentResolver to Context Context is more useful than ContentResolver, it can provide more information if we want to change the behavior in the future. Bug: 172183305 Test: atest FrameworksNetTests Change-Id: I5702c7d74b862a76558b94f1abe2c6df9eb7f097 --- framework/api/module-lib-current.txt | 2 +- framework/src/android/net/ConnectivityManager.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index a04571496c..b9bcddba5d 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -8,7 +8,7 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); method @NonNull public static android.util.Range getIpSecNetIdRange(); - method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver); + method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 66c45ed6fc..6d6a554793 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5140,7 +5140,8 @@ public class ConnectivityManager { /** * Get private DNS mode from settings. * - * @param cr The ContentResolver to query private DNS mode from settings. + * @param context The Context to get its ContentResolver to query the private DNS mode from + * settings. * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. * * @hide @@ -5148,7 +5149,8 @@ public class ConnectivityManager { @SystemApi(client = MODULE_LIBRARIES) @NonNull @PrivateDnsMode - public static String getPrivateDnsMode(@NonNull ContentResolver cr) { + public static String getPrivateDnsMode(@NonNull Context context) { + final ContentResolver cr = context.getContentResolver(); String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose From e2cd02d9ab9950acb82090cd4450ffc7ae853722 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 16 Mar 2021 17:11:14 +0800 Subject: [PATCH 115/343] Change the parameter type from ContentResolver to Context Context is more useful than ContentResolver, it can provide more information if we want to change the behavior in the future. Bug: 172183305 Test: atest FrameworksNetTests Change-Id: I5702c7d74b862a76558b94f1abe2c6df9eb7f097 Merged-In: I5702c7d74b862a76558b94f1abe2c6df9eb7f097 --- framework/api/module-lib-current.txt | 2 +- framework/src/android/net/ConnectivityManager.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index c3b1800af2..cc95a7cc24 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -8,7 +8,7 @@ package android.net { public class ConnectivityManager { method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); method @NonNull public static android.util.Range getIpSecNetIdRange(); - method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver); + method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 5907f23799..417246318a 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5124,7 +5124,8 @@ public class ConnectivityManager { /** * Get private DNS mode from settings. * - * @param cr The ContentResolver to query private DNS mode from settings. + * @param context The Context to get its ContentResolver to query the private DNS mode from + * settings. * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. * * @hide @@ -5132,7 +5133,8 @@ public class ConnectivityManager { @SystemApi(client = MODULE_LIBRARIES) @NonNull @PrivateDnsMode - public static String getPrivateDnsMode(@NonNull ContentResolver cr) { + public static String getPrivateDnsMode(@NonNull Context context) { + final ContentResolver cr = context.getContentResolver(); String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE); if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE); // If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose From ad565e26d9e61d21674affb21c307b84a3096eb8 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 25 Feb 2021 17:23:40 +0900 Subject: [PATCH 116/343] Public API for per-profile network preference. This patch defines the API, but does not make it public yet as there is no implementation yet. Test: none so far Change-Id: I854a952dfe35cc80847eb62f522b1667b8e9b8a0 --- .../src/android/net/ConnectivityManager.java | 71 +++++++++++++++++++ .../src/android/net/IConnectivityManager.aidl | 5 ++ 2 files changed, 76 insertions(+) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 8b669284ad..dab9491095 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -64,6 +64,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceSpecificException; +import android.os.UserHandle; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -970,6 +971,33 @@ public class ConnectivityManager { } } + /** + * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. + * Specify that the traffic for this user should by follow the default rules. + * @hide + */ + // TODO : @SystemApi + public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; + + /** + * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}. + * Specify that the traffic for this user should by default go on a network with + * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE}, and on the system default network + * if no such network is available. + * @hide + */ + // TODO : @SystemApi + public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + PROFILE_NETWORK_PREFERENCE_DEFAULT, + PROFILE_NETWORK_PREFERENCE_ENTERPRISE + }) + public @interface ProfileNetworkPreference { + } + /** * Specifies the preferred network type. When the device has more * than one type available the preferred network type will be used. @@ -5053,6 +5081,8 @@ public class ConnectivityManager { * OnSetOemNetworkPreferenceListener)}. * @hide */ + // TODO : remove this in favor of a vanilla runnable to follow API guidance to use + // functional interfaces when they are appropriate. @SystemApi public interface OnSetOemNetworkPreferenceListener { /** @@ -5104,6 +5134,47 @@ public class ConnectivityManager { } } + /** + * Request that a user profile is put by default on a network matching a given preference. + * + * See the documentation for the individual preferences for a description of the supported + * behaviors. + * + * @param profile the profile concerned. + * @param preference the preference for this profile. + * @param executor an executor to execute the listener on. Optional if listener is null. + * @param listener an optional listener to listen for completion of the operation. + * @throws IllegalArgumentException if {@code profile} is not a valid user profile. + * @throws SecurityException if missing the appropriate permissions. + * @hide + */ + // TODO : @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + public void setProfileNetworkPreference(@NonNull final UserHandle profile, + @ProfileNetworkPreference final int preference, + @Nullable @CallbackExecutor final Executor executor, + @Nullable final Runnable listener) { + if (null != listener) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + } + final IOnCompleteListener proxy; + if (null == listener) { + proxy = null; + } else { + proxy = new IOnCompleteListener.Stub() { + @Override + public void onComplete() { + executor.execute(listener::run); + } + }; + } + try { + mService.setProfileNetworkPreference(profile, preference, proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + // The first network ID of IPSec tunnel interface. private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512 // The network ID range of IPSec tunnel interface. diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 1bbf1a95fc..d1a23ecf54 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -20,6 +20,7 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; +import android.net.IOnCompleteListener; import android.net.IOnSetOemNetworkPreferenceListener; import android.net.INetworkActivityListener; import android.net.IQosCallback; @@ -43,6 +44,7 @@ import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.ResultReceiver; +import android.os.UserHandle; import com.android.connectivity.aidl.INetworkAgent; @@ -216,4 +218,7 @@ interface IConnectivityManager void setOemNetworkPreference(in OemNetworkPreferences preference, in IOnSetOemNetworkPreferenceListener listener); + + void setProfileNetworkPreference(in UserHandle profile, int preference, + in IOnCompleteListener listener); } From 76b0c7efda67ffa40a934034908355d9dcc14320 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 25 Feb 2021 21:46:34 +0900 Subject: [PATCH 117/343] Implement setNetworkPreferenceForUser. Test: FrameworksNetTests Change-Id: I8f18083b5857289892fe8adea5f5ea3f5dbe0809 --- framework/src/android/net/OemNetworkPreferences.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/framework/src/android/net/OemNetworkPreferences.java b/framework/src/android/net/OemNetworkPreferences.java index 48bd29769f..5a76cd6d6b 100644 --- a/framework/src/android/net/OemNetworkPreferences.java +++ b/framework/src/android/net/OemNetworkPreferences.java @@ -72,6 +72,14 @@ public final class OemNetworkPreferences implements Parcelable { @NonNull private final Bundle mNetworkMappings; + /** + * Return whether this object is empty. + * @hide + */ + public boolean isEmpty() { + return mNetworkMappings.keySet().size() == 0; + } + /** * Return the currently built application package name to {@link OemNetworkPreference} mappings. * @return the current network preferences map. From 0a4aefcec27f6a56524bc9ac9227f579619b5863 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 3 Mar 2021 16:37:13 +0900 Subject: [PATCH 118/343] Expose the enterprise per-profile networking API. Also unify the listener for Oem settings, which have never been released as public API (it is slated to be released in S). Test: FrameworksNetTests Change-Id: I84ba363dd0ec03871c37b1c3a31e5557d9aa12e7 --- framework/api/module-lib-current.txt | 1 + framework/api/system-current.txt | 8 ++--- .../src/android/net/ConnectivityManager.java | 34 +++++++------------ .../src/android/net/IConnectivityManager.aidl | 3 +- .../IOnSetOemNetworkPreferenceListener.aidl | 23 ------------- 5 files changed, 17 insertions(+), 52 deletions(-) delete mode 100644 framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index c3b1800af2..088bb41330 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -11,6 +11,7 @@ package android.net { method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index a98f14ea94..4dca411cca 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -56,7 +56,7 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean); - method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener); + method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi(); method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle); method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback); @@ -67,6 +67,8 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; + field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 + field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 field public static final int TETHERING_BLUETOOTH = 2; // 0x2 field public static final int TETHERING_USB = 1; // 0x1 field public static final int TETHERING_WIFI = 0; // 0x0 @@ -78,10 +80,6 @@ package android.net { field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd } - public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener { - method public void onComplete(); - } - @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback { ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback(); method @Deprecated public void onTetheringFailed(); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index dab9491095..ff07ee4ebd 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -976,7 +976,7 @@ public class ConnectivityManager { * Specify that the traffic for this user should by follow the default rules. * @hide */ - // TODO : @SystemApi + @SystemApi public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; /** @@ -986,7 +986,7 @@ public class ConnectivityManager { * if no such network is available. * @hide */ - // TODO : @SystemApi + @SystemApi public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; /** @hide */ @@ -5076,21 +5076,6 @@ public class ConnectivityManager { TYPE_NONE, new CallbackHandler(handler)); } - /** - * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor, - * OnSetOemNetworkPreferenceListener)}. - * @hide - */ - // TODO : remove this in favor of a vanilla runnable to follow API guidance to use - // functional interfaces when they are appropriate. - @SystemApi - public interface OnSetOemNetworkPreferenceListener { - /** - * Called when setOemNetworkPreference() successfully completes. - */ - void onComplete(); - } - /** * Used by automotive devices to set the network preferences used to direct traffic at an * application level as per the given OemNetworkPreferences. An example use-case would be an @@ -5113,16 +5098,16 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference, @Nullable @CallbackExecutor final Executor executor, - @Nullable final OnSetOemNetworkPreferenceListener listener) { + @Nullable final Runnable listener) { Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null"); if (null != listener) { Objects.requireNonNull(executor, "Executor must be non-null"); } - final IOnSetOemNetworkPreferenceListener listenerInternal = listener == null ? null : - new IOnSetOemNetworkPreferenceListener.Stub() { + final IOnCompleteListener listenerInternal = listener == null ? null : + new IOnCompleteListener.Stub() { @Override public void onComplete() { - executor.execute(listener::onComplete); + executor.execute(listener::run); } }; @@ -5148,7 +5133,12 @@ public class ConnectivityManager { * @throws SecurityException if missing the appropriate permissions. * @hide */ - // TODO : @SystemApi + // This function is for establishing per-profile default networking and can only be called by + // the device policy manager, running as the system server. It would make no sense to call it + // on a context for a user because it does not establish a setting on behalf of a user, rather + // it establishes a setting for a user on behalf of the DPM. + @SuppressLint({"UserHandle"}) + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull final UserHandle profile, @ProfileNetworkPreference final int preference, diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index d1a23ecf54..d83cc163b5 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -21,7 +21,6 @@ import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; import android.net.IOnCompleteListener; -import android.net.IOnSetOemNetworkPreferenceListener; import android.net.INetworkActivityListener; import android.net.IQosCallback; import android.net.ISocketKeepaliveCallback; @@ -217,7 +216,7 @@ interface IConnectivityManager void unregisterQosCallback(in IQosCallback callback); void setOemNetworkPreference(in OemNetworkPreferences preference, - in IOnSetOemNetworkPreferenceListener listener); + in IOnCompleteListener listener); void setProfileNetworkPreference(in UserHandle profile, int preference, in IOnCompleteListener listener); diff --git a/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl deleted file mode 100644 index 7979afc54f..0000000000 --- a/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl +++ /dev/null @@ -1,23 +0,0 @@ -/** - * - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** @hide */ -oneway interface IOnSetOemNetworkPreferenceListener { - void onComplete(); -} From 7664f62d37f55099e1b913373efcc7a613154dd6 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 12 Mar 2021 20:05:08 +0800 Subject: [PATCH 119/343] [VCN13] Implement tracking best matching network This is done by: 1. In requestNetwork, provide a basic permission check. 2. rematchNetworksAndRequests: no change, since non listen requests will be automatically processed to track best satisfying network. 3. applyNetworkReassignment: no change, since non-request will not be sent to factories. Test: atest ConnectivityServiceTest#testRegisterBestMatchingNetworkCallback_noIssueToFactory Test: atest ConnectivityServiceTest#testRegisterBestMatchingNetworkCallback_trackBestNetwork Bug: 175662146 Change-Id: I8cf4ab334df6812d84cdda160e9b72b6f54062af --- framework/src/android/net/ConnectivityManager.java | 4 ++-- framework/src/android/net/NetworkRequest.java | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 8b669284ad..81590a84a4 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -18,8 +18,8 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; +import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST; import static android.net.NetworkRequest.Type.REQUEST; -import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; @@ -4249,7 +4249,7 @@ public class ConnectivityManager { @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { final NetworkCapabilities nc = request.networkCapabilities; final CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler); + sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 3fd95ee58d..dbe3ecc4d7 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -140,7 +140,7 @@ public class NetworkRequest implements Parcelable { REQUEST, BACKGROUND_REQUEST, TRACK_SYSTEM_DEFAULT, - TRACK_BEST, + LISTEN_FOR_BEST, }; /** @@ -513,6 +513,15 @@ public class NetworkRequest implements Parcelable { return type == Type.LISTEN; } + /** + * Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST. + * + * @hide + */ + public boolean isListenForBest() { + return type == Type.LISTEN_FOR_BEST; + } + /** * Returns true iff. the contained NetworkRequest is one that: * From bd1230675ec6d7171c161ed9c10b0cff4ab7162d Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 15 Mar 2021 11:48:48 +0800 Subject: [PATCH 120/343] [VCN14] Expose registerBestMatchingNetworkCallback Test: m -j doc-comment-check-docs Bug: 175662146 Change-Id: Ie67dd2f4f8d973de37bc64a03908d7cbb7c2b7ad --- framework/api/current.txt | 1 + .../src/android/net/ConnectivityManager.java | 22 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index 243e4ca429..f22d4b7b77 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -87,6 +87,7 @@ package android.net { method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered(); method public boolean isDefaultNetworkActive(); method @Deprecated public static boolean isNetworkTypeValid(int); + method public void registerBestMatchingNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 81590a84a4..d7cae2f0e5 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4241,9 +4241,27 @@ public class ConnectivityManager { } /** - * @hide + * Registers to receive notifications about the best matching network which satisfy the given + * {@link NetworkRequest}. The callbacks will continue to be called until + * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is + * called. + * + *

    To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * {@link #registerNetworkCallback} and its variants and {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} that the system will call as suitable + * networks change state. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. */ - // TODO: Make it public api. @SuppressLint("ExecutorRegistration") public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { From 7cb4439a92f03b892482b814b4e903f012a97a30 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 16 Mar 2021 14:06:58 +0900 Subject: [PATCH 121/343] Move trimV4AddrZeros to libs/net The utility is @UnsupportedAppUsage, and also used by internal classes like WifiTrackerLib or Mms, so it needs to be in a shared location. Bug: 182859030 Test: m Change-Id: I25cb374f4743a5869e9da5b01d3a543a9a165c0e --- framework/src/android/net/NetworkUtils.java | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java index c0f262815b..c4bebc0a98 100644 --- a/framework/src/android/net/NetworkUtils.java +++ b/framework/src/android/net/NetworkUtils.java @@ -323,22 +323,7 @@ public class NetworkUtils { */ @UnsupportedAppUsage public static String trimV4AddrZeros(String addr) { - if (addr == null) return null; - String[] octets = addr.split("\\."); - if (octets.length != 4) return addr; - StringBuilder builder = new StringBuilder(16); - String result = null; - for (int i = 0; i < 4; i++) { - try { - if (octets[i].length() > 3) return addr; - builder.append(Integer.parseInt(octets[i])); - } catch (NumberFormatException e) { - return addr; - } - if (i < 3) builder.append('.'); - } - result = builder.toString(); - return result; + return Inet4AddressUtils.trimAddressZeros(addr); } /** From 611b02178d580502359aa5ab3980c62e3c92c404 Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Tue, 16 Mar 2021 20:59:42 -0700 Subject: [PATCH 122/343] CaptivePortalData: use CharSequence in VenueFriendlyName API Following up on feedback from API council, change the String type to CharSequence in the get and set Venue friendly name API. Bug: 179163405 Test: atest ConnectivityServiceTest CtsNetTestCasesLatestSdk:CaptivePortalDataTest Test: atest NetworkNotificationManagerTest NetworkMonitorTest Change-Id: Ia63974cd2ff5975bde410eb93731d4b1def36d19 --- framework/api/system-current.txt | 4 ++-- framework/src/android/net/CaptivePortalData.java | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index a98f14ea94..54b3f56301 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -18,7 +18,7 @@ package android.net { method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); method public int getUserPortalUrlSource(); - method @Nullable public String getVenueFriendlyName(); + method @Nullable public CharSequence getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); method public int getVenueInfoUrlSource(); method public boolean isCaptive(); @@ -40,7 +40,7 @@ package android.net { method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); - method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); + method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable CharSequence); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); } diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java index eafda4d2d6..82dbd0fb1f 100644 --- a/framework/src/android/net/CaptivePortalData.java +++ b/framework/src/android/net/CaptivePortalData.java @@ -42,7 +42,7 @@ public final class CaptivePortalData implements Parcelable { private final long mByteLimit; private final long mExpiryTimeMillis; private final boolean mCaptive; - private final String mVenueFriendlyName; + private final CharSequence mVenueFriendlyName; private final int mVenueInfoUrlSource; private final int mUserPortalUrlSource; @@ -65,7 +65,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { + CharSequence venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -80,7 +80,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), - p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(), + p.readLong(), p.readLong(), p.readBoolean(), p.readCharSequence(), p.readInt(), p.readInt()); } @@ -98,7 +98,7 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mByteLimit); dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); - dest.writeString(mVenueFriendlyName); + dest.writeCharSequence(mVenueFriendlyName); dest.writeInt(mVenueInfoUrlSource); dest.writeInt(mUserPortalUrlSource); } @@ -114,7 +114,7 @@ public final class CaptivePortalData implements Parcelable { private long mBytesRemaining = -1; private long mExpiryTime = -1; private boolean mCaptive; - private String mVenueFriendlyName; + private CharSequence mVenueFriendlyName; private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; private @CaptivePortalDataSource int mUserPortalUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; @@ -228,7 +228,7 @@ public final class CaptivePortalData implements Parcelable { * Set the venue friendly name. */ @NonNull - public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { + public Builder setVenueFriendlyName(@Nullable CharSequence venueFriendlyName) { mVenueFriendlyName = venueFriendlyName; return this; } @@ -321,7 +321,7 @@ public final class CaptivePortalData implements Parcelable { * Get the venue friendly name */ @Nullable - public String getVenueFriendlyName() { + public CharSequence getVenueFriendlyName() { return mVenueFriendlyName; } From bef6b09cd997f48832179064327f1d002010deb7 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 17 Mar 2021 14:33:24 +0900 Subject: [PATCH 123/343] Move constants to MODULE_LIB These constants are used by a MODULE_LIBRARIES API, they should have the same visibility. Test: ConnectivityServiceTest Change-Id: I14cb189d949fe552f463cae3002801fd8cf8230c --- framework/api/module-lib-current.txt | 2 ++ framework/api/system-current.txt | 2 -- framework/src/android/net/ConnectivityManager.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 088bb41330..c7fbbd85ba 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -16,6 +16,8 @@ package android.net { field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; + field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 + field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 } public final class NetworkAgentConfig implements android.os.Parcelable { diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 4dca411cca..031bb916c4 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -67,8 +67,6 @@ package android.net { method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback); field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC"; field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT"; - field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0 - field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1 field public static final int TETHERING_BLUETOOTH = 2; // 0x2 field public static final int TETHERING_USB = 1; // 0x1 field public static final int TETHERING_WIFI = 0; // 0x0 diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 59d213135e..3f1ef61570 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -976,7 +976,7 @@ public class ConnectivityManager { * Specify that the traffic for this user should by follow the default rules. * @hide */ - @SystemApi + @SystemApi(client = MODULE_LIBRARIES) public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; /** @@ -986,7 +986,7 @@ public class ConnectivityManager { * if no such network is available. * @hide */ - @SystemApi + @SystemApi(client = MODULE_LIBRARIES) public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; /** @hide */ From 10774b7ebc9e116d7a75076f3d39f19d3dc88468 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 17 Mar 2021 14:16:01 +0800 Subject: [PATCH 124/343] Expose systemReady for SystemServer SystemServer cannot call the hidden API of ConnectivityManager after it becomes a part of mainline module. So expose the hidden API for SystemServer. Bug: 182963354 Test: m services Change-Id: I9c1dc8eb1401dbdc069d5c9fc3992f4c7939b70e --- framework/api/module-lib-current.txt | 1 + framework/src/android/net/ConnectivityManager.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index c3b1800af2..05e0813395 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -12,6 +12,7 @@ package android.net { method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + method public void systemReady(); field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 8b669284ad..dc06cd96ef 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -915,8 +915,8 @@ public class ConnectivityManager { /** * @hide - * TODO: Expose for SystemServer when becomes a module. */ + @SystemApi(client = MODULE_LIBRARIES) public void systemReady() { try { mService.systemReady(); From debfe6062a440bc45d27359bacc76312bbecfc24 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 17 Mar 2021 14:53:35 +0800 Subject: [PATCH 125/343] Modify the comment of getPrivateDnsMode Bug: 172183305 Test: m Change-Id: I2f1b44cf2a362b42f052ea5d34a5cec03d46e661 --- framework/src/android/net/ConnectivityManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 9cd3179d25..6c989a0b72 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -5203,8 +5203,7 @@ public class ConnectivityManager { /** * Get private DNS mode from settings. * - * @param context The Context to get its ContentResolver to query the private DNS mode from - * settings. + * @param context The Context to query the private DNS mode from settings. * @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants. * * @hide From 845456ebdce5d2089ca953808d952be1ecf64765 Mon Sep 17 00:00:00 2001 From: paulhu Date: Wed, 17 Mar 2021 17:19:09 +0800 Subject: [PATCH 126/343] Add ConnectivitySettingsManager This class is used to manager the connectivity module related settings. Bug: 182538166 Test: make Change-Id: I5e02e719ce0d305d7c8a45fefb850d7b981f07eb --- .../net/ConnectivitySettingsManager.java | 46 +++++++++++++++++++ .../net/util/MultinetworkPolicyTracker.java | 8 ++-- 2 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 framework/src/android/net/ConnectivitySettingsManager.java diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java new file mode 100644 index 0000000000..d454365452 --- /dev/null +++ b/framework/src/android/net/ConnectivitySettingsManager.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * A manager class for connectivity module settings. + * + * @hide + */ +public class ConnectivitySettingsManager { + + private ConnectivitySettingsManager() {} + + /** + * Whether to automatically switch away from wifi networks that lose Internet access. + * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always + * avoids such networks. Valid values are: + * + * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013. + * null: Ask the user whether to switch away from bad wifi. + * 1: Avoid bad wifi. + */ + public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi"; + + /** + * User setting for ConnectivityManager.getMeteredMultipathPreference(). This value may be + * overridden by the system based on device or application state. If null, the value + * specified by config_networkMeteredMultipathPreference is used. + */ + public static final String NETWORK_METERED_MULTIPATH_PREFERENCE = + "network_metered_multipath_preference"; +} diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java index 739ddada50..6a49aa2576 100644 --- a/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -16,8 +16,8 @@ package android.net.util; -import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI; -import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE; +import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; +import static android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; import android.annotation.NonNull; import android.content.BroadcastReceiver; @@ -110,8 +110,8 @@ public class MultinetworkPolicyTracker { mHandler = handler; mAvoidBadWifiCallback = avoidBadWifiCallback; mSettingsUris = Arrays.asList( - Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), - Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); + Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI), + Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE)); mResolver = mContext.getContentResolver(); mSettingObserver = new SettingObserver(); mBroadcastReceiver = new BroadcastReceiver() { From 5b9dd873332e24a8ffb09e0d2c2c6c1a73cf56a3 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 17 Mar 2021 10:57:31 +0000 Subject: [PATCH 127/343] Remove extra comment This fixes a merge conflict with downstream branches due to an incomplete cherry-pick. Bug: 171540887 Test: m Change-Id: I27a8f20f1a1d83b472700648f3f5a68413a76ac3 Merged-In: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 --- framework/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/Android.bp b/framework/Android.bp index 9da27d2711..86b85e8398 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -23,7 +23,6 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -// TODO: use a java_library in the bootclasspath instead filegroup { name: "framework-connectivity-internal-sources", srcs: [ From 1b9f03a190c6fb83ee1689563153105ac919a28f Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 12 Mar 2021 15:24:06 +0900 Subject: [PATCH 128/343] Remove Protocol.BASE_* usage in Connectivity ConnectivityManager and NetworkAgent do not share their handler with any other component, so there is no reason to use addresses that do not overlap. Protocol.BASE_* was written to allow for interaction "between different StateMachine implementations without a conflict", but the classes do not use StateMachine, and they do not have such interactions. Bug: 177046265 Test: atest FrameworksNetTests Change-Id: I18c341d4a2c01cb9559d682a9ad1ff259e6b5855 --- .../src/android/net/ConnectivityManager.java | 24 +++++++++---------- framework/src/android/net/NetworkAgent.java | 6 +++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 9cd3179d25..d6ca8be48f 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -77,7 +77,6 @@ import android.util.SparseIntArray; import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; -import com.android.internal.util.Protocol; import libcore.net.event.NetworkEventDispatcher; @@ -3551,29 +3550,28 @@ public class ConnectivityManager { } } - private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; /** @hide */ - public static final int CALLBACK_PRECHECK = BASE + 1; + public static final int CALLBACK_PRECHECK = 1; /** @hide */ - public static final int CALLBACK_AVAILABLE = BASE + 2; + public static final int CALLBACK_AVAILABLE = 2; /** @hide arg1 = TTL */ - public static final int CALLBACK_LOSING = BASE + 3; + public static final int CALLBACK_LOSING = 3; /** @hide */ - public static final int CALLBACK_LOST = BASE + 4; + public static final int CALLBACK_LOST = 4; /** @hide */ - public static final int CALLBACK_UNAVAIL = BASE + 5; + public static final int CALLBACK_UNAVAIL = 5; /** @hide */ - public static final int CALLBACK_CAP_CHANGED = BASE + 6; + public static final int CALLBACK_CAP_CHANGED = 6; /** @hide */ - public static final int CALLBACK_IP_CHANGED = BASE + 7; + public static final int CALLBACK_IP_CHANGED = 7; /** @hide obj = NetworkCapabilities, arg1 = seq number */ - private static final int EXPIRE_LEGACY_REQUEST = BASE + 8; + private static final int EXPIRE_LEGACY_REQUEST = 8; /** @hide */ - public static final int CALLBACK_SUSPENDED = BASE + 9; + public static final int CALLBACK_SUSPENDED = 9; /** @hide */ - public static final int CALLBACK_RESUMED = BASE + 10; + public static final int CALLBACK_RESUMED = 10; /** @hide */ - public static final int CALLBACK_BLK_CHANGED = BASE + 11; + public static final int CALLBACK_BLK_CHANGED = 11; /** @hide */ public static String getCallbackName(int whichCallback) { diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index b3ab0ee8bd..a127c6f6de 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -37,7 +37,6 @@ import android.util.Log; import com.android.connectivity.aidl.INetworkAgent; import com.android.connectivity.aidl.INetworkAgentRegistry; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -125,7 +124,10 @@ public abstract class NetworkAgent { */ public final int providerId; - private static final int BASE = Protocol.BASE_NETWORK_AGENT; + // ConnectivityService parses message constants from itself and NetworkAgent with MessageUtils + // for debugging purposes, and crashes if some messages have the same values. + // TODO: have ConnectivityService store message names in different maps and remove this base + private static final int BASE = 200; /** * Sent by ConnectivityService to the NetworkAgent to inform it of From 92ebd70044634ddb502dd8bd999e8e528e68d04d Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 22 Feb 2021 18:36:38 +0800 Subject: [PATCH 129/343] Replace the usage of UidRange UidRange is used in a shared way between ConnectivityService and VPN through the use of NetworkCapabilities. UidRange will be part of the ConnectivityService mainline but Vpn.java will stay in the framework. We need a way to replace the APIs using UidRange, or to make UidRange system API. The only really relevant surface here is NetworkCapabilities#{setUids, getUids}. The need for UidRange could be replaced by an integer Range, so replace the usage of UidRange by a integer Range in NetworkCapabilities#{setUids, getUids} and update the relevant callers. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCasesLatestSdk Change-Id: I4e5aec6ef1ea02e038fcd7ed117a3b67b69c5cb9 --- .../src/android/net/NetworkCapabilities.java | 31 ++++++++++++------- framework/src/android/net/NetworkRequest.java | 5 +-- framework/src/android/net/UidRange.java | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 058f3c999d..ba9f21b261 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -32,6 +32,7 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; +import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -153,7 +154,7 @@ public final class NetworkCapabilities implements Parcelable { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - setUids(nc.mUids); // Will make the defensive copy + mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -1458,9 +1459,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - final ArraySet identity = new ArraySet<>(1); - identity.add(new UidRange(uid, uid)); - setUids(identity); + mUids = new ArraySet<>(1); + mUids.add(new UidRange(uid, uid)); return this; } @@ -1469,12 +1469,8 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(Set uids) { - if (null == uids) { - mUids = null; - } else { - mUids = new ArraySet<>(uids); - } + public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { + mUids = UidRange.fromIntRanges(uids); return this; } @@ -1483,8 +1479,19 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public @Nullable Set getUids() { - return null == mUids ? null : new ArraySet<>(mUids); + public @Nullable Set> getUids() { + return UidRange.toIntRanges(mUids); + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set getUidRanges() { + if (mUids == null) return null; + + return new ArraySet<>(mUids); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index dbe3ecc4d7..4ebbf06c51 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -45,6 +45,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; +import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -277,11 +278,11 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @param uids The watched UIDs as a set of {@code Range}, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(Set uids) { + public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; } diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java index 26518d32ed..bc67c745c9 100644 --- a/framework/src/android/net/UidRange.java +++ b/framework/src/android/net/UidRange.java @@ -20,8 +20,11 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Range; import java.util.Collection; +import java.util.Set; /** * An inclusive range of UIDs. @@ -149,4 +152,32 @@ public final class UidRange implements Parcelable { } return false; } + + /** + * Convert a set of {@code Range} to a set of {@link UidRange}. + */ + @Nullable + public static ArraySet fromIntRanges(@Nullable Set> ranges) { + if (null == ranges) return null; + + final ArraySet uids = new ArraySet<>(); + for (Range range : ranges) { + uids.add(new UidRange(range.getLower(), range.getUpper())); + } + return uids; + } + + /** + * Convert a set of {@link UidRange} to a set of {@code Range}. + */ + @Nullable + public static ArraySet> toIntRanges(@Nullable Set ranges) { + if (null == ranges) return null; + + final ArraySet> uids = new ArraySet<>(); + for (UidRange range : ranges) { + uids.add(new Range(range.start, range.stop)); + } + return uids; + } } From 0c32e09028fffb8fb0008a3d86561f2bedc1d6c9 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 11 Mar 2021 16:13:13 +0800 Subject: [PATCH 130/343] Expose uids related APIs in NetworkRequest and NetworkCapabilities NetworkRequest is moving into the incoming connectivity mainline module. The hidden setUids becomes inaccessible outside the module. Shims for support cts in different API levels will need to use it to verify the behavior of NetworkRequest. Thus, expose it to the API surface. Also, VPN uses getUids and setUids to control network capabilities. Networkcapabilities is a part of incoming connectivity mainline module but VPN is not. Thus, exposing these two methods are needed to allow VPN to continue using it. Test: make update-api Bug: 172183305 Change-Id: I107c329d4d7130d488772166eae8b5e7aaa2ff04 --- framework/api/module-lib-current.txt | 9 ++++++++ .../src/android/net/NetworkCapabilities.java | 21 +++++++++++++++++++ framework/src/android/net/NetworkRequest.java | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index bb296476c7..6339094341 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -27,9 +27,18 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + method @Nullable public java.util.Set> getUids(); field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static final class NetworkCapabilities.Builder { + method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); + } + + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); + } + public class ParseException extends java.lang.RuntimeException { ctor public ParseException(@NonNull String); ctor public ParseException(@NonNull String, @NonNull Throwable); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index ba9f21b261..182bc7141a 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -1477,8 +1478,13 @@ public final class NetworkCapabilities implements Parcelable { /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. + * + * @return the list of UIDs this network applies to. If {@code null}, then the network applies + * to all UIDs. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("NullableCollection") public @Nullable Set> getUids() { return UidRange.toIntRanges(mUids); } @@ -2661,6 +2667,21 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Set the list of UIDs this network applies to. + * + * @param uids the list of UIDs this network applies to, or {@code null} if this network + * applies to all UIDs. + * @return this builder + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder setUids(@Nullable Set> uids) { + mCaps.setUids(uids); + return this; + } + /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4ebbf06c51..cf131f0df6 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -282,6 +283,9 @@ public class NetworkRequest implements Parcelable { * @return The builder to facilitate chaining. * @hide */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("MissingGetterMatchingBuilder") public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; From eb6aa22205385bf334031382d17357f597a01ee6 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 14 Mar 2021 12:56:26 +0900 Subject: [PATCH 131/343] Add framework-connectivity.impl The library will be included in the connectivity module APEX when migrating its sources out of framework-minus-apex. Bug: 171540887 Test: m Change-Id: I1595521eaced6e6997c076bb56b06ffdd22a4fa0 --- framework/Android.bp | 35 +++++++++++++++++++++++++++++++++++ framework/jarjar-rules.txt | 7 +++++++ 2 files changed, 42 insertions(+) create mode 100644 framework/jarjar-rules.txt diff --git a/framework/Android.bp b/framework/Android.bp index 86b85e8398..86433e1c38 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -83,3 +83,38 @@ java_sdk_library { ], permitted_packages: ["android.net", "com.android.connectivity.aidl"], } + +java_library { + name: "framework-connectivity.impl", + // Instead of building against private API (framework.jar), + // build against core_platform + framework-minus-apex + module + // stub libs. This allows framework.jar to depend on this library, + // so it can be part of the private API until all clients have been migrated. + // TODO: just build against module_api, and remove this jar from + // the private API. + sdk_version: "core_platform", + srcs: [ + ":framework-connectivity-sources", + ], + aidl: { + include_dirs: [ + "frameworks/base/core/java", // For framework parcelables + "frameworks/native/aidl/binder", // For PersistableBundle.aidl + ], + }, + libs: [ + "framework-minus-apex", + // TODO: just framework-tethering, framework-wifi when building against module_api + "framework-tethering.stubs.module_lib", + "framework-wifi.stubs.module_lib", + "unsupportedappusage", + "ServiceConnectivityResources", + ], + static_libs: [ + "net-utils-device-common", + ], + jarjar_rules: "jarjar-rules.txt", + apex_available: ["com.android.tethering"], + installable: true, + permitted_packages: ["android.net", "com.android.connectivity.aidl"], +} diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt new file mode 100644 index 0000000000..381a4ac875 --- /dev/null +++ b/framework/jarjar-rules.txt @@ -0,0 +1,7 @@ +rule com.android.net.module.util.** android.net.connectivity.framework.util.@1 + +# TODO (b/149403767): remove the annotations from net-utils-device-common instead of here +zap android.annotation.** +zap com.android.net.module.annotation.** +zap com.android.internal.annotations.** + From f9294e7cd1a9bd3772a66636c0f181b486052dd3 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 18 Mar 2021 09:44:34 +0800 Subject: [PATCH 132/343] Expose APIs for Settings ConnectivityManager will be a part of incoming connectivity mainline. Settings will no longer to access the hidden methods. For those methods that accept the interaction from users, they should be exposed as formal interface to allow the functionality. Expose them to API surface. Bug: 172183305 Test: make update-api Change-Id: Id4533b94291766bb060af0091b5ccb81a00630fd --- framework/api/module-lib-current.txt | 6 +++ .../src/android/net/ConnectivityManager.java | 38 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index bb296476c7..f4469417e3 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -6,11 +6,17 @@ package android.net { } public class ConnectivityManager { + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset(); method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List getAllNetworkStateSnapshot(); + method @Nullable public android.net.ProxyInfo getGlobalProxy(); method @NonNull public static android.util.Range getIpSecNetIdRange(); method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network); + method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo); method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); field public static final String PRIVATE_DNS_MODE_OFF = "off"; diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index a621233e32..0434f32ea4 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -3038,8 +3038,9 @@ public class ConnectivityManager { * HTTP proxy. A {@code null} value will clear the global HTTP proxy. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setGlobalProxy(ProxyInfo p) { + public void setGlobalProxy(@Nullable ProxyInfo p) { try { mService.setGlobalProxy(p); } catch (RemoteException e) { @@ -3054,6 +3055,8 @@ public class ConnectivityManager { * if no global HTTP proxy is set. * @hide */ + @SystemApi(client = MODULE_LIBRARIES) + @Nullable public ProxyInfo getGlobalProxy() { try { return mService.getGlobalProxy(); @@ -4388,8 +4391,13 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void setAcceptUnvalidated(Network network, boolean accept, boolean always) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAcceptUnvalidated(@NonNull Network network, boolean accept, boolean always) { try { mService.setAcceptUnvalidated(network, accept, always); } catch (RemoteException e) { @@ -4411,8 +4419,14 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAcceptPartialConnectivity(@NonNull Network network, boolean accept, + boolean always) { try { mService.setAcceptPartialConnectivity(network, accept, always); } catch (RemoteException e) { @@ -4430,8 +4444,13 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void setAvoidUnvalidated(Network network) { + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + public void setAvoidUnvalidated(@NonNull Network network) { try { mService.setAvoidUnvalidated(network); } catch (RemoteException e) { @@ -4561,7 +4580,10 @@ public class ConnectivityManager { * Resets all connectivity manager settings back to factory defaults. * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset() { try { mService.factoryReset(); From c9925e096be99759f500698709f5e0c684c4fe31 Mon Sep 17 00:00:00 2001 From: paulhu Date: Wed, 17 Mar 2021 20:30:33 +0800 Subject: [PATCH 133/343] Add more connectivity module settings Add more connectivity module settings and update all references to ConnectivitySettingsManager. Bug: 182538166 Test: atest FrameworksNetTests Change-Id: Ie96fbd0996ed3acb37099b6270bf3d4c2e558e9a --- .../src/android/net/ConnectivityManager.java | 4 +- .../net/ConnectivitySettingsManager.java | 195 ++++++++++++++++++ 2 files changed, 197 insertions(+), 2 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 8b669284ad..b350bc2527 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -16,6 +16,8 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE; +import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE; import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST; import static android.net.NetworkRequest.Type.LISTEN; import static android.net.NetworkRequest.Type.REQUEST; @@ -23,8 +25,6 @@ import static android.net.NetworkRequest.Type.TRACK_BEST; import static android.net.NetworkRequest.Type.TRACK_DEFAULT; import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT; import static android.net.QosCallback.QosCallbackRegistrationException; -import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; -import static android.provider.Settings.Global.PRIVATE_DNS_MODE; import android.annotation.CallbackExecutor; import android.annotation.IntDef; diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java index d454365452..bbd83931ee 100644 --- a/framework/src/android/net/ConnectivitySettingsManager.java +++ b/framework/src/android/net/ConnectivitySettingsManager.java @@ -16,6 +16,11 @@ package android.net; +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * A manager class for connectivity module settings. * @@ -25,6 +30,196 @@ public class ConnectivitySettingsManager { private ConnectivitySettingsManager() {} + /** Data activity timeout settings */ + + /** + * Inactivity timeout to track mobile data activity. + * + * If set to a positive integer, it indicates the inactivity timeout value in seconds to + * infer the data activity of mobile network. After a period of no activity on mobile + * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE} + * intent is fired to indicate a transition of network status from "active" to "idle". Any + * subsequent activity on mobile networks triggers the firing of {@code + * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active". + * + * Network activity refers to transmitting or receiving data on the network interfaces. + * + * Tracking is disabled if set to zero or negative value. + */ + public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile"; + + /** + * Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE} + * but for Wifi network. + */ + public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi"; + + /** Dns resolver settings */ + + /** + * Sample validity in seconds to configure for the system DNS resolver. + */ + public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS = + "dns_resolver_sample_validity_seconds"; + + /** + * Success threshold in percent for use with the system DNS resolver. + */ + public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT = + "dns_resolver_success_threshold_percent"; + + /** + * Minimum number of samples needed for statistics to be considered meaningful in the + * system DNS resolver. + */ + public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples"; + + /** + * Maximum number taken into account for statistics purposes in the system DNS resolver. + */ + public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples"; + + /** Network switch notification settings */ + + /** + * The maximum number of notifications shown in 24 hours when switching networks. + */ + public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT = + "network_switch_notification_daily_limit"; + + /** + * The minimum time in milliseconds between notifications when switching networks. + */ + public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS = + "network_switch_notification_rate_limit_millis"; + + /** Captive portal settings */ + + /** + * The URL used for HTTP captive portal detection upon a new connection. + * A 204 response code from the server is used for validation. + */ + public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url"; + + /** + * What to do when connecting a network that presents a captive portal. + * Must be one of the CAPTIVE_PORTAL_MODE_* constants above. + * + * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT. + */ + public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode"; + + /** + * Don't attempt to detect captive portals. + */ + public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; + + /** + * When detecting a captive portal, display a notification that + * prompts the user to sign in. + */ + public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; + + /** + * When detecting a captive portal, immediately disconnect from the + * network and do not reconnect to that network in the future. + */ + public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + CAPTIVE_PORTAL_MODE_IGNORE, + CAPTIVE_PORTAL_MODE_PROMPT, + CAPTIVE_PORTAL_MODE_AVOID, + }) + public @interface CaptivePortalMode {} + + /** Global http proxy settings */ + + /** + * Host name for global http proxy. Set via ConnectivityManager. + */ + public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host"; + + /** + * Integer host port for global http proxy. Set via ConnectivityManager. + */ + public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port"; + + /** + * Exclusion list for global proxy. This string contains a list of + * comma-separated domains where the global proxy does not apply. + * Domains should be listed in a comma- separated list. Example of + * acceptable formats: ".domain1.com,my.domain2.com" Use + * ConnectivityManager to set/get. + */ + public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST = + "global_http_proxy_exclusion_list"; + + /** + * The location PAC File for the proxy. + */ + public static final String GLOBAL_HTTP_PROXY_PAC = "global_proxy_pac_url"; + + /** Private dns settings */ + + /** + * The requested Private DNS mode (string), and an accompanying specifier (string). + * + * Currently, the specifier holds the chosen provider name when the mode requests + * a specific provider. It may be used to store the provider name even when the + * mode changes so that temporarily disabling and re-enabling the specific + * provider mode does not necessitate retyping the provider hostname. + */ + public static final String PRIVATE_DNS_MODE = "private_dns_mode"; + + /** + * The specific Private DNS provider name. + */ + public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier"; + + /** + * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic"). + * This allows changing the default mode without effectively disabling other modes, + * all of which require explicit user action to enable/configure. See also b/79719289. + * + * Value is a string, suitable for assignment to PRIVATE_DNS_MODE above. + */ + public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode"; + + /** Other settings */ + + /** + * The number of milliseconds to hold on to a PendingIntent based request. This delay gives + * the receivers of the PendingIntent an opportunity to make a new network request before + * the Network satisfying the request is potentially removed. + */ + public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS = + "connectivity_release_pending_intent_delay_ms"; + + /** + * Whether the mobile data connection should remain active even when higher + * priority networks like WiFi are active, to help make network switching faster. + * + * See ConnectivityService for more info. + * + * (0 = disabled, 1 = enabled) + */ + public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on"; + + /** + * Whether the wifi data connection should remain active even when higher + * priority networks like Ethernet are active, to keep both networks. + * In the case where higher priority networks are connected, wifi will be + * unused unless an application explicitly requests to use it. + * + * See ConnectivityService for more info. + * + * (0 = disabled, 1 = enabled) + */ + public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested"; + /** * Whether to automatically switch away from wifi networks that lose Internet access. * Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always From 1fdeb50d9afa334647c1a6e8d5c042ce62de1741 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 14:23:12 +0900 Subject: [PATCH 134/343] Add multipath preference, background status API Add APIs for getMultipathPreference and getRestrictBackgroundStatus. Both are used by Connectivity to back the external ConnectivityManager.getRestrictBackgroundStatus, and ConnectivityManager.getMultipathPreference APIs. Test: atest CtsNetTestCases atest ConnectivityServiceTests atest NetworkPolicyManagerServiceTest Bug: 176289731 Change-Id: I8a03162b2f6691086bb64e75ffd354cdfca7f86a --- .../src/android/net/ConnectivityManager.java | 15 +-------------- .../src/android/net/IConnectivityManager.aidl | 2 ++ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index ba5eb1090d..ace029161c 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -62,7 +62,6 @@ import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; -import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.UserHandle; import android.provider.Settings; @@ -842,7 +841,6 @@ public class ConnectivityManager { private final Context mContext; - private INetworkPolicyManager mNPManager; private final TetheringManager mTetheringManager; /** @@ -4764,17 +4762,6 @@ public class ConnectivityManager { public @interface RestrictBackgroundStatus { } - private INetworkPolicyManager getNetworkPolicyManager() { - synchronized (this) { - if (mNPManager != null) { - return mNPManager; - } - mNPManager = INetworkPolicyManager.Stub.asInterface(ServiceManager - .getService(Context.NETWORK_POLICY_SERVICE)); - return mNPManager; - } - } - /** * Determines if the calling application is subject to metered network restrictions while * running on background. @@ -4785,7 +4772,7 @@ public class ConnectivityManager { */ public @RestrictBackgroundStatus int getRestrictBackgroundStatus() { try { - return getNetworkPolicyManager().getRestrictBackgroundByCaller(); + return mService.getRestrictBackgroundStatusByCaller(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index d83cc163b5..98f3d40c0b 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -220,4 +220,6 @@ interface IConnectivityManager void setProfileNetworkPreference(in UserHandle profile, int preference, in IOnCompleteListener listener); + + int getRestrictBackgroundStatusByCaller(); } From efd24e0f3a33ac37a42a2b0e156c4b44675840eb Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 07:10:38 +0000 Subject: [PATCH 135/343] Remove extra comment This fixes a merge conflict with downstream branches due to an incomplete cherry-pick. Bug: 171540887 Test: m Merged-In: I0c0daa91ef272a19c548cf55eb2f764c95f8f844 Change-Id: I0ec602f573698578e4d72d38772c39a1b88b87d2 --- framework/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/Android.bp b/framework/Android.bp index 2aa56e2fe4..86433e1c38 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -23,7 +23,6 @@ package { default_applicable_licenses: ["frameworks_base_license"], } -// TODO: use a java_library in the bootclasspath instead filegroup { name: "framework-connectivity-internal-sources", srcs: [ From 8c2d521b8d4813a431bb190effc7c1d50c905982 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 14 Mar 2021 15:28:10 +0900 Subject: [PATCH 136/343] Add connectivity protos to framework-connectivity The protos are built separately by framework-connectivity from framework protos, keeping only android.net protos for the connectivity jar. Bug: 171860710 Test: m framework-connectivity.impl Change-Id: I2c4a37ff2ee9e8efde49885feeafa27dcff7ca2c --- framework/Android.bp | 20 ++++++++++++++++++++ framework/jarjar-rules-proto.txt | 3 +++ framework/jarjar-rules.txt | 3 +++ 3 files changed, 26 insertions(+) create mode 100644 framework/jarjar-rules-proto.txt diff --git a/framework/Android.bp b/framework/Android.bp index 86433e1c38..017ff51f36 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -23,6 +23,25 @@ package { default_applicable_licenses: ["frameworks_base_license"], } +java_library { + name: "framework-connectivity-protos", + proto: { + type: "nano", + }, + srcs: [ + // TODO: consider moving relevant .proto files directly to the module directory + ":framework-javastream-protos", + ], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], + jarjar_rules: "jarjar-rules-proto.txt", + visibility: [ + "//visibility:private", + ], +} + filegroup { name: "framework-connectivity-internal-sources", srcs: [ @@ -111,6 +130,7 @@ java_library { "ServiceConnectivityResources", ], static_libs: [ + "framework-connectivity-protos", "net-utils-device-common", ], jarjar_rules: "jarjar-rules.txt", diff --git a/framework/jarjar-rules-proto.txt b/framework/jarjar-rules-proto.txt new file mode 100644 index 0000000000..37b4dec1c3 --- /dev/null +++ b/framework/jarjar-rules-proto.txt @@ -0,0 +1,3 @@ +keep android.net.NetworkCapabilitiesProto +keep android.net.NetworkProto +keep android.net.NetworkRequestProto diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt index 381a4ac875..0959840f2d 100644 --- a/framework/jarjar-rules.txt +++ b/framework/jarjar-rules.txt @@ -5,3 +5,6 @@ zap android.annotation.** zap com.android.net.module.annotation.** zap com.android.internal.annotations.** +rule android.net.NetworkCapabilitiesProto* android.net.connectivity.proto.NetworkCapabilitiesProto@1 +rule android.net.NetworkProto* android.net.connectivity.proto.NetworkProto@1 +rule android.net.NetworkRequestProto* android.net.connectivity.proto.NetworkRequestProto@1 From 749a39a4318a48156c8f92466869787c7a1bee76 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 17 Mar 2021 23:14:53 +0900 Subject: [PATCH 137/343] Migrate framework-connectivity internal resources Use ServiceConnectivityResources instead. Start by creating resources in the ServiceConnectivityResources package to match the internal configuration, and common overlays. Bug: 182125649 Test: device boots, has connectivity Change-Id: I77a3efca2cd644f9828db1ed5d3cae8070fb8363 --- .../android/net/ConnectivityResources.java | 108 ++++++++++++++++++ .../src/android/net/apf/ApfCapabilities.java | 48 +++++++- .../src/android/net/util/KeepaliveUtils.java | 10 +- .../net/util/MultinetworkPolicyTracker.java | 18 ++- .../ServiceConnectivityResources/Android.bp | 2 +- .../res/values-mcc204-mnc04/config.xml | 27 +++++ .../res/values-mcc310-mnc004/config.xml | 27 +++++ .../res/values-mcc311-mnc480/config.xml | 27 +++++ .../res/values/config.xml | 39 ++++++- .../res/values/overlayable.xml | 5 + 10 files changed, 296 insertions(+), 15 deletions(-) create mode 100644 framework/src/android/net/ConnectivityResources.java create mode 100644 service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml create mode 100644 service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml create mode 100644 service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml diff --git a/framework/src/android/net/ConnectivityResources.java b/framework/src/android/net/ConnectivityResources.java new file mode 100644 index 0000000000..18f0de0cc9 --- /dev/null +++ b/framework/src/android/net/ConnectivityResources.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.List; + +/** + * Utility to obtain the {@link com.android.server.ConnectivityService} {@link Resources}, in the + * ServiceConnectivityResources APK. + * @hide + */ +public class ConnectivityResources { + private static final String RESOURCES_APK_INTENT = + "com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK"; + private static final String RES_PKG_DIR = "/apex/com.android.tethering/"; + + @NonNull + private final Context mContext; + + @Nullable + private Context mResourcesContext = null; + + @Nullable + private static Context sTestResourcesContext = null; + + public ConnectivityResources(Context context) { + mContext = context; + } + + /** + * Convenience method to mock all resources for the duration of a test. + * + * Call with a null context to reset after the test. + */ + @VisibleForTesting + public static void setResourcesContextForTest(@Nullable Context testContext) { + sTestResourcesContext = testContext; + } + + /** + * Get the {@link Context} of the resources package. + */ + public synchronized Context getResourcesContext() { + if (sTestResourcesContext != null) { + return sTestResourcesContext; + } + + if (mResourcesContext != null) { + return mResourcesContext; + } + + final List pkgs = mContext.getPackageManager() + .queryIntentActivities(new Intent(RESOURCES_APK_INTENT), MATCH_SYSTEM_ONLY); + pkgs.removeIf(pkg -> !pkg.activityInfo.applicationInfo.sourceDir.startsWith(RES_PKG_DIR)); + if (pkgs.size() > 1) { + Log.wtf(ConnectivityResources.class.getSimpleName(), + "More than one package found: " + pkgs); + } + if (pkgs.isEmpty()) { + throw new IllegalStateException("No connectivity resource package found"); + } + + final Context pkgContext; + try { + pkgContext = mContext.createPackageContext( + pkgs.get(0).activityInfo.applicationInfo.packageName, 0 /* flags */); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("Resolved package not found", e); + } + + mResourcesContext = pkgContext; + return pkgContext; + } + + /** + * Get the {@link Resources} of the ServiceConnectivityResources APK. + */ + public Resources get() { + return getResourcesContext().getResources(); + } +} diff --git a/framework/src/android/net/apf/ApfCapabilities.java b/framework/src/android/net/apf/ApfCapabilities.java index bf5b26e278..85b24713f2 100644 --- a/framework/src/android/net/apf/ApfCapabilities.java +++ b/framework/src/android/net/apf/ApfCapabilities.java @@ -19,12 +19,12 @@ package android.net.apf; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.R; - /** * APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible * way to drop unwanted network packets to save power. @@ -36,6 +36,8 @@ import com.android.internal.R; */ @SystemApi public final class ApfCapabilities implements Parcelable { + private static ConnectivityResources sResources; + /** * Version of APF instruction set supported for packet filtering. 0 indicates no support for * packet filtering using APF programs. @@ -65,6 +67,14 @@ public final class ApfCapabilities implements Parcelable { apfPacketFormat = in.readInt(); } + @NonNull + private static synchronized ConnectivityResources getResources(@NonNull Context ctx) { + if (sResources == null) { + sResources = new ConnectivityResources(ctx); + } + return sResources; + } + @Override public int describeContents() { @@ -121,13 +131,43 @@ public final class ApfCapabilities implements Parcelable { * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. */ public static boolean getApfDrop8023Frames() { - return Resources.getSystem().getBoolean(R.bool.config_apfDrop802_3Frames); + // TODO(b/183076074): remove reading resources from system resources + final Resources systemRes = Resources.getSystem(); + final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android"); + return systemRes.getBoolean(id); + } + + /** + * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. + * @hide + */ + public static boolean getApfDrop8023Frames(@NonNull Context context) { + final ConnectivityResources res = getResources(context); + // TODO(b/183076074): use R.bool.config_apfDrop802_3Frames directly + final int id = res.get().getIdentifier("config_apfDrop802_3Frames", "bool", + res.getResourcesContext().getPackageName()); + return res.get().getBoolean(id); } /** * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. */ public static @NonNull int[] getApfEtherTypeBlackList() { - return Resources.getSystem().getIntArray(R.array.config_apfEthTypeBlackList); + // TODO(b/183076074): remove reading resources from system resources + final Resources systemRes = Resources.getSystem(); + final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android"); + return systemRes.getIntArray(id); + } + + /** + * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. + * @hide + */ + public static @NonNull int[] getApfEtherTypeDenyList(@NonNull Context context) { + final ConnectivityResources res = getResources(context); + // TODO(b/183076074): use R.array.config_apfEthTypeDenyList directly + final int id = res.get().getIdentifier("config_apfEthTypeDenyList", "array", + res.getResourcesContext().getPackageName()); + return res.get().getIntArray(id); } } diff --git a/framework/src/android/net/util/KeepaliveUtils.java b/framework/src/android/net/util/KeepaliveUtils.java index bfc4563fbf..8d7a0b3d02 100644 --- a/framework/src/android/net/util/KeepaliveUtils.java +++ b/framework/src/android/net/util/KeepaliveUtils.java @@ -19,12 +19,11 @@ package android.net.util; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.net.NetworkCapabilities; import android.text.TextUtils; import android.util.AndroidRuntimeException; -import com.android.internal.R; - /** * Collection of utilities for socket keepalive offload. * @@ -52,8 +51,11 @@ public final class KeepaliveUtils { public static int[] getSupportedKeepalives(@NonNull Context context) { String[] res = null; try { - res = context.getResources().getStringArray( - R.array.config_networkSupportedKeepaliveCount); + final ConnectivityResources connRes = new ConnectivityResources(context); + // TODO: use R.id.config_networkSupportedKeepaliveCount directly + final int id = connRes.get().getIdentifier("config_networkSupportedKeepaliveCount", + "array", connRes.getResourcesContext().getPackageName()); + res = new ConnectivityResources(context).get().getStringArray(id); } catch (Resources.NotFoundException unused) { } if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource"); diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java index 6a49aa2576..0b42a00369 100644 --- a/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.ContentObserver; +import android.net.ConnectivityResources; import android.net.Uri; import android.os.Handler; import android.provider.Settings; @@ -35,7 +36,6 @@ import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; @@ -64,6 +64,7 @@ public class MultinetworkPolicyTracker { private static String TAG = MultinetworkPolicyTracker.class.getSimpleName(); private final Context mContext; + private final ConnectivityResources mResources; private final Handler mHandler; private final Runnable mAvoidBadWifiCallback; private final List mSettingsUris; @@ -107,6 +108,7 @@ public class MultinetworkPolicyTracker { public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) { mContext = ctx; + mResources = new ConnectivityResources(ctx); mHandler = handler; mAvoidBadWifiCallback = avoidBadWifiCallback; mSettingsUris = Arrays.asList( @@ -160,12 +162,16 @@ public class MultinetworkPolicyTracker { * Whether the device or carrier configuration disables avoiding bad wifi by default. */ public boolean configRestrictsAvoidBadWifi() { - return (getResourcesForActiveSubId().getInteger(R.integer.config_networkAvoidBadWifi) == 0); + // TODO: use R.integer.config_networkAvoidBadWifi directly + final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi", + "integer", mResources.getResourcesContext().getPackageName()); + return (getResourcesForActiveSubId().getInteger(id) == 0); } @NonNull private Resources getResourcesForActiveSubId() { - return SubscriptionManager.getResourcesForSubId(mContext, mActiveSubId); + return SubscriptionManager.getResourcesForSubId( + mResources.getResourcesContext(), mActiveSubId); } /** @@ -205,8 +211,10 @@ public class MultinetworkPolicyTracker { * The default (device and carrier-dependent) value for metered multipath preference. */ public int configMeteredMultipathPreference() { - return mContext.getResources().getInteger( - R.integer.config_networkMeteredMultipathPreference); + // TODO: use R.integer.config_networkMeteredMultipathPreference directly + final int id = mResources.get().getIdentifier("config_networkMeteredMultipathPreference", + "integer", mResources.getResourcesContext().getPackageName()); + return mResources.get().getInteger(id); } public void updateMeteredMultipathPreference() { diff --git a/service/ServiceConnectivityResources/Android.bp b/service/ServiceConnectivityResources/Android.bp index f2446b7f7e..fa4501ac7f 100644 --- a/service/ServiceConnectivityResources/Android.bp +++ b/service/ServiceConnectivityResources/Android.bp @@ -21,7 +21,7 @@ package { android_app { name: "ServiceConnectivityResources", - sdk_version: "system_current", + sdk_version: "module_current", resource_dirs: [ "res", ], diff --git a/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml b/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml new file mode 100644 index 0000000000..7e7025fb04 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml @@ -0,0 +1,27 @@ + + + + + + + 0 + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml b/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml new file mode 100644 index 0000000000..7e7025fb04 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml @@ -0,0 +1,27 @@ + + + + + + + 0 + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml new file mode 100644 index 0000000000..7e7025fb04 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml @@ -0,0 +1,27 @@ + + + + + + + 0 + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml index 06c81921fd..71674e4dc6 100644 --- a/service/ServiceConnectivityResources/res/values/config.xml +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -52,4 +52,41 @@ 12,60000 - \ No newline at end of file + + true + + + + 0x88A2 + 0x88A4 + 0x88B8 + 0x88CD + 0x88E3 + + + + + + 0,1 + 1,3 + + + + + 0 + + + 1 + + diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml index da8aee5627..25e19cedbb 100644 --- a/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -21,6 +21,11 @@ + + + + + From d8bc0faf7da4cde13ba91a838feb4fc29b6605dd Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 11 Mar 2021 15:41:52 +0900 Subject: [PATCH 138/343] Add SystemMessages protos to Connectivity This follows the model used for the same protos by the Wifi module in service-wifi. SystemMessageProto is used by NetworkNotificationManager to define IDs for notifications that are also counted in system notification metrics. Bug: 171860710 Test: m Change-Id: Iec674913fad9ad59c04249714a08b5a0d8ab0f84 --- service/Android.bp | 16 ++++++++++++++++ service/jarjar-rules.txt | 3 +++ service/proto/connectivityproto.proto | 20 ++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 service/proto/connectivityproto.proto diff --git a/service/Android.bp b/service/Android.bp index f630ceac36..1330e719e7 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -68,6 +68,7 @@ java_library { "net-utils-framework-common", "netd-client", "PlatformProperties", + "service-connectivity-protos", ], apex_available: [ "//apex_available:platform", @@ -75,6 +76,21 @@ java_library { ], } +java_library { + name: "service-connectivity-protos", + proto: { + type: "nano", + }, + srcs: [ + ":system-messages-proto-src", + ], + libs: ["libprotobuf-java-nano"], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], +} + java_library { name: "service-connectivity", installable: true, diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt index a7b419b020..5caa11b11a 100644 --- a/service/jarjar-rules.txt +++ b/service/jarjar-rules.txt @@ -12,3 +12,6 @@ rule android.util.LocalLog* com.android.connectivity.util.LocalLog@1 # the one in com.android.internal.util rule android.util.IndentingPrintWriter* android.connectivity.util.IndentingPrintWriter@1 rule com.android.internal.util.** com.android.connectivity.util.@1 + +rule com.android.internal.messages.** com.android.connectivity.messages.@1 +rule com.google.protobuf.** com.android.connectivity.protobuf.@1 diff --git a/service/proto/connectivityproto.proto b/service/proto/connectivityproto.proto new file mode 100644 index 0000000000..a992d7c263 --- /dev/null +++ b/service/proto/connectivityproto.proto @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +// Connectivity protos can be created in this directory. Note this file must be included before +// building system-messages-proto, otherwise it will not build by itself. From 8e0c1f0850a2f2f830294bb20d583c716f908a2a Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 18 Mar 2021 20:30:22 +0800 Subject: [PATCH 139/343] Expose getCapabilities Expose getCapabilities() for EthernetNetworkFactory. Bug: 182963415 Test: m ethernet-service Change-Id: I430416af8fae3d4ee99f2f2abe529e3051e9e5cb --- framework/api/current.txt | 1 + framework/src/android/net/NetworkCapabilities.java | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/framework/api/current.txt b/framework/api/current.txt index f22d4b7b77..e415e01fea 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -291,6 +291,7 @@ package android.net { ctor public NetworkCapabilities(); ctor public NetworkCapabilities(android.net.NetworkCapabilities); method public int describeContents(); + method @NonNull public int[] getCapabilities(); method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 058f3c999d..5ec7aa1b23 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -609,10 +609,8 @@ public final class NetworkCapabilities implements Parcelable { * Gets all the capabilities set on this {@code NetworkCapability} instance. * * @return an array of capability values for this instance. - * @hide */ - @UnsupportedAppUsage - public @NetCapability int[] getCapabilities() { + public @NonNull @NetCapability int[] getCapabilities() { return NetworkCapabilitiesUtils.unpackBits(mNetworkCapabilities); } From 8238a7665a0222e11289c222f83bf62210bc5d27 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 16 Mar 2021 18:06:06 +0900 Subject: [PATCH 140/343] Add startCaptivePortalApp to system API The API is already used by settings and should be usable by setup wizards. It is the only way for a caller outside of the system_server to trigger the captive portal application. The API is already CTS tested in android.net.cts.CaptivePortalTest. Fixes: 182871577 Test: atest CtsNetTestCases:android.net.cts.CaptivePortalTest Change-Id: Ie8d9a546b54524ba837715baa94a07d1f993d8d3 --- framework/api/module-lib-current.txt | 1 + framework/src/android/net/ConnectivityManager.java | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index ab039165ad..37312fa79d 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -19,6 +19,7 @@ package android.net { method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo); method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network); method public void systemReady(); field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 786ed240e3..fe05f3a9de 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4461,12 +4461,20 @@ public class ConnectivityManager { /** * Requests that the system open the captive portal app on the specified network. * + *

    This is to be used on networks where a captive portal was detected, as per + * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}. + * * @param network The network to log into. * * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) - public void startCaptivePortalApp(Network network) { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) + public void startCaptivePortalApp(@NonNull Network network) { try { mService.startCaptivePortalApp(network); } catch (RemoteException e) { From 342ddddd9dbe2ee06daede95ff7bec81d5226e65 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 23:27:19 +0900 Subject: [PATCH 141/343] Add InetAddressCompat Although the InetAddress symbols used by Connectivity are stable core platform API, and should be usable, the core_current stubs are not yet part of the module_current API. Until that is fixed, add an InetAddressCompat utility that calls the three static methods by reflection. Test: atest FrameworksNetTests CtsNetTestCases Bug: 183097033 Change-Id: I797009aeff1d39ae2dc06ef69d2e235689b43c89 --- .../src/android/net/ConnectivityManager.java | 2 +- .../src/android/net/InetAddressCompat.java | 76 +++++++++++++++++++ framework/src/android/net/Network.java | 4 +- 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 framework/src/android/net/InetAddressCompat.java diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index a621233e32..dcb80e6240 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4639,7 +4639,7 @@ public class ConnectivityManager { Log.e(TAG, "Can't set proxy properties", e); } // Must flush DNS cache as new network may have different DNS resolutions. - InetAddress.clearDnsCache(); + InetAddressCompat.clearDnsCache(); // Must flush socket pool as idle sockets will be bound to previous network and may // cause subsequent fetches to be performed on old network. NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged(); diff --git a/framework/src/android/net/InetAddressCompat.java b/framework/src/android/net/InetAddressCompat.java new file mode 100644 index 0000000000..8404441de6 --- /dev/null +++ b/framework/src/android/net/InetAddressCompat.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.util.Log; + +import java.lang.reflect.InvocationTargetException; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Compatibility utility for InetAddress core platform APIs. + * + * Connectivity has access to such APIs, but they are not part of the module_current stubs yet + * (only core_current). Most stable core platform APIs are included manually in the connectivity + * build rules, but because InetAddress is also part of the base java SDK that is earlier on the + * classpath, the extra core platform APIs are not seen. + * + * TODO (b/183097033): remove this utility as soon as core_current is part of module_current + * @hide + */ +public class InetAddressCompat { + + /** + * @see InetAddress#clearDnsCache() + */ + public static void clearDnsCache() { + try { + InetAddress.class.getMethod("clearDnsCache").invoke(null); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e); + } + } + + /** + * @see InetAddress#getAllByNameOnNet(String, int) + */ + public static InetAddress[] getAllByNameOnNet(String host, int netId) throws + UnknownHostException { + try { + return (InetAddress[]) InetAddress.class.getMethod("getAllByNameOnNet", + String.class, int.class).invoke(null, host, netId); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); + throw new IllegalStateException("Error querying via getAllNameOnNet", e); + } + } + + /** + * @see InetAddress#getByNameOnNet(String, int) + */ + public static InetAddress getByNameOnNet(String host, int netId) throws + UnknownHostException { + try { + return (InetAddress) InetAddress.class.getMethod("getByNameOnNet", + String.class, int.class).invoke(null, host, netId); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); + throw new IllegalStateException("Error querying via getByNameOnNet", e); + } + } +} diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java index 7245db3b17..0741414ab3 100644 --- a/framework/src/android/net/Network.java +++ b/framework/src/android/net/Network.java @@ -142,7 +142,7 @@ public class Network implements Parcelable { * @throws UnknownHostException if the address lookup fails. */ public InetAddress[] getAllByName(String host) throws UnknownHostException { - return InetAddress.getAllByNameOnNet(host, getNetIdForResolv()); + return InetAddressCompat.getAllByNameOnNet(host, getNetIdForResolv()); } /** @@ -155,7 +155,7 @@ public class Network implements Parcelable { * if the address lookup fails. */ public InetAddress getByName(String host) throws UnknownHostException { - return InetAddress.getByNameOnNet(host, getNetIdForResolv()); + return InetAddressCompat.getByNameOnNet(host, getNetIdForResolv()); } /** From 5bfc990e4a8f77c59851266ae268ce2c98b9903e Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 23:57:26 +0900 Subject: [PATCH 142/343] Move network selection utils to Connectivity NetworkScore, IOnCompleteListener should be in the Connectivity scope, as they are supporting classes for the ConnectivityManager APIs. Bug: 181512874 Test: m Change-Id: I6dc40a80e0bf5f86f5625b657b01eba969d41fcf --- .../aidl-export/android/net/NetworkScore.aidl | 20 ++++ .../src/android/net/IOnCompleteListener.aidl | 23 ++++ framework/src/android/net/NetworkScore.java | 108 ++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 framework/aidl-export/android/net/NetworkScore.aidl create mode 100644 framework/src/android/net/IOnCompleteListener.aidl create mode 100644 framework/src/android/net/NetworkScore.java diff --git a/framework/aidl-export/android/net/NetworkScore.aidl b/framework/aidl-export/android/net/NetworkScore.aidl new file mode 100644 index 0000000000..af12dcf7f1 --- /dev/null +++ b/framework/aidl-export/android/net/NetworkScore.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable NetworkScore; + diff --git a/framework/src/android/net/IOnCompleteListener.aidl b/framework/src/android/net/IOnCompleteListener.aidl new file mode 100644 index 0000000000..4bb89f6c89 --- /dev/null +++ b/framework/src/android/net/IOnCompleteListener.aidl @@ -0,0 +1,23 @@ +/** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +oneway interface IOnCompleteListener { + void onComplete(); +} diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java new file mode 100644 index 0000000000..f478010022 --- /dev/null +++ b/framework/src/android/net/NetworkScore.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Object representing the quality of a network as perceived by the user. + * + * A NetworkScore object represents the characteristics of a network that affects how good the + * network is considered for a particular use. + * @hide + */ +// TODO : @SystemApi when the implementation is complete +public final class NetworkScore implements Parcelable { + // This will be removed soon. Do *NOT* depend on it for any new code that is not part of + // a migration. + private final int mLegacyInt; + + /** @hide */ + NetworkScore(final int legacyInt) { + this.mLegacyInt = legacyInt; + } + + private NetworkScore(@NonNull final Parcel in) { + mLegacyInt = in.readInt(); + } + + public int getLegacyInt() { + return mLegacyInt; + } + + @Override + public String toString() { + return "Score(" + mLegacyInt + ")"; + } + + @Override + public void writeToParcel(@NonNull final Parcel dest, final int flags) { + dest.writeInt(mLegacyInt); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull public static final Creator CREATOR = new Creator<>() { + @Override + @NonNull + public NetworkScore createFromParcel(@NonNull final Parcel in) { + return new NetworkScore(in); + } + + @Override + @NonNull + public NetworkScore[] newArray(int size) { + return new NetworkScore[size]; + } + }; + + /** + * A builder for NetworkScore. + */ + public static final class Builder { + private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE; + private int mLegacyInt = INVALID_LEGACY_INT; + + /** + * Sets the legacy int for this score. + * + * Do not rely on this. It will be gone by the time S is released. + * + * @param score the legacy int + * @return this + */ + @NonNull + public Builder setLegacyInt(final int score) { + mLegacyInt = score; + return this; + } + + /** + * Builds this NetworkScore. + * @return The built NetworkScore object. + */ + @NonNull + public NetworkScore build() { + return new NetworkScore(mLegacyInt); + } + } +} From fa6349a6c7ce3be0c2e26fae60913de9e8152e1e Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Thu, 18 Mar 2021 16:30:59 +0000 Subject: [PATCH 143/343] Revert "Expose uids related APIs in NetworkRequest and NetworkCa..." Revert "Add shims for NetworkRequest" Revert submission 1626206-replaceUidRange Reason for revert: Breaking build - b/183106405 Reverted Changes: I0b79c73e8:Add shims for NetworkRequest I4bc0daf5a:Replace the usage of UidRange I4e5aec6ef:Replace the usage of UidRange I107c329d4:Expose uids related APIs in NetworkRequest and Net... Change-Id: I45e08f89533af0d6851add38fecb5c6c114615ae --- framework/api/module-lib-current.txt | 9 -------- .../src/android/net/NetworkCapabilities.java | 21 ------------------- framework/src/android/net/NetworkRequest.java | 4 ---- 3 files changed, 34 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 6339094341..bb296476c7 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -27,18 +27,9 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { - method @Nullable public java.util.Set> getUids(); field public static final int TRANSPORT_TEST = 7; // 0x7 } - public static final class NetworkCapabilities.Builder { - method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); - } - - public static class NetworkRequest.Builder { - method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); - } - public class ParseException extends java.lang.RuntimeException { ctor public ParseException(@NonNull String); ctor public ParseException(@NonNull String, @NonNull Throwable); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 182bc7141a..ba9f21b261 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -22,7 +22,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -1478,13 +1477,8 @@ public final class NetworkCapabilities implements Parcelable { /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. - * - * @return the list of UIDs this network applies to. If {@code null}, then the network applies - * to all UIDs. * @hide */ - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @SuppressLint("NullableCollection") public @Nullable Set> getUids() { return UidRange.toIntRanges(mUids); } @@ -2667,21 +2661,6 @@ public final class NetworkCapabilities implements Parcelable { return this; } - /** - * Set the list of UIDs this network applies to. - * - * @param uids the list of UIDs this network applies to, or {@code null} if this network - * applies to all UIDs. - * @return this builder - * @hide - */ - @NonNull - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - public Builder setUids(@Nullable Set> uids) { - mCaps.setUids(uids); - return this; - } - /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index cf131f0df6..4ebbf06c51 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -36,7 +36,6 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -283,9 +282,6 @@ public class NetworkRequest implements Parcelable { * @return The builder to facilitate chaining. * @hide */ - @NonNull - @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) - @SuppressLint("MissingGetterMatchingBuilder") public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; From b6c51b2c978fbcb9c1507b61635c64229c8ffe53 Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Thu, 18 Mar 2021 16:30:59 +0000 Subject: [PATCH 144/343] Revert "Replace the usage of UidRange" Revert "Add shims for NetworkRequest" Revert submission 1626206-replaceUidRange Reason for revert: Breaking build - b/183106405 Reverted Changes: I0b79c73e8:Add shims for NetworkRequest I4bc0daf5a:Replace the usage of UidRange I4e5aec6ef:Replace the usage of UidRange I107c329d4:Expose uids related APIs in NetworkRequest and Net... Change-Id: I6290429db1c8e787f8138b55b98fd92a74ac6402 --- .../src/android/net/NetworkCapabilities.java | 31 +++++++------------ framework/src/android/net/NetworkRequest.java | 5 ++- framework/src/android/net/UidRange.java | 31 ------------------- 3 files changed, 14 insertions(+), 53 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index ba9f21b261..058f3c999d 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -32,7 +32,6 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; -import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -154,7 +153,7 @@ public final class NetworkCapabilities implements Parcelable { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); + setUids(nc.mUids); // Will make the defensive copy setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -1459,8 +1458,9 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - mUids = new ArraySet<>(1); - mUids.add(new UidRange(uid, uid)); + final ArraySet identity = new ArraySet<>(1); + identity.add(new UidRange(uid, uid)); + setUids(identity); return this; } @@ -1469,8 +1469,12 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { - mUids = UidRange.fromIntRanges(uids); + public @NonNull NetworkCapabilities setUids(Set uids) { + if (null == uids) { + mUids = null; + } else { + mUids = new ArraySet<>(uids); + } return this; } @@ -1479,19 +1483,8 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public @Nullable Set> getUids() { - return UidRange.toIntRanges(mUids); - } - - /** - * Get the list of UIDs this network applies to. - * This returns a copy of the set so that callers can't modify the original object. - * @hide - */ - public @Nullable Set getUidRanges() { - if (mUids == null) return null; - - return new ArraySet<>(mUids); + public @Nullable Set getUids() { + return null == mUids ? null : new ArraySet<>(mUids); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4ebbf06c51..dbe3ecc4d7 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -45,7 +45,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; -import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -278,11 +277,11 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of {@code Range}, or null for everything. + * @param uids The watched UIDs as a set of UidRanges, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(@Nullable Set> uids) { + public Builder setUids(Set uids) { mNetworkCapabilities.setUids(uids); return this; } diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java index bc67c745c9..26518d32ed 100644 --- a/framework/src/android/net/UidRange.java +++ b/framework/src/android/net/UidRange.java @@ -20,11 +20,8 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; -import android.util.ArraySet; -import android.util.Range; import java.util.Collection; -import java.util.Set; /** * An inclusive range of UIDs. @@ -152,32 +149,4 @@ public final class UidRange implements Parcelable { } return false; } - - /** - * Convert a set of {@code Range} to a set of {@link UidRange}. - */ - @Nullable - public static ArraySet fromIntRanges(@Nullable Set> ranges) { - if (null == ranges) return null; - - final ArraySet uids = new ArraySet<>(); - for (Range range : ranges) { - uids.add(new UidRange(range.getLower(), range.getUpper())); - } - return uids; - } - - /** - * Convert a set of {@link UidRange} to a set of {@code Range}. - */ - @Nullable - public static ArraySet> toIntRanges(@Nullable Set ranges) { - if (null == ranges) return null; - - final ArraySet> uids = new ArraySet<>(); - for (UidRange range : ranges) { - uids.add(new Range(range.start, range.stop)); - } - return uids; - } } From 4956b3225dc29fa1c1d73bf6f99193e61978430b Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 22 Feb 2021 18:36:38 +0800 Subject: [PATCH 145/343] Replace the usage of UidRange UidRange is used in a shared way between ConnectivityService and VPN through the use of NetworkCapabilities. UidRange will be part of the ConnectivityService mainline but Vpn.java will stay in the framework. We need a way to replace the APIs using UidRange, or to make UidRange system API. The only really relevant surface here is NetworkCapabilities#{setUids, getUids}. The need for UidRange could be replaced by an integer Range, so replace the usage of UidRange by a integer Range in NetworkCapabilities#{setUids, getUids} and update the relevant callers. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCasesLatestSdk Change-Id: I4e5aec6ef1ea02e038fcd7ed117a3b67b69c5cb9 --- .../src/android/net/NetworkCapabilities.java | 31 ++++++++++++------- framework/src/android/net/NetworkRequest.java | 5 +-- framework/src/android/net/UidRange.java | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 058f3c999d..ba9f21b261 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -32,6 +32,7 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; +import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -153,7 +154,7 @@ public final class NetworkCapabilities implements Parcelable { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - setUids(nc.mUids); // Will make the defensive copy + mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -1458,9 +1459,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - final ArraySet identity = new ArraySet<>(1); - identity.add(new UidRange(uid, uid)); - setUids(identity); + mUids = new ArraySet<>(1); + mUids.add(new UidRange(uid, uid)); return this; } @@ -1469,12 +1469,8 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(Set uids) { - if (null == uids) { - mUids = null; - } else { - mUids = new ArraySet<>(uids); - } + public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { + mUids = UidRange.fromIntRanges(uids); return this; } @@ -1483,8 +1479,19 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public @Nullable Set getUids() { - return null == mUids ? null : new ArraySet<>(mUids); + public @Nullable Set> getUids() { + return UidRange.toIntRanges(mUids); + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set getUidRanges() { + if (mUids == null) return null; + + return new ArraySet<>(mUids); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index dbe3ecc4d7..4ebbf06c51 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -45,6 +45,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; +import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -277,11 +278,11 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @param uids The watched UIDs as a set of {@code Range}, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(Set uids) { + public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; } diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java index 26518d32ed..bc67c745c9 100644 --- a/framework/src/android/net/UidRange.java +++ b/framework/src/android/net/UidRange.java @@ -20,8 +20,11 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Range; import java.util.Collection; +import java.util.Set; /** * An inclusive range of UIDs. @@ -149,4 +152,32 @@ public final class UidRange implements Parcelable { } return false; } + + /** + * Convert a set of {@code Range} to a set of {@link UidRange}. + */ + @Nullable + public static ArraySet fromIntRanges(@Nullable Set> ranges) { + if (null == ranges) return null; + + final ArraySet uids = new ArraySet<>(); + for (Range range : ranges) { + uids.add(new UidRange(range.getLower(), range.getUpper())); + } + return uids; + } + + /** + * Convert a set of {@link UidRange} to a set of {@code Range}. + */ + @Nullable + public static ArraySet> toIntRanges(@Nullable Set ranges) { + if (null == ranges) return null; + + final ArraySet> uids = new ArraySet<>(); + for (UidRange range : ranges) { + uids.add(new Range(range.start, range.stop)); + } + return uids; + } } From 1818dbb99ab454ee24bb43d42756e9ad74c2de7b Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Mar 2021 07:31:54 +0000 Subject: [PATCH 146/343] Revert "Revert "Remove connectivity dependency on Preconditions"" Preconditions.checkNotNull is deprecated to be replaced by Objects.requireNonNull, and other methods can easily be replaced by inline checks. Preconditions is an internal API class that should not be used by unbundled jars. Bug: 177046265 Change-Id: I3a67d266b32142c034520acbcdc30f7213db5e13 Test: m --- .../net/ConnectivityDiagnosticsManager.java | 5 +- .../src/android/net/ConnectivityManager.java | 48 +++++++++++-------- framework/src/android/net/MacAddress.java | 10 ++-- .../src/android/net/NetworkCapabilities.java | 11 +++-- .../android/net/StaticIpConfiguration.java | 3 +- .../src/android/net/TestNetworkManager.java | 7 ++- 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.java b/framework/src/android/net/ConnectivityDiagnosticsManager.java index 5234494973..3598ebc701 100644 --- a/framework/src/android/net/ConnectivityDiagnosticsManager.java +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.java @@ -28,7 +28,6 @@ import android.os.PersistableBundle; import android.os.RemoteException; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -70,8 +69,8 @@ public class ConnectivityDiagnosticsManager { /** @hide */ public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) { - mContext = Preconditions.checkNotNull(context, "missing context"); - mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mContext = Objects.requireNonNull(context, "missing context"); + mService = Objects.requireNonNull(service, "missing IConnectivityManager"); } /** @hide */ diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index eac896c666..6e5c76d81c 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -75,7 +75,6 @@ import android.util.SparseIntArray; import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.Preconditions; import libcore.net.event.NetworkEventDispatcher; @@ -1775,7 +1774,9 @@ public class ConnectivityManager { // Map from type to transports. final int NOT_FOUND = -1; final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND); - Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type); + if (transport == NOT_FOUND) { + throw new IllegalArgumentException("unknown legacy type: " + type); + } nc.addTransportType(transport); // Map from type to capabilities. @@ -1880,8 +1881,8 @@ public class ConnectivityManager { } private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { - Preconditions.checkNotNull(network, "network cannot be null"); - Preconditions.checkNotNull(callback, "callback cannot be null"); + Objects.requireNonNull(network, "network cannot be null"); + Objects.requireNonNull(callback, "callback cannot be null"); mNetwork = network; mExecutor = Executors.newSingleThreadExecutor(); mCallback = new ISocketKeepaliveCallback.Stub() { @@ -2256,7 +2257,9 @@ public class ConnectivityManager { */ public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) { INetworkActivityListener rl = mNetworkActivityListeners.get(l); - Preconditions.checkArgument(rl != null, "Listener was not registered."); + if (rl == null) { + throw new IllegalArgumentException("Listener was not registered."); + } try { mService.registerNetworkActivityListener(rl); } catch (RemoteException e) { @@ -2284,8 +2287,8 @@ public class ConnectivityManager { * {@hide} */ public ConnectivityManager(Context context, IConnectivityManager service) { - mContext = Preconditions.checkNotNull(context, "missing context"); - mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mContext = Objects.requireNonNull(context, "missing context"); + mService = Objects.requireNonNull(service, "missing IConnectivityManager"); mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); sInstance = this; } @@ -2552,7 +2555,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { - Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); + Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null."); final Executor executor = new Executor() { @Override @@ -2645,7 +2648,7 @@ public class ConnectivityManager { public void registerTetheringEventCallback( @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEventCallback callback) { - Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); + Objects.requireNonNull(callback, "OnTetheringEventCallback cannot be null."); final TetheringEventCallback tetherCallback = new TetheringEventCallback() { @@ -2943,7 +2946,7 @@ public class ConnectivityManager { public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEntitlementResultListener listener) { - Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null."); + Objects.requireNonNull(listener, "TetheringEntitlementResultListener cannot be null."); ResultReceiver wrappedListener = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -3316,7 +3319,9 @@ public class ConnectivityManager { } public NetworkCallback(@Flag int flags) { - Preconditions.checkArgument((flags & VALID_FLAGS) == flags); + if ((flags & VALID_FLAGS) != flags) { + throw new IllegalArgumentException("Invalid flags"); + } mFlags = flags; } @@ -3602,7 +3607,7 @@ public class ConnectivityManager { } CallbackHandler(Handler handler) { - this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper()); + this(Objects.requireNonNull(handler, "Handler cannot be null.").getLooper()); } @Override @@ -3700,9 +3705,9 @@ public class ConnectivityManager { int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { printStackTrace(); checkCallbackNotNull(callback); - Preconditions.checkArgument( - reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null, - "null NetworkCapabilities"); + if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) { + throw new IllegalArgumentException("null NetworkCapabilities"); + } final NetworkRequest request; final String callingPackageName = mContext.getOpPackageName(); try { @@ -4049,15 +4054,17 @@ public class ConnectivityManager { } private static void checkPendingIntentNotNull(PendingIntent intent) { - Preconditions.checkNotNull(intent, "PendingIntent cannot be null."); + Objects.requireNonNull(intent, "PendingIntent cannot be null."); } private static void checkCallbackNotNull(NetworkCallback callback) { - Preconditions.checkNotNull(callback, "null NetworkCallback"); + Objects.requireNonNull(callback, "null NetworkCallback"); } private static void checkTimeout(int timeoutMs) { - Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive."); + if (timeoutMs <= 0) { + throw new IllegalArgumentException("timeoutMs must be strictly positive."); + } } /** @@ -4337,8 +4344,9 @@ public class ConnectivityManager { // Find all requests associated to this callback and stop callback triggers immediately. // Callback is reusable immediately. http://b/20701525, http://b/35921499. synchronized (sCallbacks) { - Preconditions.checkArgument(networkCallback.networkRequest != null, - "NetworkCallback was not registered"); + if (networkCallback.networkRequest == null) { + throw new IllegalArgumentException("NetworkCallback was not registered"); + } if (networkCallback.networkRequest == ALREADY_UNREGISTERED) { Log.d(TAG, "NetworkCallback was already unregistered"); return; diff --git a/framework/src/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java index c83c23a4b6..26a504a29c 100644 --- a/framework/src/android/net/MacAddress.java +++ b/framework/src/android/net/MacAddress.java @@ -25,7 +25,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; @@ -34,6 +33,7 @@ import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Arrays; +import java.util.Objects; /** * Representation of a MAC address. @@ -229,7 +229,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static @NonNull byte[] byteAddrFromStringAddr(String addr) { - Preconditions.checkNotNull(addr); + Objects.requireNonNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -275,7 +275,7 @@ public final class MacAddress implements Parcelable { // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) // that avoids the allocation of an intermediary byte[]. private static long longAddrFromStringAddr(String addr) { - Preconditions.checkNotNull(addr); + Objects.requireNonNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -364,8 +364,8 @@ public final class MacAddress implements Parcelable { * */ public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) { - Preconditions.checkNotNull(baseAddress); - Preconditions.checkNotNull(mask); + Objects.requireNonNull(baseAddress); + Objects.requireNonNull(mask); return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 058f3c999d..c6dfcee202 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -35,7 +35,6 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; @@ -2099,8 +2098,9 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidTransportType(@Transport int transport) { - Preconditions.checkArgument( - isValidTransport(transport), "Invalid TransportType " + transport); + if (!isValidTransport(transport)) { + throw new IllegalArgumentException("Invalid TransportType " + transport); + } } private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { @@ -2108,8 +2108,9 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { - Preconditions.checkArgument(isValidCapability(capability), - "NetworkCapability " + capability + "out of range"); + if (!isValidCapability(capability)) { + throw new IllegalArgumentException("NetworkCapability " + capability + "out of range"); + } } /** diff --git a/framework/src/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java index ce545974f5..7904f7a4ec 100644 --- a/framework/src/android/net/StaticIpConfiguration.java +++ b/framework/src/android/net/StaticIpConfiguration.java @@ -24,7 +24,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; import com.android.net.module.util.InetAddressUtils; import java.net.InetAddress; @@ -153,7 +152,7 @@ public final class StaticIpConfiguration implements Parcelable { * @return The {@link Builder} for chaining. */ public @NonNull Builder setDnsServers(@NonNull Iterable dnsServers) { - Preconditions.checkNotNull(dnsServers); + Objects.requireNonNull(dnsServers); mDnsServers = dnsServers; return this; } diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java index a174a7be85..a7a62351e5 100644 --- a/framework/src/android/net/TestNetworkManager.java +++ b/framework/src/android/net/TestNetworkManager.java @@ -21,10 +21,9 @@ import android.annotation.SystemApi; import android.os.IBinder; import android.os.RemoteException; -import com.android.internal.util.Preconditions; - import java.util.Arrays; import java.util.Collection; +import java.util.Objects; /** * Class that allows creation and management of per-app, test-only networks @@ -50,7 +49,7 @@ public class TestNetworkManager { /** @hide */ public TestNetworkManager(@NonNull ITestNetworkManager service) { - mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager"); + mService = Objects.requireNonNull(service, "missing ITestNetworkManager"); } /** @@ -93,7 +92,7 @@ public class TestNetworkManager { */ public void setupTestNetwork( @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { - Preconditions.checkNotNull(lp, "Invalid LinkProperties"); + Objects.requireNonNull(lp, "Invalid LinkProperties"); setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); } From bcd9def0751ba832a0ddde7ea8ab41a067aff60f Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 22:08:01 +0900 Subject: [PATCH 147/343] Remove Preconditions usage in TestNetworkSpecifier Preconditions is a hidden API utility. It can be easily replace by inline checks. Bug: 177046265 Test: m Change-Id: I3f722075fb9c74e12e40348ba4faad2f0fa67178 --- framework/src/android/net/TestNetworkSpecifier.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/TestNetworkSpecifier.java b/framework/src/android/net/TestNetworkSpecifier.java index b7470a591d..117457dffc 100644 --- a/framework/src/android/net/TestNetworkSpecifier.java +++ b/framework/src/android/net/TestNetworkSpecifier.java @@ -23,8 +23,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import com.android.internal.util.Preconditions; - import java.util.Objects; /** @@ -43,7 +41,9 @@ public final class TestNetworkSpecifier extends NetworkSpecifier implements Parc private final String mInterfaceName; public TestNetworkSpecifier(@NonNull String interfaceName) { - Preconditions.checkStringNotEmpty(interfaceName); + if (TextUtils.isEmpty(interfaceName)) { + throw new IllegalArgumentException("Empty interfaceName"); + } mInterfaceName = interfaceName; } From aacf237c27fa797cb608dfc4dad866c3c538a866 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 11 Mar 2021 16:13:13 +0800 Subject: [PATCH 148/343] Expose uids related APIs in NetworkRequest and NetworkCapabilities NetworkRequest is moving into the incoming connectivity mainline module. The hidden setUids becomes inaccessible outside the module. Shims for support cts in different API levels will need to use it to verify the behavior of NetworkRequest. Thus, expose it to the API surface. Also, VPN uses getUids and setUids to control network capabilities. Networkcapabilities is a part of incoming connectivity mainline module but VPN is not. Thus, exposing these two methods are needed to allow VPN to continue using it. Test: make update-api Bug: 172183305 Change-Id: I107c329d4d7130d488772166eae8b5e7aaa2ff04 --- framework/api/module-lib-current.txt | 9 ++++++++ .../src/android/net/NetworkCapabilities.java | 21 +++++++++++++++++++ framework/src/android/net/NetworkRequest.java | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 7a91f6454b..ab039165ad 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -36,9 +36,18 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + method @Nullable public java.util.Set> getUids(); field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static final class NetworkCapabilities.Builder { + method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); + } + + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); + } + public class ParseException extends java.lang.RuntimeException { ctor public ParseException(@NonNull String); ctor public ParseException(@NonNull String, @NonNull Throwable); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index ba9f21b261..182bc7141a 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -1477,8 +1478,13 @@ public final class NetworkCapabilities implements Parcelable { /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. + * + * @return the list of UIDs this network applies to. If {@code null}, then the network applies + * to all UIDs. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("NullableCollection") public @Nullable Set> getUids() { return UidRange.toIntRanges(mUids); } @@ -2661,6 +2667,21 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Set the list of UIDs this network applies to. + * + * @param uids the list of UIDs this network applies to, or {@code null} if this network + * applies to all UIDs. + * @return this builder + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder setUids(@Nullable Set> uids) { + mCaps.setUids(uids); + return this; + } + /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4ebbf06c51..cf131f0df6 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -282,6 +283,9 @@ public class NetworkRequest implements Parcelable { * @return The builder to facilitate chaining. * @hide */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("MissingGetterMatchingBuilder") public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; From 34ab07c7b37a1d896c71a615b6176c72a09ce4a4 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Fri, 19 Mar 2021 00:45:39 +0000 Subject: [PATCH 149/343] Revert^2 "Replace the usage of UidRange" b6c51b2c978fbcb9c1507b61635c64229c8ffe53 UidRange is used in a shared way between ConnectivityService and VPN through the use of NetworkCapabilities. UidRange will be part of the ConnectivityService mainline but Vpn.java will stay in the framework. We need a way to replace the APIs using UidRange, or to make UidRange system API. The only really relevant surface here is NetworkCapabilities#{setUids, getUids}. The need for UidRange could be replaced by an integer Range, so replace the usage of UidRange by a integer Range in NetworkCapabilities#{setUids, getUids} and update the relevant callers. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCasesLatestSdk Change-Id: I0f679fb5fb8f4fe26461ca4912ca1fdfe7f43c9e Merged-In: I4e5aec6ef1ea02e038fcd7ed117a3b67b69c5cb9 --- .../src/android/net/NetworkCapabilities.java | 31 ++++++++++++------- framework/src/android/net/NetworkRequest.java | 5 +-- framework/src/android/net/UidRange.java | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 058f3c999d..ba9f21b261 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -32,6 +32,7 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; +import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -153,7 +154,7 @@ public final class NetworkCapabilities implements Parcelable { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - setUids(nc.mUids); // Will make the defensive copy + mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -1458,9 +1459,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - final ArraySet identity = new ArraySet<>(1); - identity.add(new UidRange(uid, uid)); - setUids(identity); + mUids = new ArraySet<>(1); + mUids.add(new UidRange(uid, uid)); return this; } @@ -1469,12 +1469,8 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(Set uids) { - if (null == uids) { - mUids = null; - } else { - mUids = new ArraySet<>(uids); - } + public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { + mUids = UidRange.fromIntRanges(uids); return this; } @@ -1483,8 +1479,19 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public @Nullable Set getUids() { - return null == mUids ? null : new ArraySet<>(mUids); + public @Nullable Set> getUids() { + return UidRange.toIntRanges(mUids); + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set getUidRanges() { + if (mUids == null) return null; + + return new ArraySet<>(mUids); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index dbe3ecc4d7..4ebbf06c51 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -45,6 +45,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; +import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -277,11 +278,11 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @param uids The watched UIDs as a set of {@code Range}, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(Set uids) { + public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; } diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java index 26518d32ed..bc67c745c9 100644 --- a/framework/src/android/net/UidRange.java +++ b/framework/src/android/net/UidRange.java @@ -20,8 +20,11 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Range; import java.util.Collection; +import java.util.Set; /** * An inclusive range of UIDs. @@ -149,4 +152,32 @@ public final class UidRange implements Parcelable { } return false; } + + /** + * Convert a set of {@code Range} to a set of {@link UidRange}. + */ + @Nullable + public static ArraySet fromIntRanges(@Nullable Set> ranges) { + if (null == ranges) return null; + + final ArraySet uids = new ArraySet<>(); + for (Range range : ranges) { + uids.add(new UidRange(range.getLower(), range.getUpper())); + } + return uids; + } + + /** + * Convert a set of {@link UidRange} to a set of {@code Range}. + */ + @Nullable + public static ArraySet> toIntRanges(@Nullable Set ranges) { + if (null == ranges) return null; + + final ArraySet> uids = new ArraySet<>(); + for (UidRange range : ranges) { + uids.add(new Range(range.start, range.stop)); + } + return uids; + } } From 628cb1187ee994a2a7b974d286db6f796ab51405 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Fri, 19 Mar 2021 00:45:39 +0000 Subject: [PATCH 150/343] Revert "Revert "Expose uids related APIs in NetworkRequest and N..." Revert^2 "Add shims for NetworkRequest" b72b3ca768fc25ef72dc78f1396b08447b8ef5c6 NetworkRequest is moving into the incoming connectivity mainline module. The hidden setUids becomes inaccessible outside the module. Shims for support cts in different API levels will need to use it to verify the behavior of NetworkRequest. Thus, expose it to the API surface. Also, VPN uses getUids and setUids to control network capabilities. Networkcapabilities is a part of incoming connectivity mainline module but VPN is not. Thus, exposing these two methods are needed to allow VPN to continue using it. Test: make update-api Bug: 172183305 Change-Id: I4b8e1aa558e3459a932535f9901f4ae86b0ecb67 Merged-In: I107c329d4d7130d488772166eae8b5e7aaa2ff04 --- framework/api/module-lib-current.txt | 9 ++++++++ .../src/android/net/NetworkCapabilities.java | 21 +++++++++++++++++++ framework/src/android/net/NetworkRequest.java | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index bb296476c7..6339094341 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -27,9 +27,18 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + method @Nullable public java.util.Set> getUids(); field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static final class NetworkCapabilities.Builder { + method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); + } + + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); + } + public class ParseException extends java.lang.RuntimeException { ctor public ParseException(@NonNull String); ctor public ParseException(@NonNull String, @NonNull Throwable); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index ba9f21b261..182bc7141a 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -22,6 +22,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -1477,8 +1478,13 @@ public final class NetworkCapabilities implements Parcelable { /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. + * + * @return the list of UIDs this network applies to. If {@code null}, then the network applies + * to all UIDs. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("NullableCollection") public @Nullable Set> getUids() { return UidRange.toIntRanges(mUids); } @@ -2661,6 +2667,21 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Set the list of UIDs this network applies to. + * + * @param uids the list of UIDs this network applies to, or {@code null} if this network + * applies to all UIDs. + * @return this builder + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder setUids(@Nullable Set> uids) { + mCaps.setUids(uids); + return this; + } + /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4ebbf06c51..cf131f0df6 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -282,6 +283,9 @@ public class NetworkRequest implements Parcelable { * @return The builder to facilitate chaining. * @hide */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("MissingGetterMatchingBuilder") public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; From cf6d450eb85640c908040c94b2185744c716f53f Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 4 Mar 2021 17:09:51 +0800 Subject: [PATCH 151/343] Expose constants of ConnectivityManager The callers cannot call the hidden APIs after ConnectivityManager became a part of mainline module, so expose them for callers. Also change the value of ACTION_PROMPT_PARTIAL_CONNECTIVITY, ACTION_PROMPT_LOST_VALIDATION and ACTION_PROMPT_UNVALIDATED because of API lint errors. Bug: 172183305 Test: Check private DNS settings is normal, and test NO_INTERNET notification can be shown normally. Change-Id: I715c766ad8e5eb54f4dc67239c1dbca7239506fc --- framework/api/module-lib-current.txt | 3 +++ framework/src/android/net/ConnectivityManager.java | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 7a91f6454b..8e9e6acb52 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -20,6 +20,9 @@ package android.net { method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); method public void systemReady(); + field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION"; + field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY"; + field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED"; field public static final String PRIVATE_DNS_MODE_OFF = "off"; field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic"; field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname"; diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index eac896c666..a5e38fa976 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -425,7 +425,8 @@ public class ConnectivityManager { * * @hide */ - public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED"; + @SystemApi(client = MODULE_LIBRARIES) + public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED"; /** * Action used to display a dialog that asks the user whether to avoid a network that is no @@ -433,8 +434,9 @@ public class ConnectivityManager { * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String ACTION_PROMPT_LOST_VALIDATION = - "android.net.conn.PROMPT_LOST_VALIDATION"; + "android.net.action.PROMPT_LOST_VALIDATION"; /** * Action used to display a dialog that asks the user whether to stay connected to a network @@ -443,8 +445,9 @@ public class ConnectivityManager { * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = - "android.net.conn.PROMPT_PARTIAL_CONNECTIVITY"; + "android.net.action.PROMPT_PARTIAL_CONNECTIVITY"; /** * Invalid tethering type. From 1dddf2671e4860d6db74fb7fbde8a4c42afc837f Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 20 Jan 2021 20:47:32 +0900 Subject: [PATCH 152/343] [NS02] Mix in validation of the score Test: FrameworksNetTests FrameworksWifiTests NetworkStackTests Change-Id: I9cac3a05ad0c4008599973b12d2c5e4c02233a5c --- framework/src/android/net/NetworkScore.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java index f478010022..e640737168 100644 --- a/framework/src/android/net/NetworkScore.java +++ b/framework/src/android/net/NetworkScore.java @@ -33,13 +33,21 @@ public final class NetworkScore implements Parcelable { // a migration. private final int mLegacyInt; + // Agent-managed policies + // TODO : add them here, starting from 1 + + // Bitmask of all the policies applied to this score. + private final long mPolicies; + /** @hide */ - NetworkScore(final int legacyInt) { - this.mLegacyInt = legacyInt; + NetworkScore(final int legacyInt, final long policies) { + mLegacyInt = legacyInt; + mPolicies = policies; } private NetworkScore(@NonNull final Parcel in) { mLegacyInt = in.readInt(); + mPolicies = in.readLong(); } public int getLegacyInt() { @@ -54,6 +62,7 @@ public final class NetworkScore implements Parcelable { @Override public void writeToParcel(@NonNull final Parcel dest, final int flags) { dest.writeInt(mLegacyInt); + dest.writeLong(mPolicies); } @Override @@ -79,6 +88,7 @@ public final class NetworkScore implements Parcelable { * A builder for NetworkScore. */ public static final class Builder { + private static final long POLICY_NONE = 0L; private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE; private int mLegacyInt = INVALID_LEGACY_INT; @@ -102,7 +112,7 @@ public final class NetworkScore implements Parcelable { */ @NonNull public NetworkScore build() { - return new NetworkScore(mLegacyInt); + return new NetworkScore(mLegacyInt, POLICY_NONE); } } } From 816ea0324c6a7ad5dc0d5056933521a59edf3fd6 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 20 Jan 2021 20:47:32 +0900 Subject: [PATCH 153/343] [NS03] Mix in other CS-managed properties These properties are necessary to figure out the maximum score of a network. Test: FrameworksNetTests Change-Id: I48dce20ad4a80597039393dca607e8da829b2a61 --- framework/src/android/net/NetworkAgentConfig.java | 3 ++- framework/src/android/net/NetworkScore.java | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java index 664c2650ff..5e50a6404a 100644 --- a/framework/src/android/net/NetworkAgentConfig.java +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -50,7 +50,8 @@ public final class NetworkAgentConfig implements Parcelable { * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to * connect to a particular access point is also explicit, though this may change in the future * as we want apps to use the multinetwork apis. - * + * TODO : this is a bad name, because it sounds like the user just tapped on the network. + * It's not necessarily the case ; auto-reconnection to WiFi has this true for example. * @hide */ public boolean explicitlySelected; diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java index e640737168..eadcb2d0a7 100644 --- a/framework/src/android/net/NetworkScore.java +++ b/framework/src/android/net/NetworkScore.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.annotations.VisibleForTesting; + /** * Object representing the quality of a network as perceived by the user. * @@ -35,6 +37,10 @@ public final class NetworkScore implements Parcelable { // Agent-managed policies // TODO : add them here, starting from 1 + /** @hide */ + public static final int MIN_AGENT_MANAGED_POLICY = 0; + /** @hide */ + public static final int MAX_AGENT_MANAGED_POLICY = -1; // Bitmask of all the policies applied to this score. private final long mPolicies; @@ -54,6 +60,14 @@ public final class NetworkScore implements Parcelable { return mLegacyInt; } + /** + * @return whether this score has a particular policy. + */ + @VisibleForTesting + public boolean hasPolicy(final int policy) { + return 0 != (mPolicies & (1L << policy)); + } + @Override public String toString() { return "Score(" + mLegacyInt + ")"; From 3b52af9c6edd8795e559908a9589650ef04fb8de Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 00:24:45 +0000 Subject: [PATCH 154/343] Build framework-connectivity using module_current framework-connectivity needs to build only against stable APIs. Bug: 171540887 Test: m framework-connectivity.impl Change-Id: I2d51d37d067bf6fe86e4dedf05855a2dd67ed57c --- framework/Android.bp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/framework/Android.bp b/framework/Android.bp index 017ff51f36..5b33328833 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -25,6 +25,7 @@ package { java_library { name: "framework-connectivity-protos", + sdk_version: "module_current", proto: { type: "nano", }, @@ -82,8 +83,7 @@ java_sdk_library { name: "framework-connectivity", api_only: true, defaults: ["framework-module-defaults"], - // TODO: build against module API - platform_apis: true, + installable: true, srcs: [ ":framework-connectivity-sources", ], @@ -100,18 +100,15 @@ java_sdk_library { libs: [ "unsupportedappusage", ], - permitted_packages: ["android.net", "com.android.connectivity.aidl"], + permitted_packages: [ + "android.net", + "com.android.connectivity.aidl", + ], } java_library { name: "framework-connectivity.impl", - // Instead of building against private API (framework.jar), - // build against core_platform + framework-minus-apex + module - // stub libs. This allows framework.jar to depend on this library, - // so it can be part of the private API until all clients have been migrated. - // TODO: just build against module_api, and remove this jar from - // the private API. - sdk_version: "core_platform", + sdk_version: "module_current", srcs: [ ":framework-connectivity-sources", ], @@ -122,10 +119,10 @@ java_library { ], }, libs: [ - "framework-minus-apex", - // TODO: just framework-tethering, framework-wifi when building against module_api - "framework-tethering.stubs.module_lib", - "framework-wifi.stubs.module_lib", + // TODO (b/183097033) remove once module_current includes core_current + "stable.core.platform.api.stubs", + "framework-tethering", + "framework-wifi", "unsupportedappusage", "ServiceConnectivityResources", ], @@ -136,5 +133,8 @@ java_library { jarjar_rules: "jarjar-rules.txt", apex_available: ["com.android.tethering"], installable: true, - permitted_packages: ["android.net", "com.android.connectivity.aidl"], + permitted_packages: [ + "android.net", + "com.android.connectivity.aidl", + ], } From 60ad218d72f5cf20f210095edd9f82526c5c6cd4 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Feb 2021 12:53:54 +0900 Subject: [PATCH 155/343] Move connectivity AIDLs to android.net java_sdk_libraries and apexes need to contain bootclasspath classes under predefined packages. Tethering currently uses android.net, so make sure all the connectivity bootclasspath classes are under android.net. This avoids maintaining two packages for the tethering APEX, where com.android.connectivity.aidl is only used by internal AIDL files. Bug: 182984842 Test: m Change-Id: I611f1941698c574e37aea912ee76dadc8b32e41a --- framework/src/android/net/ConnectivityManager.java | 1 - framework/src/android/net/IConnectivityManager.aidl | 3 +-- .../connectivity/aidl => android/net}/INetworkAgent.aidl | 4 ++-- .../aidl => android/net}/INetworkAgentRegistry.aidl | 2 +- framework/src/android/net/NetworkAgent.java | 2 -- 5 files changed, 4 insertions(+), 8 deletions(-) rename framework/src/{com/android/connectivity/aidl => android/net}/INetworkAgent.aidl (95%) rename framework/src/{com/android/connectivity/aidl => android/net}/INetworkAgentRegistry.aidl (97%) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 9f63abf0ce..3a5f2c1b6a 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -73,7 +73,6 @@ import android.util.Log; import android.util.Range; import android.util.SparseIntArray; -import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; import libcore.net.event.NetworkEventDispatcher; diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 98f3d40c0b..3300fa8fd1 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -20,6 +20,7 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; +import android.net.INetworkAgent; import android.net.IOnCompleteListener; import android.net.INetworkActivityListener; import android.net.IQosCallback; @@ -45,8 +46,6 @@ import android.os.PersistableBundle; import android.os.ResultReceiver; import android.os.UserHandle; -import com.android.connectivity.aidl.INetworkAgent; - /** * Interface that answers queries about, and allows changing, the * state of network connectivity. diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl b/framework/src/android/net/INetworkAgent.aidl similarity index 95% rename from framework/src/com/android/connectivity/aidl/INetworkAgent.aidl rename to framework/src/android/net/INetworkAgent.aidl index 64b556720c..1f66e18717 100644 --- a/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl +++ b/framework/src/android/net/INetworkAgent.aidl @@ -13,13 +13,13 @@ * See the License for the specific language governing perNmissions and * limitations under the License. */ -package com.android.connectivity.aidl; +package android.net; import android.net.NattKeepalivePacketData; import android.net.QosFilterParcelable; import android.net.TcpKeepalivePacketData; -import com.android.connectivity.aidl.INetworkAgentRegistry; +import android.net.INetworkAgentRegistry; /** * Interface to notify NetworkAgent of connectivity events. diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/framework/src/android/net/INetworkAgentRegistry.aidl similarity index 97% rename from framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl rename to framework/src/android/net/INetworkAgentRegistry.aidl index 18d26a7e4b..c5464d3241 100644 --- a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl +++ b/framework/src/android/net/INetworkAgentRegistry.aidl @@ -13,7 +13,7 @@ * See the License for the specific language governing perNmissions and * limitations under the License. */ -package com.android.connectivity.aidl; +package android.net; import android.net.LinkProperties; import android.net.Network; diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index a127c6f6de..1416bb9775 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -34,8 +34,6 @@ import android.os.RemoteException; import android.telephony.data.EpsBearerQosSessionAttributes; import android.util.Log; -import com.android.connectivity.aidl.INetworkAgent; -import com.android.connectivity.aidl.INetworkAgentRegistry; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; From d9b56cea16f27cfbe2941b2ea7bacf51a2c77c38 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 08:00:25 +0000 Subject: [PATCH 156/343] Revert "CaptivePortalData: use CharSequence in VenueFriendlyName API" This reverts commit 6ae29ff41a17ff71026f8f382417554e616be7d6. Reason for revert: b/183174863 Bug: 183174863 Change-Id: I4db923e112bba149f4e8eb4cfa8c3f97defd5e63 --- framework/api/system-current.txt | 4 ++-- framework/src/android/net/CaptivePortalData.java | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 8845225823..031bb916c4 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -18,7 +18,7 @@ package android.net { method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); method public int getUserPortalUrlSource(); - method @Nullable public CharSequence getVenueFriendlyName(); + method @Nullable public String getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); method public int getVenueInfoUrlSource(); method public boolean isCaptive(); @@ -40,7 +40,7 @@ package android.net { method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); - method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable CharSequence); + method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); } diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java index 82dbd0fb1f..eafda4d2d6 100644 --- a/framework/src/android/net/CaptivePortalData.java +++ b/framework/src/android/net/CaptivePortalData.java @@ -42,7 +42,7 @@ public final class CaptivePortalData implements Parcelable { private final long mByteLimit; private final long mExpiryTimeMillis; private final boolean mCaptive; - private final CharSequence mVenueFriendlyName; + private final String mVenueFriendlyName; private final int mVenueInfoUrlSource; private final int mUserPortalUrlSource; @@ -65,7 +65,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - CharSequence venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { + String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -80,7 +80,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), - p.readLong(), p.readLong(), p.readBoolean(), p.readCharSequence(), p.readInt(), + p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(), p.readInt()); } @@ -98,7 +98,7 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mByteLimit); dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); - dest.writeCharSequence(mVenueFriendlyName); + dest.writeString(mVenueFriendlyName); dest.writeInt(mVenueInfoUrlSource); dest.writeInt(mUserPortalUrlSource); } @@ -114,7 +114,7 @@ public final class CaptivePortalData implements Parcelable { private long mBytesRemaining = -1; private long mExpiryTime = -1; private boolean mCaptive; - private CharSequence mVenueFriendlyName; + private String mVenueFriendlyName; private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; private @CaptivePortalDataSource int mUserPortalUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; @@ -228,7 +228,7 @@ public final class CaptivePortalData implements Parcelable { * Set the venue friendly name. */ @NonNull - public Builder setVenueFriendlyName(@Nullable CharSequence venueFriendlyName) { + public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { mVenueFriendlyName = venueFriendlyName; return this; } @@ -321,7 +321,7 @@ public final class CaptivePortalData implements Parcelable { * Get the venue friendly name */ @Nullable - public CharSequence getVenueFriendlyName() { + public String getVenueFriendlyName() { return mVenueFriendlyName; } From 60372ff53d011094ae1d59a435689e6fe6b600b1 Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Tue, 16 Mar 2021 20:59:42 -0700 Subject: [PATCH 157/343] Reland: CaptivePortalData: use CharSequence in VenueFriendlyName API Following up on feedback from API council, change the String type to CharSequence in the get and set Venue friendly name API. Bug: 179163405 Test: atest ConnectivityServiceTest CtsNetTestCasesLatestSdk:CaptivePortalDataTest Test: atest NetworkNotificationManagerTest NetworkMonitorTest Change-Id: Ifa3ea9aae0cabf5757791c4ae13e6f551759ed97 --- framework/api/system-current.txt | 4 ++-- framework/src/android/net/CaptivePortalData.java | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 031bb916c4..8845225823 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -18,7 +18,7 @@ package android.net { method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); method public int getUserPortalUrlSource(); - method @Nullable public String getVenueFriendlyName(); + method @Nullable public CharSequence getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); method public int getVenueInfoUrlSource(); method public boolean isCaptive(); @@ -40,7 +40,7 @@ package android.net { method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri, int); - method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable String); + method @NonNull public android.net.CaptivePortalData.Builder setVenueFriendlyName(@Nullable CharSequence); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri, int); } diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java index eafda4d2d6..53aa1b92ed 100644 --- a/framework/src/android/net/CaptivePortalData.java +++ b/framework/src/android/net/CaptivePortalData.java @@ -65,7 +65,7 @@ public final class CaptivePortalData implements Parcelable { private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, - String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { + CharSequence venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; @@ -73,7 +73,7 @@ public final class CaptivePortalData implements Parcelable { mByteLimit = byteLimit; mExpiryTimeMillis = expiryTimeMillis; mCaptive = captive; - mVenueFriendlyName = venueFriendlyName; + mVenueFriendlyName = venueFriendlyName == null ? null : venueFriendlyName.toString(); mVenueInfoUrlSource = venueInfoUrlSource; mUserPortalUrlSource = userPortalUrlSource; } @@ -114,7 +114,7 @@ public final class CaptivePortalData implements Parcelable { private long mBytesRemaining = -1; private long mExpiryTime = -1; private boolean mCaptive; - private String mVenueFriendlyName; + private CharSequence mVenueFriendlyName; private @CaptivePortalDataSource int mVenueInfoUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; private @CaptivePortalDataSource int mUserPortalUrlSource = CAPTIVE_PORTAL_DATA_SOURCE_OTHER; @@ -228,7 +228,7 @@ public final class CaptivePortalData implements Parcelable { * Set the venue friendly name. */ @NonNull - public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { + public Builder setVenueFriendlyName(@Nullable CharSequence venueFriendlyName) { mVenueFriendlyName = venueFriendlyName; return this; } @@ -321,7 +321,7 @@ public final class CaptivePortalData implements Parcelable { * Get the venue friendly name */ @Nullable - public String getVenueFriendlyName() { + public CharSequence getVenueFriendlyName() { return mVenueFriendlyName; } From 33ec5c1ae24ec5a9713a028eac234cbc21e0309f Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 20 Jan 2021 20:47:32 +0900 Subject: [PATCH 158/343] [NS03] Mix in other CS-managed properties These properties are necessary to figure out the maximum score of a network. Test: FrameworksNetTests Bug: 167544279 Change-Id: I48dce20ad4a80597039393dca607e8da829b2a61 --- framework/src/android/net/NetworkAgentConfig.java | 3 ++- framework/src/android/net/NetworkScore.java | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java index 664c2650ff..5e50a6404a 100644 --- a/framework/src/android/net/NetworkAgentConfig.java +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -50,7 +50,8 @@ public final class NetworkAgentConfig implements Parcelable { * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to * connect to a particular access point is also explicit, though this may change in the future * as we want apps to use the multinetwork apis. - * + * TODO : this is a bad name, because it sounds like the user just tapped on the network. + * It's not necessarily the case ; auto-reconnection to WiFi has this true for example. * @hide */ public boolean explicitlySelected; diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java index e640737168..eadcb2d0a7 100644 --- a/framework/src/android/net/NetworkScore.java +++ b/framework/src/android/net/NetworkScore.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.annotations.VisibleForTesting; + /** * Object representing the quality of a network as perceived by the user. * @@ -35,6 +37,10 @@ public final class NetworkScore implements Parcelable { // Agent-managed policies // TODO : add them here, starting from 1 + /** @hide */ + public static final int MIN_AGENT_MANAGED_POLICY = 0; + /** @hide */ + public static final int MAX_AGENT_MANAGED_POLICY = -1; // Bitmask of all the policies applied to this score. private final long mPolicies; @@ -54,6 +60,14 @@ public final class NetworkScore implements Parcelable { return mLegacyInt; } + /** + * @return whether this score has a particular policy. + */ + @VisibleForTesting + public boolean hasPolicy(final int policy) { + return 0 != (mPolicies & (1L << policy)); + } + @Override public String toString() { return "Score(" + mLegacyInt + ")"; From c58c993dda76bf3932983e7b66e5ae17d1433698 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 10:13:40 +0000 Subject: [PATCH 159/343] Move NetworkUtils JNI out of core/jni Keep the utilities included via a library, but move them out of core/jni, and prepare a library to package them together with framework-connectivity. Also remove unnecessary dependencies in framework-connectivity. Bug: 171540887 Test: device boots and has connectivity Change-Id: I0b55dfe92f3cb6e848d79ac7953756f39aaa2597 --- framework/Android.bp | 53 +++- framework/jni/android_net_NetworkUtils.cpp | 308 +++++++++++++++++++++ framework/jni/onload.cpp | 38 +++ 3 files changed, 391 insertions(+), 8 deletions(-) create mode 100644 framework/jni/android_net_NetworkUtils.cpp create mode 100644 framework/jni/onload.cpp diff --git a/framework/Android.bp b/framework/Android.bp index 5b33328833..657d5a3d2e 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -100,9 +100,50 @@ java_sdk_library { libs: [ "unsupportedappusage", ], - permitted_packages: [ - "android.net", - "com.android.connectivity.aidl", + permitted_packages: ["android.net"], +} + +cc_defaults { + name: "libframework-connectivity-defaults", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], + shared_libs: [ + "libbase", + "liblog", + "libnativehelper", + "libnetd_client", + ], + header_libs: [ + "dnsproxyd_protocol_headers", + ], +} + +cc_library_static { + name: "libconnectivityframeworkutils", + defaults: ["libframework-connectivity-defaults"], + srcs: [ + "jni/android_net_NetworkUtils.cpp", + ], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], +} + +cc_library_shared { + name: "libframework-connectivity-jni", + defaults: ["libframework-connectivity-defaults"], + srcs: [ + "jni/onload.cpp", + ], + static_libs: ["libconnectivityframeworkutils"], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", ], } @@ -124,7 +165,6 @@ java_library { "framework-tethering", "framework-wifi", "unsupportedappusage", - "ServiceConnectivityResources", ], static_libs: [ "framework-connectivity-protos", @@ -133,8 +173,5 @@ java_library { jarjar_rules: "jarjar-rules.txt", apex_available: ["com.android.tethering"], installable: true, - permitted_packages: [ - "android.net", - "com.android.connectivity.aidl", - ], + permitted_packages: ["android.net"], } diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp new file mode 100644 index 0000000000..19ffe77c1f --- /dev/null +++ b/framework/jni/android_net_NetworkUtils.cpp @@ -0,0 +1,308 @@ +/* + * Copyright 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "NetworkUtils" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // NETID_USE_LOCAL_NAMESERVERS +#include +#include +#include +#include +#include + +#include "NetdClient.h" +#include "jni.h" + +extern "C" { +int ifc_enable(const char *ifname); +int ifc_disable(const char *ifname); +} + +#define NETUTILS_PKG_NAME "android/net/NetworkUtils" + +namespace android { + +constexpr int MAXPACKETSIZE = 8 * 1024; +// FrameworkListener limits the size of commands to 4096 bytes. +constexpr int MAXCMDSIZE = 4096; + +static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) { + jclass clazz = env->FindClass(class_name); + LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name); + return clazz; +} + +static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, + const char* method_signature) { + jmethodID res = env->GetMethodID(clazz, method_name, method_signature); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name, + method_signature); + return res; +} + +template +static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { + jobject res = env->NewGlobalRef(in); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference."); + return static_cast(res); +} + +static void throwErrnoException(JNIEnv* env, const char* functionName, int error) { + ScopedLocalRef detailMessage(env, env->NewStringUTF(functionName)); + if (detailMessage.get() == NULL) { + // Not really much we can do here. We're probably dead in the water, + // but let's try to stumble on... + env->ExceptionClear(); + } + static jclass errnoExceptionClass = + MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException")); + + static jmethodID errnoExceptionCtor = + GetMethodIDOrDie(env, errnoExceptionClass, + "", "(Ljava/lang/String;I)V"); + + jobject exception = env->NewObject(errnoExceptionClass, + errnoExceptionCtor, + detailMessage.get(), + error); + env->Throw(reinterpret_cast(exception)); +} + +static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) +{ + struct sock_filter filter_code[] = { + // Reject all. + BPF_STMT(BPF_RET | BPF_K, 0) + }; + struct sock_fprog filter = { + sizeof(filter_code) / sizeof(filter_code[0]), + filter_code, + }; + + int fd = AFileDescriptor_getFD(env, javaFd); + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno)); + } +} + +static void android_net_utils_detachBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) +{ + int optval_ignored = 0; + int fd = AFileDescriptor_getFD(env, javaFd); + if (setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &optval_ignored, sizeof(optval_ignored)) != + 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(SO_DETACH_FILTER): %s", strerror(errno)); + } +} + +static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId) +{ + return (jboolean) !setNetworkForProcess(netId); +} + +static jint android_net_utils_getBoundNetworkForProcess(JNIEnv *env, jobject thiz) +{ + return getNetworkForProcess(); +} + +static jboolean android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz, + jint netId) +{ + return (jboolean) !setNetworkForResolv(netId); +} + +static jint android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jobject javaFd, + jint netId) { + return setNetworkForSocket(netId, AFileDescriptor_getFD(env, javaFd)); +} + +static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jint uid, jint netId) +{ + return (jboolean) !queryUserAccess(uid, netId); +} + +static bool checkLenAndCopy(JNIEnv* env, const jbyteArray& addr, int len, void* dst) +{ + if (env->GetArrayLength(addr) != len) { + return false; + } + env->GetByteArrayRegion(addr, 0, len, reinterpret_cast(dst)); + return true; +} + +static jobject android_net_utils_resNetworkQuery(JNIEnv *env, jobject thiz, jint netId, + jstring dname, jint ns_class, jint ns_type, jint flags) { + const jsize javaCharsCount = env->GetStringLength(dname); + const jsize byteCountUTF8 = env->GetStringUTFLength(dname); + + // Only allow dname which could be simply formatted to UTF8. + // In native layer, res_mkquery would re-format the input char array to packet. + std::vector queryname(byteCountUTF8 + 1, 0); + + env->GetStringUTFRegion(dname, 0, javaCharsCount, queryname.data()); + int fd = resNetworkQuery(netId, queryname.data(), ns_class, ns_type, flags); + + if (fd < 0) { + throwErrnoException(env, "resNetworkQuery", -fd); + return nullptr; + } + + return jniCreateFileDescriptor(env, fd); +} + +static jobject android_net_utils_resNetworkSend(JNIEnv *env, jobject thiz, jint netId, + jbyteArray msg, jint msgLen, jint flags) { + uint8_t data[MAXCMDSIZE]; + + checkLenAndCopy(env, msg, msgLen, data); + int fd = resNetworkSend(netId, data, msgLen, flags); + + if (fd < 0) { + throwErrnoException(env, "resNetworkSend", -fd); + return nullptr; + } + + return jniCreateFileDescriptor(env, fd); +} + +static jobject android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, jobject javaFd) { + int fd = AFileDescriptor_getFD(env, javaFd); + int rcode; + std::vector buf(MAXPACKETSIZE, 0); + + int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE); + jniSetFileDescriptorOfFD(env, javaFd, -1); + if (res < 0) { + throwErrnoException(env, "resNetworkResult", -res); + return nullptr; + } + + jbyteArray answer = env->NewByteArray(res); + if (answer == nullptr) { + throwErrnoException(env, "resNetworkResult", ENOMEM); + return nullptr; + } else { + env->SetByteArrayRegion(answer, 0, res, + reinterpret_cast(buf.data())); + } + + jclass class_DnsResponse = env->FindClass("android/net/DnsResolver$DnsResponse"); + jmethodID ctor = env->GetMethodID(class_DnsResponse, "", "([BI)V"); + + return env->NewObject(class_DnsResponse, ctor, answer, rcode); +} + +static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) { + int fd = AFileDescriptor_getFD(env, javaFd); + resNetworkCancel(fd); + jniSetFileDescriptorOfFD(env, javaFd, -1); +} + +static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) { + unsigned dnsNetId = 0; + if (int res = getNetworkForDns(&dnsNetId) < 0) { + throwErrnoException(env, "getDnsNetId", -res); + return nullptr; + } + bool privateDnsBypass = dnsNetId & NETID_USE_LOCAL_NAMESERVERS; + + static jclass class_Network = MakeGlobalRefOrDie( + env, FindClassOrDie(env, "android/net/Network")); + static jmethodID ctor = env->GetMethodID(class_Network, "", "(IZ)V"); + return env->NewObject( + class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass); +} + +static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) { + if (javaFd == NULL) { + jniThrowNullPointerException(env, NULL); + return NULL; + } + + int fd = AFileDescriptor_getFD(env, javaFd); + struct tcp_repair_window trw = {}; + socklen_t size = sizeof(trw); + + // Obtain the parameters of the TCP repair window. + int rc = getsockopt(fd, IPPROTO_TCP, TCP_REPAIR_WINDOW, &trw, &size); + if (rc == -1) { + throwErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno); + return NULL; + } + + struct tcp_info tcpinfo = {}; + socklen_t tcpinfo_size = sizeof(tcp_info); + + // Obtain the window scale from the tcp info structure. This contains a scale factor that + // should be applied to the window size. + rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpinfo, &tcpinfo_size); + if (rc == -1) { + throwErrnoException(env, "getsockopt : TCP_INFO", errno); + return NULL; + } + + jclass class_TcpRepairWindow = env->FindClass("android/net/TcpRepairWindow"); + jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "", "(IIIIII)V"); + + return env->NewObject(class_TcpRepairWindow, ctor, trw.snd_wl1, trw.snd_wnd, trw.max_window, + trw.rcv_wnd, trw.rcv_wup, tcpinfo.tcpi_rcv_wscale); +} + +// ---------------------------------------------------------------------------- + +/* + * JNI registration. + */ +// clang-format off +static const JNINativeMethod gNetworkUtilMethods[] = { + /* name, signature, funcPtr */ + { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork }, + { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess }, + { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, + { "bindSocketToNetwork", "(Ljava/io/FileDescriptor;I)I", (void*) android_net_utils_bindSocketToNetwork }, + { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess }, + { "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter }, + { "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter }, + { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow }, + { "resNetworkSend", "(I[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend }, + { "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery }, + { "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult }, + { "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel }, + { "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork }, +}; +// clang-format on + +int register_android_net_NetworkUtils(JNIEnv* env) +{ + return jniRegisterNativeMethods(env, NETUTILS_PKG_NAME, gNetworkUtilMethods, + NELEM(gNetworkUtilMethods)); +} + +}; // namespace android diff --git a/framework/jni/onload.cpp b/framework/jni/onload.cpp new file mode 100644 index 0000000000..435f4343ed --- /dev/null +++ b/framework/jni/onload.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace android { + +int register_android_net_NetworkUtils(JNIEnv* env); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("GetEnv failed"); + return JNI_ERR; + } + + if (register_android_net_NetworkUtils(env) < 0) { + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} + +}; \ No newline at end of file From c1f2d31b393c583bcbe6c1cad8ee164f41fe81bc Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 13:37:40 +0000 Subject: [PATCH 160/343] Use jniThrowErrnoException from JNIHelp Use the jniThrowErrnoException that is available in JNIHelp, instead of reimplementing in NetworkUtils. Bug: 179229316 Test: device boots and has connectivity Change-Id: I257a9d55ce1f5a7c588e209b4a89d3e7a3e09994 --- framework/jni/android_net_NetworkUtils.cpp | 44 ++++------------------ 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp index 19ffe77c1f..c5b1ff8112 100644 --- a/framework/jni/android_net_NetworkUtils.cpp +++ b/framework/jni/android_net_NetworkUtils.cpp @@ -30,6 +30,7 @@ #include // NETID_USE_LOCAL_NAMESERVERS #include +#include #include #include #include @@ -57,14 +58,6 @@ static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) { return clazz; } -static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, - const char* method_signature) { - jmethodID res = env->GetMethodID(clazz, method_name, method_signature); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name, - method_signature); - return res; -} - template static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { jobject res = env->NewGlobalRef(in); @@ -72,27 +65,6 @@ static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { return static_cast(res); } -static void throwErrnoException(JNIEnv* env, const char* functionName, int error) { - ScopedLocalRef detailMessage(env, env->NewStringUTF(functionName)); - if (detailMessage.get() == NULL) { - // Not really much we can do here. We're probably dead in the water, - // but let's try to stumble on... - env->ExceptionClear(); - } - static jclass errnoExceptionClass = - MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException")); - - static jmethodID errnoExceptionCtor = - GetMethodIDOrDie(env, errnoExceptionClass, - "", "(Ljava/lang/String;I)V"); - - jobject exception = env->NewObject(errnoExceptionClass, - errnoExceptionCtor, - detailMessage.get(), - error); - env->Throw(reinterpret_cast(exception)); -} - static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) { struct sock_filter filter_code[] = { @@ -170,7 +142,7 @@ static jobject android_net_utils_resNetworkQuery(JNIEnv *env, jobject thiz, jint int fd = resNetworkQuery(netId, queryname.data(), ns_class, ns_type, flags); if (fd < 0) { - throwErrnoException(env, "resNetworkQuery", -fd); + jniThrowErrnoException(env, "resNetworkQuery", -fd); return nullptr; } @@ -185,7 +157,7 @@ static jobject android_net_utils_resNetworkSend(JNIEnv *env, jobject thiz, jint int fd = resNetworkSend(netId, data, msgLen, flags); if (fd < 0) { - throwErrnoException(env, "resNetworkSend", -fd); + jniThrowErrnoException(env, "resNetworkSend", -fd); return nullptr; } @@ -200,13 +172,13 @@ static jobject android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, job int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE); jniSetFileDescriptorOfFD(env, javaFd, -1); if (res < 0) { - throwErrnoException(env, "resNetworkResult", -res); + jniThrowErrnoException(env, "resNetworkResult", -res); return nullptr; } jbyteArray answer = env->NewByteArray(res); if (answer == nullptr) { - throwErrnoException(env, "resNetworkResult", ENOMEM); + jniThrowErrnoException(env, "resNetworkResult", ENOMEM); return nullptr; } else { env->SetByteArrayRegion(answer, 0, res, @@ -228,7 +200,7 @@ static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobjec static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) { unsigned dnsNetId = 0; if (int res = getNetworkForDns(&dnsNetId) < 0) { - throwErrnoException(env, "getDnsNetId", -res); + jniThrowErrnoException(env, "getDnsNetId", -res); return nullptr; } bool privateDnsBypass = dnsNetId & NETID_USE_LOCAL_NAMESERVERS; @@ -253,7 +225,7 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j // Obtain the parameters of the TCP repair window. int rc = getsockopt(fd, IPPROTO_TCP, TCP_REPAIR_WINDOW, &trw, &size); if (rc == -1) { - throwErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno); + jniThrowErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno); return NULL; } @@ -264,7 +236,7 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j // should be applied to the window size. rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpinfo, &tcpinfo_size); if (rc == -1) { - throwErrnoException(env, "getsockopt : TCP_INFO", errno); + jniThrowErrnoException(env, "getsockopt : TCP_INFO", errno); return NULL; } From 57707a50da284f384a2353b3542c35e21dd2e094 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 14:42:50 +0000 Subject: [PATCH 161/343] Fix InetAddressCompat exception handling Fix InetAddressCompat exception handling to throw the original exception in case of InvocationTargetException, rather than wrapping in a generic IllegalStateException. Bug: 183198868 Test: Test device with and without connectivity Change-Id: Idc4d678afe9f20f920d7061790af4203ab75be26 --- .../src/android/net/InetAddressCompat.java | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/framework/src/android/net/InetAddressCompat.java b/framework/src/android/net/InetAddressCompat.java index 8404441de6..6b7e75c753 100644 --- a/framework/src/android/net/InetAddressCompat.java +++ b/framework/src/android/net/InetAddressCompat.java @@ -41,7 +41,12 @@ public class InetAddressCompat { public static void clearDnsCache() { try { InetAddress.class.getMethod("clearDnsCache").invoke(null); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); + } catch (IllegalAccessException | NoSuchMethodException e) { Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e); } } @@ -51,13 +56,7 @@ public class InetAddressCompat { */ public static InetAddress[] getAllByNameOnNet(String host, int netId) throws UnknownHostException { - try { - return (InetAddress[]) InetAddress.class.getMethod("getAllByNameOnNet", - String.class, int.class).invoke(null, host, netId); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); - throw new IllegalStateException("Error querying via getAllNameOnNet", e); - } + return (InetAddress[]) callGetByNameMethod("getAllByNameOnNet", host, netId); } /** @@ -65,12 +64,25 @@ public class InetAddressCompat { */ public static InetAddress getByNameOnNet(String host, int netId) throws UnknownHostException { + return (InetAddress) callGetByNameMethod("getByNameOnNet", host, netId); + } + + private static Object callGetByNameMethod(String method, String host, int netId) + throws UnknownHostException { try { - return (InetAddress) InetAddress.class.getMethod("getByNameOnNet", - String.class, int.class).invoke(null, host, netId); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); - throw new IllegalStateException("Error querying via getByNameOnNet", e); + return InetAddress.class.getMethod(method, String.class, int.class) + .invoke(null, host, netId); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof UnknownHostException) { + throw (UnknownHostException) e.getCause(); + } + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); + } catch (IllegalAccessException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling " + method, e); + throw new IllegalStateException("Error querying via " + method, e); } } } From 257d49c3000643852536f2fc3f529363cf93bef7 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 14:42:50 +0000 Subject: [PATCH 162/343] Fix InetAddressCompat exception handling Fix InetAddressCompat exception handling to throw the original exception in case of InvocationTargetException, rather than wrapping in a generic IllegalStateException. Bug: 183198868 Test: Test device with and without connectivity Change-Id: Idc4d678afe9f20f920d7061790af4203ab75be26 --- .../src/android/net/InetAddressCompat.java | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/framework/src/android/net/InetAddressCompat.java b/framework/src/android/net/InetAddressCompat.java index 8404441de6..6b7e75c753 100644 --- a/framework/src/android/net/InetAddressCompat.java +++ b/framework/src/android/net/InetAddressCompat.java @@ -41,7 +41,12 @@ public class InetAddressCompat { public static void clearDnsCache() { try { InetAddress.class.getMethod("clearDnsCache").invoke(null); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + } catch (InvocationTargetException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); + } catch (IllegalAccessException | NoSuchMethodException e) { Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e); } } @@ -51,13 +56,7 @@ public class InetAddressCompat { */ public static InetAddress[] getAllByNameOnNet(String host, int netId) throws UnknownHostException { - try { - return (InetAddress[]) InetAddress.class.getMethod("getAllByNameOnNet", - String.class, int.class).invoke(null, host, netId); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); - throw new IllegalStateException("Error querying via getAllNameOnNet", e); - } + return (InetAddress[]) callGetByNameMethod("getAllByNameOnNet", host, netId); } /** @@ -65,12 +64,25 @@ public class InetAddressCompat { */ public static InetAddress getByNameOnNet(String host, int netId) throws UnknownHostException { + return (InetAddress) callGetByNameMethod("getByNameOnNet", host, netId); + } + + private static Object callGetByNameMethod(String method, String host, int netId) + throws UnknownHostException { try { - return (InetAddress) InetAddress.class.getMethod("getByNameOnNet", - String.class, int.class).invoke(null, host, netId); - } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling getAllByNameOnNet", e); - throw new IllegalStateException("Error querying via getByNameOnNet", e); + return InetAddress.class.getMethod(method, String.class, int.class) + .invoke(null, host, netId); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof UnknownHostException) { + throw (UnknownHostException) e.getCause(); + } + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw new IllegalStateException("Unknown InvocationTargetException", e.getCause()); + } catch (IllegalAccessException | NoSuchMethodException e) { + Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling " + method, e); + throw new IllegalStateException("Error querying via " + method, e); } } } From cd2bf4959f2d86beac9c9e90c32584239bbe9a4f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Mar 2021 17:04:08 +0900 Subject: [PATCH 163/343] Copy NetworkNotificationManager resources to conectivity module. The localized resources were automatically generated with: =========== export OLDRES=core/res/res export NEWRES=packages/Connectivity/service/ServiceConnectivityResources/res export FILE=services/core/java/com/android/server/connectivity/NetworkNotificationManager.java for i in $OLDRES/values-*/strings.xml; do outfile=$NEWRES/${i#core/res/res/} outdir=$(dirname $outfile) if egrep -q "$regex" $i || egrep -q "$strarrayregex" $i; then mkdir -p $outdir cat << EOF > $outfile EOF egrep $regex $i >> $outfile egrep -A $strarraylines "$strarrayregex" $i >> $outfile echo "" >> $outfile fi done =========== The text to the the base resources file was added manually from the output of: =========== egrep -B 2 $regex core/res/res/values/strings.xml | grep -v -- ^-- egrep -B 2 -A 6 $strarrayregex core/res/res/values/strings.xml | grep -v -- ^-- =========== The drawables were copied from the Wifi resources and from the framework resources. Test: m Bug: 183097033 Change-Id: I99c0d28069dd1a13d452105b0a83a03a833232a2 --- .../stat_notify_rssi_in_range.png | Bin 0 -> 1160 bytes .../stat_notify_rssi_in_range.png | Bin 0 -> 855 bytes .../stat_notify_rssi_in_range.png | Bin 0 -> 1500 bytes .../stat_notify_rssi_in_range.png | Bin 0 -> 3517 bytes .../drawable/stat_notify_wifi_in_range.xml | 27 ++++++++ .../res/values-af/strings.xml | 39 ++++++++++++ .../res/values-am/strings.xml | 39 ++++++++++++ .../res/values-ar/strings.xml | 39 ++++++++++++ .../res/values-as/strings.xml | 39 ++++++++++++ .../res/values-az/strings.xml | 39 ++++++++++++ .../res/values-b+sr+Latn/strings.xml | 39 ++++++++++++ .../res/values-be/strings.xml | 39 ++++++++++++ .../res/values-bg/strings.xml | 39 ++++++++++++ .../res/values-bn/strings.xml | 39 ++++++++++++ .../res/values-bs/strings.xml | 39 ++++++++++++ .../res/values-ca/strings.xml | 39 ++++++++++++ .../res/values-cs/strings.xml | 39 ++++++++++++ .../res/values-da/strings.xml | 39 ++++++++++++ .../res/values-de/strings.xml | 39 ++++++++++++ .../res/values-el/strings.xml | 39 ++++++++++++ .../res/values-en-rAU/strings.xml | 39 ++++++++++++ .../res/values-en-rCA/strings.xml | 39 ++++++++++++ .../res/values-en-rGB/strings.xml | 39 ++++++++++++ .../res/values-en-rIN/strings.xml | 39 ++++++++++++ .../res/values-en-rXC/strings.xml | 39 ++++++++++++ .../res/values-es-rUS/strings.xml | 39 ++++++++++++ .../res/values-es/strings.xml | 39 ++++++++++++ .../res/values-et/strings.xml | 39 ++++++++++++ .../res/values-eu/strings.xml | 39 ++++++++++++ .../res/values-fa/strings.xml | 39 ++++++++++++ .../res/values-fi/strings.xml | 39 ++++++++++++ .../res/values-fr-rCA/strings.xml | 39 ++++++++++++ .../res/values-fr/strings.xml | 39 ++++++++++++ .../res/values-gl/strings.xml | 39 ++++++++++++ .../res/values-gu/strings.xml | 39 ++++++++++++ .../res/values-hi/strings.xml | 39 ++++++++++++ .../res/values-hr/strings.xml | 39 ++++++++++++ .../res/values-hu/strings.xml | 39 ++++++++++++ .../res/values-hy/strings.xml | 39 ++++++++++++ .../res/values-in/strings.xml | 39 ++++++++++++ .../res/values-is/strings.xml | 39 ++++++++++++ .../res/values-it/strings.xml | 39 ++++++++++++ .../res/values-iw/strings.xml | 39 ++++++++++++ .../res/values-ja/strings.xml | 39 ++++++++++++ .../res/values-ka/strings.xml | 39 ++++++++++++ .../res/values-kk/strings.xml | 39 ++++++++++++ .../res/values-km/strings.xml | 39 ++++++++++++ .../res/values-kn/strings.xml | 39 ++++++++++++ .../res/values-ko/strings.xml | 39 ++++++++++++ .../res/values-ky/strings.xml | 39 ++++++++++++ .../res/values-lo/strings.xml | 39 ++++++++++++ .../res/values-lt/strings.xml | 39 ++++++++++++ .../res/values-lv/strings.xml | 39 ++++++++++++ .../res/values-mk/strings.xml | 39 ++++++++++++ .../res/values-ml/strings.xml | 39 ++++++++++++ .../res/values-mn/strings.xml | 39 ++++++++++++ .../res/values-mr/strings.xml | 39 ++++++++++++ .../res/values-ms/strings.xml | 39 ++++++++++++ .../res/values-my/strings.xml | 39 ++++++++++++ .../res/values-nb/strings.xml | 39 ++++++++++++ .../res/values-ne/strings.xml | 39 ++++++++++++ .../res/values-nl/strings.xml | 39 ++++++++++++ .../res/values-or/strings.xml | 39 ++++++++++++ .../res/values-pa/strings.xml | 39 ++++++++++++ .../res/values-pl/strings.xml | 39 ++++++++++++ .../res/values-pt-rBR/strings.xml | 39 ++++++++++++ .../res/values-pt-rPT/strings.xml | 39 ++++++++++++ .../res/values-pt/strings.xml | 39 ++++++++++++ .../res/values-ro/strings.xml | 39 ++++++++++++ .../res/values-ru/strings.xml | 39 ++++++++++++ .../res/values-si/strings.xml | 39 ++++++++++++ .../res/values-sk/strings.xml | 39 ++++++++++++ .../res/values-sl/strings.xml | 39 ++++++++++++ .../res/values-sq/strings.xml | 39 ++++++++++++ .../res/values-sr/strings.xml | 39 ++++++++++++ .../res/values-sv/strings.xml | 39 ++++++++++++ .../res/values-sw/strings.xml | 39 ++++++++++++ .../res/values-ta/strings.xml | 39 ++++++++++++ .../res/values-te/strings.xml | 39 ++++++++++++ .../res/values-th/strings.xml | 39 ++++++++++++ .../res/values-tl/strings.xml | 39 ++++++++++++ .../res/values-tr/strings.xml | 39 ++++++++++++ .../res/values-uk/strings.xml | 39 ++++++++++++ .../res/values-ur/strings.xml | 39 ++++++++++++ .../res/values-uz/strings.xml | 39 ++++++++++++ .../res/values-vi/strings.xml | 39 ++++++++++++ .../res/values-zh-rCN/strings.xml | 39 ++++++++++++ .../res/values-zh-rHK/strings.xml | 39 ++++++++++++ .../res/values-zh-rTW/strings.xml | 39 ++++++++++++ .../res/values-zu/strings.xml | 39 ++++++++++++ .../res/values/strings.xml | 58 +++++++++++++++++- 91 files changed, 3398 insertions(+), 2 deletions(-) create mode 100644 service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml create mode 100644 service/ServiceConnectivityResources/res/values-af/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-am/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ar/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-as/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-az/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-be/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-bg/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-bn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-bs/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ca/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-cs/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-da/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-de/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-el/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rAU/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rCA/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rGB/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rIN/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rXC/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-es-rUS/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-es/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-et/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-eu/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fa/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fi/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-gl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-gu/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hi/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hu/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hy/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-in/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-is/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-it/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-iw/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ja/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ka/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-kk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-km/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-kn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ko/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ky/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-lo/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-lt/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-lv/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-mk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ml/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-mn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-mr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ms/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-my/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-nb/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ne/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-nl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-or/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pa/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pt/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ro/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ru/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-si/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sq/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sv/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sw/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ta/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-te/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-th/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-tl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-tr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-uk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ur/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-uz/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-vi/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zu/strings.xml diff --git a/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png b/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png new file mode 100644 index 0000000000000000000000000000000000000000..74977e6aefffb385b33ee169faf7bd0c63cf38a2 GIT binary patch literal 1160 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBSkfJR9T^xl_H+M9WCijWi-X*q z7}lMWc?skwBzpw;GB8xBGB7kWGcf%852S(Or3MTPuM!v-tbhiH=TC}1>IPKHmgMd3 z!tfsi7wla=87RV8;1OBOz`!j8!i<;h*8O2%V6OFaaSVw#e0Ik9{2oV%qAN=gZp5G0DtB#^cY51)M^&JnqQOvG7o__`xl6_Yb>;XTg z`)zT?c=zR-mG^76?-rfBXXd#x#^*oR&iiTi*+=}}=Cq{AN{{%t9oqNvglyUFsi>5k z6fN|{Sg9!VY0o#_gDmmWJHGs|N}4_A)25C+fsaMsrn{!t&Dg!@lWb%Ilft=&f`XPW z&s)msqlBnYH1dbce&)yF-SSn(WcV9B6>;Ea{C5bJ2!WicTonE!wYJY%hfcBnu zEBcszH_qpsbB_On@)z$15iU!-W-y##e4}eK`|`t@hAGZWUzpT4)Oa#`+oGd5@)_`r11Qy zh1uo{9kskE*O(SZJX#+1cN(K)@|^a`2Xa^J{vq_{aJO@4M3^ z_4bI^>9_~m*_SPyCc03|OlM~81l9*K8+d0N6g#_ZOWP8^%8#;)-;%V;qm>>@pWr@r zevVPDLP2mt&;gzV?pJq;8Zspm{oOXOmR0Ojn#`%8kpDxhOz^jPgHl3OBli`rlbg0# zIm~+Z?vZw~{ytHix*6W5+$Vo7y}484ZF9Pdd4Xg^|K1 zRdP`(kYX@0Ff`ING|)9L3NbXXGBL6OvCXXv3~mHe^P_0U%}>cptHiBgCGX+QKn)C@ Lu6{1-oD!M!lvI6;x#X;^) z4C~IxyaaL-l0AZa85pWm85kOx85n;42hu?CQUeBtR|yOZRx=nF#PcV`A9Vw&WlQpQ zcVYMsf(!O8p9~b?EbxddW?97dyXIW z_-xmgRDMHe%2KTZ-;=rSd!OICB3)Q>|Dn|k67KTshs$=IC{x^Y;(>J`+vmG%FH1XC zbr*dt)aCf!Xf69`RnryEH3!f0UF?=jxm2`L>dv9unnSF6bd=7i&g!{T%Uyf2;fnJY zw(0`oZ+ed-S%RC^A63oajoTH$tdf56<@vT|yLtSI_NR!0*93uY=PqB#Kh5A9S2|DPEiP-8Gx^4KK94E**E9bFJ*+g}C^Q z&3?%}g`47*eukY-MMjL1Spl=*TicDN5G!Eb+n^ zTVXQlNiQBo#AKTnQN7ZfQ!itQH~xHoymQZYzx&;DzkC0?`Q8K{g003DxSDcTS zO%H&O5NAKgR<4*}Q5a7Q0CW^f?}ov}8YKI;V1c&rBOk;1-?vmP(HxSfYoDJio<>%rTeSDD?XnFuQ9pha4Y&55Jc=qk zOWLO)LM2AkuaDqYWl{VpwR7ub*mgAJ3>VOvhYNpVLF{3bkiE%uIaP21lwVoLJejvH z`14mu`Ut(duZUAIq&F#9Jr%{II!M|>ciT6Y!9j=?Xl=-F6dDSBgZ`FuHesCRn#}|p z<5a9S>}_5%Rt09kFGeDr_dBve3)0V&wBp9Wn3yYSB515(-ODsS%wry)xDA!HEMQ|i z-mM+=MRs>w)Musdr3rMGN}s*(PuD~gjCcpRD<2ZJinbMAqA@kU=u^N%NC-D~rKHft zl6TZt`2_E2haO4o5nL-4&O&A`d<*~TEijU_uhV_~!hda=s;$j#bD*MP>zWuA?zr>I zxuQQbE(rC7WgTf}bE3*38y*{0Cxll$_lo6}e`h2y{2pMjjqlA%W>-!--zNR`hNtfp zq+v+6X7pyOY%|+q3#EB%&ZDQ@BJ3X9o^1&h`#E_sGQx&9}e!aV#8Q6 z_IVSDRrTfk32e9&lK&z2psrHPw- zJWG|5tUP*umC9APEozA?O(-Nv^I>BhyBv{m95w3A)~cf6%y7-hqUQFtSCEw@T}5Ce z2)Ozs`hqY4aW{CXOi#_W+1L(IJ&{A_e4_0pr{jDdEIp5^Np<2?&sA$Z%@7c6>qi5m z{L^d@l{fZwbahJ}u)|I+-Dc%8x^Es6bw$nkW)BDI$ZkO7TCCr8PdB>G+pyFJ(TE0O zgzAurHC?M0lBo_+mLLk&=?$kqn$Kwa7kJm8FCX0tp#(uBHU@h79RCVQyJtKfZwD#` zP3D+42FlHcq~#PYPA?$*-KW1!{NtI{W!b~|lrNy2X_a3rcCZpY%iw-zI|L@WuMxD_ z1A+;6FCUH8F?gl{Bp(YWS+KOUHp$TC3a4Zl@IN*23t9KjdWDDQtIn)t1H7Wmkfp+$MX3PYFG|HbpTp z@z6|k3(s8Kf0YuY#402k2<>S`2~oAL9};h>26?C3*sC&Y?x`~?9J@!py+Wvpeu(5X zAi?#>Ce4}LBGe43-z~pg_Iv6j`mz^MjvJsAL~M<%>CWS_#-(j)0yYKZNT~k$*qqH3 z3~rnIMD0g;6}cQ2S^V)9t|qIJ3`OyC+tJOW0YT-lbLeOtQ{QC5v{k3qaZV#R#B(*7 z)sL7AZYHM&mueXJfkG~OLOG%^K>YFaQtKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0008$NklGu?NrI1pWfoHauto{KyCg zHU0=V^kC)eC`iVa*a#RFyune)khX!YjTjUee6SJFD*;XfY}yLaNuDzW_JF?noF~|1zLH(APb-iPXu0Cy9<0%ki4(OdXBxT348$_ zhElA?$ph0~d83jahf>WS#*`#e3n~6dT9xbrpq|niIvcM-yCV+HQOx!4C1$tM0S%e= zf!Z-k%cS>oLjp8OC@rR{EHSB)KZF8kl8~{+hT#-a$)<&3nrtj)r? zZ31rvklu3!vc#6#dMGNn3_y!JE+j}VQOW!2Q?l4CyMx0W7oh=a0G~rt$*uqms-Sml z0qRr2j*CzLZ2@nj)X=Nsh!wCrFAiJ4Q_^in__c6;o^sCR!uijXbN(!x|0exriR+{R rHTi?3a;td(B!C2vm;e$$_UzvPcEfJQwa{BG00000NkvXXu0mjfV3c|Q literal 0 HcmV?d00001 diff --git a/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml b/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml new file mode 100644 index 0000000000..a271ca5224 --- /dev/null +++ b/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/service/ServiceConnectivityResources/res/values-af/strings.xml b/service/ServiceConnectivityResources/res/values-af/strings.xml new file mode 100644 index 0000000000..68720d5d27 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-af/strings.xml @@ -0,0 +1,39 @@ + + + + "Meld aan by Wi-Fi-netwerk" + "Meld by netwerk aan" + + "%1$s het geen internettoegang nie" + "Tik vir opsies" + "Selnetwerk het nie internettoegang nie" + "Netwerk het nie internettoegang nie" + "Daar kan nie by private DNS-bediener ingegaan word nie" + "%1$s het beperkte konnektiwiteit" + "Tik om in elk geval te koppel" + "Het oorgeskakel na %1$s" + "Toestel gebruik %1$s wanneer %2$s geen internettoegang het nie. Heffings kan geld." + "Het oorgeskakel van %1$s na %2$s" + "\'n onbekende netwerktipe" + + "mobiele data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-am/strings.xml b/service/ServiceConnectivityResources/res/values-am/strings.xml new file mode 100644 index 0000000000..78d928351d --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-am/strings.xml @@ -0,0 +1,39 @@ + + + + "ወደ Wi-Fi አውታረ መረብ በመለያ ግባ" + "ወደ አውታረ መረብ በመለያ ይግቡ" + + "%1$s ምንም የበይነ መረብ መዳረሻ የለም" + "ለአማራጮች መታ ያድርጉ" + "የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም" + "አውታረ መረብ የበይነመረብ መዳረሻ የለውም" + "የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም" + "%1$s የተገደበ ግንኙነት አለው" + "ለማንኛውም ለማገናኘት መታ ያድርጉ" + "ወደ %1$s ተቀይሯል" + "%2$s ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች %1$sን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።" + "ከ%1$s ወደ %2$s ተቀይሯል" + "አንድ ያልታወቀ አውታረ መረብ ዓይነት" + + "የተንቀሳቃሽ ስልክ ውሂብ" + "Wi-Fi" + "ብሉቱዝ" + "ኤተርኔት" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ar/strings.xml b/service/ServiceConnectivityResources/res/values-ar/strings.xml new file mode 100644 index 0000000000..8698a7e6e1 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ar/strings.xml @@ -0,0 +1,39 @@ + + + + "‏تسجيل الدخول إلى شبكة Wi-Fi" + "تسجيل الدخول إلى الشبكة" + + "لا يتوفّر في %1$s إمكانية الاتصال بالإنترنت." + "انقر للحصول على الخيارات." + "شبكة الجوّال هذه غير متصلة بالإنترنت" + "الشبكة غير متصلة بالإنترنت" + "لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص" + "إمكانية اتصال %1$s محدودة." + "يمكنك النقر للاتصال على أي حال." + "تم التبديل إلى %1$s" + "يستخدم الجهاز %1$s عندما لا يتوفر اتصال بالإنترنت في شبكة %2$s، ويمكن أن يتم فرض رسوم مقابل ذلك." + "تم التبديل من %1$s إلى %2$s" + "نوع شبكة غير معروف" + + "بيانات الجوّال" + "Wi-Fi" + "بلوتوث" + "إيثرنت" + "‏شبكة افتراضية خاصة (VPN)" + + diff --git a/service/ServiceConnectivityResources/res/values-as/strings.xml b/service/ServiceConnectivityResources/res/values-as/strings.xml new file mode 100644 index 0000000000..10b234adce --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-as/strings.xml @@ -0,0 +1,39 @@ + + + + "ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক" + "নেটৱৰ্কত ছাইন ইন কৰক" + + "%1$sৰ ইণ্টাৰনেটৰ এক্সেছ নাই" + "অধিক বিকল্পৰ বাবে টিপক" + "ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" + "নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" + "ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি" + "%1$sৰ সকলো সেৱাৰ এক্সেছ নাই" + "যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক" + "%1$sলৈ সলনি কৰা হ’ল" + "যেতিয়া %2$sত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে %1$sক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।" + "%1$sৰ পৰা %2$s লৈ সলনি কৰা হ’ল" + "অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক" + + "ম’বাইল ডেটা" + "ৱাই-ফাই" + "ব্লুটুথ" + "ইথাৰনেট" + "ভিপিএন" + + diff --git a/service/ServiceConnectivityResources/res/values-az/strings.xml b/service/ServiceConnectivityResources/res/values-az/strings.xml new file mode 100644 index 0000000000..d75a20460c --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-az/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi şəbəkəsinə daxil ol" + "Şəbəkəyə daxil olun" + + "%1$s üçün internet girişi əlçatan deyil" + "Seçimlər üçün tıklayın" + "Mobil şəbəkənin internetə girişi yoxdur" + "Şəbəkənin internetə girişi yoxdur" + "Özəl DNS serverinə giriş mümkün deyil" + "%1$s bağlantını məhdudlaşdırdı" + "İstənilən halda klikləyin" + "%1$s şəbəkə növünə keçirildi" + "%2$s şəbəkəsinin internetə girişi olmadıqda, cihaz %1$s şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər." + "%1$s şəbəkəsindən %2$s şəbəkəsinə keçirildi" + "naməlum şəbəkə növü" + + "mobil data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml b/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000..11e4957a7b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijavljivanje na WiFi mrežu" + "Prijavite se na mrežu" + + "%1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Pristup privatnom DNS serveru nije uspeo" + "%1$s ima ograničenu vezu" + "Dodirnite da biste se ipak povezali" + "Prešli ste na tip mreže %1$s" + "Uređaj koristi tip mreže %1$s kada tip mreže %2$s nema pristup internetu. Možda će se naplaćivati troškovi." + "Prešli ste sa tipa mreže %1$s na tip mreže %2$s" + "nepoznat tip mreže" + + "mobilni podaci" + "WiFi" + "Bluetooth" + "Eternet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-be/strings.xml b/service/ServiceConnectivityResources/res/values-be/strings.xml new file mode 100644 index 0000000000..6b0b1f1130 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-be/strings.xml @@ -0,0 +1,39 @@ + + + + "Уваход у сетку Wi-Fi" + "Увайдзіце ў сетку" + + "%1$s не мае доступу ў інтэрнэт" + "Дакраніцеся, каб убачыць параметры" + "Мабільная сетка не мае доступу ў інтэрнэт" + "Сетка не мае доступу ў інтэрнэт" + "Не ўдалося атрымаць доступ да прыватнага DNS-сервера" + "%1$s мае абмежаваную магчымасць падключэння" + "Націсніце, каб падключыцца" + "Выкананы пераход да %1$s" + "Прылада выкарыстоўвае сетку %1$s, калі ў сетцы %2$s няма доступу да інтэрнэту. Можа спаганяцца плата." + "Выкананы пераход з %1$s да %2$s" + "невядомы тып сеткі" + + "мабільная перадача даных" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-bg/strings.xml b/service/ServiceConnectivityResources/res/values-bg/strings.xml new file mode 100644 index 0000000000..6427bd09cf --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-bg/strings.xml @@ -0,0 +1,39 @@ + + + + "Влизане в Wi-Fi мрежа" + "Вход в мрежата" + + "%1$s няма достъп до интернет" + "Докоснете за опции" + "Мобилната мрежа няма достъп до интернет" + "Мрежата няма достъп до интернет" + "Не може да се осъществи достъп до частния DNS сървър" + "%1$s има ограничена свързаност" + "Докоснете, за да се свържете въпреки това" + "Превключи се към %1$s" + "Устройството използва %1$s, когато %2$s няма достъп до интернет. Възможно е да бъдете таксувани." + "Превключи се от %1$s към %2$s" + "неизвестен тип мрежа" + + "мобилни данни" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "виртуална частна мрежа (VPN)" + + diff --git a/service/ServiceConnectivityResources/res/values-bn/strings.xml b/service/ServiceConnectivityResources/res/values-bn/strings.xml new file mode 100644 index 0000000000..74d4cd6d7e --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-bn/strings.xml @@ -0,0 +1,39 @@ + + + + "ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন" + "নেটওয়ার্কে সাইন-ইন করুন" + + "%1$s-এর ইন্টারনেটে অ্যাক্সেস নেই" + "বিকল্পগুলির জন্য আলতো চাপুন" + "মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" + "নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" + "ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না" + "%1$s-এর সীমিত কানেক্টিভিটি আছে" + "তবুও কানেক্ট করতে ট্যাপ করুন" + "%1$s এ পাল্টানো হয়েছে" + "%2$s এ ইন্টারনেট অ্যাক্সেস না থাকলে %1$s ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷" + "%1$s থেকে %2$s এ পাল্টানো হয়েছে" + "এই নেটওয়ার্কের প্রকার অজানা" + + "মোবাইল ডেটা" + "Wi-Fi" + "ব্লুটুথ" + "ইথারনেট" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-bs/strings.xml b/service/ServiceConnectivityResources/res/values-bs/strings.xml new file mode 100644 index 0000000000..19f6e1a3f5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-bs/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijavljivanje na WiFi mrežu" + "Prijava na mrežu" + + "Mreža %1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Nije moguće pristupiti privatnom DNS serveru" + "Mreža %1$s ima ograničenu povezivost" + "Dodirnite da se ipak povežete" + "Prebačeno na: %1$s" + "Kada %2$s nema pristup internetu, uređaj koristi mrežu %1$s. Moguća je naplata usluge." + "Prebačeno iz mreže %1$s u %2$s mrežu" + "nepoznata vrsta mreže" + + "prijenos podataka na mobilnoj mreži" + "WiFi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ca/strings.xml b/service/ServiceConnectivityResources/res/values-ca/strings.xml new file mode 100644 index 0000000000..c55684d6e0 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ca/strings.xml @@ -0,0 +1,39 @@ + + + + "Inicia la sessió a la xarxa Wi-Fi" + "Inicia la sessió a la xarxa" + + "%1$s no té accés a Internet" + "Toca per veure les opcions" + "La xarxa mòbil no té accés a Internet" + "La xarxa no té accés a Internet" + "No es pot accedir al servidor DNS privat" + "%1$s té una connectivitat limitada" + "Toca per connectar igualment" + "Actualment en ús: %1$s" + "El dispositiu utilitza %1$s en cas que %2$s no tingui accés a Internet. És possible que s\'hi apliquin càrrecs." + "Abans es feia servir la xarxa %1$s; ara s\'utilitza %2$s" + "una tipus de xarxa desconegut" + + "dades mòbils" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-cs/strings.xml b/service/ServiceConnectivityResources/res/values-cs/strings.xml new file mode 100644 index 0000000000..fa8c411e48 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-cs/strings.xml @@ -0,0 +1,39 @@ + + + + "Přihlásit se k síti Wi-Fi" + "Přihlásit se k síti" + + "Síť %1$s nemá přístup k internetu" + "Klepnutím zobrazíte možnosti" + "Mobilní síť nemá přístup k internetu" + "Síť nemá přístup k internetu" + "Nelze získat přístup k soukromému serveru DNS" + "Síť %1$s umožňuje jen omezené připojení" + "Klepnutím se i přesto připojíte" + "Přechod na síť %1$s" + "Když síť %2$s nebude mít přístup k internetu, zařízení použije síť %1$s. Mohou být účtovány poplatky." + "Přechod ze sítě %1$s na síť %2$s" + "neznámý typ sítě" + + "mobilní data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-da/strings.xml b/service/ServiceConnectivityResources/res/values-da/strings.xml new file mode 100644 index 0000000000..f7be6df981 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-da/strings.xml @@ -0,0 +1,39 @@ + + + + "Log ind på Wi-Fi-netværk" + "Log ind på netværk" + + "%1$s har ingen internetforbindelse" + "Tryk for at se valgmuligheder" + "Mobilnetværket har ingen internetadgang" + "Netværket har ingen internetadgang" + "Der er ikke adgang til den private DNS-server" + "%1$s har begrænset forbindelse" + "Tryk for at oprette forbindelse alligevel" + "Der blev skiftet til %1$s" + "Enheden benytter %1$s, når der ikke er internetadgang via %2$s. Der opkræves muligvis betaling." + "Der blev skiftet fra %1$s til %2$s" + "en ukendt netværkstype" + + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-de/strings.xml b/service/ServiceConnectivityResources/res/values-de/strings.xml new file mode 100644 index 0000000000..1e7b80c8f6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-de/strings.xml @@ -0,0 +1,39 @@ + + + + "In WLAN anmelden" + "Im Netzwerk anmelden" + + "%1$s hat keinen Internetzugriff" + "Für Optionen tippen" + "Mobiles Netzwerk hat keinen Internetzugriff" + "Netzwerk hat keinen Internetzugriff" + "Auf den privaten DNS-Server kann nicht zugegriffen werden" + "Schlechte Verbindung mit %1$s" + "Tippen, um die Verbindung trotzdem herzustellen" + "Zu %1$s gewechselt" + "Auf dem Gerät werden %1$s genutzt, wenn über %2$s kein Internet verfügbar ist. Eventuell fallen Gebühren an." + "Von \"%1$s\" zu \"%2$s\" gewechselt" + "ein unbekannter Netzwerktyp" + + "Mobile Daten" + "WLAN" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-el/strings.xml b/service/ServiceConnectivityResources/res/values-el/strings.xml new file mode 100644 index 0000000000..89647fdb1e --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-el/strings.xml @@ -0,0 +1,39 @@ + + + + "Συνδεθείτε στο δίκτυο Wi-Fi" + "Σύνδεση στο δίκτυο" + + "Η εφαρμογή %1$s δεν έχει πρόσβαση στο διαδίκτυο" + "Πατήστε για να δείτε τις επιλογές" + "Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο." + "Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο." + "Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS." + "Το δίκτυο %1$s έχει περιορισμένη συνδεσιμότητα" + "Πατήστε για σύνδεση ούτως ή άλλως" + "Μετάβαση σε δίκτυο %1$s" + "Η συσκευή χρησιμοποιεί το δίκτυο %1$s όταν το δίκτυο %2$s δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις." + "Μετάβαση από το δίκτυο %1$s στο δίκτυο %2$s" + "άγνωστος τύπος δικτύου" + + "δεδομένα κινητής τηλεφωνίας" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml b/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml b/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml b/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml b/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml b/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml new file mode 100644 index 0000000000..cd69133966 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml @@ -0,0 +1,39 @@ + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎Sign in to Wi-Fi network‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎Sign in to network‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎Tap for options‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎Mobile network has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎Network has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎Private DNS server cannot be accessed‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has limited connectivity‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎Tap to connect anyway‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎Switched to ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎Device uses ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ when ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ has no internet access. Charges may apply.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎Switched from ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎an unknown network type‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎mobile data‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎Wi-Fi‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎Bluetooth‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‎Ethernet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎VPN‎‏‎‎‏‎" + + diff --git a/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml b/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml new file mode 100644 index 0000000000..9102dc019a --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml @@ -0,0 +1,39 @@ + + + + "Accede a una red Wi-Fi." + "Acceder a la red" + + "%1$sno tiene acceso a Internet" + "Presiona para ver opciones" + "La red móvil no tiene acceso a Internet" + "La red no tiene acceso a Internet" + "No se puede acceder al servidor DNS privado" + "%1$s tiene conectividad limitada" + "Presiona para conectarte de todas formas" + "Se cambió a %1$s" + "El dispositivo usa %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." + "Se cambió de %1$s a %2$s" + "un tipo de red desconocido" + + "Datos móviles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-es/strings.xml b/service/ServiceConnectivityResources/res/values-es/strings.xml new file mode 100644 index 0000000000..4c15566a73 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-es/strings.xml @@ -0,0 +1,39 @@ + + + + "Iniciar sesión en red Wi-Fi" + "Iniciar sesión en la red" + + "%1$s no tiene acceso a Internet" + "Toca para ver opciones" + "La red móvil no tiene acceso a Internet" + "La red no tiene acceso a Internet" + "No se ha podido acceder al servidor DNS privado" + "%1$s tiene una conectividad limitada" + "Toca para conectarte de todas formas" + "Se ha cambiado a %1$s" + "El dispositivo utiliza %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." + "Se ha cambiado de %1$s a %2$s" + "tipo de red desconocido" + + "datos móviles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-et/strings.xml b/service/ServiceConnectivityResources/res/values-et/strings.xml new file mode 100644 index 0000000000..398223a341 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-et/strings.xml @@ -0,0 +1,39 @@ + + + + "Logi sisse WiFi-võrku" + "Võrku sisselogimine" + + "Võrgul %1$s puudub Interneti-ühendus" + "Puudutage valikute nägemiseks" + "Mobiilsidevõrgul puudub Interneti-ühendus" + "Võrgul puudub Interneti-ühendus" + "Privaatsele DNS-serverile ei pääse juurde" + "Võrgu %1$s ühendus on piiratud" + "Puudutage, kui soovite siiski ühenduse luua" + "Lülitati võrgule %1$s" + "Seade kasutab võrku %1$s, kui võrgul %2$s puudub juurdepääs Internetile. Rakenduda võivad tasud." + "Lülitati võrgult %1$s võrgule %2$s" + "tundmatu võrgutüüp" + + "mobiilne andmeside" + "WiFi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-eu/strings.xml b/service/ServiceConnectivityResources/res/values-eu/strings.xml new file mode 100644 index 0000000000..dd70316f69 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-eu/strings.xml @@ -0,0 +1,39 @@ + + + + "Hasi saioa Wi-Fi sarean" + "Hasi saioa sarean" + + "Ezin da konektatu Internetera %1$s sarearen bidez" + "Sakatu aukerak ikusteko" + "Sare mugikorra ezin da konektatu Internetera" + "Sarea ezin da konektatu Internetera" + "Ezin da atzitu DNS zerbitzari pribatua" + "%1$s sareak konektagarritasun murriztua du" + "Sakatu hala ere konektatzeko" + "%1$s erabiltzen ari zara orain" + "%2$s Internetera konektatzeko gauza ez denean, %1$s erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu." + "%1$s erabiltzen ari zinen, baina %2$s erabiltzen ari zara orain" + "sare mota ezezaguna" + + "datu-konexioa" + "Wifia" + "Bluetooth-a" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-fa/strings.xml b/service/ServiceConnectivityResources/res/values-fa/strings.xml new file mode 100644 index 0000000000..46a946c50b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fa/strings.xml @@ -0,0 +1,39 @@ + + + + "‏ورود به شبکه Wi-Fi" + "ورود به سیستم شبکه" + + "%1$s به اینترنت دسترسی ندارد" + "برای گزینه‌ها ضربه بزنید" + "شبکه تلفن همراه به اینترنت دسترسی ندارد" + "شبکه به اینترنت دسترسی ندارد" + "‏سرور DNS خصوصی قابل دسترسی نیست" + "%1$s اتصال محدودی دارد" + "به‌هرصورت، برای اتصال ضربه بزنید" + "به %1$s تغییر کرد" + "وقتی %2$s به اینترنت دسترسی نداشته باشد، دستگاه از %1$s استفاده می‌کند. ممکن است هزینه‌هایی اعمال شود." + "از %1$s به %2$s تغییر کرد" + "نوع شبکه نامشخص" + + "داده تلفن همراه" + "Wi-Fi" + "بلوتوث" + "اترنت" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-fi/strings.xml b/service/ServiceConnectivityResources/res/values-fi/strings.xml new file mode 100644 index 0000000000..dd944415c9 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fi/strings.xml @@ -0,0 +1,39 @@ + + + + "Kirjaudu Wi-Fi-verkkoon" + "Kirjaudu verkkoon" + + "%1$s ei ole yhteydessä internetiin" + "Näytä vaihtoehdot napauttamalla." + "Mobiiliverkko ei ole yhteydessä internetiin" + "Verkko ei ole yhteydessä internetiin" + "Ei pääsyä yksityiselle DNS-palvelimelle" + "%1$s toimii rajoitetulla yhteydellä" + "Yhdistä napauttamalla" + "%1$s otettiin käyttöön" + "%1$s otetaan käyttöön, kun %2$s ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia." + "%1$s poistettiin käytöstä ja %2$s otettiin käyttöön." + "tuntematon verkon tyyppi" + + "mobiilidata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml b/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml new file mode 100644 index 0000000000..02ef50b2c1 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml @@ -0,0 +1,39 @@ + + + + "Connectez-vous au réseau Wi-Fi" + "Connectez-vous au réseau" + + "Le réseau %1$s n\'offre aucun accès à Internet" + "Touchez pour afficher les options" + "Le réseau cellulaire n\'offre aucun accès à Internet" + "Le réseau n\'offre aucun accès à Internet" + "Impossible d\'accéder au serveur DNS privé" + "Le réseau %1$s offre une connectivité limitée" + "Touchez pour vous connecter quand même" + "Passé au réseau %1$s" + "L\'appareil utilise %1$s quand %2$s n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer." + "Passé du réseau %1$s au %2$s" + "un type de réseau inconnu" + + "données cellulaires" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "RPV" + + diff --git a/service/ServiceConnectivityResources/res/values-fr/strings.xml b/service/ServiceConnectivityResources/res/values-fr/strings.xml new file mode 100644 index 0000000000..08c9d8157a --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fr/strings.xml @@ -0,0 +1,39 @@ + + + + "Connectez-vous au réseau Wi-Fi" + "Se connecter au réseau" + + "Aucune connexion à Internet pour %1$s" + "Appuyez ici pour afficher des options." + "Le réseau mobile ne dispose d\'aucun accès à Internet" + "Le réseau ne dispose d\'aucun accès à Internet" + "Impossible d\'accéder au serveur DNS privé" + "La connectivité de %1$s est limitée" + "Appuyer pour se connecter quand même" + "Nouveau réseau : %1$s" + "L\'appareil utilise %1$s lorsque %2$s n\'a pas de connexion Internet. Des frais peuvent s\'appliquer." + "Ancien réseau : %1$s. Nouveau réseau : %2$s" + "type de réseau inconnu" + + "données mobiles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-gl/strings.xml b/service/ServiceConnectivityResources/res/values-gl/strings.xml new file mode 100644 index 0000000000..9f98055ab9 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-gl/strings.xml @@ -0,0 +1,39 @@ + + + + "Inicia sesión na rede wifi" + "Inicia sesión na rede" + + "%1$s non ten acceso a Internet" + "Toca para ver opcións." + "A rede de telefonía móbil non ten acceso a Internet" + "A rede non ten acceso a Internet" + "Non se puido acceder ao servidor DNS privado" + "A conectividade de %1$s é limitada" + "Toca para conectarte de todas formas" + "Cambiouse a: %1$s" + "O dispositivo utiliza %1$s cando %2$s non ten acceso a Internet. Pódense aplicar cargos." + "Cambiouse de %1$s a %2$s" + "un tipo de rede descoñecido" + + "datos móbiles" + "wifi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-gu/strings.xml b/service/ServiceConnectivityResources/res/values-gu/strings.xml new file mode 100644 index 0000000000..4ae5a2c45f --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-gu/strings.xml @@ -0,0 +1,39 @@ + + + + "વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો" + "નેટવર્ક પર સાઇન ઇન કરો" + + "%1$s ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "વિકલ્પો માટે ટૅપ કરો" + "મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી" + "%1$s મર્યાદિત કનેક્ટિવિટી ધરાવે છે" + "છતાં કનેક્ટ કરવા માટે ટૅપ કરો" + "%1$s પર સ્વિચ કર્યું" + "જ્યારે %2$s પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ %1$sનો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે." + "%1$s પરથી %2$s પર સ્વિચ કર્યું" + "અજાણ્યો નેટવર્ક પ્રકાર" + + "મોબાઇલ ડેટા" + "વાઇ-ફાઇ" + "બ્લૂટૂથ" + "ઇથરનેટ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-hi/strings.xml b/service/ServiceConnectivityResources/res/values-hi/strings.xml new file mode 100644 index 0000000000..eff1b600e4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hi/strings.xml @@ -0,0 +1,39 @@ + + + + "वाई-फ़ाई नेटवर्क में साइन इन करें" + "नेटवर्क में साइन इन करें" + + "%1$s का इंटरनेट नहीं चल रहा है" + "विकल्पों के लिए टैप करें" + "मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" + "इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" + "निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता" + "%1$s की कनेक्टिविटी सीमित है" + "फिर भी कनेक्ट करने के लिए टैप करें" + "%1$s पर ले जाया गया" + "%2$s में इंटरनेट की सुविधा नहीं होने पर डिवाइस %1$s का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है." + "%1$s से %2$s पर ले जाया गया" + "अज्ञात नेटवर्क प्रकार" + + "मोबाइल डेटा" + "वाई-फ़ाई" + "ब्लूटूथ" + "ईथरनेट" + "वीपीएन" + + diff --git a/service/ServiceConnectivityResources/res/values-hr/strings.xml b/service/ServiceConnectivityResources/res/values-hr/strings.xml new file mode 100644 index 0000000000..52bfb936ba --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hr/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijava na Wi-Fi mrežu" + "Prijava na mrežu" + + "%1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Nije moguće pristupiti privatnom DNS poslužitelju" + "%1$s ima ograničenu povezivost" + "Dodirnite da biste se ipak povezali" + "Prelazak na drugu mrežu: %1$s" + "Kada %2$s nema pristup internetu, na uređaju se upotrebljava %1$s. Moguća je naplata naknade." + "Mreža je promijenjena: %1$s > %2$s" + "nepoznata vrsta mreže" + + "mobilni podaci" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-hu/strings.xml b/service/ServiceConnectivityResources/res/values-hu/strings.xml new file mode 100644 index 0000000000..2ff59b5173 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hu/strings.xml @@ -0,0 +1,39 @@ + + + + "Bejelentkezés Wi-Fi hálózatba" + "Bejelentkezés a hálózatba" + + "A(z) %1$s hálózaton nincs internet-hozzáférés" + "Koppintson a beállítások megjelenítéséhez" + "A mobilhálózaton nincs internet-hozzáférés" + "A hálózaton nincs internet-hozzáférés" + "A privát DNS-kiszolgálóhoz nem lehet hozzáférni" + "A(z) %1$s hálózat korlátozott kapcsolatot biztosít" + "Koppintson, ha mindenképpen csatlakozni szeretne" + "Átváltva erre: %1$s" + "%1$s használata, ha nincs internet-hozzáférés %2$s-kapcsolaton keresztül. A szolgáltató díjat számíthat fel." + "Átváltva %1$s-hálózatról erre: %2$s" + "ismeretlen hálózati típus" + + "mobiladatok" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-hy/strings.xml b/service/ServiceConnectivityResources/res/values-hy/strings.xml new file mode 100644 index 0000000000..b35d31c7b6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hy/strings.xml @@ -0,0 +1,39 @@ + + + + "Մուտք գործեք Wi-Fi ցանց" + "Մուտք գործեք ցանց" + + "%1$s ցանցը չունի մուտք ինտերնետին" + "Հպեք՝ ընտրանքները տեսնելու համար" + "Բջջային ցանցը չի ապահովում ինտերնետ կապ" + "Ցանցը միացված չէ ինտերնետին" + "Մասնավոր DNS սերվերն անհասանելի է" + "%1$s ցանցի կապը սահմանափակ է" + "Հպեք՝ միանալու համար" + "Անցել է %1$s ցանցի" + "Երբ %2$s ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է %1$s ցանցի: Նման դեպքում կարող են վճարներ գանձվել:" + "%1$s ցանցից անցել է %2$s ցանցի" + "ցանցի անհայտ տեսակ" + + "բջջային ինտերնետ" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-in/strings.xml b/service/ServiceConnectivityResources/res/values-in/strings.xml new file mode 100644 index 0000000000..27d7d89601 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-in/strings.xml @@ -0,0 +1,39 @@ + + + + "Login ke jaringan Wi-Fi" + "Login ke jaringan" + + "%1$s tidak memiliki akses internet" + "Ketuk untuk melihat opsi" + "Jaringan seluler tidak memiliki akses internet" + "Jaringan tidak memiliki akses internet" + "Server DNS pribadi tidak dapat diakses" + "%1$s memiliki konektivitas terbatas" + "Ketuk untuk tetap menyambungkan" + "Dialihkan ke %1$s" + "Perangkat menggunakan %1$s jika %2$s tidak memiliki akses internet. Tarif mungkin berlaku." + "Dialihkan dari %1$s ke %2$s" + "jenis jaringan yang tidak dikenal" + + "data seluler" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-is/strings.xml b/service/ServiceConnectivityResources/res/values-is/strings.xml new file mode 100644 index 0000000000..97f42dcf07 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-is/strings.xml @@ -0,0 +1,39 @@ + + + + "Skrá inn á Wi-Fi net" + "Skrá inn á net" + + "%1$s er ekki með internetaðgang" + "Ýttu til að sjá valkosti" + "Farsímakerfið er ekki tengt við internetið" + "Netkerfið er ekki tengt við internetið" + "Ekki næst í DNS-einkaþjón" + "Tengigeta %1$s er takmörkuð" + "Ýttu til að tengjast samt" + "Skipt yfir á %1$s" + "Tækið notar %1$s þegar %2$s er ekki með internetaðgang. Gjöld kunna að eiga við." + "Skipt úr %1$s yfir í %2$s" + "óþekkt tegund netkerfis" + + "farsímagögn" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-it/strings.xml b/service/ServiceConnectivityResources/res/values-it/strings.xml new file mode 100644 index 0000000000..7836101137 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-it/strings.xml @@ -0,0 +1,39 @@ + + + + "Accedi a rete Wi-Fi" + "Accedi alla rete" + + "%1$s non ha accesso a Internet" + "Tocca per le opzioni" + "La rete mobile non ha accesso a Internet" + "La rete non ha accesso a Internet" + "Non è possibile accedere al server DNS privato" + "%1$s ha una connettività limitata" + "Tocca per connettere comunque" + "Passato a %1$s" + "Il dispositivo utilizza %1$s quando %2$s non ha accesso a Internet. Potrebbero essere applicati costi." + "Passato da %1$s a %2$s" + "tipo di rete sconosciuto" + + "dati mobili" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-iw/strings.xml b/service/ServiceConnectivityResources/res/values-iw/strings.xml new file mode 100644 index 0000000000..f322b99547 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-iw/strings.xml @@ -0,0 +1,39 @@ + + + + "‏היכנס לרשת Wi-Fi" + "היכנס לרשת" + + "ל-%1$s אין גישה לאינטרנט" + "הקש לקבלת אפשרויות" + "לרשת הסלולרית אין גישה לאינטרנט" + "לרשת אין גישה לאינטרנט" + "‏לא ניתן לגשת לשרת DNS הפרטי" + "הקישוריות של %1$s מוגבלת" + "כדי להתחבר למרות זאת יש להקיש" + "מעבר אל %1$s" + "המכשיר משתמש ברשת %1$s כשלרשת %2$s אין גישה לאינטרנט. עשויים לחול חיובים." + "עבר מרשת %1$s לרשת %2$s" + "סוג רשת לא מזוהה" + + "חבילת גלישה" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ja/strings.xml b/service/ServiceConnectivityResources/res/values-ja/strings.xml new file mode 100644 index 0000000000..1aa3216fbc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ja/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fiネットワークにログイン" + "ネットワークにログインしてください" + + "%1$s はインターネットにアクセスできません" + "タップしてその他のオプションを表示" + "モバイル ネットワークがインターネットに接続されていません" + "ネットワークがインターネットに接続されていません" + "プライベート DNS サーバーにアクセスできません" + "%1$s の接続が制限されています" + "接続するにはタップしてください" + "「%1$s」に切り替えました" + "デバイスで「%2$s」によるインターネット接続ができない場合に「%1$s」を使用します。通信料が発生することがあります。" + "「%1$s」から「%2$s」に切り替えました" + "不明なネットワーク タイプ" + + "モバイルデータ" + "Wi-Fi" + "Bluetooth" + "イーサネット" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ka/strings.xml b/service/ServiceConnectivityResources/res/values-ka/strings.xml new file mode 100644 index 0000000000..61d21b55a0 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ka/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi ქსელთან დაკავშირება" + "ქსელში შესვლა" + + "%1$s-ს არ აქვს ინტერნეტზე წვდომა" + "შეეხეთ ვარიანტების სანახავად" + "მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა" + "ქსელს არ აქვს ინტერნეტზე წვდომა" + "პირად DNS სერვერზე წვდომა შეუძლებელია" + "%1$s-ის კავშირები შეზღუდულია" + "შეეხეთ, თუ მაინც გსურთ დაკავშირება" + "ახლა გამოიყენება %1$s" + "თუ %2$s ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ %1$s იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს." + "ახლა გამოიყენება %1$s (გამოიყენებოდა %2$s)" + "უცნობი ტიპის ქსელი" + + "მობილური ინტერნეტი" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-kk/strings.xml b/service/ServiceConnectivityResources/res/values-kk/strings.xml new file mode 100644 index 0000000000..969aaef522 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-kk/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi желісіне кіру" + "Желіге кіру" + + "%1$s желісінің интернетті пайдалану мүмкіндігі шектеулі." + "Опциялар үшін түртіңіз" + "Мобильдік желі интернетке қосылмаған." + "Желі интернетке қосылмаған." + "Жеке DNS серверіне кіру мүмкін емес." + "%1$s желісінің қосылу мүмкіндігі шектеулі." + "Бәрібір жалғау үшін түртіңіз." + "%1$s желісіне ауысты" + "Құрылғы %2$s желісінде интернетпен байланыс жоғалған жағдайда %1$s желісін пайдаланады. Деректер ақысы алынуы мүмкін." + "%1$s желісінен %2$s желісіне ауысты" + "желі түрі белгісіз" + + "мобильдік деректер" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-km/strings.xml b/service/ServiceConnectivityResources/res/values-km/strings.xml new file mode 100644 index 0000000000..da3c337860 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-km/strings.xml @@ -0,0 +1,39 @@ + + + + "ចូល​បណ្ដាញ​វ៉ាយហ្វាយ" + "ចូលទៅបណ្តាញ" + + "%1$s មិនមាន​ការតភ្ជាប់អ៊ីនធឺណិត​ទេ" + "ប៉ះសម្រាប់ជម្រើស" + "បណ្ដាញ​ទូរសព្ទ​ចល័ត​មិនមានការតភ្ជាប់​អ៊ីនធឺណិតទេ" + "បណ្ដាញ​មិនមាន​ការតភ្ជាប់​អ៊ីនធឺណិតទេ" + "មិនអាច​ចូលប្រើ​ម៉ាស៊ីនមេ DNS ឯកជន​បានទេ" + "%1$s មានការតភ្ជាប់​មានកម្រិត" + "មិន​អី​ទេ ចុច​​ភ្ជាប់​ចុះ" + "បានប្តូរទៅ %1$s" + "ឧបករណ៍​ប្រើ %1$s នៅ​ពេល​ដែល %2$s មិនមាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត។ អាច​គិតថ្លៃ​លើការ​ប្រើប្រាស់​ទិន្នន័យ។" + "បានប្តូរពី %1$s ទៅ %2$s" + "ប្រភេទបណ្តាញមិនស្គាល់" + + "ទិន្នន័យ​ទូរសព្ទចល័ត" + "Wi-Fi" + "ប៊្លូធូស" + "អ៊ីសឺរណិត" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-kn/strings.xml b/service/ServiceConnectivityResources/res/values-kn/strings.xml new file mode 100644 index 0000000000..3b5e047731 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-kn/strings.xml @@ -0,0 +1,39 @@ + + + + "ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" + "ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" + + "%1$s ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ" + "ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" + "ನೆಟ್‌ವರ್ಕ್‌ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" + "%1$s ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ" + "ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" + "%1$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" + "%2$s ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು %1$s ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು." + "%1$s ರಿಂದ %2$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" + "ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ" + + "ಮೊಬೈಲ್ ಡೇಟಾ" + "ವೈ-ಫೈ" + "ಬ್ಲೂಟೂತ್‌" + "ಇಥರ್ನೆಟ್" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ko/strings.xml b/service/ServiceConnectivityResources/res/values-ko/strings.xml new file mode 100644 index 0000000000..874bd75970 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ko/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi 네트워크에 로그인" + "네트워크에 로그인" + + "%1$s이(가) 인터넷에 액세스할 수 없습니다." + "탭하여 옵션 보기" + "모바일 네트워크에 인터넷이 연결되어 있지 않습니다." + "네트워크에 인터넷이 연결되어 있지 않습니다." + "비공개 DNS 서버에 액세스할 수 없습니다." + "%1$s에서 연결을 제한했습니다." + "계속 연결하려면 탭하세요." + "%1$s(으)로 전환" + "%2$s(으)로 인터넷에 연결할 수 없는 경우 기기에서 %1$s이(가) 사용됩니다. 요금이 부과될 수 있습니다." + "%1$s에서 %2$s(으)로 전환" + "알 수 없는 네트워크 유형" + + "모바일 데이터" + "Wi-Fi" + "블루투스" + "이더넷" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ky/strings.xml b/service/ServiceConnectivityResources/res/values-ky/strings.xml new file mode 100644 index 0000000000..1ace4dc8ec --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ky/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi түйүнүнө кирүү" + "Тармакка кирүү" + + "%1$s Интернетке туташуусу жок" + "Параметрлерди ачуу үчүн таптап коюңуз" + "Мобилдик Интернет жок" + "Тармактын Интернет жок" + "Жеке DNS сервери жеткиликсиз" + "%1$s байланышы чектелген" + "Баары бир туташуу үчүн таптаңыз" + "%1$s тармагына которуштурулду" + "%2$s тармагы Интернетке туташпай турганда, түзмөгүңүз %1$s тармагын колдонот. Акы алынышы мүмкүн." + "%1$s дегенден %2$s тармагына которуштурулду" + "белгисиз тармак түрү" + + "мобилдик трафик" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-lo/strings.xml b/service/ServiceConnectivityResources/res/values-lo/strings.xml new file mode 100644 index 0000000000..3db497ef45 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-lo/strings.xml @@ -0,0 +1,39 @@ + + + + "ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi" + "ລົງຊື່ເຂົ້າເຄືອຂ່າຍ" + + "%1$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ" + "ແຕະເພື່ອເບິ່ງຕົວເລືອກ" + "ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" + "ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" + "ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້" + "%1$s ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ" + "ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່" + "ສະຫຼັບໄປໃຊ້ %1$s ແລ້ວ" + "ອຸປະກອນຈະໃຊ້ %1$s ເມື່ອ %2$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ." + "ສະຫຼັບຈາກ %1$s ໄປໃຊ້ %2$s ແລ້ວ" + "ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ" + + "ອິນເຕີເນັດມືຖື" + "Wi-Fi" + "Bluetooth" + "ອີເທີເນັດ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-lt/strings.xml b/service/ServiceConnectivityResources/res/values-lt/strings.xml new file mode 100644 index 0000000000..c639c1f1a5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-lt/strings.xml @@ -0,0 +1,39 @@ + + + + "Prisijungti prie „Wi-Fi“ tinklo" + "Prisijungti prie tinklo" + + "„%1$s“ negali pasiekti interneto" + "Palieskite, kad būtų rodomos parinktys." + "Mobiliojo ryšio tinkle nėra prieigos prie interneto" + "Tinkle nėra prieigos prie interneto" + "Privataus DNS serverio negalima pasiekti" + "„%1$s“ ryšys apribotas" + "Palieskite, jei vis tiek norite prisijungti" + "Perjungta į tinklą %1$s" + "Įrenginyje naudojamas kitas tinklas (%1$s), kai dabartiniame tinkle (%2$s) nėra interneto ryšio. Gali būti taikomi mokesčiai." + "Perjungta iš tinklo %1$s į tinklą %2$s" + "nežinomas tinklo tipas" + + "mobiliojo ryšio duomenys" + "Wi-Fi" + "Bluetooth" + "Eternetas" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-lv/strings.xml b/service/ServiceConnectivityResources/res/values-lv/strings.xml new file mode 100644 index 0000000000..5774603bf5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-lv/strings.xml @@ -0,0 +1,39 @@ + + + + "Pierakstieties Wi-Fi tīklā" + "Pierakstīšanās tīklā" + + "Tīklā %1$s nav piekļuves internetam" + "Pieskarieties, lai skatītu iespējas." + "Mobilajā tīklā nav piekļuves internetam." + "Tīklā nav piekļuves internetam." + "Nevar piekļūt privātam DNS serverim." + "Tīklā %1$s ir ierobežota savienojamība" + "Lai tik un tā izveidotu savienojumu, pieskarieties" + "Pārslēdzās uz tīklu %1$s" + "Kad vienā tīklā (%2$s) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (%1$s). Var tikt piemērota maksa." + "Pārslēdzās no tīkla %1$s uz tīklu %2$s" + "nezināms tīkla veids" + + "mobilie dati" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-mk/strings.xml b/service/ServiceConnectivityResources/res/values-mk/strings.xml new file mode 100644 index 0000000000..053c7cf93b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mk/strings.xml @@ -0,0 +1,39 @@ + + + + "Најавете се на мрежа на Wi-Fi" + "Најавете се на мрежа" + + "%1$s нема интернет-пристап" + "Допрете за опции" + "Мобилната мрежа нема интернет-пристап" + "Мрежата нема интернет-пристап" + "Не може да се пристапи до приватниот DNS-сервер" + "%1$s има ограничена поврзливост" + "Допрете за да се поврзете и покрај тоа" + "Префрлено на %1$s" + "Уредот користи %1$s кога %2$s нема пристап до интернет. Може да се наплатат трошоци." + "Префрлено од %1$s на %2$s" + "непознат тип мрежа" + + "мобилен интернет" + "Wi-Fi" + "Bluetooth" + "Етернет" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ml/strings.xml b/service/ServiceConnectivityResources/res/values-ml/strings.xml new file mode 100644 index 0000000000..3e80cf1cd7 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ml/strings.xml @@ -0,0 +1,39 @@ + + + + "വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" + "നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" + + "%1$s എന്നതിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക" + "മൊബെെൽ നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "സ്വകാര്യ DNS സെർവർ ആക്‌സസ് ചെയ്യാനാവില്ല" + "%1$s എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്" + "ഏതുവിധേനയും കണക്‌റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക" + "%1$s എന്നതിലേക്ക് മാറി" + "%2$s-ന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം %1$s ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം." + "%1$s നെറ്റ്‌വർക്കിൽ നിന്ന് %2$s നെറ്റ്‌വർക്കിലേക്ക് മാറി" + "തിരിച്ചറിയാനാകാത്ത ഒരു നെറ്റ്‌വർക്ക് തരം" + + "മൊബൈൽ ഡാറ്റ" + "വൈഫൈ" + "Bluetooth" + "ഇതര്‍നെറ്റ്" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-mn/strings.xml b/service/ServiceConnectivityResources/res/values-mn/strings.xml new file mode 100644 index 0000000000..214fc0c1dd --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mn/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi сүлжээнд нэвтэрнэ үү" + "Сүлжээнд нэвтэрнэ үү" + + "%1$s-д интернэтийн хандалт алга" + "Сонголт хийхийн тулд товшино уу" + "Мобайл сүлжээнд интернэт хандалт байхгүй байна" + "Сүлжээнд интернэт хандалт байхгүй байна" + "Хувийн DNS серверт хандах боломжгүй байна" + "%1$s зарим үйлчилгээнд хандах боломжгүй байна" + "Ямар ч тохиолдолд холбогдохын тулд товших" + "%1$s руу шилжүүлсэн" + "%2$s интернет холболтгүй үед төхөөрөмж %1$s-г ашигладаг. Төлбөр гарч болзошгүй." + "%1$s%2$s руу шилжүүлсэн" + "сүлжээний тодорхойгүй төрөл" + + "мобайл дата" + "Wi-Fi" + "Bluetooth" + "Этернэт" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-mr/strings.xml b/service/ServiceConnectivityResources/res/values-mr/strings.xml new file mode 100644 index 0000000000..c4b19989fc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mr/strings.xml @@ -0,0 +1,39 @@ + + + + "वाय-फाय नेटवर्कमध्‍ये साइन इन करा" + "नेटवर्कवर साइन इन करा" + + "%1$s ला इंटरनेट अ‍ॅक्सेस नाही" + "पर्यायांसाठी टॅप करा" + "मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही" + "नेटवर्कला इंटरनेट ॲक्सेस नाही" + "खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही" + "%1$s ला मर्यादित कनेक्टिव्हिटी आहे" + "तरीही कनेक्ट करण्यासाठी टॅप करा" + "%1$s वर स्विच केले" + "%2$s कडे इंटरनेटचा अ‍ॅक्सेस नसताना डिव्हाइस %1$s वापरते. शुल्क लागू शकते." + "%1$s वरून %2$s वर स्विच केले" + "अज्ञात नेटवर्क प्रकार" + + "मोबाइल डेटा" + "वाय-फाय" + "ब्लूटूथ" + "इथरनेट" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ms/strings.xml b/service/ServiceConnectivityResources/res/values-ms/strings.xml new file mode 100644 index 0000000000..529d0bd466 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ms/strings.xml @@ -0,0 +1,39 @@ + + + + "Log masuk ke rangkaian Wi-Fi" + "Log masuk ke rangkaian" + + "%1$s tiada akses Internet" + "Ketik untuk mendapatkan pilihan" + "Rangkaian mudah alih tiada akses Internet" + "Rangkaian tiada akses Internet" + "Pelayan DNS peribadi tidak boleh diakses" + "%1$s mempunyai kesambungan terhad" + "Ketik untuk menyambung juga" + "Beralih kepada %1$s" + "Peranti menggunakan %1$s apabila %2$s tiada akses Internet. Bayaran mungkin dikenakan." + "Beralih daripada %1$s kepada %2$s" + "jenis rangkaian tidak diketahui" + + "data mudah alih" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-my/strings.xml b/service/ServiceConnectivityResources/res/values-my/strings.xml new file mode 100644 index 0000000000..50590fa3fc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-my/strings.xml @@ -0,0 +1,39 @@ + + + + "ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ" + "ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်" + + "%1$s တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" + "အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ" + "မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ" + "ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" + "သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။" + "%1$s တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်" + "မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ" + "%1$s သို့ ပြောင်းလိုက်ပြီ" + "%2$s ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် %1$s ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။" + "%1$s မှ %2$s သို့ ပြောင်းလိုက်ပြီ" + "အမည်မသိကွန်ရက်အမျိုးအစား" + + "မိုဘိုင်းဒေတာ" + "Wi-Fi" + "ဘလူးတုသ်" + "အီသာနက်" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-nb/strings.xml b/service/ServiceConnectivityResources/res/values-nb/strings.xml new file mode 100644 index 0000000000..b89d198f38 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-nb/strings.xml @@ -0,0 +1,39 @@ + + + + "Logg på Wi-Fi-nettverket" + "Logg på nettverk" + + "%1$s har ingen internettilkobling" + "Trykk for å få alternativer" + "Mobilnettverket har ingen internettilgang" + "Nettverket har ingen internettilgang" + "Den private DNS-tjeneren kan ikke nås" + "%1$s har begrenset tilkobling" + "Trykk for å koble til likevel" + "Byttet til %1$s" + "Enheten bruker %1$s når %2$s ikke har Internett-tilgang. Avgifter kan påløpe." + "Byttet fra %1$s til %2$s" + "en ukjent nettverkstype" + + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ne/strings.xml b/service/ServiceConnectivityResources/res/values-ne/strings.xml new file mode 100644 index 0000000000..bdcfa3bfc4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ne/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्" + "सञ्जालमा साइन इन गर्नुहोस्" + + "%1$s को इन्टरनेटमाथि पहुँच छैन" + "विकल्पहरूका लागि ट्याप गर्नुहोस्" + "मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन" + "नेटवर्कको इन्टरनेटमाथि पहुँच छैन" + "निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन" + "%1$s को जडान सीमित छ" + "जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्" + "%1$s मा बदल्नुहोस्" + "%2$s मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले %1$s प्रयोग गर्दछ। शुल्क लाग्न सक्छ।" + "%1$s बाट %2$s मा परिवर्तन गरियो" + "नेटवर्कको कुनै अज्ञात प्रकार" + + "मोबाइल डेटा" + "Wi-Fi" + "ब्लुटुथ" + "इथरनेट" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-nl/strings.xml b/service/ServiceConnectivityResources/res/values-nl/strings.xml new file mode 100644 index 0000000000..8ecff6e3b5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-nl/strings.xml @@ -0,0 +1,39 @@ + + + + "Inloggen bij wifi-netwerk" + "Inloggen bij netwerk" + + "%1$s heeft geen internettoegang" + "Tik voor opties" + "Mobiel netwerk heeft geen internettoegang" + "Netwerk heeft geen internettoegang" + "Geen toegang tot privé-DNS-server" + "%1$s heeft beperkte connectiviteit" + "Tik om toch verbinding te maken" + "Overgeschakeld naar %1$s" + "Apparaat gebruikt %1$s wanneer %2$s geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht." + "Overgeschakeld van %1$s naar %2$s" + "een onbekend netwerktype" + + "mobiele data" + "Wifi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-or/strings.xml b/service/ServiceConnectivityResources/res/values-or/strings.xml new file mode 100644 index 0000000000..6ec1f9d3e4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-or/strings.xml @@ -0,0 +1,39 @@ + + + + "ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍‍-ଇନ୍‍ କରନ୍ତୁ" + "ନେଟ୍‌ୱର୍କରେ ସାଇନ୍‍ ଇନ୍‍ କରନ୍ତୁ" + + "%1$sର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ବିକଳ୍ପ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ" + "ମୋବାଇଲ୍ ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ" + "%1$sର ସୀମିତ ସଂଯୋଗ ଅଛି" + "ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ" + "%1$sକୁ ବଦଳାଗଲା" + "%2$sର ଇଣ୍ଟରନେଟ୍‍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍‍ %1$s ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।" + "%1$s ରୁ %2$sକୁ ବଦଳାଗଲା" + "ଏକ ଅଜଣା ନେଟ୍‌ୱର୍କ ପ୍ରକାର" + + "ମୋବାଇଲ୍‌ ଡାଟା" + "ୱାଇ-ଫାଇ" + "ବ୍ଲୁଟୁଥ" + "ଇଥରନେଟ୍‌" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pa/strings.xml b/service/ServiceConnectivityResources/res/values-pa/strings.xml new file mode 100644 index 0000000000..e9481932d6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pa/strings.xml @@ -0,0 +1,39 @@ + + + + "ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" + "ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" + + "%1$s ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ" + "ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ" + "%1$s ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ" + "ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" + "ਬਦਲਕੇ %1$s ਲਿਆਂਦਾ ਗਿਆ" + "%2$s ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ %1$s ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।" + "%1$s ਤੋਂ ਬਦਲਕੇ %2$s \'ਤੇ ਕੀਤਾ ਗਿਆ" + "ਇੱਕ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਕਿਸਮ" + + "ਮੋਬਾਈਲ ਡਾਟਾ" + "ਵਾਈ-ਫਾਈ" + "ਬਲੂਟੁੱਥ" + "ਈਥਰਨੈੱਟ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pl/strings.xml b/service/ServiceConnectivityResources/res/values-pl/strings.xml new file mode 100644 index 0000000000..038328f0fc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pl/strings.xml @@ -0,0 +1,39 @@ + + + + "Zaloguj się w sieci Wi-Fi" + "Zaloguj się do sieci" + + "%1$s nie ma dostępu do internetu" + "Kliknij, by wyświetlić opcje" + "Sieć komórkowa nie ma dostępu do internetu" + "Sieć nie ma dostępu do internetu" + "Brak dostępu do prywatnego serwera DNS" + "%1$s ma ograniczoną łączność" + "Kliknij, by mimo to nawiązać połączenie" + "Zmieniono na połączenie typu %1$s" + "Urządzenie korzysta z połączenia typu %1$s, gdy %2$s nie dostępu do internetu. Mogą zostać naliczone opłaty." + "Przełączono z połączenia typu %1$s na %2$s." + "nieznany typ sieci" + + "mobilna transmisja danych" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml b/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..fe37405ebe --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml @@ -0,0 +1,39 @@ + + + + "Fazer login na rede Wi-Fi" + "Fazer login na rede" + + "%1$s não tem acesso à Internet" + "Toque para ver opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível acessar o servidor DNS privado" + "%1$s tem conectividade limitada" + "Toque para conectar mesmo assim" + "Alternado para %1$s" + "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." + "Alternado de %1$s para %2$s" + "um tipo de rede desconhecido" + + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml b/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..69060f7266 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml @@ -0,0 +1,39 @@ + + + + "Iniciar sessão na rede Wi-Fi" + "Início de sessão na rede" + + "%1$s não tem acesso à Internet" + "Toque para obter mais opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível aceder ao servidor DNS." + "%1$s tem conetividade limitada." + "Toque para ligar mesmo assim." + "Mudou para %1$s" + "O dispositivo utiliza %1$s quando %2$s não tem acesso à Internet. Podem aplicar-se custos." + "Mudou de %1$s para %2$s" + "um tipo de rede desconhecido" + + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pt/strings.xml b/service/ServiceConnectivityResources/res/values-pt/strings.xml new file mode 100644 index 0000000000..fe37405ebe --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pt/strings.xml @@ -0,0 +1,39 @@ + + + + "Fazer login na rede Wi-Fi" + "Fazer login na rede" + + "%1$s não tem acesso à Internet" + "Toque para ver opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível acessar o servidor DNS privado" + "%1$s tem conectividade limitada" + "Toque para conectar mesmo assim" + "Alternado para %1$s" + "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." + "Alternado de %1$s para %2$s" + "um tipo de rede desconhecido" + + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ro/strings.xml b/service/ServiceConnectivityResources/res/values-ro/strings.xml new file mode 100644 index 0000000000..227b7bed70 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ro/strings.xml @@ -0,0 +1,39 @@ + + + + "Conectați-vă la rețeaua Wi-Fi" + "Conectați-vă la rețea" + + "%1$s nu are acces la internet" + "Atingeți pentru opțiuni" + "Rețeaua mobilă nu are acces la internet" + "Rețeaua nu are acces la internet" + "Serverul DNS privat nu poate fi accesat" + "%1$s are conectivitate limitată" + "Atingeți pentru a vă conecta oricum" + "S-a comutat la %1$s" + "Dispozitivul folosește %1$s când %2$s nu are acces la internet. Se pot aplica taxe." + "S-a comutat de la %1$s la %2$s" + "un tip de rețea necunoscut" + + "date mobile" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ru/strings.xml b/service/ServiceConnectivityResources/res/values-ru/strings.xml new file mode 100644 index 0000000000..18acf81537 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ru/strings.xml @@ -0,0 +1,39 @@ + + + + "Подключение к Wi-Fi" + "Регистрация в сети" + + "Сеть \"%1$s\" не подключена к Интернету" + "Нажмите, чтобы показать варианты." + "Мобильная сеть не подключена к Интернету" + "Сеть не подключена к Интернету" + "Доступа к частному DNS-серверу нет." + "Подключение к сети \"%1$s\" ограничено" + "Нажмите, чтобы подключиться" + "Новое подключение: %1$s" + "Устройство использует %1$s, если подключение к сети %2$s недоступно. Может взиматься плата за передачу данных." + "Устройство отключено от сети %2$s и теперь использует %1$s" + "неизвестный тип сети" + + "мобильный Интернет" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-si/strings.xml b/service/ServiceConnectivityResources/res/values-si/strings.xml new file mode 100644 index 0000000000..6307c2b01b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-si/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi ජාලයට පුරනය වන්න" + "ජාලයට පුරනය වන්න" + + "%1$s හට අන්තර්ජාල ප්‍රවේශය නැත" + "විකල්ප සඳහා තට්ටු කරන්න" + "ජංගම ජාලවලට අන්තර්ජාල ප්‍රවේශය නැත" + "ජාලයට අන්තර්ජාල ප්‍රවේශය නැත" + "පුද්ගලික DNS සේවාදායකයට ප්‍රවේශ වීමට නොහැකිය" + "%1$s හට සීමිත සබැඳුම් හැකියාවක් ඇත" + "කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න" + "%1$s වෙත මාරු විය" + "උපාංගය %1$s %2$s සඳහා අන්තර්ජාල ප්‍රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය." + "%1$s සිට %2$s වෙත මාරු විය" + "නොදන්නා ජාල වර්ගයකි" + + "ජංගම දත්ත" + "Wi-Fi" + "බ්ලූටූත්" + "ඊතර්නෙට්" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sk/strings.xml b/service/ServiceConnectivityResources/res/values-sk/strings.xml new file mode 100644 index 0000000000..e894fefcf4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sk/strings.xml @@ -0,0 +1,39 @@ + + + + "Prihlásiť sa do siete Wi‑Fi" + "Prihlásenie do siete" + + "%1$s nemá prístup k internetu" + "Klepnutím získate možnosti" + "Mobilná sieť nemá prístup k internetu" + "Sieť nemá prístup k internetu" + "K súkromnému serveru DNS sa nepodarilo získať prístup" + "%1$s má obmedzené pripojenie" + "Ak sa chcete aj napriek tomu pripojiť, klepnite" + "Prepnuté na sieť: %1$s" + "Keď %2$s nemá prístup k internetu, zariadenie používa %1$s. Môžu sa účtovať poplatky." + "Prepnuté zo siete %1$s na sieť %2$s" + "neznámy typ siete" + + "mobilné dáta" + "Wi‑Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sl/strings.xml b/service/ServiceConnectivityResources/res/values-sl/strings.xml new file mode 100644 index 0000000000..954b32480e --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sl/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijavite se v omrežje Wi-Fi" + "Prijava v omrežje" + + "Omrežje %1$s nima dostopa do interneta" + "Dotaknite se za možnosti" + "Mobilno omrežje nima dostopa do interneta" + "Omrežje nima dostopa do interneta" + "Do zasebnega strežnika DNS ni mogoče dostopati" + "Povezljivost omrežja %1$s je omejena" + "Dotaknite se, da kljub temu vzpostavite povezavo" + "Preklopljeno na omrežje vrste %1$s" + "Naprava uporabi omrežje vrste %1$s, ko omrežje vrste %2$s nima dostopa do interneta. Prenos podatkov se lahko zaračuna." + "Preklopljeno z omrežja vrste %1$s na omrežje vrste %2$s" + "neznana vrsta omrežja" + + "prenos podatkov v mobilnem omrežju" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sq/strings.xml b/service/ServiceConnectivityResources/res/values-sq/strings.xml new file mode 100644 index 0000000000..bd5d052034 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sq/strings.xml @@ -0,0 +1,39 @@ + + + + "Identifikohu në rrjetin Wi-Fi" + "Identifikohu në rrjet" + + "%1$s nuk ka qasje në internet" + "Trokit për opsionet" + "Rrjeti celular nuk ka qasje në internet" + "Rrjeti nuk ka qasje në internet" + "Serveri privat DNS nuk mund të qaset" + "%1$s ka lidhshmëri të kufizuar" + "Trokit për t\'u lidhur gjithsesi" + "Kaloi te %1$s" + "Pajisja përdor %1$s kur %2$s nuk ka qasje në internet. Mund të zbatohen tarifa." + "Kaloi nga %1$s te %2$s" + "një lloj rrjeti i panjohur" + + "të dhënat celulare" + "Wi-Fi" + "Bluetooth" + "Eternet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sr/strings.xml b/service/ServiceConnectivityResources/res/values-sr/strings.xml new file mode 100644 index 0000000000..8bedbffec9 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sr/strings.xml @@ -0,0 +1,39 @@ + + + + "Пријављивање на WiFi мрежу" + "Пријавите се на мрежу" + + "%1$s нема приступ интернету" + "Додирните за опције" + "Мобилна мрежа нема приступ интернету" + "Мрежа нема приступ интернету" + "Приступ приватном DNS серверу није успео" + "%1$s има ограничену везу" + "Додирните да бисте се ипак повезали" + "Прешли сте на тип мреже %1$s" + "Уређај користи тип мреже %1$s када тип мреже %2$s нема приступ интернету. Можда ће се наплаћивати трошкови." + "Прешли сте са типа мреже %1$s на тип мреже %2$s" + "непознат тип мреже" + + "мобилни подаци" + "WiFi" + "Bluetooth" + "Етернет" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sv/strings.xml b/service/ServiceConnectivityResources/res/values-sv/strings.xml new file mode 100644 index 0000000000..b3f1763043 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sv/strings.xml @@ -0,0 +1,39 @@ + + + + "Logga in på ett Wi-Fi-nätverk" + "Logga in på nätverket" + + "%1$s har ingen internetanslutning" + "Tryck för alternativ" + "Mobilnätverket har ingen internetanslutning" + "Nätverket har ingen internetanslutning" + "Det går inte att komma åt den privata DNS-servern." + "%1$s har begränsad anslutning" + "Tryck för att ansluta ändå" + "Byte av nätverk till %1$s" + "%1$s används på enheten när det inte finns internetåtkomst via %2$s. Avgifter kan tillkomma." + "Byte av nätverk från %1$s till %2$s" + "en okänd nätverkstyp" + + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sw/strings.xml b/service/ServiceConnectivityResources/res/values-sw/strings.xml new file mode 100644 index 0000000000..9674654c69 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sw/strings.xml @@ -0,0 +1,39 @@ + + + + "Ingia kwa mtandao wa Wi-Fi" + "Ingia katika mtandao" + + "%1$s haina uwezo wa kufikia intaneti" + "Gusa ili upate chaguo" + "Mtandao wa simu hauna uwezo wa kufikia intaneti" + "Mtandao hauna uwezo wa kufikia intaneti" + "Seva ya faragha ya DNS haiwezi kufikiwa" + "%1$s ina muunganisho unaofikia huduma chache." + "Gusa ili uunganishe tu" + "Sasa inatumia %1$s" + "Kifaa hutumia %1$s wakati %2$s haina intaneti. Huenda ukalipishwa." + "Imebadilisha mtandao kutoka %1$s na sasa inatumia %2$s" + "aina ya mtandao isiyojulikana" + + "data ya simu" + "Wi-Fi" + "Bluetooth" + "Ethaneti" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ta/strings.xml b/service/ServiceConnectivityResources/res/values-ta/strings.xml new file mode 100644 index 0000000000..12604cbf1c --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ta/strings.xml @@ -0,0 +1,39 @@ + + + + "வைஃபை நெட்வொர்க்கில் உள்நுழையவும்" + "நெட்வொர்க்கில் உள்நுழையவும்" + + "%1$s நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "விருப்பங்களுக்கு, தட்டவும்" + "மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது" + "%1$s வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது" + "எப்படியேனும் இணைப்பதற்குத் தட்டவும்" + "%1$sக்கு மாற்றப்பட்டது" + "%2$s நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது %1$s நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்." + "%1$s இலிருந்து %2$sக்கு மாற்றப்பட்டது" + "தெரியாத நெட்வொர்க் வகை" + + "மொபைல் டேட்டா" + "வைஃபை" + "புளூடூத்" + "ஈத்தர்நெட்" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-te/strings.xml b/service/ServiceConnectivityResources/res/values-te/strings.xml new file mode 100644 index 0000000000..84a8640b07 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-te/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" + "నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" + + "%1$sకి ఇంటర్నెట్ యాక్సెస్ లేదు" + "ఎంపికల కోసం నొక్కండి" + "మొబైల్ నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "ప్రైవేట్ DNS సర్వర్‌ను యాక్సెస్ చేయడం సాధ్యపడదు" + "%1$s పరిమిత కనెక్టివిటీని కలిగి ఉంది" + "ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి" + "%1$sకి మార్చబడింది" + "పరికరం %2$sకి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు %1$sని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు." + "%1$s నుండి %2$sకి మార్చబడింది" + "తెలియని నెట్‌వర్క్ రకం" + + "మొబైల్ డేటా" + "Wi-Fi" + "బ్లూటూత్" + "ఈథర్‌నెట్" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-th/strings.xml b/service/ServiceConnectivityResources/res/values-th/strings.xml new file mode 100644 index 0000000000..1616e5151d --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-th/strings.xml @@ -0,0 +1,39 @@ + + + + "ลงชื่อเข้าใช้เครือข่าย WiFi" + "ลงชื่อเข้าใช้เครือข่าย" + + "%1$s เข้าถึงอินเทอร์เน็ตไม่ได้" + "แตะเพื่อดูตัวเลือก" + "เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต" + "เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต" + "เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้" + "%1$s มีการเชื่อมต่อจำกัด" + "แตะเพื่อเชื่อมต่อ" + "เปลี่ยนเป็น %1$s" + "อุปกรณ์จะใช้ %1$s เมื่อ %2$s เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ" + "เปลี่ยนจาก %1$s เป็น %2$s" + "ประเภทเครือข่ายที่ไม่รู้จัก" + + "เน็ตมือถือ" + "Wi-Fi" + "บลูทูธ" + "อีเทอร์เน็ต" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-tl/strings.xml b/service/ServiceConnectivityResources/res/values-tl/strings.xml new file mode 100644 index 0000000000..3bf1ce494a --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-tl/strings.xml @@ -0,0 +1,39 @@ + + + + "Mag-sign in sa Wi-Fi network" + "Mag-sign in sa network" + + "Walang access sa internet ang %1$s" + "I-tap para sa mga opsyon" + "Walang access sa internet ang mobile network" + "Walang access sa internet ang network" + "Hindi ma-access ang pribadong DNS server" + "Limitado ang koneksyon ng %1$s" + "I-tap para kumonekta pa rin" + "Lumipat sa %1$s" + "Ginagamit ng device ang %1$s kapag walang access sa internet ang %2$s. Maaaring may mga malapat na singilin." + "Lumipat sa %2$s mula sa %1$s" + "isang hindi kilalang uri ng network" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-tr/strings.xml b/service/ServiceConnectivityResources/res/values-tr/strings.xml new file mode 100644 index 0000000000..5c326e5eee --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-tr/strings.xml @@ -0,0 +1,39 @@ + + + + "Kablosuz ağda oturum açın" + "Ağda oturum açın" + + "%1$s ağının internet bağlantısı yok" + "Seçenekler için dokunun" + "Mobil ağın internet bağlantısı yok" + "Ağın internet bağlantısı yok" + "Gizli DNS sunucusuna erişilemiyor" + "%1$s sınırlı bağlantıya sahip" + "Yine de bağlanmak için dokunun" + "%1$s ağına geçildi" + "%2$s ağının internet erişimi olmadığında cihaz %1$s ağını kullanır. Bunun için ödeme alınabilir." + "%1$s ağından %2$s ağına geçildi" + "bilinmeyen ağ türü" + + "mobil veri" + "Kablosuz" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-uk/strings.xml b/service/ServiceConnectivityResources/res/values-uk/strings.xml new file mode 100644 index 0000000000..d1382da924 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-uk/strings.xml @@ -0,0 +1,39 @@ + + + + "Вхід у мережу Wi-Fi" + "Вхід у мережу" + + "Мережа %1$s не має доступу до Інтернету" + "Торкніться, щоб відкрити опції" + "Мобільна мережа не має доступу до Інтернету" + "Мережа не має доступу до Інтернету" + "Немає доступу до приватного DNS-сервера" + "Підключення до мережі %1$s обмежено" + "Натисніть, щоб усе одно підключитися" + "Пристрій перейшов на мережу %1$s" + "Коли мережа %2$s не має доступу до Інтернету, використовується %1$s. Може стягуватися плата." + "Пристрій перейшов з мережі %1$s на мережу %2$s" + "невідомий тип мережі" + + "мобільне передавання даних" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "Мережа VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ur/strings.xml b/service/ServiceConnectivityResources/res/values-ur/strings.xml new file mode 100644 index 0000000000..3c031ad318 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ur/strings.xml @@ -0,0 +1,39 @@ + + + + "‏Wi-Fi نیٹ ورک میں سائن ان کریں" + "نیٹ ورک میں سائن ان کریں" + + "%1$s کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "اختیارات کیلئے تھپتھپائیں" + "موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "‏نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی" + "%1$s کی کنیکٹوٹی محدود ہے" + "بہر حال منسلک کرنے کے لیے تھپتھپائیں" + "%1$s پر سوئچ ہو گیا" + "جب %2$s کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ %1$s کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔" + "%1$s سے %2$s پر سوئچ ہو گیا" + "نیٹ ورک کی نامعلوم قسم" + + "موبائل ڈیٹا" + "Wi-Fi" + "بلوٹوتھ" + "ایتھرنیٹ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-uz/strings.xml b/service/ServiceConnectivityResources/res/values-uz/strings.xml new file mode 100644 index 0000000000..7518db3a7b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-uz/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi tarmoqqa kirish" + "Tarmoqqa kirish" + + "%1$s nomli tarmoqda internetga ruxsati yoʻq" + "Variantlarni ko‘rsatish uchun bosing" + "Mobil tarmoq internetga ulanmagan" + "Tarmoq internetga ulanmagan" + "Xususiy DNS server ishlamayapti" + "%1$s nomli tarmoqda aloqa cheklangan" + "Baribir ulash uchun bosing" + "Yangi ulanish: %1$s" + "Agar %2$s tarmoqda internet uzilsa, qurilma %1$sga ulanadi. Sarflangan trafik uchun haq olinishi mumkin." + "%1$s tarmog‘idan %2$s tarmog‘iga o‘tildi" + "noma’lum tarmoq turi" + + "mobil internet" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-vi/strings.xml b/service/ServiceConnectivityResources/res/values-vi/strings.xml new file mode 100644 index 0000000000..d2284d4905 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-vi/strings.xml @@ -0,0 +1,39 @@ + + + + "Đăng nhập vào mạng Wi-Fi" + "Đăng nhập vào mạng" + + "%1$s không có quyền truy cập Internet" + "Nhấn để biết tùy chọn" + "Mạng di động không có quyền truy cập Internet" + "Mạng không có quyền truy cập Internet" + "Không thể truy cập máy chủ DNS riêng tư" + "%1$s có khả năng kết nối giới hạn" + "Nhấn để tiếp tục kết nối" + "Đã chuyển sang %1$s" + "Thiết bị sử dụng %1$s khi %2$s không có quyền truy cập Internet. Bạn có thể phải trả phí." + "Đã chuyển từ %1$s sang %2$s" + "loại mạng không xác định" + + "dữ liệu di động" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..813482b499 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml @@ -0,0 +1,39 @@ + + + + "登录到WLAN网络" + "登录到网络" + + "%1$s 无法访问互联网" + "点按即可查看相关选项" + "此移动网络无法访问互联网" + "此网络无法访问互联网" + "无法访问私人 DNS 服务器" + "%1$s 的连接受限" + "点按即可继续连接" + "已切换至%1$s" + "设备会在%2$s无法访问互联网时使用%1$s(可能需要支付相应的费用)。" + "已从%1$s切换至%2$s" + "未知网络类型" + + "移动数据" + "WLAN" + "蓝牙" + "以太网" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml new file mode 100644 index 0000000000..676404fe2c --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml @@ -0,0 +1,39 @@ + + + + "登入 Wi-Fi 網絡" + "登入網絡" + + "%1$s未有連接至互聯網" + "輕按即可查看選項" + "流動網絡並未連接互聯網" + "網絡並未連接互聯網" + "無法存取私人 DNS 伺服器" + "%1$s連線受限" + "仍要輕按以連結至此網絡" + "已切換至%1$s" + "裝置會在 %2$s 無法連線至互聯網時使用%1$s (可能需要支付相關費用)。" + "已從%1$s切換至%2$s" + "不明網絡類型" + + "流動數據" + "Wi-Fi" + "藍牙" + "以太網" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..f355138bd6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml @@ -0,0 +1,39 @@ + + + + "登入 Wi-Fi 網路" + "登入網路" + + "%1$s 沒有網際網路連線" + "輕觸即可查看選項" + "這個行動網路沒有網際網路連線" + "這個網路沒有網際網路連線" + "無法存取私人 DNS 伺服器" + "%1$s 的連線能力受限" + "輕觸即可繼續連線" + "已切換至%1$s" + "裝置會在無法連上「%2$s」時切換至「%1$s」(可能需要支付相關費用)。" + "已從 %1$s 切換至%2$s" + "不明的網路類型" + + "行動數據" + "Wi-Fi" + "藍牙" + "乙太網路" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zu/strings.xml b/service/ServiceConnectivityResources/res/values-zu/strings.xml new file mode 100644 index 0000000000..55fefb7939 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zu/strings.xml @@ -0,0 +1,39 @@ + + + + "Ngena ngemvume kunethiwekhi ye-Wi-Fi" + "Ngena ngemvume kunethiwekhi" + + "I-%1$s ayinakho ukufinyelela kwe-inthanethi" + "Thepha ukuze uthole izinketho" + "Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi" + "Inethiwekhi ayinakho ukufinyelela kwenethiwekhi" + "Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa" + "I-%1$s inokuxhumeka okukhawulelwe" + "Thepha ukuze uxhume noma kunjalo" + "Kushintshelwe ku-%1$s" + "Idivayisi isebenzisa i-%1$s uma i-%2$s inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko." + "Kushintshelewe kusuka ku-%1$s kuya ku-%2$s" + "uhlobo olungaziwa lwenethiwekhi" + + "idatha yeselula" + "I-Wi-Fi" + "I-Bluetooth" + "I-Ethernet" + "I-VPN" + + diff --git a/service/ServiceConnectivityResources/res/values/strings.xml b/service/ServiceConnectivityResources/res/values/strings.xml index 2c7b992650..7a9cf57afc 100644 --- a/service/ServiceConnectivityResources/res/values/strings.xml +++ b/service/ServiceConnectivityResources/res/values/strings.xml @@ -14,9 +14,63 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + System Connectivity Resources - \ No newline at end of file + + + Sign in to Wi-Fi network + + + Sign in to network + + + %1$s + + + %1$s has no internet access + + + Tap for options + + + Mobile network has no internet access + + + Network has no internet access + + + Private DNS server cannot be accessed + + + %1$s has limited connectivity + + + Tap to connect anyway + + + Switched to %1$s + + + Device uses %1$s when %2$s has no internet access. Charges may apply. + + + Switched from %1$s to %2$s + + + + mobile data + Wi-Fi + Bluetooth + Ethernet + VPN + + + + + + an unknown network type + + From a338d5aa58ce9dca01792fa04e00003992a353f5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Mar 2021 17:45:27 +0900 Subject: [PATCH 164/343] Use module resources in NetworkNotificationManager. Also make getTransportName non-static so it can access the module resources. Also fix a duplicate comment in a resource file. Bug: 183097033 Test: atest FrameworksNetTests Test: connected to Wi-Fi with no Internet, observed notification Change-Id: Ic0d24d36af0b87153d527083f8964ddc6cd78482 --- service/ServiceConnectivityResources/res/values/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/service/ServiceConnectivityResources/res/values/strings.xml b/service/ServiceConnectivityResources/res/values/strings.xml index 7a9cf57afc..b2fa5f5b41 100644 --- a/service/ServiceConnectivityResources/res/values/strings.xml +++ b/service/ServiceConnectivityResources/res/values/strings.xml @@ -68,8 +68,6 @@ VPN - - an unknown network type From f353baf176b429e6f9a6f6314a34763b14af2146 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 16:03:06 +0000 Subject: [PATCH 165/343] Add TEST_MAPPING for Connectivity The TEST_MAPPING triggers connectivity tests in other paths. Bug: 183198868 Change-Id: I8d9b0450ea4b3ef3e5115d1f858b1aa7badef742 Test: Needs treehugger for testing --- TEST_MAPPING | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 TEST_MAPPING diff --git a/TEST_MAPPING b/TEST_MAPPING new file mode 100644 index 0000000000..94f9232bc4 --- /dev/null +++ b/TEST_MAPPING @@ -0,0 +1,19 @@ +{ + "imports": [ + { + "path": "frameworks/base/core/java/android/net" + }, + { + "path": "packages/modules/NetworkStack" + }, + { + "path": "packages/modules/CaptivePortalLogin" + }, + { + "path": "packages/modules/Connectivity" + }, + { + "path": "packages/modules/Connectivity/Tethering" + } + ] +} \ No newline at end of file From e2d2838805f14b20b8f09e30e27863758e38b851 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 23 Feb 2021 08:47:39 -0800 Subject: [PATCH 166/343] TransportInfo: Add a generic redaction mechanism This replaces the existing mechanism for redacting location sensitive fields with a more extensible mechanism. Currently supported redactions are for the following permissions: i. ACCESS_FINE_LOCATION ii. LOCAL_MAC_ADDRESS iii. NETWORK_SETTINGS Also, removed WifiInfo from ConnectivityServiceTest to reduce cross dependencies on wifi code. Bug: 156867433 Bug: 162602799 Test: atest android.net Test: atest com.android.server Change-Id: I2bb980c624667a55c1383f13ab71b9b97ed6eeab --- framework/api/module-lib-current.txt | 11 ++ framework/api/system-current.txt | 6 - framework/src/android/net/NetworkAgent.java | 5 +- .../src/android/net/NetworkCapabilities.java | 111 +++++++++++++++--- framework/src/android/net/TransportInfo.java | 48 +++++--- 5 files changed, 139 insertions(+), 42 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 6339094341..f484c3cdb0 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -27,7 +27,13 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); method @Nullable public java.util.Set> getUids(); + field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL + field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L + field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L + field public static final long REDACT_FOR_NETWORK_SETTINGS = 4L; // 0x4L + field public static final long REDACT_NONE = 0L; // 0x0L field public static final int TRANSPORT_TEST = 7; // 0x7 } @@ -79,6 +85,11 @@ package android.net { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public interface TransportInfo { + method public default long getApplicableRedactions(); + method @NonNull public default android.net.TransportInfo makeCopy(long); + } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { ctor public VpnTransportInfo(int); method public int describeContents(); diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 4dca411cca..5cab0bcf1c 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -263,7 +263,6 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { - ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); @@ -437,11 +436,6 @@ package android.net { field public final int tcpWindowScale; } - public interface TransportInfo { - method public default boolean hasLocationSensitiveFields(); - method @NonNull public default android.net.TransportInfo makeCopy(boolean); - } - } package android.net.apf { diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index b3ab0ee8bd..c21aff9639 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -434,7 +434,7 @@ public abstract class NetworkAgent { } mInitialConfiguration = new InitialConfiguration(context, - new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true), + new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE), new LinkProperties(lp), score, config, ni); } @@ -878,8 +878,7 @@ public abstract class NetworkAgent { mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); final NetworkCapabilities nc = - new NetworkCapabilities(networkCapabilities, - /* parcelLocationSensitiveFields */ true); + new NetworkCapabilities(networkCapabilities, NetworkCapabilities.REDACT_NONE); queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 182bc7141a..add9a15db4 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -19,6 +19,7 @@ package android.net; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.annotation.IntDef; +import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -65,6 +66,68 @@ import java.util.StringJoiner; public final class NetworkCapabilities implements Parcelable { private static final String TAG = "NetworkCapabilities"; + /** + * Mechanism to support redaction of fields in NetworkCapabilities that are guarded by specific + * app permissions. + **/ + /** + * Don't redact any fields since the receiving app holds all the necessary permissions. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_NONE = 0; + + /** + * Redact any fields that need {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission since the receiving app does not hold this permission or the location toggle + * is off. + * + * @see android.Manifest.permission#ACCESS_FINE_LOCATION + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1 << 0; + + /** + * Redact any fields that need {@link android.Manifest.permission#LOCAL_MAC_ADDRESS} + * permission since the receiving app does not hold this permission. + * + * @see android.Manifest.permission#LOCAL_MAC_ADDRESS + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 1 << 1; + + /** + * + * Redact any fields that need {@link android.Manifest.permission#NETWORK_SETTINGS} + * permission since the receiving app does not hold this permission. + * + * @see android.Manifest.permission#NETWORK_SETTINGS + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_NETWORK_SETTINGS = 1 << 2; + + /** + * Redact all fields in this object that require any relevant permission. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_ALL = -1L; + + /** @hide */ + @LongDef(flag = true, prefix = { "REDACT_" }, value = { + REDACT_NONE, + REDACT_FOR_ACCESS_FINE_LOCATION, + REDACT_FOR_LOCAL_MAC_ADDRESS, + REDACT_FOR_NETWORK_SETTINGS, + REDACT_ALL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RedactionType {} + // Set to true when private DNS is broken. private boolean mPrivateDnsBroken; @@ -79,32 +142,31 @@ public final class NetworkCapabilities implements Parcelable { private String mRequestorPackageName; /** - * Indicates whether parceling should preserve fields that are set based on permissions of - * the process receiving the {@link NetworkCapabilities}. + * Indicates what fields should be redacted from this instance. */ - private final boolean mParcelLocationSensitiveFields; + private final @RedactionType long mRedactions; public NetworkCapabilities() { - mParcelLocationSensitiveFields = false; + mRedactions = REDACT_ALL; clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { - this(nc, false /* parcelLocationSensitiveFields */); + this(nc, REDACT_ALL); } /** * Make a copy of NetworkCapabilities. * * @param nc Original NetworkCapabilities - * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not. + * @param redactions bitmask of redactions that needs to be performed on this new instance of + * {@link NetworkCapabilities}. * @hide */ - @SystemApi - public NetworkCapabilities( - @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) { - mParcelLocationSensitiveFields = parcelLocationSensitiveFields; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) { + mRedactions = redactions; if (nc != null) { set(nc); } @@ -116,11 +178,13 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { - // Ensures that the internal copies maintained by the connectivity stack does not set - // this bit. - if (mParcelLocationSensitiveFields) { + // Ensures that the internal copies maintained by the connectivity stack does not set it to + // anything other than |REDACT_ALL|. + if (mRedactions != REDACT_ALL) { + // This is needed because the current redaction mechanism relies on redaction while + // parceling. throw new UnsupportedOperationException( - "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set"); + "Cannot clear NetworkCapabilities when mRedactions is set"); } mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; @@ -150,7 +214,7 @@ public final class NetworkCapabilities implements Parcelable { mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; if (nc.getTransportInfo() != null) { - setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields)); + setTransportInfo(nc.getTransportInfo().makeCopy(mRedactions)); } else { setTransportInfo(null); } @@ -2350,6 +2414,23 @@ public final class NetworkCapabilities implements Parcelable { } } + /** + * Returns a bitmask of all the applicable redactions (based on the permissions held by the + * receiving app) to be performed on this object. + * + * @return bitmask of redactions applicable on this instance. + * @hide + */ + public @RedactionType long getApplicableRedactions() { + // Currently, there are no fields redacted in NetworkCapabilities itself, so we just + // passthrough the redactions required by the embedded TransportInfo. If this changes + // in the future, modify this method. + if (mTransportInfo == null) { + return NetworkCapabilities.REDACT_NONE; + } + return mTransportInfo.getApplicableRedactions(); + } + /** * Builder class for NetworkCapabilities. * diff --git a/framework/src/android/net/TransportInfo.java b/framework/src/android/net/TransportInfo.java index aa4bbb0511..fa889eabb8 100644 --- a/framework/src/android/net/TransportInfo.java +++ b/framework/src/android/net/TransportInfo.java @@ -29,35 +29,47 @@ import android.annotation.SystemApi; public interface TransportInfo { /** - * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that - * were set based on the permissions of the process that originally received it. + * Create a copy of a {@link TransportInfo} with some fields redacted based on the permissions + * held by the receiving app. * - *

    By default {@link TransportInfo} does not preserve such fields during parceling, as - * they should not be shared outside of the process that receives them without appropriate - * checks. + *

    + * Usage by connectivity stack: + *

      + *
    • Connectivity stack will invoke {@link #getApplicableRedactions()} to find the list + * of redactions that are required by this {@link TransportInfo} instance.
    • + *
    • Connectivity stack then loops through each bit in the bitmask returned and checks if the + * receiving app holds the corresponding permission. + *
        + *
      • If the app holds the corresponding permission, the bit is cleared from the + * |redactions| bitmask.
      • + *
      • If the app does not hold the corresponding permission, the bit is retained in the + * |redactions| bitmask.
      • + *
      + *
    • Connectivity stack then invokes {@link #makeCopy(long)} with the necessary |redactions| + * to create a copy to send to the corresponding app.
    • + *
    + *

    * - * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept - * when parceling - * @return Copy of this instance. + * @param redactions bitmask of redactions that needs to be performed on this instance. + * @return Copy of this instance with the necessary redactions. * @hide */ - @SystemApi + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @NonNull - default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { + default TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { return this; } /** - * Returns whether this TransportInfo type has location sensitive fields or not (helps - * to determine whether to perform a location permission check or not before sending to - * apps). + * Returns a bitmask of all the applicable redactions (based on the permissions held by the + * receiving app) to be performed on this TransportInfo. * - * @return {@code true} if this instance contains location sensitive info, {@code false} - * otherwise. + * @return bitmask of redactions applicable on this instance. + * @see #makeCopy(long) * @hide */ - @SystemApi - default boolean hasLocationSensitiveFields() { - return false; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + default @NetworkCapabilities.RedactionType long getApplicableRedactions() { + return NetworkCapabilities.REDACT_NONE; } } From 3a5b9228901cb89394e91c7f3661bd697b372463 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Mar 2021 17:04:08 +0900 Subject: [PATCH 167/343] Copy NetworkNotificationManager resources to conectivity module. The localized resources were automatically generated with: =========== export OLDRES=core/res/res export NEWRES=packages/Connectivity/service/ServiceConnectivityResources/res export FILE=services/core/java/com/android/server/connectivity/NetworkNotificationManager.java for i in $OLDRES/values-*/strings.xml; do outfile=$NEWRES/${i#core/res/res/} outdir=$(dirname $outfile) if egrep -q "$regex" $i || egrep -q "$strarrayregex" $i; then mkdir -p $outdir cat << EOF > $outfile EOF egrep $regex $i >> $outfile egrep -A $strarraylines "$strarrayregex" $i >> $outfile echo "" >> $outfile fi done =========== The text to the the base resources file was added manually from the output of: =========== egrep -B 2 $regex core/res/res/values/strings.xml | grep -v -- ^-- egrep -B 2 -A 6 $strarrayregex core/res/res/values/strings.xml | grep -v -- ^-- =========== The drawables were copied from the Wifi resources and from the framework resources. Test: m Bug: 183097033 Change-Id: I99c0d28069dd1a13d452105b0a83a03a833232a2 Merged-In: I99c0d28069dd1a13d452105b0a83a03a833232a2 --- .../stat_notify_rssi_in_range.png | Bin 0 -> 1160 bytes .../stat_notify_rssi_in_range.png | Bin 0 -> 855 bytes .../stat_notify_rssi_in_range.png | Bin 0 -> 1500 bytes .../stat_notify_rssi_in_range.png | Bin 0 -> 3517 bytes .../drawable/stat_notify_wifi_in_range.xml | 27 ++++++++ .../res/values-af/strings.xml | 39 ++++++++++++ .../res/values-am/strings.xml | 39 ++++++++++++ .../res/values-ar/strings.xml | 39 ++++++++++++ .../res/values-as/strings.xml | 39 ++++++++++++ .../res/values-az/strings.xml | 39 ++++++++++++ .../res/values-b+sr+Latn/strings.xml | 39 ++++++++++++ .../res/values-be/strings.xml | 39 ++++++++++++ .../res/values-bg/strings.xml | 39 ++++++++++++ .../res/values-bn/strings.xml | 39 ++++++++++++ .../res/values-bs/strings.xml | 39 ++++++++++++ .../res/values-ca/strings.xml | 39 ++++++++++++ .../res/values-cs/strings.xml | 39 ++++++++++++ .../res/values-da/strings.xml | 39 ++++++++++++ .../res/values-de/strings.xml | 39 ++++++++++++ .../res/values-el/strings.xml | 39 ++++++++++++ .../res/values-en-rAU/strings.xml | 39 ++++++++++++ .../res/values-en-rCA/strings.xml | 39 ++++++++++++ .../res/values-en-rGB/strings.xml | 39 ++++++++++++ .../res/values-en-rIN/strings.xml | 39 ++++++++++++ .../res/values-en-rXC/strings.xml | 39 ++++++++++++ .../res/values-es-rUS/strings.xml | 39 ++++++++++++ .../res/values-es/strings.xml | 39 ++++++++++++ .../res/values-et/strings.xml | 39 ++++++++++++ .../res/values-eu/strings.xml | 39 ++++++++++++ .../res/values-fa/strings.xml | 39 ++++++++++++ .../res/values-fi/strings.xml | 39 ++++++++++++ .../res/values-fr-rCA/strings.xml | 39 ++++++++++++ .../res/values-fr/strings.xml | 39 ++++++++++++ .../res/values-gl/strings.xml | 39 ++++++++++++ .../res/values-gu/strings.xml | 39 ++++++++++++ .../res/values-hi/strings.xml | 39 ++++++++++++ .../res/values-hr/strings.xml | 39 ++++++++++++ .../res/values-hu/strings.xml | 39 ++++++++++++ .../res/values-hy/strings.xml | 39 ++++++++++++ .../res/values-in/strings.xml | 39 ++++++++++++ .../res/values-is/strings.xml | 39 ++++++++++++ .../res/values-it/strings.xml | 39 ++++++++++++ .../res/values-iw/strings.xml | 39 ++++++++++++ .../res/values-ja/strings.xml | 39 ++++++++++++ .../res/values-ka/strings.xml | 39 ++++++++++++ .../res/values-kk/strings.xml | 39 ++++++++++++ .../res/values-km/strings.xml | 39 ++++++++++++ .../res/values-kn/strings.xml | 39 ++++++++++++ .../res/values-ko/strings.xml | 39 ++++++++++++ .../res/values-ky/strings.xml | 39 ++++++++++++ .../res/values-lo/strings.xml | 39 ++++++++++++ .../res/values-lt/strings.xml | 39 ++++++++++++ .../res/values-lv/strings.xml | 39 ++++++++++++ .../res/values-mk/strings.xml | 39 ++++++++++++ .../res/values-ml/strings.xml | 39 ++++++++++++ .../res/values-mn/strings.xml | 39 ++++++++++++ .../res/values-mr/strings.xml | 39 ++++++++++++ .../res/values-ms/strings.xml | 39 ++++++++++++ .../res/values-my/strings.xml | 39 ++++++++++++ .../res/values-nb/strings.xml | 39 ++++++++++++ .../res/values-ne/strings.xml | 39 ++++++++++++ .../res/values-nl/strings.xml | 39 ++++++++++++ .../res/values-or/strings.xml | 39 ++++++++++++ .../res/values-pa/strings.xml | 39 ++++++++++++ .../res/values-pl/strings.xml | 39 ++++++++++++ .../res/values-pt-rBR/strings.xml | 39 ++++++++++++ .../res/values-pt-rPT/strings.xml | 39 ++++++++++++ .../res/values-pt/strings.xml | 39 ++++++++++++ .../res/values-ro/strings.xml | 39 ++++++++++++ .../res/values-ru/strings.xml | 39 ++++++++++++ .../res/values-si/strings.xml | 39 ++++++++++++ .../res/values-sk/strings.xml | 39 ++++++++++++ .../res/values-sl/strings.xml | 39 ++++++++++++ .../res/values-sq/strings.xml | 39 ++++++++++++ .../res/values-sr/strings.xml | 39 ++++++++++++ .../res/values-sv/strings.xml | 39 ++++++++++++ .../res/values-sw/strings.xml | 39 ++++++++++++ .../res/values-ta/strings.xml | 39 ++++++++++++ .../res/values-te/strings.xml | 39 ++++++++++++ .../res/values-th/strings.xml | 39 ++++++++++++ .../res/values-tl/strings.xml | 39 ++++++++++++ .../res/values-tr/strings.xml | 39 ++++++++++++ .../res/values-uk/strings.xml | 39 ++++++++++++ .../res/values-ur/strings.xml | 39 ++++++++++++ .../res/values-uz/strings.xml | 39 ++++++++++++ .../res/values-vi/strings.xml | 39 ++++++++++++ .../res/values-zh-rCN/strings.xml | 39 ++++++++++++ .../res/values-zh-rHK/strings.xml | 39 ++++++++++++ .../res/values-zh-rTW/strings.xml | 39 ++++++++++++ .../res/values-zu/strings.xml | 39 ++++++++++++ .../res/values/strings.xml | 58 +++++++++++++++++- 91 files changed, 3398 insertions(+), 2 deletions(-) create mode 100644 service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable-mdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable-xhdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable-xxhdpi/stat_notify_rssi_in_range.png create mode 100644 service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml create mode 100644 service/ServiceConnectivityResources/res/values-af/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-am/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ar/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-as/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-az/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-be/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-bg/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-bn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-bs/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ca/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-cs/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-da/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-de/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-el/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rAU/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rCA/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rGB/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rIN/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-en-rXC/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-es-rUS/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-es/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-et/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-eu/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fa/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fi/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-fr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-gl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-gu/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hi/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hu/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-hy/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-in/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-is/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-it/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-iw/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ja/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ka/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-kk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-km/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-kn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ko/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ky/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-lo/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-lt/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-lv/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-mk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ml/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-mn/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-mr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ms/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-my/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-nb/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ne/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-nl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-or/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pa/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-pt/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ro/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ru/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-si/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sq/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sv/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-sw/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ta/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-te/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-th/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-tl/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-tr/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-uk/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-ur/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-uz/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-vi/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml create mode 100644 service/ServiceConnectivityResources/res/values-zu/strings.xml diff --git a/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png b/service/ServiceConnectivityResources/res/drawable-hdpi/stat_notify_rssi_in_range.png new file mode 100644 index 0000000000000000000000000000000000000000..74977e6aefffb385b33ee169faf7bd0c63cf38a2 GIT binary patch literal 1160 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBSkfJR9T^xl_H+M9WCijWi-X*q z7}lMWc?skwBzpw;GB8xBGB7kWGcf%852S(Or3MTPuM!v-tbhiH=TC}1>IPKHmgMd3 z!tfsi7wla=87RV8;1OBOz`!j8!i<;h*8O2%V6OFaaSVw#e0Ik9{2oV%qAN=gZp5G0DtB#^cY51)M^&JnqQOvG7o__`xl6_Yb>;XTg z`)zT?c=zR-mG^76?-rfBXXd#x#^*oR&iiTi*+=}}=Cq{AN{{%t9oqNvglyUFsi>5k z6fN|{Sg9!VY0o#_gDmmWJHGs|N}4_A)25C+fsaMsrn{!t&Dg!@lWb%Ilft=&f`XPW z&s)msqlBnYH1dbce&)yF-SSn(WcV9B6>;Ea{C5bJ2!WicTonE!wYJY%hfcBnu zEBcszH_qpsbB_On@)z$15iU!-W-y##e4}eK`|`t@hAGZWUzpT4)Oa#`+oGd5@)_`r11Qy zh1uo{9kskE*O(SZJX#+1cN(K)@|^a`2Xa^J{vq_{aJO@4M3^ z_4bI^>9_~m*_SPyCc03|OlM~81l9*K8+d0N6g#_ZOWP8^%8#;)-;%V;qm>>@pWr@r zevVPDLP2mt&;gzV?pJq;8Zspm{oOXOmR0Ojn#`%8kpDxhOz^jPgHl3OBli`rlbg0# zIm~+Z?vZw~{ytHix*6W5+$Vo7y}484ZF9Pdd4Xg^|K1 zRdP`(kYX@0Ff`ING|)9L3NbXXGBL6OvCXXv3~mHe^P_0U%}>cptHiBgCGX+QKn)C@ Lu6{1-oD!M!lvI6;x#X;^) z4C~IxyaaL-l0AZa85pWm85kOx85n;42hu?CQUeBtR|yOZRx=nF#PcV`A9Vw&WlQpQ zcVYMsf(!O8p9~b?EbxddW?97dyXIW z_-xmgRDMHe%2KTZ-;=rSd!OICB3)Q>|Dn|k67KTshs$=IC{x^Y;(>J`+vmG%FH1XC zbr*dt)aCf!Xf69`RnryEH3!f0UF?=jxm2`L>dv9unnSF6bd=7i&g!{T%Uyf2;fnJY zw(0`oZ+ed-S%RC^A63oajoTH$tdf56<@vT|yLtSI_NR!0*93uY=PqB#Kh5A9S2|DPEiP-8Gx^4KK94E**E9bFJ*+g}C^Q z&3?%}g`47*eukY-MMjL1Spl=*TicDN5G!Eb+n^ zTVXQlNiQBo#AKTnQN7ZfQ!itQH~xHoymQZYzx&;DzkC0?`Q8K{g003DxSDcTS zO%H&O5NAKgR<4*}Q5a7Q0CW^f?}ov}8YKI;V1c&rBOk;1-?vmP(HxSfYoDJio<>%rTeSDD?XnFuQ9pha4Y&55Jc=qk zOWLO)LM2AkuaDqYWl{VpwR7ub*mgAJ3>VOvhYNpVLF{3bkiE%uIaP21lwVoLJejvH z`14mu`Ut(duZUAIq&F#9Jr%{II!M|>ciT6Y!9j=?Xl=-F6dDSBgZ`FuHesCRn#}|p z<5a9S>}_5%Rt09kFGeDr_dBve3)0V&wBp9Wn3yYSB515(-ODsS%wry)xDA!HEMQ|i z-mM+=MRs>w)Musdr3rMGN}s*(PuD~gjCcpRD<2ZJinbMAqA@kU=u^N%NC-D~rKHft zl6TZt`2_E2haO4o5nL-4&O&A`d<*~TEijU_uhV_~!hda=s;$j#bD*MP>zWuA?zr>I zxuQQbE(rC7WgTf}bE3*38y*{0Cxll$_lo6}e`h2y{2pMjjqlA%W>-!--zNR`hNtfp zq+v+6X7pyOY%|+q3#EB%&ZDQ@BJ3X9o^1&h`#E_sGQx&9}e!aV#8Q6 z_IVSDRrTfk32e9&lK&z2psrHPw- zJWG|5tUP*umC9APEozA?O(-Nv^I>BhyBv{m95w3A)~cf6%y7-hqUQFtSCEw@T}5Ce z2)Ozs`hqY4aW{CXOi#_W+1L(IJ&{A_e4_0pr{jDdEIp5^Np<2?&sA$Z%@7c6>qi5m z{L^d@l{fZwbahJ}u)|I+-Dc%8x^Es6bw$nkW)BDI$ZkO7TCCr8PdB>G+pyFJ(TE0O zgzAurHC?M0lBo_+mLLk&=?$kqn$Kwa7kJm8FCX0tp#(uBHU@h79RCVQyJtKfZwD#` zP3D+42FlHcq~#PYPA?$*-KW1!{NtI{W!b~|lrNy2X_a3rcCZpY%iw-zI|L@WuMxD_ z1A+;6FCUH8F?gl{Bp(YWS+KOUHp$TC3a4Zl@IN*23t9KjdWDDQtIn)t1H7Wmkfp+$MX3PYFG|HbpTp z@z6|k3(s8Kf0YuY#402k2<>S`2~oAL9};h>26?C3*sC&Y?x`~?9J@!py+Wvpeu(5X zAi?#>Ce4}LBGe43-z~pg_Iv6j`mz^MjvJsAL~M<%>CWS_#-(j)0yYKZNT~k$*qqH3 z3~rnIMD0g;6}cQ2S^V)9t|qIJ3`OyC+tJOW0YT-lbLeOtQ{QC5v{k3qaZV#R#B(*7 z)sL7AZYHM&mueXJfkG~OLOG%^K>YFaQtKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0008$NklGu?NrI1pWfoHauto{KyCg zHU0=V^kC)eC`iVa*a#RFyune)khX!YjTjUee6SJFD*;XfY}yLaNuDzW_JF?noF~|1zLH(APb-iPXu0Cy9<0%ki4(OdXBxT348$_ zhElA?$ph0~d83jahf>WS#*`#e3n~6dT9xbrpq|niIvcM-yCV+HQOx!4C1$tM0S%e= zf!Z-k%cS>oLjp8OC@rR{EHSB)KZF8kl8~{+hT#-a$)<&3nrtj)r? zZ31rvklu3!vc#6#dMGNn3_y!JE+j}VQOW!2Q?l4CyMx0W7oh=a0G~rt$*uqms-Sml z0qRr2j*CzLZ2@nj)X=Nsh!wCrFAiJ4Q_^in__c6;o^sCR!uijXbN(!x|0exriR+{R rHTi?3a;td(B!C2vm;e$$_UzvPcEfJQwa{BG00000NkvXXu0mjfV3c|Q literal 0 HcmV?d00001 diff --git a/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml b/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml new file mode 100644 index 0000000000..a271ca5224 --- /dev/null +++ b/service/ServiceConnectivityResources/res/drawable/stat_notify_wifi_in_range.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/service/ServiceConnectivityResources/res/values-af/strings.xml b/service/ServiceConnectivityResources/res/values-af/strings.xml new file mode 100644 index 0000000000..68720d5d27 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-af/strings.xml @@ -0,0 +1,39 @@ + + + + "Meld aan by Wi-Fi-netwerk" + "Meld by netwerk aan" + + "%1$s het geen internettoegang nie" + "Tik vir opsies" + "Selnetwerk het nie internettoegang nie" + "Netwerk het nie internettoegang nie" + "Daar kan nie by private DNS-bediener ingegaan word nie" + "%1$s het beperkte konnektiwiteit" + "Tik om in elk geval te koppel" + "Het oorgeskakel na %1$s" + "Toestel gebruik %1$s wanneer %2$s geen internettoegang het nie. Heffings kan geld." + "Het oorgeskakel van %1$s na %2$s" + "\'n onbekende netwerktipe" + + "mobiele data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-am/strings.xml b/service/ServiceConnectivityResources/res/values-am/strings.xml new file mode 100644 index 0000000000..78d928351d --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-am/strings.xml @@ -0,0 +1,39 @@ + + + + "ወደ Wi-Fi አውታረ መረብ በመለያ ግባ" + "ወደ አውታረ መረብ በመለያ ይግቡ" + + "%1$s ምንም የበይነ መረብ መዳረሻ የለም" + "ለአማራጮች መታ ያድርጉ" + "የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም" + "አውታረ መረብ የበይነመረብ መዳረሻ የለውም" + "የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም" + "%1$s የተገደበ ግንኙነት አለው" + "ለማንኛውም ለማገናኘት መታ ያድርጉ" + "ወደ %1$s ተቀይሯል" + "%2$s ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች %1$sን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።" + "ከ%1$s ወደ %2$s ተቀይሯል" + "አንድ ያልታወቀ አውታረ መረብ ዓይነት" + + "የተንቀሳቃሽ ስልክ ውሂብ" + "Wi-Fi" + "ብሉቱዝ" + "ኤተርኔት" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ar/strings.xml b/service/ServiceConnectivityResources/res/values-ar/strings.xml new file mode 100644 index 0000000000..8698a7e6e1 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ar/strings.xml @@ -0,0 +1,39 @@ + + + + "‏تسجيل الدخول إلى شبكة Wi-Fi" + "تسجيل الدخول إلى الشبكة" + + "لا يتوفّر في %1$s إمكانية الاتصال بالإنترنت." + "انقر للحصول على الخيارات." + "شبكة الجوّال هذه غير متصلة بالإنترنت" + "الشبكة غير متصلة بالإنترنت" + "لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص" + "إمكانية اتصال %1$s محدودة." + "يمكنك النقر للاتصال على أي حال." + "تم التبديل إلى %1$s" + "يستخدم الجهاز %1$s عندما لا يتوفر اتصال بالإنترنت في شبكة %2$s، ويمكن أن يتم فرض رسوم مقابل ذلك." + "تم التبديل من %1$s إلى %2$s" + "نوع شبكة غير معروف" + + "بيانات الجوّال" + "Wi-Fi" + "بلوتوث" + "إيثرنت" + "‏شبكة افتراضية خاصة (VPN)" + + diff --git a/service/ServiceConnectivityResources/res/values-as/strings.xml b/service/ServiceConnectivityResources/res/values-as/strings.xml new file mode 100644 index 0000000000..10b234adce --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-as/strings.xml @@ -0,0 +1,39 @@ + + + + "ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক" + "নেটৱৰ্কত ছাইন ইন কৰক" + + "%1$sৰ ইণ্টাৰনেটৰ এক্সেছ নাই" + "অধিক বিকল্পৰ বাবে টিপক" + "ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" + "নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" + "ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি" + "%1$sৰ সকলো সেৱাৰ এক্সেছ নাই" + "যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক" + "%1$sলৈ সলনি কৰা হ’ল" + "যেতিয়া %2$sত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে %1$sক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।" + "%1$sৰ পৰা %2$s লৈ সলনি কৰা হ’ল" + "অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক" + + "ম’বাইল ডেটা" + "ৱাই-ফাই" + "ব্লুটুথ" + "ইথাৰনেট" + "ভিপিএন" + + diff --git a/service/ServiceConnectivityResources/res/values-az/strings.xml b/service/ServiceConnectivityResources/res/values-az/strings.xml new file mode 100644 index 0000000000..d75a20460c --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-az/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi şəbəkəsinə daxil ol" + "Şəbəkəyə daxil olun" + + "%1$s üçün internet girişi əlçatan deyil" + "Seçimlər üçün tıklayın" + "Mobil şəbəkənin internetə girişi yoxdur" + "Şəbəkənin internetə girişi yoxdur" + "Özəl DNS serverinə giriş mümkün deyil" + "%1$s bağlantını məhdudlaşdırdı" + "İstənilən halda klikləyin" + "%1$s şəbəkə növünə keçirildi" + "%2$s şəbəkəsinin internetə girişi olmadıqda, cihaz %1$s şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər." + "%1$s şəbəkəsindən %2$s şəbəkəsinə keçirildi" + "naməlum şəbəkə növü" + + "mobil data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml b/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml new file mode 100644 index 0000000000..11e4957a7b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijavljivanje na WiFi mrežu" + "Prijavite se na mrežu" + + "%1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Pristup privatnom DNS serveru nije uspeo" + "%1$s ima ograničenu vezu" + "Dodirnite da biste se ipak povezali" + "Prešli ste na tip mreže %1$s" + "Uređaj koristi tip mreže %1$s kada tip mreže %2$s nema pristup internetu. Možda će se naplaćivati troškovi." + "Prešli ste sa tipa mreže %1$s na tip mreže %2$s" + "nepoznat tip mreže" + + "mobilni podaci" + "WiFi" + "Bluetooth" + "Eternet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-be/strings.xml b/service/ServiceConnectivityResources/res/values-be/strings.xml new file mode 100644 index 0000000000..6b0b1f1130 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-be/strings.xml @@ -0,0 +1,39 @@ + + + + "Уваход у сетку Wi-Fi" + "Увайдзіце ў сетку" + + "%1$s не мае доступу ў інтэрнэт" + "Дакраніцеся, каб убачыць параметры" + "Мабільная сетка не мае доступу ў інтэрнэт" + "Сетка не мае доступу ў інтэрнэт" + "Не ўдалося атрымаць доступ да прыватнага DNS-сервера" + "%1$s мае абмежаваную магчымасць падключэння" + "Націсніце, каб падключыцца" + "Выкананы пераход да %1$s" + "Прылада выкарыстоўвае сетку %1$s, калі ў сетцы %2$s няма доступу да інтэрнэту. Можа спаганяцца плата." + "Выкананы пераход з %1$s да %2$s" + "невядомы тып сеткі" + + "мабільная перадача даных" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-bg/strings.xml b/service/ServiceConnectivityResources/res/values-bg/strings.xml new file mode 100644 index 0000000000..6427bd09cf --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-bg/strings.xml @@ -0,0 +1,39 @@ + + + + "Влизане в Wi-Fi мрежа" + "Вход в мрежата" + + "%1$s няма достъп до интернет" + "Докоснете за опции" + "Мобилната мрежа няма достъп до интернет" + "Мрежата няма достъп до интернет" + "Не може да се осъществи достъп до частния DNS сървър" + "%1$s има ограничена свързаност" + "Докоснете, за да се свържете въпреки това" + "Превключи се към %1$s" + "Устройството използва %1$s, когато %2$s няма достъп до интернет. Възможно е да бъдете таксувани." + "Превключи се от %1$s към %2$s" + "неизвестен тип мрежа" + + "мобилни данни" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "виртуална частна мрежа (VPN)" + + diff --git a/service/ServiceConnectivityResources/res/values-bn/strings.xml b/service/ServiceConnectivityResources/res/values-bn/strings.xml new file mode 100644 index 0000000000..74d4cd6d7e --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-bn/strings.xml @@ -0,0 +1,39 @@ + + + + "ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন" + "নেটওয়ার্কে সাইন-ইন করুন" + + "%1$s-এর ইন্টারনেটে অ্যাক্সেস নেই" + "বিকল্পগুলির জন্য আলতো চাপুন" + "মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" + "নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" + "ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না" + "%1$s-এর সীমিত কানেক্টিভিটি আছে" + "তবুও কানেক্ট করতে ট্যাপ করুন" + "%1$s এ পাল্টানো হয়েছে" + "%2$s এ ইন্টারনেট অ্যাক্সেস না থাকলে %1$s ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷" + "%1$s থেকে %2$s এ পাল্টানো হয়েছে" + "এই নেটওয়ার্কের প্রকার অজানা" + + "মোবাইল ডেটা" + "Wi-Fi" + "ব্লুটুথ" + "ইথারনেট" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-bs/strings.xml b/service/ServiceConnectivityResources/res/values-bs/strings.xml new file mode 100644 index 0000000000..19f6e1a3f5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-bs/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijavljivanje na WiFi mrežu" + "Prijava na mrežu" + + "Mreža %1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Nije moguće pristupiti privatnom DNS serveru" + "Mreža %1$s ima ograničenu povezivost" + "Dodirnite da se ipak povežete" + "Prebačeno na: %1$s" + "Kada %2$s nema pristup internetu, uređaj koristi mrežu %1$s. Moguća je naplata usluge." + "Prebačeno iz mreže %1$s u %2$s mrežu" + "nepoznata vrsta mreže" + + "prijenos podataka na mobilnoj mreži" + "WiFi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ca/strings.xml b/service/ServiceConnectivityResources/res/values-ca/strings.xml new file mode 100644 index 0000000000..c55684d6e0 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ca/strings.xml @@ -0,0 +1,39 @@ + + + + "Inicia la sessió a la xarxa Wi-Fi" + "Inicia la sessió a la xarxa" + + "%1$s no té accés a Internet" + "Toca per veure les opcions" + "La xarxa mòbil no té accés a Internet" + "La xarxa no té accés a Internet" + "No es pot accedir al servidor DNS privat" + "%1$s té una connectivitat limitada" + "Toca per connectar igualment" + "Actualment en ús: %1$s" + "El dispositiu utilitza %1$s en cas que %2$s no tingui accés a Internet. És possible que s\'hi apliquin càrrecs." + "Abans es feia servir la xarxa %1$s; ara s\'utilitza %2$s" + "una tipus de xarxa desconegut" + + "dades mòbils" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-cs/strings.xml b/service/ServiceConnectivityResources/res/values-cs/strings.xml new file mode 100644 index 0000000000..fa8c411e48 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-cs/strings.xml @@ -0,0 +1,39 @@ + + + + "Přihlásit se k síti Wi-Fi" + "Přihlásit se k síti" + + "Síť %1$s nemá přístup k internetu" + "Klepnutím zobrazíte možnosti" + "Mobilní síť nemá přístup k internetu" + "Síť nemá přístup k internetu" + "Nelze získat přístup k soukromému serveru DNS" + "Síť %1$s umožňuje jen omezené připojení" + "Klepnutím se i přesto připojíte" + "Přechod na síť %1$s" + "Když síť %2$s nebude mít přístup k internetu, zařízení použije síť %1$s. Mohou být účtovány poplatky." + "Přechod ze sítě %1$s na síť %2$s" + "neznámý typ sítě" + + "mobilní data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-da/strings.xml b/service/ServiceConnectivityResources/res/values-da/strings.xml new file mode 100644 index 0000000000..f7be6df981 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-da/strings.xml @@ -0,0 +1,39 @@ + + + + "Log ind på Wi-Fi-netværk" + "Log ind på netværk" + + "%1$s har ingen internetforbindelse" + "Tryk for at se valgmuligheder" + "Mobilnetværket har ingen internetadgang" + "Netværket har ingen internetadgang" + "Der er ikke adgang til den private DNS-server" + "%1$s har begrænset forbindelse" + "Tryk for at oprette forbindelse alligevel" + "Der blev skiftet til %1$s" + "Enheden benytter %1$s, når der ikke er internetadgang via %2$s. Der opkræves muligvis betaling." + "Der blev skiftet fra %1$s til %2$s" + "en ukendt netværkstype" + + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-de/strings.xml b/service/ServiceConnectivityResources/res/values-de/strings.xml new file mode 100644 index 0000000000..1e7b80c8f6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-de/strings.xml @@ -0,0 +1,39 @@ + + + + "In WLAN anmelden" + "Im Netzwerk anmelden" + + "%1$s hat keinen Internetzugriff" + "Für Optionen tippen" + "Mobiles Netzwerk hat keinen Internetzugriff" + "Netzwerk hat keinen Internetzugriff" + "Auf den privaten DNS-Server kann nicht zugegriffen werden" + "Schlechte Verbindung mit %1$s" + "Tippen, um die Verbindung trotzdem herzustellen" + "Zu %1$s gewechselt" + "Auf dem Gerät werden %1$s genutzt, wenn über %2$s kein Internet verfügbar ist. Eventuell fallen Gebühren an." + "Von \"%1$s\" zu \"%2$s\" gewechselt" + "ein unbekannter Netzwerktyp" + + "Mobile Daten" + "WLAN" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-el/strings.xml b/service/ServiceConnectivityResources/res/values-el/strings.xml new file mode 100644 index 0000000000..89647fdb1e --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-el/strings.xml @@ -0,0 +1,39 @@ + + + + "Συνδεθείτε στο δίκτυο Wi-Fi" + "Σύνδεση στο δίκτυο" + + "Η εφαρμογή %1$s δεν έχει πρόσβαση στο διαδίκτυο" + "Πατήστε για να δείτε τις επιλογές" + "Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο." + "Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο." + "Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS." + "Το δίκτυο %1$s έχει περιορισμένη συνδεσιμότητα" + "Πατήστε για σύνδεση ούτως ή άλλως" + "Μετάβαση σε δίκτυο %1$s" + "Η συσκευή χρησιμοποιεί το δίκτυο %1$s όταν το δίκτυο %2$s δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις." + "Μετάβαση από το δίκτυο %1$s στο δίκτυο %2$s" + "άγνωστος τύπος δικτύου" + + "δεδομένα κινητής τηλεφωνίας" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml b/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml b/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml b/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml b/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml new file mode 100644 index 0000000000..d29e2ec9f3 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml @@ -0,0 +1,39 @@ + + + + "Sign in to a Wi-Fi network" + "Sign in to network" + + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" + "an unknown network type" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml b/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml new file mode 100644 index 0000000000..cd69133966 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml @@ -0,0 +1,39 @@ + + + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎Sign in to Wi-Fi network‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎Sign in to network‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎Tap for options‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎Mobile network has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎Network has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎Private DNS server cannot be accessed‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has limited connectivity‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎Tap to connect anyway‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎Switched to ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‎‎Device uses ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ when ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ has no internet access. Charges may apply.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎Switched from ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎an unknown network type‎‏‎‎‏‎" + + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎mobile data‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎Wi-Fi‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎Bluetooth‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‎‎Ethernet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎VPN‎‏‎‎‏‎" + + diff --git a/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml b/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml new file mode 100644 index 0000000000..9102dc019a --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml @@ -0,0 +1,39 @@ + + + + "Accede a una red Wi-Fi." + "Acceder a la red" + + "%1$sno tiene acceso a Internet" + "Presiona para ver opciones" + "La red móvil no tiene acceso a Internet" + "La red no tiene acceso a Internet" + "No se puede acceder al servidor DNS privado" + "%1$s tiene conectividad limitada" + "Presiona para conectarte de todas formas" + "Se cambió a %1$s" + "El dispositivo usa %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." + "Se cambió de %1$s a %2$s" + "un tipo de red desconocido" + + "Datos móviles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-es/strings.xml b/service/ServiceConnectivityResources/res/values-es/strings.xml new file mode 100644 index 0000000000..4c15566a73 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-es/strings.xml @@ -0,0 +1,39 @@ + + + + "Iniciar sesión en red Wi-Fi" + "Iniciar sesión en la red" + + "%1$s no tiene acceso a Internet" + "Toca para ver opciones" + "La red móvil no tiene acceso a Internet" + "La red no tiene acceso a Internet" + "No se ha podido acceder al servidor DNS privado" + "%1$s tiene una conectividad limitada" + "Toca para conectarte de todas formas" + "Se ha cambiado a %1$s" + "El dispositivo utiliza %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." + "Se ha cambiado de %1$s a %2$s" + "tipo de red desconocido" + + "datos móviles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-et/strings.xml b/service/ServiceConnectivityResources/res/values-et/strings.xml new file mode 100644 index 0000000000..398223a341 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-et/strings.xml @@ -0,0 +1,39 @@ + + + + "Logi sisse WiFi-võrku" + "Võrku sisselogimine" + + "Võrgul %1$s puudub Interneti-ühendus" + "Puudutage valikute nägemiseks" + "Mobiilsidevõrgul puudub Interneti-ühendus" + "Võrgul puudub Interneti-ühendus" + "Privaatsele DNS-serverile ei pääse juurde" + "Võrgu %1$s ühendus on piiratud" + "Puudutage, kui soovite siiski ühenduse luua" + "Lülitati võrgule %1$s" + "Seade kasutab võrku %1$s, kui võrgul %2$s puudub juurdepääs Internetile. Rakenduda võivad tasud." + "Lülitati võrgult %1$s võrgule %2$s" + "tundmatu võrgutüüp" + + "mobiilne andmeside" + "WiFi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-eu/strings.xml b/service/ServiceConnectivityResources/res/values-eu/strings.xml new file mode 100644 index 0000000000..dd70316f69 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-eu/strings.xml @@ -0,0 +1,39 @@ + + + + "Hasi saioa Wi-Fi sarean" + "Hasi saioa sarean" + + "Ezin da konektatu Internetera %1$s sarearen bidez" + "Sakatu aukerak ikusteko" + "Sare mugikorra ezin da konektatu Internetera" + "Sarea ezin da konektatu Internetera" + "Ezin da atzitu DNS zerbitzari pribatua" + "%1$s sareak konektagarritasun murriztua du" + "Sakatu hala ere konektatzeko" + "%1$s erabiltzen ari zara orain" + "%2$s Internetera konektatzeko gauza ez denean, %1$s erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu." + "%1$s erabiltzen ari zinen, baina %2$s erabiltzen ari zara orain" + "sare mota ezezaguna" + + "datu-konexioa" + "Wifia" + "Bluetooth-a" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-fa/strings.xml b/service/ServiceConnectivityResources/res/values-fa/strings.xml new file mode 100644 index 0000000000..46a946c50b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fa/strings.xml @@ -0,0 +1,39 @@ + + + + "‏ورود به شبکه Wi-Fi" + "ورود به سیستم شبکه" + + "%1$s به اینترنت دسترسی ندارد" + "برای گزینه‌ها ضربه بزنید" + "شبکه تلفن همراه به اینترنت دسترسی ندارد" + "شبکه به اینترنت دسترسی ندارد" + "‏سرور DNS خصوصی قابل دسترسی نیست" + "%1$s اتصال محدودی دارد" + "به‌هرصورت، برای اتصال ضربه بزنید" + "به %1$s تغییر کرد" + "وقتی %2$s به اینترنت دسترسی نداشته باشد، دستگاه از %1$s استفاده می‌کند. ممکن است هزینه‌هایی اعمال شود." + "از %1$s به %2$s تغییر کرد" + "نوع شبکه نامشخص" + + "داده تلفن همراه" + "Wi-Fi" + "بلوتوث" + "اترنت" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-fi/strings.xml b/service/ServiceConnectivityResources/res/values-fi/strings.xml new file mode 100644 index 0000000000..dd944415c9 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fi/strings.xml @@ -0,0 +1,39 @@ + + + + "Kirjaudu Wi-Fi-verkkoon" + "Kirjaudu verkkoon" + + "%1$s ei ole yhteydessä internetiin" + "Näytä vaihtoehdot napauttamalla." + "Mobiiliverkko ei ole yhteydessä internetiin" + "Verkko ei ole yhteydessä internetiin" + "Ei pääsyä yksityiselle DNS-palvelimelle" + "%1$s toimii rajoitetulla yhteydellä" + "Yhdistä napauttamalla" + "%1$s otettiin käyttöön" + "%1$s otetaan käyttöön, kun %2$s ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia." + "%1$s poistettiin käytöstä ja %2$s otettiin käyttöön." + "tuntematon verkon tyyppi" + + "mobiilidata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml b/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml new file mode 100644 index 0000000000..02ef50b2c1 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml @@ -0,0 +1,39 @@ + + + + "Connectez-vous au réseau Wi-Fi" + "Connectez-vous au réseau" + + "Le réseau %1$s n\'offre aucun accès à Internet" + "Touchez pour afficher les options" + "Le réseau cellulaire n\'offre aucun accès à Internet" + "Le réseau n\'offre aucun accès à Internet" + "Impossible d\'accéder au serveur DNS privé" + "Le réseau %1$s offre une connectivité limitée" + "Touchez pour vous connecter quand même" + "Passé au réseau %1$s" + "L\'appareil utilise %1$s quand %2$s n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer." + "Passé du réseau %1$s au %2$s" + "un type de réseau inconnu" + + "données cellulaires" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "RPV" + + diff --git a/service/ServiceConnectivityResources/res/values-fr/strings.xml b/service/ServiceConnectivityResources/res/values-fr/strings.xml new file mode 100644 index 0000000000..08c9d8157a --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-fr/strings.xml @@ -0,0 +1,39 @@ + + + + "Connectez-vous au réseau Wi-Fi" + "Se connecter au réseau" + + "Aucune connexion à Internet pour %1$s" + "Appuyez ici pour afficher des options." + "Le réseau mobile ne dispose d\'aucun accès à Internet" + "Le réseau ne dispose d\'aucun accès à Internet" + "Impossible d\'accéder au serveur DNS privé" + "La connectivité de %1$s est limitée" + "Appuyer pour se connecter quand même" + "Nouveau réseau : %1$s" + "L\'appareil utilise %1$s lorsque %2$s n\'a pas de connexion Internet. Des frais peuvent s\'appliquer." + "Ancien réseau : %1$s. Nouveau réseau : %2$s" + "type de réseau inconnu" + + "données mobiles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-gl/strings.xml b/service/ServiceConnectivityResources/res/values-gl/strings.xml new file mode 100644 index 0000000000..9f98055ab9 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-gl/strings.xml @@ -0,0 +1,39 @@ + + + + "Inicia sesión na rede wifi" + "Inicia sesión na rede" + + "%1$s non ten acceso a Internet" + "Toca para ver opcións." + "A rede de telefonía móbil non ten acceso a Internet" + "A rede non ten acceso a Internet" + "Non se puido acceder ao servidor DNS privado" + "A conectividade de %1$s é limitada" + "Toca para conectarte de todas formas" + "Cambiouse a: %1$s" + "O dispositivo utiliza %1$s cando %2$s non ten acceso a Internet. Pódense aplicar cargos." + "Cambiouse de %1$s a %2$s" + "un tipo de rede descoñecido" + + "datos móbiles" + "wifi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-gu/strings.xml b/service/ServiceConnectivityResources/res/values-gu/strings.xml new file mode 100644 index 0000000000..4ae5a2c45f --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-gu/strings.xml @@ -0,0 +1,39 @@ + + + + "વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો" + "નેટવર્ક પર સાઇન ઇન કરો" + + "%1$s ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "વિકલ્પો માટે ટૅપ કરો" + "મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી" + "%1$s મર્યાદિત કનેક્ટિવિટી ધરાવે છે" + "છતાં કનેક્ટ કરવા માટે ટૅપ કરો" + "%1$s પર સ્વિચ કર્યું" + "જ્યારે %2$s પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ %1$sનો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે." + "%1$s પરથી %2$s પર સ્વિચ કર્યું" + "અજાણ્યો નેટવર્ક પ્રકાર" + + "મોબાઇલ ડેટા" + "વાઇ-ફાઇ" + "બ્લૂટૂથ" + "ઇથરનેટ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-hi/strings.xml b/service/ServiceConnectivityResources/res/values-hi/strings.xml new file mode 100644 index 0000000000..eff1b600e4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hi/strings.xml @@ -0,0 +1,39 @@ + + + + "वाई-फ़ाई नेटवर्क में साइन इन करें" + "नेटवर्क में साइन इन करें" + + "%1$s का इंटरनेट नहीं चल रहा है" + "विकल्पों के लिए टैप करें" + "मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" + "इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" + "निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता" + "%1$s की कनेक्टिविटी सीमित है" + "फिर भी कनेक्ट करने के लिए टैप करें" + "%1$s पर ले जाया गया" + "%2$s में इंटरनेट की सुविधा नहीं होने पर डिवाइस %1$s का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है." + "%1$s से %2$s पर ले जाया गया" + "अज्ञात नेटवर्क प्रकार" + + "मोबाइल डेटा" + "वाई-फ़ाई" + "ब्लूटूथ" + "ईथरनेट" + "वीपीएन" + + diff --git a/service/ServiceConnectivityResources/res/values-hr/strings.xml b/service/ServiceConnectivityResources/res/values-hr/strings.xml new file mode 100644 index 0000000000..52bfb936ba --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hr/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijava na Wi-Fi mrežu" + "Prijava na mrežu" + + "%1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Nije moguće pristupiti privatnom DNS poslužitelju" + "%1$s ima ograničenu povezivost" + "Dodirnite da biste se ipak povezali" + "Prelazak na drugu mrežu: %1$s" + "Kada %2$s nema pristup internetu, na uređaju se upotrebljava %1$s. Moguća je naplata naknade." + "Mreža je promijenjena: %1$s > %2$s" + "nepoznata vrsta mreže" + + "mobilni podaci" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-hu/strings.xml b/service/ServiceConnectivityResources/res/values-hu/strings.xml new file mode 100644 index 0000000000..2ff59b5173 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hu/strings.xml @@ -0,0 +1,39 @@ + + + + "Bejelentkezés Wi-Fi hálózatba" + "Bejelentkezés a hálózatba" + + "A(z) %1$s hálózaton nincs internet-hozzáférés" + "Koppintson a beállítások megjelenítéséhez" + "A mobilhálózaton nincs internet-hozzáférés" + "A hálózaton nincs internet-hozzáférés" + "A privát DNS-kiszolgálóhoz nem lehet hozzáférni" + "A(z) %1$s hálózat korlátozott kapcsolatot biztosít" + "Koppintson, ha mindenképpen csatlakozni szeretne" + "Átváltva erre: %1$s" + "%1$s használata, ha nincs internet-hozzáférés %2$s-kapcsolaton keresztül. A szolgáltató díjat számíthat fel." + "Átváltva %1$s-hálózatról erre: %2$s" + "ismeretlen hálózati típus" + + "mobiladatok" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-hy/strings.xml b/service/ServiceConnectivityResources/res/values-hy/strings.xml new file mode 100644 index 0000000000..b35d31c7b6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-hy/strings.xml @@ -0,0 +1,39 @@ + + + + "Մուտք գործեք Wi-Fi ցանց" + "Մուտք գործեք ցանց" + + "%1$s ցանցը չունի մուտք ինտերնետին" + "Հպեք՝ ընտրանքները տեսնելու համար" + "Բջջային ցանցը չի ապահովում ինտերնետ կապ" + "Ցանցը միացված չէ ինտերնետին" + "Մասնավոր DNS սերվերն անհասանելի է" + "%1$s ցանցի կապը սահմանափակ է" + "Հպեք՝ միանալու համար" + "Անցել է %1$s ցանցի" + "Երբ %2$s ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է %1$s ցանցի: Նման դեպքում կարող են վճարներ գանձվել:" + "%1$s ցանցից անցել է %2$s ցանցի" + "ցանցի անհայտ տեսակ" + + "բջջային ինտերնետ" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-in/strings.xml b/service/ServiceConnectivityResources/res/values-in/strings.xml new file mode 100644 index 0000000000..27d7d89601 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-in/strings.xml @@ -0,0 +1,39 @@ + + + + "Login ke jaringan Wi-Fi" + "Login ke jaringan" + + "%1$s tidak memiliki akses internet" + "Ketuk untuk melihat opsi" + "Jaringan seluler tidak memiliki akses internet" + "Jaringan tidak memiliki akses internet" + "Server DNS pribadi tidak dapat diakses" + "%1$s memiliki konektivitas terbatas" + "Ketuk untuk tetap menyambungkan" + "Dialihkan ke %1$s" + "Perangkat menggunakan %1$s jika %2$s tidak memiliki akses internet. Tarif mungkin berlaku." + "Dialihkan dari %1$s ke %2$s" + "jenis jaringan yang tidak dikenal" + + "data seluler" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-is/strings.xml b/service/ServiceConnectivityResources/res/values-is/strings.xml new file mode 100644 index 0000000000..97f42dcf07 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-is/strings.xml @@ -0,0 +1,39 @@ + + + + "Skrá inn á Wi-Fi net" + "Skrá inn á net" + + "%1$s er ekki með internetaðgang" + "Ýttu til að sjá valkosti" + "Farsímakerfið er ekki tengt við internetið" + "Netkerfið er ekki tengt við internetið" + "Ekki næst í DNS-einkaþjón" + "Tengigeta %1$s er takmörkuð" + "Ýttu til að tengjast samt" + "Skipt yfir á %1$s" + "Tækið notar %1$s þegar %2$s er ekki með internetaðgang. Gjöld kunna að eiga við." + "Skipt úr %1$s yfir í %2$s" + "óþekkt tegund netkerfis" + + "farsímagögn" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-it/strings.xml b/service/ServiceConnectivityResources/res/values-it/strings.xml new file mode 100644 index 0000000000..7836101137 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-it/strings.xml @@ -0,0 +1,39 @@ + + + + "Accedi a rete Wi-Fi" + "Accedi alla rete" + + "%1$s non ha accesso a Internet" + "Tocca per le opzioni" + "La rete mobile non ha accesso a Internet" + "La rete non ha accesso a Internet" + "Non è possibile accedere al server DNS privato" + "%1$s ha una connettività limitata" + "Tocca per connettere comunque" + "Passato a %1$s" + "Il dispositivo utilizza %1$s quando %2$s non ha accesso a Internet. Potrebbero essere applicati costi." + "Passato da %1$s a %2$s" + "tipo di rete sconosciuto" + + "dati mobili" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-iw/strings.xml b/service/ServiceConnectivityResources/res/values-iw/strings.xml new file mode 100644 index 0000000000..f322b99547 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-iw/strings.xml @@ -0,0 +1,39 @@ + + + + "‏היכנס לרשת Wi-Fi" + "היכנס לרשת" + + "ל-%1$s אין גישה לאינטרנט" + "הקש לקבלת אפשרויות" + "לרשת הסלולרית אין גישה לאינטרנט" + "לרשת אין גישה לאינטרנט" + "‏לא ניתן לגשת לשרת DNS הפרטי" + "הקישוריות של %1$s מוגבלת" + "כדי להתחבר למרות זאת יש להקיש" + "מעבר אל %1$s" + "המכשיר משתמש ברשת %1$s כשלרשת %2$s אין גישה לאינטרנט. עשויים לחול חיובים." + "עבר מרשת %1$s לרשת %2$s" + "סוג רשת לא מזוהה" + + "חבילת גלישה" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ja/strings.xml b/service/ServiceConnectivityResources/res/values-ja/strings.xml new file mode 100644 index 0000000000..1aa3216fbc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ja/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fiネットワークにログイン" + "ネットワークにログインしてください" + + "%1$s はインターネットにアクセスできません" + "タップしてその他のオプションを表示" + "モバイル ネットワークがインターネットに接続されていません" + "ネットワークがインターネットに接続されていません" + "プライベート DNS サーバーにアクセスできません" + "%1$s の接続が制限されています" + "接続するにはタップしてください" + "「%1$s」に切り替えました" + "デバイスで「%2$s」によるインターネット接続ができない場合に「%1$s」を使用します。通信料が発生することがあります。" + "「%1$s」から「%2$s」に切り替えました" + "不明なネットワーク タイプ" + + "モバイルデータ" + "Wi-Fi" + "Bluetooth" + "イーサネット" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ka/strings.xml b/service/ServiceConnectivityResources/res/values-ka/strings.xml new file mode 100644 index 0000000000..61d21b55a0 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ka/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi ქსელთან დაკავშირება" + "ქსელში შესვლა" + + "%1$s-ს არ აქვს ინტერნეტზე წვდომა" + "შეეხეთ ვარიანტების სანახავად" + "მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა" + "ქსელს არ აქვს ინტერნეტზე წვდომა" + "პირად DNS სერვერზე წვდომა შეუძლებელია" + "%1$s-ის კავშირები შეზღუდულია" + "შეეხეთ, თუ მაინც გსურთ დაკავშირება" + "ახლა გამოიყენება %1$s" + "თუ %2$s ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ %1$s იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს." + "ახლა გამოიყენება %1$s (გამოიყენებოდა %2$s)" + "უცნობი ტიპის ქსელი" + + "მობილური ინტერნეტი" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-kk/strings.xml b/service/ServiceConnectivityResources/res/values-kk/strings.xml new file mode 100644 index 0000000000..969aaef522 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-kk/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi желісіне кіру" + "Желіге кіру" + + "%1$s желісінің интернетті пайдалану мүмкіндігі шектеулі." + "Опциялар үшін түртіңіз" + "Мобильдік желі интернетке қосылмаған." + "Желі интернетке қосылмаған." + "Жеке DNS серверіне кіру мүмкін емес." + "%1$s желісінің қосылу мүмкіндігі шектеулі." + "Бәрібір жалғау үшін түртіңіз." + "%1$s желісіне ауысты" + "Құрылғы %2$s желісінде интернетпен байланыс жоғалған жағдайда %1$s желісін пайдаланады. Деректер ақысы алынуы мүмкін." + "%1$s желісінен %2$s желісіне ауысты" + "желі түрі белгісіз" + + "мобильдік деректер" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-km/strings.xml b/service/ServiceConnectivityResources/res/values-km/strings.xml new file mode 100644 index 0000000000..da3c337860 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-km/strings.xml @@ -0,0 +1,39 @@ + + + + "ចូល​បណ្ដាញ​វ៉ាយហ្វាយ" + "ចូលទៅបណ្តាញ" + + "%1$s មិនមាន​ការតភ្ជាប់អ៊ីនធឺណិត​ទេ" + "ប៉ះសម្រាប់ជម្រើស" + "បណ្ដាញ​ទូរសព្ទ​ចល័ត​មិនមានការតភ្ជាប់​អ៊ីនធឺណិតទេ" + "បណ្ដាញ​មិនមាន​ការតភ្ជាប់​អ៊ីនធឺណិតទេ" + "មិនអាច​ចូលប្រើ​ម៉ាស៊ីនមេ DNS ឯកជន​បានទេ" + "%1$s មានការតភ្ជាប់​មានកម្រិត" + "មិន​អី​ទេ ចុច​​ភ្ជាប់​ចុះ" + "បានប្តូរទៅ %1$s" + "ឧបករណ៍​ប្រើ %1$s នៅ​ពេល​ដែល %2$s មិនមាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត។ អាច​គិតថ្លៃ​លើការ​ប្រើប្រាស់​ទិន្នន័យ។" + "បានប្តូរពី %1$s ទៅ %2$s" + "ប្រភេទបណ្តាញមិនស្គាល់" + + "ទិន្នន័យ​ទូរសព្ទចល័ត" + "Wi-Fi" + "ប៊្លូធូស" + "អ៊ីសឺរណិត" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-kn/strings.xml b/service/ServiceConnectivityResources/res/values-kn/strings.xml new file mode 100644 index 0000000000..3b5e047731 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-kn/strings.xml @@ -0,0 +1,39 @@ + + + + "ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" + "ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" + + "%1$s ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ" + "ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" + "ನೆಟ್‌ವರ್ಕ್‌ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" + "%1$s ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ" + "ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" + "%1$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" + "%2$s ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು %1$s ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು." + "%1$s ರಿಂದ %2$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" + "ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ" + + "ಮೊಬೈಲ್ ಡೇಟಾ" + "ವೈ-ಫೈ" + "ಬ್ಲೂಟೂತ್‌" + "ಇಥರ್ನೆಟ್" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ko/strings.xml b/service/ServiceConnectivityResources/res/values-ko/strings.xml new file mode 100644 index 0000000000..874bd75970 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ko/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi 네트워크에 로그인" + "네트워크에 로그인" + + "%1$s이(가) 인터넷에 액세스할 수 없습니다." + "탭하여 옵션 보기" + "모바일 네트워크에 인터넷이 연결되어 있지 않습니다." + "네트워크에 인터넷이 연결되어 있지 않습니다." + "비공개 DNS 서버에 액세스할 수 없습니다." + "%1$s에서 연결을 제한했습니다." + "계속 연결하려면 탭하세요." + "%1$s(으)로 전환" + "%2$s(으)로 인터넷에 연결할 수 없는 경우 기기에서 %1$s이(가) 사용됩니다. 요금이 부과될 수 있습니다." + "%1$s에서 %2$s(으)로 전환" + "알 수 없는 네트워크 유형" + + "모바일 데이터" + "Wi-Fi" + "블루투스" + "이더넷" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ky/strings.xml b/service/ServiceConnectivityResources/res/values-ky/strings.xml new file mode 100644 index 0000000000..1ace4dc8ec --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ky/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi түйүнүнө кирүү" + "Тармакка кирүү" + + "%1$s Интернетке туташуусу жок" + "Параметрлерди ачуу үчүн таптап коюңуз" + "Мобилдик Интернет жок" + "Тармактын Интернет жок" + "Жеке DNS сервери жеткиликсиз" + "%1$s байланышы чектелген" + "Баары бир туташуу үчүн таптаңыз" + "%1$s тармагына которуштурулду" + "%2$s тармагы Интернетке туташпай турганда, түзмөгүңүз %1$s тармагын колдонот. Акы алынышы мүмкүн." + "%1$s дегенден %2$s тармагына которуштурулду" + "белгисиз тармак түрү" + + "мобилдик трафик" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-lo/strings.xml b/service/ServiceConnectivityResources/res/values-lo/strings.xml new file mode 100644 index 0000000000..3db497ef45 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-lo/strings.xml @@ -0,0 +1,39 @@ + + + + "ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi" + "ລົງຊື່ເຂົ້າເຄືອຂ່າຍ" + + "%1$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ" + "ແຕະເພື່ອເບິ່ງຕົວເລືອກ" + "ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" + "ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" + "ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້" + "%1$s ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ" + "ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່" + "ສະຫຼັບໄປໃຊ້ %1$s ແລ້ວ" + "ອຸປະກອນຈະໃຊ້ %1$s ເມື່ອ %2$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ." + "ສະຫຼັບຈາກ %1$s ໄປໃຊ້ %2$s ແລ້ວ" + "ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ" + + "ອິນເຕີເນັດມືຖື" + "Wi-Fi" + "Bluetooth" + "ອີເທີເນັດ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-lt/strings.xml b/service/ServiceConnectivityResources/res/values-lt/strings.xml new file mode 100644 index 0000000000..c639c1f1a5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-lt/strings.xml @@ -0,0 +1,39 @@ + + + + "Prisijungti prie „Wi-Fi“ tinklo" + "Prisijungti prie tinklo" + + "„%1$s“ negali pasiekti interneto" + "Palieskite, kad būtų rodomos parinktys." + "Mobiliojo ryšio tinkle nėra prieigos prie interneto" + "Tinkle nėra prieigos prie interneto" + "Privataus DNS serverio negalima pasiekti" + "„%1$s“ ryšys apribotas" + "Palieskite, jei vis tiek norite prisijungti" + "Perjungta į tinklą %1$s" + "Įrenginyje naudojamas kitas tinklas (%1$s), kai dabartiniame tinkle (%2$s) nėra interneto ryšio. Gali būti taikomi mokesčiai." + "Perjungta iš tinklo %1$s į tinklą %2$s" + "nežinomas tinklo tipas" + + "mobiliojo ryšio duomenys" + "Wi-Fi" + "Bluetooth" + "Eternetas" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-lv/strings.xml b/service/ServiceConnectivityResources/res/values-lv/strings.xml new file mode 100644 index 0000000000..5774603bf5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-lv/strings.xml @@ -0,0 +1,39 @@ + + + + "Pierakstieties Wi-Fi tīklā" + "Pierakstīšanās tīklā" + + "Tīklā %1$s nav piekļuves internetam" + "Pieskarieties, lai skatītu iespējas." + "Mobilajā tīklā nav piekļuves internetam." + "Tīklā nav piekļuves internetam." + "Nevar piekļūt privātam DNS serverim." + "Tīklā %1$s ir ierobežota savienojamība" + "Lai tik un tā izveidotu savienojumu, pieskarieties" + "Pārslēdzās uz tīklu %1$s" + "Kad vienā tīklā (%2$s) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (%1$s). Var tikt piemērota maksa." + "Pārslēdzās no tīkla %1$s uz tīklu %2$s" + "nezināms tīkla veids" + + "mobilie dati" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-mk/strings.xml b/service/ServiceConnectivityResources/res/values-mk/strings.xml new file mode 100644 index 0000000000..053c7cf93b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mk/strings.xml @@ -0,0 +1,39 @@ + + + + "Најавете се на мрежа на Wi-Fi" + "Најавете се на мрежа" + + "%1$s нема интернет-пристап" + "Допрете за опции" + "Мобилната мрежа нема интернет-пристап" + "Мрежата нема интернет-пристап" + "Не може да се пристапи до приватниот DNS-сервер" + "%1$s има ограничена поврзливост" + "Допрете за да се поврзете и покрај тоа" + "Префрлено на %1$s" + "Уредот користи %1$s кога %2$s нема пристап до интернет. Може да се наплатат трошоци." + "Префрлено од %1$s на %2$s" + "непознат тип мрежа" + + "мобилен интернет" + "Wi-Fi" + "Bluetooth" + "Етернет" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ml/strings.xml b/service/ServiceConnectivityResources/res/values-ml/strings.xml new file mode 100644 index 0000000000..3e80cf1cd7 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ml/strings.xml @@ -0,0 +1,39 @@ + + + + "വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" + "നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" + + "%1$s എന്നതിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക" + "മൊബെെൽ നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "സ്വകാര്യ DNS സെർവർ ആക്‌സസ് ചെയ്യാനാവില്ല" + "%1$s എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്" + "ഏതുവിധേനയും കണക്‌റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക" + "%1$s എന്നതിലേക്ക് മാറി" + "%2$s-ന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം %1$s ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം." + "%1$s നെറ്റ്‌വർക്കിൽ നിന്ന് %2$s നെറ്റ്‌വർക്കിലേക്ക് മാറി" + "തിരിച്ചറിയാനാകാത്ത ഒരു നെറ്റ്‌വർക്ക് തരം" + + "മൊബൈൽ ഡാറ്റ" + "വൈഫൈ" + "Bluetooth" + "ഇതര്‍നെറ്റ്" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-mn/strings.xml b/service/ServiceConnectivityResources/res/values-mn/strings.xml new file mode 100644 index 0000000000..214fc0c1dd --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mn/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi сүлжээнд нэвтэрнэ үү" + "Сүлжээнд нэвтэрнэ үү" + + "%1$s-д интернэтийн хандалт алга" + "Сонголт хийхийн тулд товшино уу" + "Мобайл сүлжээнд интернэт хандалт байхгүй байна" + "Сүлжээнд интернэт хандалт байхгүй байна" + "Хувийн DNS серверт хандах боломжгүй байна" + "%1$s зарим үйлчилгээнд хандах боломжгүй байна" + "Ямар ч тохиолдолд холбогдохын тулд товших" + "%1$s руу шилжүүлсэн" + "%2$s интернет холболтгүй үед төхөөрөмж %1$s-г ашигладаг. Төлбөр гарч болзошгүй." + "%1$s%2$s руу шилжүүлсэн" + "сүлжээний тодорхойгүй төрөл" + + "мобайл дата" + "Wi-Fi" + "Bluetooth" + "Этернэт" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-mr/strings.xml b/service/ServiceConnectivityResources/res/values-mr/strings.xml new file mode 100644 index 0000000000..c4b19989fc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mr/strings.xml @@ -0,0 +1,39 @@ + + + + "वाय-फाय नेटवर्कमध्‍ये साइन इन करा" + "नेटवर्कवर साइन इन करा" + + "%1$s ला इंटरनेट अ‍ॅक्सेस नाही" + "पर्यायांसाठी टॅप करा" + "मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही" + "नेटवर्कला इंटरनेट ॲक्सेस नाही" + "खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही" + "%1$s ला मर्यादित कनेक्टिव्हिटी आहे" + "तरीही कनेक्ट करण्यासाठी टॅप करा" + "%1$s वर स्विच केले" + "%2$s कडे इंटरनेटचा अ‍ॅक्सेस नसताना डिव्हाइस %1$s वापरते. शुल्क लागू शकते." + "%1$s वरून %2$s वर स्विच केले" + "अज्ञात नेटवर्क प्रकार" + + "मोबाइल डेटा" + "वाय-फाय" + "ब्लूटूथ" + "इथरनेट" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ms/strings.xml b/service/ServiceConnectivityResources/res/values-ms/strings.xml new file mode 100644 index 0000000000..529d0bd466 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ms/strings.xml @@ -0,0 +1,39 @@ + + + + "Log masuk ke rangkaian Wi-Fi" + "Log masuk ke rangkaian" + + "%1$s tiada akses Internet" + "Ketik untuk mendapatkan pilihan" + "Rangkaian mudah alih tiada akses Internet" + "Rangkaian tiada akses Internet" + "Pelayan DNS peribadi tidak boleh diakses" + "%1$s mempunyai kesambungan terhad" + "Ketik untuk menyambung juga" + "Beralih kepada %1$s" + "Peranti menggunakan %1$s apabila %2$s tiada akses Internet. Bayaran mungkin dikenakan." + "Beralih daripada %1$s kepada %2$s" + "jenis rangkaian tidak diketahui" + + "data mudah alih" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-my/strings.xml b/service/ServiceConnectivityResources/res/values-my/strings.xml new file mode 100644 index 0000000000..50590fa3fc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-my/strings.xml @@ -0,0 +1,39 @@ + + + + "ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ" + "ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်" + + "%1$s တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" + "အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ" + "မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ" + "ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" + "သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။" + "%1$s တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်" + "မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ" + "%1$s သို့ ပြောင်းလိုက်ပြီ" + "%2$s ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် %1$s ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။" + "%1$s မှ %2$s သို့ ပြောင်းလိုက်ပြီ" + "အမည်မသိကွန်ရက်အမျိုးအစား" + + "မိုဘိုင်းဒေတာ" + "Wi-Fi" + "ဘလူးတုသ်" + "အီသာနက်" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-nb/strings.xml b/service/ServiceConnectivityResources/res/values-nb/strings.xml new file mode 100644 index 0000000000..b89d198f38 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-nb/strings.xml @@ -0,0 +1,39 @@ + + + + "Logg på Wi-Fi-nettverket" + "Logg på nettverk" + + "%1$s har ingen internettilkobling" + "Trykk for å få alternativer" + "Mobilnettverket har ingen internettilgang" + "Nettverket har ingen internettilgang" + "Den private DNS-tjeneren kan ikke nås" + "%1$s har begrenset tilkobling" + "Trykk for å koble til likevel" + "Byttet til %1$s" + "Enheten bruker %1$s når %2$s ikke har Internett-tilgang. Avgifter kan påløpe." + "Byttet fra %1$s til %2$s" + "en ukjent nettverkstype" + + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ne/strings.xml b/service/ServiceConnectivityResources/res/values-ne/strings.xml new file mode 100644 index 0000000000..bdcfa3bfc4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ne/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्" + "सञ्जालमा साइन इन गर्नुहोस्" + + "%1$s को इन्टरनेटमाथि पहुँच छैन" + "विकल्पहरूका लागि ट्याप गर्नुहोस्" + "मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन" + "नेटवर्कको इन्टरनेटमाथि पहुँच छैन" + "निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन" + "%1$s को जडान सीमित छ" + "जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्" + "%1$s मा बदल्नुहोस्" + "%2$s मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले %1$s प्रयोग गर्दछ। शुल्क लाग्न सक्छ।" + "%1$s बाट %2$s मा परिवर्तन गरियो" + "नेटवर्कको कुनै अज्ञात प्रकार" + + "मोबाइल डेटा" + "Wi-Fi" + "ब्लुटुथ" + "इथरनेट" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-nl/strings.xml b/service/ServiceConnectivityResources/res/values-nl/strings.xml new file mode 100644 index 0000000000..8ecff6e3b5 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-nl/strings.xml @@ -0,0 +1,39 @@ + + + + "Inloggen bij wifi-netwerk" + "Inloggen bij netwerk" + + "%1$s heeft geen internettoegang" + "Tik voor opties" + "Mobiel netwerk heeft geen internettoegang" + "Netwerk heeft geen internettoegang" + "Geen toegang tot privé-DNS-server" + "%1$s heeft beperkte connectiviteit" + "Tik om toch verbinding te maken" + "Overgeschakeld naar %1$s" + "Apparaat gebruikt %1$s wanneer %2$s geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht." + "Overgeschakeld van %1$s naar %2$s" + "een onbekend netwerktype" + + "mobiele data" + "Wifi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-or/strings.xml b/service/ServiceConnectivityResources/res/values-or/strings.xml new file mode 100644 index 0000000000..6ec1f9d3e4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-or/strings.xml @@ -0,0 +1,39 @@ + + + + "ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍‍-ଇନ୍‍ କରନ୍ତୁ" + "ନେଟ୍‌ୱର୍କରେ ସାଇନ୍‍ ଇନ୍‍ କରନ୍ତୁ" + + "%1$sର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ବିକଳ୍ପ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ" + "ମୋବାଇଲ୍ ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ" + "%1$sର ସୀମିତ ସଂଯୋଗ ଅଛି" + "ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ" + "%1$sକୁ ବଦଳାଗଲା" + "%2$sର ଇଣ୍ଟରନେଟ୍‍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍‍ %1$s ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।" + "%1$s ରୁ %2$sକୁ ବଦଳାଗଲା" + "ଏକ ଅଜଣା ନେଟ୍‌ୱର୍କ ପ୍ରକାର" + + "ମୋବାଇଲ୍‌ ଡାଟା" + "ୱାଇ-ଫାଇ" + "ବ୍ଲୁଟୁଥ" + "ଇଥରନେଟ୍‌" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pa/strings.xml b/service/ServiceConnectivityResources/res/values-pa/strings.xml new file mode 100644 index 0000000000..e9481932d6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pa/strings.xml @@ -0,0 +1,39 @@ + + + + "ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" + "ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" + + "%1$s ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ" + "ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ" + "%1$s ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ" + "ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" + "ਬਦਲਕੇ %1$s ਲਿਆਂਦਾ ਗਿਆ" + "%2$s ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ %1$s ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।" + "%1$s ਤੋਂ ਬਦਲਕੇ %2$s \'ਤੇ ਕੀਤਾ ਗਿਆ" + "ਇੱਕ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਕਿਸਮ" + + "ਮੋਬਾਈਲ ਡਾਟਾ" + "ਵਾਈ-ਫਾਈ" + "ਬਲੂਟੁੱਥ" + "ਈਥਰਨੈੱਟ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pl/strings.xml b/service/ServiceConnectivityResources/res/values-pl/strings.xml new file mode 100644 index 0000000000..038328f0fc --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pl/strings.xml @@ -0,0 +1,39 @@ + + + + "Zaloguj się w sieci Wi-Fi" + "Zaloguj się do sieci" + + "%1$s nie ma dostępu do internetu" + "Kliknij, by wyświetlić opcje" + "Sieć komórkowa nie ma dostępu do internetu" + "Sieć nie ma dostępu do internetu" + "Brak dostępu do prywatnego serwera DNS" + "%1$s ma ograniczoną łączność" + "Kliknij, by mimo to nawiązać połączenie" + "Zmieniono na połączenie typu %1$s" + "Urządzenie korzysta z połączenia typu %1$s, gdy %2$s nie dostępu do internetu. Mogą zostać naliczone opłaty." + "Przełączono z połączenia typu %1$s na %2$s." + "nieznany typ sieci" + + "mobilna transmisja danych" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml b/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..fe37405ebe --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml @@ -0,0 +1,39 @@ + + + + "Fazer login na rede Wi-Fi" + "Fazer login na rede" + + "%1$s não tem acesso à Internet" + "Toque para ver opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível acessar o servidor DNS privado" + "%1$s tem conectividade limitada" + "Toque para conectar mesmo assim" + "Alternado para %1$s" + "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." + "Alternado de %1$s para %2$s" + "um tipo de rede desconhecido" + + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml b/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..69060f7266 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml @@ -0,0 +1,39 @@ + + + + "Iniciar sessão na rede Wi-Fi" + "Início de sessão na rede" + + "%1$s não tem acesso à Internet" + "Toque para obter mais opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível aceder ao servidor DNS." + "%1$s tem conetividade limitada." + "Toque para ligar mesmo assim." + "Mudou para %1$s" + "O dispositivo utiliza %1$s quando %2$s não tem acesso à Internet. Podem aplicar-se custos." + "Mudou de %1$s para %2$s" + "um tipo de rede desconhecido" + + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-pt/strings.xml b/service/ServiceConnectivityResources/res/values-pt/strings.xml new file mode 100644 index 0000000000..fe37405ebe --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-pt/strings.xml @@ -0,0 +1,39 @@ + + + + "Fazer login na rede Wi-Fi" + "Fazer login na rede" + + "%1$s não tem acesso à Internet" + "Toque para ver opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível acessar o servidor DNS privado" + "%1$s tem conectividade limitada" + "Toque para conectar mesmo assim" + "Alternado para %1$s" + "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." + "Alternado de %1$s para %2$s" + "um tipo de rede desconhecido" + + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ro/strings.xml b/service/ServiceConnectivityResources/res/values-ro/strings.xml new file mode 100644 index 0000000000..227b7bed70 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ro/strings.xml @@ -0,0 +1,39 @@ + + + + "Conectați-vă la rețeaua Wi-Fi" + "Conectați-vă la rețea" + + "%1$s nu are acces la internet" + "Atingeți pentru opțiuni" + "Rețeaua mobilă nu are acces la internet" + "Rețeaua nu are acces la internet" + "Serverul DNS privat nu poate fi accesat" + "%1$s are conectivitate limitată" + "Atingeți pentru a vă conecta oricum" + "S-a comutat la %1$s" + "Dispozitivul folosește %1$s când %2$s nu are acces la internet. Se pot aplica taxe." + "S-a comutat de la %1$s la %2$s" + "un tip de rețea necunoscut" + + "date mobile" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ru/strings.xml b/service/ServiceConnectivityResources/res/values-ru/strings.xml new file mode 100644 index 0000000000..18acf81537 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ru/strings.xml @@ -0,0 +1,39 @@ + + + + "Подключение к Wi-Fi" + "Регистрация в сети" + + "Сеть \"%1$s\" не подключена к Интернету" + "Нажмите, чтобы показать варианты." + "Мобильная сеть не подключена к Интернету" + "Сеть не подключена к Интернету" + "Доступа к частному DNS-серверу нет." + "Подключение к сети \"%1$s\" ограничено" + "Нажмите, чтобы подключиться" + "Новое подключение: %1$s" + "Устройство использует %1$s, если подключение к сети %2$s недоступно. Может взиматься плата за передачу данных." + "Устройство отключено от сети %2$s и теперь использует %1$s" + "неизвестный тип сети" + + "мобильный Интернет" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-si/strings.xml b/service/ServiceConnectivityResources/res/values-si/strings.xml new file mode 100644 index 0000000000..6307c2b01b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-si/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi ජාලයට පුරනය වන්න" + "ජාලයට පුරනය වන්න" + + "%1$s හට අන්තර්ජාල ප්‍රවේශය නැත" + "විකල්ප සඳහා තට්ටු කරන්න" + "ජංගම ජාලවලට අන්තර්ජාල ප්‍රවේශය නැත" + "ජාලයට අන්තර්ජාල ප්‍රවේශය නැත" + "පුද්ගලික DNS සේවාදායකයට ප්‍රවේශ වීමට නොහැකිය" + "%1$s හට සීමිත සබැඳුම් හැකියාවක් ඇත" + "කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න" + "%1$s වෙත මාරු විය" + "උපාංගය %1$s %2$s සඳහා අන්තර්ජාල ප්‍රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය." + "%1$s සිට %2$s වෙත මාරු විය" + "නොදන්නා ජාල වර්ගයකි" + + "ජංගම දත්ත" + "Wi-Fi" + "බ්ලූටූත්" + "ඊතර්නෙට්" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sk/strings.xml b/service/ServiceConnectivityResources/res/values-sk/strings.xml new file mode 100644 index 0000000000..e894fefcf4 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sk/strings.xml @@ -0,0 +1,39 @@ + + + + "Prihlásiť sa do siete Wi‑Fi" + "Prihlásenie do siete" + + "%1$s nemá prístup k internetu" + "Klepnutím získate možnosti" + "Mobilná sieť nemá prístup k internetu" + "Sieť nemá prístup k internetu" + "K súkromnému serveru DNS sa nepodarilo získať prístup" + "%1$s má obmedzené pripojenie" + "Ak sa chcete aj napriek tomu pripojiť, klepnite" + "Prepnuté na sieť: %1$s" + "Keď %2$s nemá prístup k internetu, zariadenie používa %1$s. Môžu sa účtovať poplatky." + "Prepnuté zo siete %1$s na sieť %2$s" + "neznámy typ siete" + + "mobilné dáta" + "Wi‑Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sl/strings.xml b/service/ServiceConnectivityResources/res/values-sl/strings.xml new file mode 100644 index 0000000000..954b32480e --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sl/strings.xml @@ -0,0 +1,39 @@ + + + + "Prijavite se v omrežje Wi-Fi" + "Prijava v omrežje" + + "Omrežje %1$s nima dostopa do interneta" + "Dotaknite se za možnosti" + "Mobilno omrežje nima dostopa do interneta" + "Omrežje nima dostopa do interneta" + "Do zasebnega strežnika DNS ni mogoče dostopati" + "Povezljivost omrežja %1$s je omejena" + "Dotaknite se, da kljub temu vzpostavite povezavo" + "Preklopljeno na omrežje vrste %1$s" + "Naprava uporabi omrežje vrste %1$s, ko omrežje vrste %2$s nima dostopa do interneta. Prenos podatkov se lahko zaračuna." + "Preklopljeno z omrežja vrste %1$s na omrežje vrste %2$s" + "neznana vrsta omrežja" + + "prenos podatkov v mobilnem omrežju" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sq/strings.xml b/service/ServiceConnectivityResources/res/values-sq/strings.xml new file mode 100644 index 0000000000..bd5d052034 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sq/strings.xml @@ -0,0 +1,39 @@ + + + + "Identifikohu në rrjetin Wi-Fi" + "Identifikohu në rrjet" + + "%1$s nuk ka qasje në internet" + "Trokit për opsionet" + "Rrjeti celular nuk ka qasje në internet" + "Rrjeti nuk ka qasje në internet" + "Serveri privat DNS nuk mund të qaset" + "%1$s ka lidhshmëri të kufizuar" + "Trokit për t\'u lidhur gjithsesi" + "Kaloi te %1$s" + "Pajisja përdor %1$s kur %2$s nuk ka qasje në internet. Mund të zbatohen tarifa." + "Kaloi nga %1$s te %2$s" + "një lloj rrjeti i panjohur" + + "të dhënat celulare" + "Wi-Fi" + "Bluetooth" + "Eternet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sr/strings.xml b/service/ServiceConnectivityResources/res/values-sr/strings.xml new file mode 100644 index 0000000000..8bedbffec9 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sr/strings.xml @@ -0,0 +1,39 @@ + + + + "Пријављивање на WiFi мрежу" + "Пријавите се на мрежу" + + "%1$s нема приступ интернету" + "Додирните за опције" + "Мобилна мрежа нема приступ интернету" + "Мрежа нема приступ интернету" + "Приступ приватном DNS серверу није успео" + "%1$s има ограничену везу" + "Додирните да бисте се ипак повезали" + "Прешли сте на тип мреже %1$s" + "Уређај користи тип мреже %1$s када тип мреже %2$s нема приступ интернету. Можда ће се наплаћивати трошкови." + "Прешли сте са типа мреже %1$s на тип мреже %2$s" + "непознат тип мреже" + + "мобилни подаци" + "WiFi" + "Bluetooth" + "Етернет" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sv/strings.xml b/service/ServiceConnectivityResources/res/values-sv/strings.xml new file mode 100644 index 0000000000..b3f1763043 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sv/strings.xml @@ -0,0 +1,39 @@ + + + + "Logga in på ett Wi-Fi-nätverk" + "Logga in på nätverket" + + "%1$s har ingen internetanslutning" + "Tryck för alternativ" + "Mobilnätverket har ingen internetanslutning" + "Nätverket har ingen internetanslutning" + "Det går inte att komma åt den privata DNS-servern." + "%1$s har begränsad anslutning" + "Tryck för att ansluta ändå" + "Byte av nätverk till %1$s" + "%1$s används på enheten när det inte finns internetåtkomst via %2$s. Avgifter kan tillkomma." + "Byte av nätverk från %1$s till %2$s" + "en okänd nätverkstyp" + + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-sw/strings.xml b/service/ServiceConnectivityResources/res/values-sw/strings.xml new file mode 100644 index 0000000000..9674654c69 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-sw/strings.xml @@ -0,0 +1,39 @@ + + + + "Ingia kwa mtandao wa Wi-Fi" + "Ingia katika mtandao" + + "%1$s haina uwezo wa kufikia intaneti" + "Gusa ili upate chaguo" + "Mtandao wa simu hauna uwezo wa kufikia intaneti" + "Mtandao hauna uwezo wa kufikia intaneti" + "Seva ya faragha ya DNS haiwezi kufikiwa" + "%1$s ina muunganisho unaofikia huduma chache." + "Gusa ili uunganishe tu" + "Sasa inatumia %1$s" + "Kifaa hutumia %1$s wakati %2$s haina intaneti. Huenda ukalipishwa." + "Imebadilisha mtandao kutoka %1$s na sasa inatumia %2$s" + "aina ya mtandao isiyojulikana" + + "data ya simu" + "Wi-Fi" + "Bluetooth" + "Ethaneti" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ta/strings.xml b/service/ServiceConnectivityResources/res/values-ta/strings.xml new file mode 100644 index 0000000000..12604cbf1c --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ta/strings.xml @@ -0,0 +1,39 @@ + + + + "வைஃபை நெட்வொர்க்கில் உள்நுழையவும்" + "நெட்வொர்க்கில் உள்நுழையவும்" + + "%1$s நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "விருப்பங்களுக்கு, தட்டவும்" + "மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது" + "%1$s வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது" + "எப்படியேனும் இணைப்பதற்குத் தட்டவும்" + "%1$sக்கு மாற்றப்பட்டது" + "%2$s நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது %1$s நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்." + "%1$s இலிருந்து %2$sக்கு மாற்றப்பட்டது" + "தெரியாத நெட்வொர்க் வகை" + + "மொபைல் டேட்டா" + "வைஃபை" + "புளூடூத்" + "ஈத்தர்நெட்" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-te/strings.xml b/service/ServiceConnectivityResources/res/values-te/strings.xml new file mode 100644 index 0000000000..84a8640b07 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-te/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" + "నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" + + "%1$sకి ఇంటర్నెట్ యాక్సెస్ లేదు" + "ఎంపికల కోసం నొక్కండి" + "మొబైల్ నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "ప్రైవేట్ DNS సర్వర్‌ను యాక్సెస్ చేయడం సాధ్యపడదు" + "%1$s పరిమిత కనెక్టివిటీని కలిగి ఉంది" + "ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి" + "%1$sకి మార్చబడింది" + "పరికరం %2$sకి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు %1$sని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు." + "%1$s నుండి %2$sకి మార్చబడింది" + "తెలియని నెట్‌వర్క్ రకం" + + "మొబైల్ డేటా" + "Wi-Fi" + "బ్లూటూత్" + "ఈథర్‌నెట్" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-th/strings.xml b/service/ServiceConnectivityResources/res/values-th/strings.xml new file mode 100644 index 0000000000..1616e5151d --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-th/strings.xml @@ -0,0 +1,39 @@ + + + + "ลงชื่อเข้าใช้เครือข่าย WiFi" + "ลงชื่อเข้าใช้เครือข่าย" + + "%1$s เข้าถึงอินเทอร์เน็ตไม่ได้" + "แตะเพื่อดูตัวเลือก" + "เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต" + "เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต" + "เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้" + "%1$s มีการเชื่อมต่อจำกัด" + "แตะเพื่อเชื่อมต่อ" + "เปลี่ยนเป็น %1$s" + "อุปกรณ์จะใช้ %1$s เมื่อ %2$s เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ" + "เปลี่ยนจาก %1$s เป็น %2$s" + "ประเภทเครือข่ายที่ไม่รู้จัก" + + "เน็ตมือถือ" + "Wi-Fi" + "บลูทูธ" + "อีเทอร์เน็ต" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-tl/strings.xml b/service/ServiceConnectivityResources/res/values-tl/strings.xml new file mode 100644 index 0000000000..3bf1ce494a --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-tl/strings.xml @@ -0,0 +1,39 @@ + + + + "Mag-sign in sa Wi-Fi network" + "Mag-sign in sa network" + + "Walang access sa internet ang %1$s" + "I-tap para sa mga opsyon" + "Walang access sa internet ang mobile network" + "Walang access sa internet ang network" + "Hindi ma-access ang pribadong DNS server" + "Limitado ang koneksyon ng %1$s" + "I-tap para kumonekta pa rin" + "Lumipat sa %1$s" + "Ginagamit ng device ang %1$s kapag walang access sa internet ang %2$s. Maaaring may mga malapat na singilin." + "Lumipat sa %2$s mula sa %1$s" + "isang hindi kilalang uri ng network" + + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-tr/strings.xml b/service/ServiceConnectivityResources/res/values-tr/strings.xml new file mode 100644 index 0000000000..5c326e5eee --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-tr/strings.xml @@ -0,0 +1,39 @@ + + + + "Kablosuz ağda oturum açın" + "Ağda oturum açın" + + "%1$s ağının internet bağlantısı yok" + "Seçenekler için dokunun" + "Mobil ağın internet bağlantısı yok" + "Ağın internet bağlantısı yok" + "Gizli DNS sunucusuna erişilemiyor" + "%1$s sınırlı bağlantıya sahip" + "Yine de bağlanmak için dokunun" + "%1$s ağına geçildi" + "%2$s ağının internet erişimi olmadığında cihaz %1$s ağını kullanır. Bunun için ödeme alınabilir." + "%1$s ağından %2$s ağına geçildi" + "bilinmeyen ağ türü" + + "mobil veri" + "Kablosuz" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-uk/strings.xml b/service/ServiceConnectivityResources/res/values-uk/strings.xml new file mode 100644 index 0000000000..d1382da924 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-uk/strings.xml @@ -0,0 +1,39 @@ + + + + "Вхід у мережу Wi-Fi" + "Вхід у мережу" + + "Мережа %1$s не має доступу до Інтернету" + "Торкніться, щоб відкрити опції" + "Мобільна мережа не має доступу до Інтернету" + "Мережа не має доступу до Інтернету" + "Немає доступу до приватного DNS-сервера" + "Підключення до мережі %1$s обмежено" + "Натисніть, щоб усе одно підключитися" + "Пристрій перейшов на мережу %1$s" + "Коли мережа %2$s не має доступу до Інтернету, використовується %1$s. Може стягуватися плата." + "Пристрій перейшов з мережі %1$s на мережу %2$s" + "невідомий тип мережі" + + "мобільне передавання даних" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "Мережа VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-ur/strings.xml b/service/ServiceConnectivityResources/res/values-ur/strings.xml new file mode 100644 index 0000000000..3c031ad318 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-ur/strings.xml @@ -0,0 +1,39 @@ + + + + "‏Wi-Fi نیٹ ورک میں سائن ان کریں" + "نیٹ ورک میں سائن ان کریں" + + "%1$s کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "اختیارات کیلئے تھپتھپائیں" + "موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "‏نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی" + "%1$s کی کنیکٹوٹی محدود ہے" + "بہر حال منسلک کرنے کے لیے تھپتھپائیں" + "%1$s پر سوئچ ہو گیا" + "جب %2$s کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ %1$s کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔" + "%1$s سے %2$s پر سوئچ ہو گیا" + "نیٹ ورک کی نامعلوم قسم" + + "موبائل ڈیٹا" + "Wi-Fi" + "بلوٹوتھ" + "ایتھرنیٹ" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-uz/strings.xml b/service/ServiceConnectivityResources/res/values-uz/strings.xml new file mode 100644 index 0000000000..7518db3a7b --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-uz/strings.xml @@ -0,0 +1,39 @@ + + + + "Wi-Fi tarmoqqa kirish" + "Tarmoqqa kirish" + + "%1$s nomli tarmoqda internetga ruxsati yoʻq" + "Variantlarni ko‘rsatish uchun bosing" + "Mobil tarmoq internetga ulanmagan" + "Tarmoq internetga ulanmagan" + "Xususiy DNS server ishlamayapti" + "%1$s nomli tarmoqda aloqa cheklangan" + "Baribir ulash uchun bosing" + "Yangi ulanish: %1$s" + "Agar %2$s tarmoqda internet uzilsa, qurilma %1$sga ulanadi. Sarflangan trafik uchun haq olinishi mumkin." + "%1$s tarmog‘idan %2$s tarmog‘iga o‘tildi" + "noma’lum tarmoq turi" + + "mobil internet" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-vi/strings.xml b/service/ServiceConnectivityResources/res/values-vi/strings.xml new file mode 100644 index 0000000000..d2284d4905 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-vi/strings.xml @@ -0,0 +1,39 @@ + + + + "Đăng nhập vào mạng Wi-Fi" + "Đăng nhập vào mạng" + + "%1$s không có quyền truy cập Internet" + "Nhấn để biết tùy chọn" + "Mạng di động không có quyền truy cập Internet" + "Mạng không có quyền truy cập Internet" + "Không thể truy cập máy chủ DNS riêng tư" + "%1$s có khả năng kết nối giới hạn" + "Nhấn để tiếp tục kết nối" + "Đã chuyển sang %1$s" + "Thiết bị sử dụng %1$s khi %2$s không có quyền truy cập Internet. Bạn có thể phải trả phí." + "Đã chuyển từ %1$s sang %2$s" + "loại mạng không xác định" + + "dữ liệu di động" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..813482b499 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml @@ -0,0 +1,39 @@ + + + + "登录到WLAN网络" + "登录到网络" + + "%1$s 无法访问互联网" + "点按即可查看相关选项" + "此移动网络无法访问互联网" + "此网络无法访问互联网" + "无法访问私人 DNS 服务器" + "%1$s 的连接受限" + "点按即可继续连接" + "已切换至%1$s" + "设备会在%2$s无法访问互联网时使用%1$s(可能需要支付相应的费用)。" + "已从%1$s切换至%2$s" + "未知网络类型" + + "移动数据" + "WLAN" + "蓝牙" + "以太网" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml new file mode 100644 index 0000000000..676404fe2c --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml @@ -0,0 +1,39 @@ + + + + "登入 Wi-Fi 網絡" + "登入網絡" + + "%1$s未有連接至互聯網" + "輕按即可查看選項" + "流動網絡並未連接互聯網" + "網絡並未連接互聯網" + "無法存取私人 DNS 伺服器" + "%1$s連線受限" + "仍要輕按以連結至此網絡" + "已切換至%1$s" + "裝置會在 %2$s 無法連線至互聯網時使用%1$s (可能需要支付相關費用)。" + "已從%1$s切換至%2$s" + "不明網絡類型" + + "流動數據" + "Wi-Fi" + "藍牙" + "以太網" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..f355138bd6 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml @@ -0,0 +1,39 @@ + + + + "登入 Wi-Fi 網路" + "登入網路" + + "%1$s 沒有網際網路連線" + "輕觸即可查看選項" + "這個行動網路沒有網際網路連線" + "這個網路沒有網際網路連線" + "無法存取私人 DNS 伺服器" + "%1$s 的連線能力受限" + "輕觸即可繼續連線" + "已切換至%1$s" + "裝置會在無法連上「%2$s」時切換至「%1$s」(可能需要支付相關費用)。" + "已從 %1$s 切換至%2$s" + "不明的網路類型" + + "行動數據" + "Wi-Fi" + "藍牙" + "乙太網路" + "VPN" + + diff --git a/service/ServiceConnectivityResources/res/values-zu/strings.xml b/service/ServiceConnectivityResources/res/values-zu/strings.xml new file mode 100644 index 0000000000..55fefb7939 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-zu/strings.xml @@ -0,0 +1,39 @@ + + + + "Ngena ngemvume kunethiwekhi ye-Wi-Fi" + "Ngena ngemvume kunethiwekhi" + + "I-%1$s ayinakho ukufinyelela kwe-inthanethi" + "Thepha ukuze uthole izinketho" + "Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi" + "Inethiwekhi ayinakho ukufinyelela kwenethiwekhi" + "Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa" + "I-%1$s inokuxhumeka okukhawulelwe" + "Thepha ukuze uxhume noma kunjalo" + "Kushintshelwe ku-%1$s" + "Idivayisi isebenzisa i-%1$s uma i-%2$s inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko." + "Kushintshelewe kusuka ku-%1$s kuya ku-%2$s" + "uhlobo olungaziwa lwenethiwekhi" + + "idatha yeselula" + "I-Wi-Fi" + "I-Bluetooth" + "I-Ethernet" + "I-VPN" + + diff --git a/service/ServiceConnectivityResources/res/values/strings.xml b/service/ServiceConnectivityResources/res/values/strings.xml index 2c7b992650..7a9cf57afc 100644 --- a/service/ServiceConnectivityResources/res/values/strings.xml +++ b/service/ServiceConnectivityResources/res/values/strings.xml @@ -14,9 +14,63 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + System Connectivity Resources - \ No newline at end of file + + + Sign in to Wi-Fi network + + + Sign in to network + + + %1$s + + + %1$s has no internet access + + + Tap for options + + + Mobile network has no internet access + + + Network has no internet access + + + Private DNS server cannot be accessed + + + %1$s has limited connectivity + + + Tap to connect anyway + + + Switched to %1$s + + + Device uses %1$s when %2$s has no internet access. Charges may apply. + + + Switched from %1$s to %2$s + + + + mobile data + Wi-Fi + Bluetooth + Ethernet + VPN + + + + + + an unknown network type + + From e62e7ff645cf7d102fcbeec399249ddfa047c2ee Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 14:23:12 +0900 Subject: [PATCH 168/343] Add multipath preference, background status API Add APIs for getMultipathPreference and getRestrictBackgroundStatus. Both are used by Connectivity to back the external ConnectivityManager.getRestrictBackgroundStatus, and ConnectivityManager.getMultipathPreference APIs. Test: atest CtsNetTestCases atest ConnectivityServiceTests atest NetworkPolicyManagerServiceTest Bug: 176289731 Change-Id: I8a03162b2f6691086bb64e75ffd354cdfca7f86a Merged-In: I8a03162b2f6691086bb64e75ffd354cdfca7f86a --- .../src/android/net/ConnectivityManager.java | 15 +-------------- .../src/android/net/IConnectivityManager.aidl | 2 ++ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index e32622391c..001e3a72d2 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -62,7 +62,6 @@ import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; -import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.UserHandle; import android.provider.Settings; @@ -842,7 +841,6 @@ public class ConnectivityManager { private final Context mContext; - private INetworkPolicyManager mNPManager; private final TetheringManager mTetheringManager; /** @@ -4794,17 +4792,6 @@ public class ConnectivityManager { public @interface RestrictBackgroundStatus { } - private INetworkPolicyManager getNetworkPolicyManager() { - synchronized (this) { - if (mNPManager != null) { - return mNPManager; - } - mNPManager = INetworkPolicyManager.Stub.asInterface(ServiceManager - .getService(Context.NETWORK_POLICY_SERVICE)); - return mNPManager; - } - } - /** * Determines if the calling application is subject to metered network restrictions while * running on background. @@ -4815,7 +4802,7 @@ public class ConnectivityManager { */ public @RestrictBackgroundStatus int getRestrictBackgroundStatus() { try { - return getNetworkPolicyManager().getRestrictBackgroundByCaller(); + return mService.getRestrictBackgroundStatusByCaller(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index d83cc163b5..98f3d40c0b 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -220,4 +220,6 @@ interface IConnectivityManager void setProfileNetworkPreference(in UserHandle profile, int preference, in IOnCompleteListener listener); + + int getRestrictBackgroundStatusByCaller(); } From 5245c4c0f00eab5bc4408bb36b349d9f0d792610 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 17 Mar 2021 23:14:53 +0900 Subject: [PATCH 169/343] Migrate framework-connectivity internal resources Use ServiceConnectivityResources instead. Start by creating resources in the ServiceConnectivityResources package to match the internal configuration, and common overlays. Bug: 182125649 Test: device boots, has connectivity Change-Id: I77a3efca2cd644f9828db1ed5d3cae8070fb8363 Merged-In: I77a3efca2cd644f9828db1ed5d3cae8070fb8363 --- .../android/net/ConnectivityResources.java | 108 ++++++++++++++++++ .../src/android/net/apf/ApfCapabilities.java | 48 +++++++- .../src/android/net/util/KeepaliveUtils.java | 10 +- .../net/util/MultinetworkPolicyTracker.java | 18 ++- .../ServiceConnectivityResources/Android.bp | 2 +- .../res/values-mcc204-mnc04/config.xml | 27 +++++ .../res/values-mcc310-mnc004/config.xml | 27 +++++ .../res/values-mcc311-mnc480/config.xml | 27 +++++ .../res/values/config.xml | 39 ++++++- .../res/values/overlayable.xml | 5 + 10 files changed, 296 insertions(+), 15 deletions(-) create mode 100644 framework/src/android/net/ConnectivityResources.java create mode 100644 service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml create mode 100644 service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml create mode 100644 service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml diff --git a/framework/src/android/net/ConnectivityResources.java b/framework/src/android/net/ConnectivityResources.java new file mode 100644 index 0000000000..18f0de0cc9 --- /dev/null +++ b/framework/src/android/net/ConnectivityResources.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.List; + +/** + * Utility to obtain the {@link com.android.server.ConnectivityService} {@link Resources}, in the + * ServiceConnectivityResources APK. + * @hide + */ +public class ConnectivityResources { + private static final String RESOURCES_APK_INTENT = + "com.android.server.connectivity.intent.action.SERVICE_CONNECTIVITY_RESOURCES_APK"; + private static final String RES_PKG_DIR = "/apex/com.android.tethering/"; + + @NonNull + private final Context mContext; + + @Nullable + private Context mResourcesContext = null; + + @Nullable + private static Context sTestResourcesContext = null; + + public ConnectivityResources(Context context) { + mContext = context; + } + + /** + * Convenience method to mock all resources for the duration of a test. + * + * Call with a null context to reset after the test. + */ + @VisibleForTesting + public static void setResourcesContextForTest(@Nullable Context testContext) { + sTestResourcesContext = testContext; + } + + /** + * Get the {@link Context} of the resources package. + */ + public synchronized Context getResourcesContext() { + if (sTestResourcesContext != null) { + return sTestResourcesContext; + } + + if (mResourcesContext != null) { + return mResourcesContext; + } + + final List pkgs = mContext.getPackageManager() + .queryIntentActivities(new Intent(RESOURCES_APK_INTENT), MATCH_SYSTEM_ONLY); + pkgs.removeIf(pkg -> !pkg.activityInfo.applicationInfo.sourceDir.startsWith(RES_PKG_DIR)); + if (pkgs.size() > 1) { + Log.wtf(ConnectivityResources.class.getSimpleName(), + "More than one package found: " + pkgs); + } + if (pkgs.isEmpty()) { + throw new IllegalStateException("No connectivity resource package found"); + } + + final Context pkgContext; + try { + pkgContext = mContext.createPackageContext( + pkgs.get(0).activityInfo.applicationInfo.packageName, 0 /* flags */); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("Resolved package not found", e); + } + + mResourcesContext = pkgContext; + return pkgContext; + } + + /** + * Get the {@link Resources} of the ServiceConnectivityResources APK. + */ + public Resources get() { + return getResourcesContext().getResources(); + } +} diff --git a/framework/src/android/net/apf/ApfCapabilities.java b/framework/src/android/net/apf/ApfCapabilities.java index bf5b26e278..85b24713f2 100644 --- a/framework/src/android/net/apf/ApfCapabilities.java +++ b/framework/src/android/net/apf/ApfCapabilities.java @@ -19,12 +19,12 @@ package android.net.apf; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.R; - /** * APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible * way to drop unwanted network packets to save power. @@ -36,6 +36,8 @@ import com.android.internal.R; */ @SystemApi public final class ApfCapabilities implements Parcelable { + private static ConnectivityResources sResources; + /** * Version of APF instruction set supported for packet filtering. 0 indicates no support for * packet filtering using APF programs. @@ -65,6 +67,14 @@ public final class ApfCapabilities implements Parcelable { apfPacketFormat = in.readInt(); } + @NonNull + private static synchronized ConnectivityResources getResources(@NonNull Context ctx) { + if (sResources == null) { + sResources = new ConnectivityResources(ctx); + } + return sResources; + } + @Override public int describeContents() { @@ -121,13 +131,43 @@ public final class ApfCapabilities implements Parcelable { * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. */ public static boolean getApfDrop8023Frames() { - return Resources.getSystem().getBoolean(R.bool.config_apfDrop802_3Frames); + // TODO(b/183076074): remove reading resources from system resources + final Resources systemRes = Resources.getSystem(); + final int id = systemRes.getIdentifier("config_apfDrop802_3Frames", "bool", "android"); + return systemRes.getBoolean(id); + } + + /** + * @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames. + * @hide + */ + public static boolean getApfDrop8023Frames(@NonNull Context context) { + final ConnectivityResources res = getResources(context); + // TODO(b/183076074): use R.bool.config_apfDrop802_3Frames directly + final int id = res.get().getIdentifier("config_apfDrop802_3Frames", "bool", + res.getResourcesContext().getPackageName()); + return res.get().getBoolean(id); } /** * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. */ public static @NonNull int[] getApfEtherTypeBlackList() { - return Resources.getSystem().getIntArray(R.array.config_apfEthTypeBlackList); + // TODO(b/183076074): remove reading resources from system resources + final Resources systemRes = Resources.getSystem(); + final int id = systemRes.getIdentifier("config_apfEthTypeBlackList", "array", "android"); + return systemRes.getIntArray(id); + } + + /** + * @return An array of denylisted EtherType, packets with EtherTypes within it will be dropped. + * @hide + */ + public static @NonNull int[] getApfEtherTypeDenyList(@NonNull Context context) { + final ConnectivityResources res = getResources(context); + // TODO(b/183076074): use R.array.config_apfEthTypeDenyList directly + final int id = res.get().getIdentifier("config_apfEthTypeDenyList", "array", + res.getResourcesContext().getPackageName()); + return res.get().getIntArray(id); } } diff --git a/framework/src/android/net/util/KeepaliveUtils.java b/framework/src/android/net/util/KeepaliveUtils.java index bfc4563fbf..8d7a0b3d02 100644 --- a/framework/src/android/net/util/KeepaliveUtils.java +++ b/framework/src/android/net/util/KeepaliveUtils.java @@ -19,12 +19,11 @@ package android.net.util; import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityResources; import android.net.NetworkCapabilities; import android.text.TextUtils; import android.util.AndroidRuntimeException; -import com.android.internal.R; - /** * Collection of utilities for socket keepalive offload. * @@ -52,8 +51,11 @@ public final class KeepaliveUtils { public static int[] getSupportedKeepalives(@NonNull Context context) { String[] res = null; try { - res = context.getResources().getStringArray( - R.array.config_networkSupportedKeepaliveCount); + final ConnectivityResources connRes = new ConnectivityResources(context); + // TODO: use R.id.config_networkSupportedKeepaliveCount directly + final int id = connRes.get().getIdentifier("config_networkSupportedKeepaliveCount", + "array", connRes.getResourcesContext().getPackageName()); + res = new ConnectivityResources(context).get().getStringArray(id); } catch (Resources.NotFoundException unused) { } if (res == null) throw new KeepaliveDeviceConfigurationException("invalid resource"); diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java index 6a49aa2576..0b42a00369 100644 --- a/framework/src/android/net/util/MultinetworkPolicyTracker.java +++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.database.ContentObserver; +import android.net.ConnectivityResources; import android.net.Uri; import android.os.Handler; import android.provider.Settings; @@ -35,7 +36,6 @@ import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; @@ -64,6 +64,7 @@ public class MultinetworkPolicyTracker { private static String TAG = MultinetworkPolicyTracker.class.getSimpleName(); private final Context mContext; + private final ConnectivityResources mResources; private final Handler mHandler; private final Runnable mAvoidBadWifiCallback; private final List mSettingsUris; @@ -107,6 +108,7 @@ public class MultinetworkPolicyTracker { public MultinetworkPolicyTracker(Context ctx, Handler handler, Runnable avoidBadWifiCallback) { mContext = ctx; + mResources = new ConnectivityResources(ctx); mHandler = handler; mAvoidBadWifiCallback = avoidBadWifiCallback; mSettingsUris = Arrays.asList( @@ -160,12 +162,16 @@ public class MultinetworkPolicyTracker { * Whether the device or carrier configuration disables avoiding bad wifi by default. */ public boolean configRestrictsAvoidBadWifi() { - return (getResourcesForActiveSubId().getInteger(R.integer.config_networkAvoidBadWifi) == 0); + // TODO: use R.integer.config_networkAvoidBadWifi directly + final int id = mResources.get().getIdentifier("config_networkAvoidBadWifi", + "integer", mResources.getResourcesContext().getPackageName()); + return (getResourcesForActiveSubId().getInteger(id) == 0); } @NonNull private Resources getResourcesForActiveSubId() { - return SubscriptionManager.getResourcesForSubId(mContext, mActiveSubId); + return SubscriptionManager.getResourcesForSubId( + mResources.getResourcesContext(), mActiveSubId); } /** @@ -205,8 +211,10 @@ public class MultinetworkPolicyTracker { * The default (device and carrier-dependent) value for metered multipath preference. */ public int configMeteredMultipathPreference() { - return mContext.getResources().getInteger( - R.integer.config_networkMeteredMultipathPreference); + // TODO: use R.integer.config_networkMeteredMultipathPreference directly + final int id = mResources.get().getIdentifier("config_networkMeteredMultipathPreference", + "integer", mResources.getResourcesContext().getPackageName()); + return mResources.get().getInteger(id); } public void updateMeteredMultipathPreference() { diff --git a/service/ServiceConnectivityResources/Android.bp b/service/ServiceConnectivityResources/Android.bp index f2446b7f7e..fa4501ac7f 100644 --- a/service/ServiceConnectivityResources/Android.bp +++ b/service/ServiceConnectivityResources/Android.bp @@ -21,7 +21,7 @@ package { android_app { name: "ServiceConnectivityResources", - sdk_version: "system_current", + sdk_version: "module_current", resource_dirs: [ "res", ], diff --git a/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml b/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml new file mode 100644 index 0000000000..7e7025fb04 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mcc204-mnc04/config.xml @@ -0,0 +1,27 @@ + + + + + + + 0 + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml b/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml new file mode 100644 index 0000000000..7e7025fb04 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mcc310-mnc004/config.xml @@ -0,0 +1,27 @@ + + + + + + + 0 + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml new file mode 100644 index 0000000000..7e7025fb04 --- /dev/null +++ b/service/ServiceConnectivityResources/res/values-mcc311-mnc480/config.xml @@ -0,0 +1,27 @@ + + + + + + + 0 + \ No newline at end of file diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml index 06c81921fd..71674e4dc6 100644 --- a/service/ServiceConnectivityResources/res/values/config.xml +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -52,4 +52,41 @@ 12,60000 - \ No newline at end of file + + true + + + + 0x88A2 + 0x88A4 + 0x88B8 + 0x88CD + 0x88E3 + + + + + + 0,1 + 1,3 + + + + + 0 + + + 1 + + diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml index da8aee5627..25e19cedbb 100644 --- a/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -21,6 +21,11 @@ + + + + + From 43dea2835ed82cf0116acd41c9fab896d14533e9 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Feb 2021 12:53:54 +0900 Subject: [PATCH 170/343] Move connectivity AIDLs to android.net java_sdk_libraries and apexes need to contain bootclasspath classes under predefined packages. Tethering currently uses android.net, so make sure all the connectivity bootclasspath classes are under android.net. This avoids maintaining two packages for the tethering APEX, where com.android.connectivity.aidl is only used by internal AIDL files. Bug: 182984842 Test: m Change-Id: I611f1941698c574e37aea912ee76dadc8b32e41a Merged-In: I611f1941698c574e37aea912ee76dadc8b32e41a --- framework/src/android/net/ConnectivityManager.java | 1 - framework/src/android/net/IConnectivityManager.aidl | 3 +-- .../connectivity/aidl => android/net}/INetworkAgent.aidl | 4 ++-- .../aidl => android/net}/INetworkAgentRegistry.aidl | 2 +- framework/src/android/net/NetworkAgent.java | 2 -- 5 files changed, 4 insertions(+), 8 deletions(-) rename framework/src/{com/android/connectivity/aidl => android/net}/INetworkAgent.aidl (95%) rename framework/src/{com/android/connectivity/aidl => android/net}/INetworkAgentRegistry.aidl (97%) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 001e3a72d2..a5e9f31a5b 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -73,7 +73,6 @@ import android.util.Log; import android.util.Range; import android.util.SparseIntArray; -import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 98f3d40c0b..3300fa8fd1 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -20,6 +20,7 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; +import android.net.INetworkAgent; import android.net.IOnCompleteListener; import android.net.INetworkActivityListener; import android.net.IQosCallback; @@ -45,8 +46,6 @@ import android.os.PersistableBundle; import android.os.ResultReceiver; import android.os.UserHandle; -import com.android.connectivity.aidl.INetworkAgent; - /** * Interface that answers queries about, and allows changing, the * state of network connectivity. diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl b/framework/src/android/net/INetworkAgent.aidl similarity index 95% rename from framework/src/com/android/connectivity/aidl/INetworkAgent.aidl rename to framework/src/android/net/INetworkAgent.aidl index 64b556720c..1f66e18717 100644 --- a/framework/src/com/android/connectivity/aidl/INetworkAgent.aidl +++ b/framework/src/android/net/INetworkAgent.aidl @@ -13,13 +13,13 @@ * See the License for the specific language governing perNmissions and * limitations under the License. */ -package com.android.connectivity.aidl; +package android.net; import android.net.NattKeepalivePacketData; import android.net.QosFilterParcelable; import android.net.TcpKeepalivePacketData; -import com.android.connectivity.aidl.INetworkAgentRegistry; +import android.net.INetworkAgentRegistry; /** * Interface to notify NetworkAgent of connectivity events. diff --git a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl b/framework/src/android/net/INetworkAgentRegistry.aidl similarity index 97% rename from framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl rename to framework/src/android/net/INetworkAgentRegistry.aidl index 18d26a7e4b..c5464d3241 100644 --- a/framework/src/com/android/connectivity/aidl/INetworkAgentRegistry.aidl +++ b/framework/src/android/net/INetworkAgentRegistry.aidl @@ -13,7 +13,7 @@ * See the License for the specific language governing perNmissions and * limitations under the License. */ -package com.android.connectivity.aidl; +package android.net; import android.net.LinkProperties; import android.net.Network; diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index a127c6f6de..1416bb9775 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -34,8 +34,6 @@ import android.os.RemoteException; import android.telephony.data.EpsBearerQosSessionAttributes; import android.util.Log; -import com.android.connectivity.aidl.INetworkAgent; -import com.android.connectivity.aidl.INetworkAgentRegistry; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; From f96b26606a1f7d591f2ddfb41e5a41ff28bc971f Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 14 Mar 2021 15:28:10 +0900 Subject: [PATCH 171/343] Add connectivity protos to framework-connectivity The protos are built separately by framework-connectivity from framework protos, keeping only android.net protos for the connectivity jar. Bug: 171860710 Test: m framework-connectivity.impl Change-Id: I2c4a37ff2ee9e8efde49885feeafa27dcff7ca2c Merged-In: I2c4a37ff2ee9e8efde49885feeafa27dcff7ca2c --- framework/Android.bp | 20 ++++++++++++++++++++ framework/jarjar-rules-proto.txt | 3 +++ framework/jarjar-rules.txt | 3 +++ 3 files changed, 26 insertions(+) create mode 100644 framework/jarjar-rules-proto.txt diff --git a/framework/Android.bp b/framework/Android.bp index 86433e1c38..017ff51f36 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -23,6 +23,25 @@ package { default_applicable_licenses: ["frameworks_base_license"], } +java_library { + name: "framework-connectivity-protos", + proto: { + type: "nano", + }, + srcs: [ + // TODO: consider moving relevant .proto files directly to the module directory + ":framework-javastream-protos", + ], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], + jarjar_rules: "jarjar-rules-proto.txt", + visibility: [ + "//visibility:private", + ], +} + filegroup { name: "framework-connectivity-internal-sources", srcs: [ @@ -111,6 +130,7 @@ java_library { "ServiceConnectivityResources", ], static_libs: [ + "framework-connectivity-protos", "net-utils-device-common", ], jarjar_rules: "jarjar-rules.txt", diff --git a/framework/jarjar-rules-proto.txt b/framework/jarjar-rules-proto.txt new file mode 100644 index 0000000000..37b4dec1c3 --- /dev/null +++ b/framework/jarjar-rules-proto.txt @@ -0,0 +1,3 @@ +keep android.net.NetworkCapabilitiesProto +keep android.net.NetworkProto +keep android.net.NetworkRequestProto diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt index 381a4ac875..0959840f2d 100644 --- a/framework/jarjar-rules.txt +++ b/framework/jarjar-rules.txt @@ -5,3 +5,6 @@ zap android.annotation.** zap com.android.net.module.annotation.** zap com.android.internal.annotations.** +rule android.net.NetworkCapabilitiesProto* android.net.connectivity.proto.NetworkCapabilitiesProto@1 +rule android.net.NetworkProto* android.net.connectivity.proto.NetworkProto@1 +rule android.net.NetworkRequestProto* android.net.connectivity.proto.NetworkRequestProto@1 From 9f4fad49a5346823bf36eeeaff5ed3a4575b0823 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 17:41:48 +0900 Subject: [PATCH 172/343] Use connectivity resources in service-connectivity Migrate resource usage to the connectivity resource package. For framework resources that have known overlays, keep a fallback until the overlays can be migrated. Bug: 182125649 Test: atest FrameworksNetTests Change-Id: I778d94a5aac0c4e20e78b1ba3a002495c17a38a0 --- .../res/values/config.xml | 34 +++++++++++++++++++ .../res/values/overlayable.xml | 6 ++++ 2 files changed, 40 insertions(+) diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml index 71674e4dc6..9ff2a2209e 100644 --- a/service/ServiceConnectivityResources/res/values/config.xml +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -78,6 +78,11 @@ 1,3 + + 2 + + + 2 1 + + + 10 + 11 + 12 + 14 + 15 + + + + false + + + + 0 + + + 0 + + + 0 + + + + + diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml index 25e19cedbb..717d08e13e 100644 --- a/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -26,6 +26,12 @@ + + + + + + From 4b79f7bd56aa187cc3c99c061fb77872148f2f02 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Mar 2021 17:45:27 +0900 Subject: [PATCH 173/343] Use module resources in NetworkNotificationManager. Also make getTransportName non-static so it can access the module resources. Also fix a duplicate comment in a resource file. Bug: 183097033 Test: atest FrameworksNetTests Test: connected to Wi-Fi with no Internet, observed notification Change-Id: Ic0d24d36af0b87153d527083f8964ddc6cd78482 Merged-In: Ic0d24d36af0b87153d527083f8964ddc6cd78482 --- service/ServiceConnectivityResources/res/values/strings.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/service/ServiceConnectivityResources/res/values/strings.xml b/service/ServiceConnectivityResources/res/values/strings.xml index 7a9cf57afc..b2fa5f5b41 100644 --- a/service/ServiceConnectivityResources/res/values/strings.xml +++ b/service/ServiceConnectivityResources/res/values/strings.xml @@ -68,8 +68,6 @@ VPN - - an unknown network type From 1e97e4549821b37afb16c339d73c9bfddbc3118d Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Sun, 21 Mar 2021 17:55:29 +0000 Subject: [PATCH 174/343] resolve merge conflicts of 403b7fd0b0a6736bcee1817fb5c774f8c8a040de to stage-aosp-master Change-Id: Ib9d7923104ac0a60f6af5a3a2d2b7f13bc0262e3 --- framework/api/module-lib-current.txt | 11 ++ framework/api/system-current.txt | 6 - framework/src/android/net/NetworkAgent.java | 5 +- .../src/android/net/NetworkCapabilities.java | 111 +++++++++++++++--- framework/src/android/net/TransportInfo.java | 48 +++++--- 5 files changed, 139 insertions(+), 42 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 5bd01a6010..9376a4b8f0 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -40,7 +40,13 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); method @Nullable public java.util.Set> getUids(); + field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL + field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L + field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L + field public static final long REDACT_FOR_NETWORK_SETTINGS = 4L; // 0x4L + field public static final long REDACT_NONE = 0L; // 0x0L field public static final int TRANSPORT_TEST = 7; // 0x7 } @@ -92,6 +98,11 @@ package android.net { field @NonNull public static final android.os.Parcelable.Creator CREATOR; } + public interface TransportInfo { + method public default long getApplicableRedactions(); + method @NonNull public default android.net.TransportInfo makeCopy(long); + } + public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo { ctor public VpnTransportInfo(int); method public int describeContents(); diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 8845225823..358cea85a2 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -261,7 +261,6 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { - ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, boolean); method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); @@ -435,11 +434,6 @@ package android.net { field public final int tcpWindowScale; } - public interface TransportInfo { - method public default boolean hasLocationSensitiveFields(); - method @NonNull public default android.net.TransportInfo makeCopy(boolean); - } - } package android.net.apf { diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index 1416bb9775..3863ed1113 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -434,7 +434,7 @@ public abstract class NetworkAgent { } mInitialConfiguration = new InitialConfiguration(context, - new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true), + new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE), new LinkProperties(lp), score, config, ni); } @@ -878,8 +878,7 @@ public abstract class NetworkAgent { mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); final NetworkCapabilities nc = - new NetworkCapabilities(networkCapabilities, - /* parcelLocationSensitiveFields */ true); + new NetworkCapabilities(networkCapabilities, NetworkCapabilities.REDACT_NONE); queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 146662976f..c9c0940dfd 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -19,6 +19,7 @@ package android.net; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.annotation.IntDef; +import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -64,6 +65,68 @@ import java.util.StringJoiner; public final class NetworkCapabilities implements Parcelable { private static final String TAG = "NetworkCapabilities"; + /** + * Mechanism to support redaction of fields in NetworkCapabilities that are guarded by specific + * app permissions. + **/ + /** + * Don't redact any fields since the receiving app holds all the necessary permissions. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_NONE = 0; + + /** + * Redact any fields that need {@link android.Manifest.permission#ACCESS_FINE_LOCATION} + * permission since the receiving app does not hold this permission or the location toggle + * is off. + * + * @see android.Manifest.permission#ACCESS_FINE_LOCATION + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1 << 0; + + /** + * Redact any fields that need {@link android.Manifest.permission#LOCAL_MAC_ADDRESS} + * permission since the receiving app does not hold this permission. + * + * @see android.Manifest.permission#LOCAL_MAC_ADDRESS + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 1 << 1; + + /** + * + * Redact any fields that need {@link android.Manifest.permission#NETWORK_SETTINGS} + * permission since the receiving app does not hold this permission. + * + * @see android.Manifest.permission#NETWORK_SETTINGS + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_FOR_NETWORK_SETTINGS = 1 << 2; + + /** + * Redact all fields in this object that require any relevant permission. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final long REDACT_ALL = -1L; + + /** @hide */ + @LongDef(flag = true, prefix = { "REDACT_" }, value = { + REDACT_NONE, + REDACT_FOR_ACCESS_FINE_LOCATION, + REDACT_FOR_LOCAL_MAC_ADDRESS, + REDACT_FOR_NETWORK_SETTINGS, + REDACT_ALL + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RedactionType {} + // Set to true when private DNS is broken. private boolean mPrivateDnsBroken; @@ -78,32 +141,31 @@ public final class NetworkCapabilities implements Parcelable { private String mRequestorPackageName; /** - * Indicates whether parceling should preserve fields that are set based on permissions of - * the process receiving the {@link NetworkCapabilities}. + * Indicates what fields should be redacted from this instance. */ - private final boolean mParcelLocationSensitiveFields; + private final @RedactionType long mRedactions; public NetworkCapabilities() { - mParcelLocationSensitiveFields = false; + mRedactions = REDACT_ALL; clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { - this(nc, false /* parcelLocationSensitiveFields */); + this(nc, REDACT_ALL); } /** * Make a copy of NetworkCapabilities. * * @param nc Original NetworkCapabilities - * @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not. + * @param redactions bitmask of redactions that needs to be performed on this new instance of + * {@link NetworkCapabilities}. * @hide */ - @SystemApi - public NetworkCapabilities( - @Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) { - mParcelLocationSensitiveFields = parcelLocationSensitiveFields; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) { + mRedactions = redactions; if (nc != null) { set(nc); } @@ -115,11 +177,13 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public void clearAll() { - // Ensures that the internal copies maintained by the connectivity stack does not set - // this bit. - if (mParcelLocationSensitiveFields) { + // Ensures that the internal copies maintained by the connectivity stack does not set it to + // anything other than |REDACT_ALL|. + if (mRedactions != REDACT_ALL) { + // This is needed because the current redaction mechanism relies on redaction while + // parceling. throw new UnsupportedOperationException( - "Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set"); + "Cannot clear NetworkCapabilities when mRedactions is set"); } mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; @@ -149,7 +213,7 @@ public final class NetworkCapabilities implements Parcelable { mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; if (nc.getTransportInfo() != null) { - setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields)); + setTransportInfo(nc.getTransportInfo().makeCopy(mRedactions)); } else { setTransportInfo(null); } @@ -2349,6 +2413,23 @@ public final class NetworkCapabilities implements Parcelable { } } + /** + * Returns a bitmask of all the applicable redactions (based on the permissions held by the + * receiving app) to be performed on this object. + * + * @return bitmask of redactions applicable on this instance. + * @hide + */ + public @RedactionType long getApplicableRedactions() { + // Currently, there are no fields redacted in NetworkCapabilities itself, so we just + // passthrough the redactions required by the embedded TransportInfo. If this changes + // in the future, modify this method. + if (mTransportInfo == null) { + return NetworkCapabilities.REDACT_NONE; + } + return mTransportInfo.getApplicableRedactions(); + } + /** * Builder class for NetworkCapabilities. * diff --git a/framework/src/android/net/TransportInfo.java b/framework/src/android/net/TransportInfo.java index aa4bbb0511..fa889eabb8 100644 --- a/framework/src/android/net/TransportInfo.java +++ b/framework/src/android/net/TransportInfo.java @@ -29,35 +29,47 @@ import android.annotation.SystemApi; public interface TransportInfo { /** - * Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that - * were set based on the permissions of the process that originally received it. + * Create a copy of a {@link TransportInfo} with some fields redacted based on the permissions + * held by the receiving app. * - *

    By default {@link TransportInfo} does not preserve such fields during parceling, as - * they should not be shared outside of the process that receives them without appropriate - * checks. + *

    + * Usage by connectivity stack: + *

      + *
    • Connectivity stack will invoke {@link #getApplicableRedactions()} to find the list + * of redactions that are required by this {@link TransportInfo} instance.
    • + *
    • Connectivity stack then loops through each bit in the bitmask returned and checks if the + * receiving app holds the corresponding permission. + *
        + *
      • If the app holds the corresponding permission, the bit is cleared from the + * |redactions| bitmask.
      • + *
      • If the app does not hold the corresponding permission, the bit is retained in the + * |redactions| bitmask.
      • + *
      + *
    • Connectivity stack then invokes {@link #makeCopy(long)} with the necessary |redactions| + * to create a copy to send to the corresponding app.
    • + *
    + *

    * - * @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept - * when parceling - * @return Copy of this instance. + * @param redactions bitmask of redactions that needs to be performed on this instance. + * @return Copy of this instance with the necessary redactions. * @hide */ - @SystemApi + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @NonNull - default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) { + default TransportInfo makeCopy(@NetworkCapabilities.RedactionType long redactions) { return this; } /** - * Returns whether this TransportInfo type has location sensitive fields or not (helps - * to determine whether to perform a location permission check or not before sending to - * apps). + * Returns a bitmask of all the applicable redactions (based on the permissions held by the + * receiving app) to be performed on this TransportInfo. * - * @return {@code true} if this instance contains location sensitive info, {@code false} - * otherwise. + * @return bitmask of redactions applicable on this instance. + * @see #makeCopy(long) * @hide */ - @SystemApi - default boolean hasLocationSensitiveFields() { - return false; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + default @NetworkCapabilities.RedactionType long getApplicableRedactions() { + return NetworkCapabilities.REDACT_NONE; } } From 28028e5066cd1edc530d87679a24696e86b301fe Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Mar 2021 07:31:54 +0000 Subject: [PATCH 175/343] Revert "Revert "Remove connectivity dependency on Preconditions"" Preconditions.checkNotNull is deprecated to be replaced by Objects.requireNonNull, and other methods can easily be replaced by inline checks. Preconditions is an internal API class that should not be used by unbundled jars. Bug: 177046265 Change-Id: I3a67d266b32142c034520acbcdc30f7213db5e13 Merged-In: I3a67d266b32142c034520acbcdc30f7213db5e13 Test: m --- .../net/ConnectivityDiagnosticsManager.java | 5 +- .../src/android/net/ConnectivityManager.java | 48 +++++++++++-------- framework/src/android/net/MacAddress.java | 10 ++-- .../src/android/net/NetworkCapabilities.java | 11 +++-- .../android/net/StaticIpConfiguration.java | 3 +- .../src/android/net/TestNetworkManager.java | 7 ++- 6 files changed, 45 insertions(+), 39 deletions(-) diff --git a/framework/src/android/net/ConnectivityDiagnosticsManager.java b/framework/src/android/net/ConnectivityDiagnosticsManager.java index 5234494973..3598ebc701 100644 --- a/framework/src/android/net/ConnectivityDiagnosticsManager.java +++ b/framework/src/android/net/ConnectivityDiagnosticsManager.java @@ -28,7 +28,6 @@ import android.os.PersistableBundle; import android.os.RemoteException; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -70,8 +69,8 @@ public class ConnectivityDiagnosticsManager { /** @hide */ public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) { - mContext = Preconditions.checkNotNull(context, "missing context"); - mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mContext = Objects.requireNonNull(context, "missing context"); + mService = Objects.requireNonNull(service, "missing IConnectivityManager"); } /** @hide */ diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index a621233e32..4cf08fcec1 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -76,7 +76,6 @@ import android.util.SparseIntArray; import com.android.connectivity.aidl.INetworkAgent; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.Preconditions; import libcore.net.event.NetworkEventDispatcher; @@ -1777,7 +1776,9 @@ public class ConnectivityManager { // Map from type to transports. final int NOT_FOUND = -1; final int transport = sLegacyTypeToTransport.get(type, NOT_FOUND); - Preconditions.checkArgument(transport != NOT_FOUND, "unknown legacy type: " + type); + if (transport == NOT_FOUND) { + throw new IllegalArgumentException("unknown legacy type: " + type); + } nc.addTransportType(transport); // Map from type to capabilities. @@ -1882,8 +1883,8 @@ public class ConnectivityManager { } private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { - Preconditions.checkNotNull(network, "network cannot be null"); - Preconditions.checkNotNull(callback, "callback cannot be null"); + Objects.requireNonNull(network, "network cannot be null"); + Objects.requireNonNull(callback, "callback cannot be null"); mNetwork = network; mExecutor = Executors.newSingleThreadExecutor(); mCallback = new ISocketKeepaliveCallback.Stub() { @@ -2258,7 +2259,9 @@ public class ConnectivityManager { */ public void removeDefaultNetworkActiveListener(@NonNull OnNetworkActiveListener l) { INetworkActivityListener rl = mNetworkActivityListeners.get(l); - Preconditions.checkArgument(rl != null, "Listener was not registered."); + if (rl == null) { + throw new IllegalArgumentException("Listener was not registered."); + } try { mService.registerNetworkActivityListener(rl); } catch (RemoteException e) { @@ -2286,8 +2289,8 @@ public class ConnectivityManager { * {@hide} */ public ConnectivityManager(Context context, IConnectivityManager service) { - mContext = Preconditions.checkNotNull(context, "missing context"); - mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mContext = Objects.requireNonNull(context, "missing context"); + mService = Objects.requireNonNull(service, "missing IConnectivityManager"); mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); sInstance = this; } @@ -2554,7 +2557,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { - Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); + Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null."); final Executor executor = new Executor() { @Override @@ -2647,7 +2650,7 @@ public class ConnectivityManager { public void registerTetheringEventCallback( @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEventCallback callback) { - Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); + Objects.requireNonNull(callback, "OnTetheringEventCallback cannot be null."); final TetheringEventCallback tetherCallback = new TetheringEventCallback() { @@ -2945,7 +2948,7 @@ public class ConnectivityManager { public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEntitlementResultListener listener) { - Preconditions.checkNotNull(listener, "TetheringEntitlementResultListener cannot be null."); + Objects.requireNonNull(listener, "TetheringEntitlementResultListener cannot be null."); ResultReceiver wrappedListener = new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { @@ -3315,7 +3318,9 @@ public class ConnectivityManager { } public NetworkCallback(@Flag int flags) { - Preconditions.checkArgument((flags & VALID_FLAGS) == flags); + if ((flags & VALID_FLAGS) != flags) { + throw new IllegalArgumentException("Invalid flags"); + } mFlags = flags; } @@ -3601,7 +3606,7 @@ public class ConnectivityManager { } CallbackHandler(Handler handler) { - this(Preconditions.checkNotNull(handler, "Handler cannot be null.").getLooper()); + this(Objects.requireNonNull(handler, "Handler cannot be null.").getLooper()); } @Override @@ -3699,9 +3704,9 @@ public class ConnectivityManager { int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { printStackTrace(); checkCallbackNotNull(callback); - Preconditions.checkArgument( - reqType == TRACK_DEFAULT || reqType == TRACK_SYSTEM_DEFAULT || need != null, - "null NetworkCapabilities"); + if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) { + throw new IllegalArgumentException("null NetworkCapabilities"); + } final NetworkRequest request; final String callingPackageName = mContext.getOpPackageName(); try { @@ -4048,15 +4053,17 @@ public class ConnectivityManager { } private static void checkPendingIntentNotNull(PendingIntent intent) { - Preconditions.checkNotNull(intent, "PendingIntent cannot be null."); + Objects.requireNonNull(intent, "PendingIntent cannot be null."); } private static void checkCallbackNotNull(NetworkCallback callback) { - Preconditions.checkNotNull(callback, "null NetworkCallback"); + Objects.requireNonNull(callback, "null NetworkCallback"); } private static void checkTimeout(int timeoutMs) { - Preconditions.checkArgumentPositive(timeoutMs, "timeoutMs must be strictly positive."); + if (timeoutMs <= 0) { + throw new IllegalArgumentException("timeoutMs must be strictly positive."); + } } /** @@ -4336,8 +4343,9 @@ public class ConnectivityManager { // Find all requests associated to this callback and stop callback triggers immediately. // Callback is reusable immediately. http://b/20701525, http://b/35921499. synchronized (sCallbacks) { - Preconditions.checkArgument(networkCallback.networkRequest != null, - "NetworkCallback was not registered"); + if (networkCallback.networkRequest == null) { + throw new IllegalArgumentException("NetworkCallback was not registered"); + } if (networkCallback.networkRequest == ALREADY_UNREGISTERED) { Log.d(TAG, "NetworkCallback was already unregistered"); return; diff --git a/framework/src/android/net/MacAddress.java b/framework/src/android/net/MacAddress.java index c83c23a4b6..26a504a29c 100644 --- a/framework/src/android/net/MacAddress.java +++ b/framework/src/android/net/MacAddress.java @@ -25,7 +25,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; @@ -34,6 +33,7 @@ import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Arrays; +import java.util.Objects; /** * Representation of a MAC address. @@ -229,7 +229,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static @NonNull byte[] byteAddrFromStringAddr(String addr) { - Preconditions.checkNotNull(addr); + Objects.requireNonNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -275,7 +275,7 @@ public final class MacAddress implements Parcelable { // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) // that avoids the allocation of an intermediary byte[]. private static long longAddrFromStringAddr(String addr) { - Preconditions.checkNotNull(addr); + Objects.requireNonNull(addr); String[] parts = addr.split(":"); if (parts.length != ETHER_ADDR_LEN) { throw new IllegalArgumentException(addr + " was not a valid MAC address"); @@ -364,8 +364,8 @@ public final class MacAddress implements Parcelable { * */ public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) { - Preconditions.checkNotNull(baseAddress); - Preconditions.checkNotNull(mask); + Objects.requireNonNull(baseAddress); + Objects.requireNonNull(mask); return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index 058f3c999d..c6dfcee202 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -35,7 +35,6 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; @@ -2099,8 +2098,9 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidTransportType(@Transport int transport) { - Preconditions.checkArgument( - isValidTransport(transport), "Invalid TransportType " + transport); + if (!isValidTransport(transport)) { + throw new IllegalArgumentException("Invalid TransportType " + transport); + } } private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) { @@ -2108,8 +2108,9 @@ public final class NetworkCapabilities implements Parcelable { } private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) { - Preconditions.checkArgument(isValidCapability(capability), - "NetworkCapability " + capability + "out of range"); + if (!isValidCapability(capability)) { + throw new IllegalArgumentException("NetworkCapability " + capability + "out of range"); + } } /** diff --git a/framework/src/android/net/StaticIpConfiguration.java b/framework/src/android/net/StaticIpConfiguration.java index ce545974f5..7904f7a4ec 100644 --- a/framework/src/android/net/StaticIpConfiguration.java +++ b/framework/src/android/net/StaticIpConfiguration.java @@ -24,7 +24,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; import com.android.net.module.util.InetAddressUtils; import java.net.InetAddress; @@ -153,7 +152,7 @@ public final class StaticIpConfiguration implements Parcelable { * @return The {@link Builder} for chaining. */ public @NonNull Builder setDnsServers(@NonNull Iterable dnsServers) { - Preconditions.checkNotNull(dnsServers); + Objects.requireNonNull(dnsServers); mDnsServers = dnsServers; return this; } diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java index a174a7be85..a7a62351e5 100644 --- a/framework/src/android/net/TestNetworkManager.java +++ b/framework/src/android/net/TestNetworkManager.java @@ -21,10 +21,9 @@ import android.annotation.SystemApi; import android.os.IBinder; import android.os.RemoteException; -import com.android.internal.util.Preconditions; - import java.util.Arrays; import java.util.Collection; +import java.util.Objects; /** * Class that allows creation and management of per-app, test-only networks @@ -50,7 +49,7 @@ public class TestNetworkManager { /** @hide */ public TestNetworkManager(@NonNull ITestNetworkManager service) { - mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager"); + mService = Objects.requireNonNull(service, "missing ITestNetworkManager"); } /** @@ -93,7 +92,7 @@ public class TestNetworkManager { */ public void setupTestNetwork( @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { - Preconditions.checkNotNull(lp, "Invalid LinkProperties"); + Objects.requireNonNull(lp, "Invalid LinkProperties"); setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); } From 2125a97fb4d7e9ab48e1ec3bc97c4f3f9706e450 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 18 Mar 2021 22:08:01 +0900 Subject: [PATCH 176/343] Remove Preconditions usage in TestNetworkSpecifier Preconditions is a hidden API utility. It can be easily replace by inline checks. Bug: 177046265 Test: m Change-Id: I3f722075fb9c74e12e40348ba4faad2f0fa67178 Merged-In: I3f722075fb9c74e12e40348ba4faad2f0fa67178 --- framework/src/android/net/TestNetworkSpecifier.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/android/net/TestNetworkSpecifier.java b/framework/src/android/net/TestNetworkSpecifier.java index b7470a591d..117457dffc 100644 --- a/framework/src/android/net/TestNetworkSpecifier.java +++ b/framework/src/android/net/TestNetworkSpecifier.java @@ -23,8 +23,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import com.android.internal.util.Preconditions; - import java.util.Objects; /** @@ -43,7 +41,9 @@ public final class TestNetworkSpecifier extends NetworkSpecifier implements Parc private final String mInterfaceName; public TestNetworkSpecifier(@NonNull String interfaceName) { - Preconditions.checkStringNotEmpty(interfaceName); + if (TextUtils.isEmpty(interfaceName)) { + throw new IllegalArgumentException("Empty interfaceName"); + } mInterfaceName = interfaceName; } From 8c1b75521a89d19a6ed2d3daa535dc6eeada33aa Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 21 Mar 2021 10:22:23 +0000 Subject: [PATCH 177/343] Add NetworkFactory to connectivity jarjar rules NetworkFactory is part of net-utils-device-common, but is outside of the com.android.net.module.util and needs a separate jarjar rule. Bug: 171540887 Test: atest FrameworksNetTests Change-Id: Iec828a789175acdbe4e7f35e4cc942922540495c --- framework/jarjar-rules.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt index 0959840f2d..7474c246a2 100644 --- a/framework/jarjar-rules.txt +++ b/framework/jarjar-rules.txt @@ -1,4 +1,5 @@ rule com.android.net.module.util.** android.net.connectivity.framework.util.@1 +rule android.net.NetworkFactory* android.net.connectivity.framework.NetworkFactory@1 # TODO (b/149403767): remove the annotations from net-utils-device-common instead of here zap android.annotation.** From 97fb10a3a62231d5eeded914a27b4d00a0130263 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Mon, 22 Mar 2021 11:51:27 +0800 Subject: [PATCH 178/343] Expose some APIs from ConnectivityManager - Expose setRequireVpnForUids to Vpn.java - Expose setLegacyLockdownVpnEnabled to LockdownVpnTracker.java - Expose requestRouteToHostAddress to GnssNetworkConnectivityHandler.java Bug: 182963397 Test: m Change-Id: I1fb5ecfbe37878ba3534e6c6c7599ca29db2735c --- framework/api/module-lib-current.txt | 3 +++ framework/src/android/net/ConnectivityManager.java | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 9376a4b8f0..9ca6d8fedc 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -13,11 +13,14 @@ package android.net { method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); + method @Deprecated public boolean requestRouteToHostAddress(int, java.net.InetAddress); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network); method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setLegacyLockdownVpnEnabled(boolean); method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setRequireVpnForUids(boolean, @NonNull java.util.Collection>); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network); method public void systemReady(); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index f8a0e4e8eb..ebedfe9ccb 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -1125,12 +1125,13 @@ public class ConnectivityManager { * @param ranges the UID ranges to restrict * @param requireVpn whether the specified UID ranges must use a VPN * - * TODO: expose as @SystemApi. * @hide */ @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_STACK}) + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + @SystemApi(client = MODULE_LIBRARIES) public void setRequireVpnForUids(boolean requireVpn, @NonNull Collection> ranges) { Objects.requireNonNull(ranges); @@ -1174,13 +1175,13 @@ public class ConnectivityManager { * * @param enabled whether legacy lockdown VPN is enabled or disabled * - * TODO: @SystemApi(client = MODULE_LIBRARIES) - * * @hide */ @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) + @SystemApi(client = MODULE_LIBRARIES) public void setLegacyLockdownVpnEnabled(boolean enabled) { try { mService.setLegacyLockdownVpnEnabled(enabled); @@ -2127,6 +2128,7 @@ public class ConnectivityManager { */ @Deprecated @UnsupportedAppUsage + @SystemApi(client = MODULE_LIBRARIES) public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) { checkLegacyRoutingApiAccess(); try { From b15b7dbdd4f8fac483957b7e2e9ebb00489fad02 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 16 Mar 2021 10:24:43 +0800 Subject: [PATCH 179/343] [VCN15] expose addUnwantedCapability and related APIs Test: m -j doc-comment-check-docs Bug: 175662146 Merged-In: I3f2e6a99e015f09cc4405f6804eac4ae33e3dcc7 Change-Id: I3f2e6a99e015f09cc4405f6804eac4ae33e3dcc7 (cherry-picked from ag/13929102) --- framework/api/module-lib-current.txt | 7 ++++ .../src/android/net/NetworkCapabilities.java | 33 +++++++++++++++---- framework/src/android/net/NetworkRequest.java | 20 +++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index aa7a0ac465..af0f50ef18 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -39,6 +39,7 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); method @Nullable public java.util.Set> getUids(); + method public boolean hasUnwantedCapability(int); field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L @@ -51,7 +52,13 @@ package android.net { method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); } + public class NetworkRequest implements android.os.Parcelable { + method public boolean hasUnwantedCapability(int); + } + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder addUnwantedCapability(int); + method @NonNull public android.net.NetworkRequest.Builder removeUnwantedCapability(int); method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index c9c0940dfd..881fa8c270 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -639,19 +639,31 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Removes (if found) the given capability from this {@code NetworkCapability} instance. + * Removes (if found) the given capability from this {@code NetworkCapability} + * instance that were added via addCapability(int) or setCapabilities(int[], int[]). * * @param capability the capability to be removed. * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { - // Note that this method removes capabilities that were added via addCapability(int), - // addUnwantedCapability(int) or setCapabilities(int[], int[]). checkValidCapability(capability); final long mask = ~(1 << capability); mNetworkCapabilities &= mask; - mUnwantedNetworkCapabilities &= mask; + return this; + } + + /** + * Removes (if found) the given unwanted capability from this {@code NetworkCapability} + * instance that were added via addUnwantedCapability(int) or setCapabilities(int[], int[]). + * + * @param capability the capability to be removed. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities removeUnwantedCapability(@NetCapability int capability) { + checkValidCapability(capability); + mUnwantedNetworkCapabilities &= ~(1 << capability); return this; } @@ -723,6 +735,7 @@ public final class NetworkCapabilities implements Parcelable { } /** @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public boolean hasUnwantedCapability(@NetCapability int capability) { return isValidCapability(capability) && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0); @@ -736,10 +749,16 @@ public final class NetworkCapabilities implements Parcelable { return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0); } - /** Note this method may result in having the same capability in wanted and unwanted lists. */ private void combineNetCapabilities(@NonNull NetworkCapabilities nc) { - this.mNetworkCapabilities |= nc.mNetworkCapabilities; - this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities; + final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities; + final long unwantedCaps = + this.mUnwantedNetworkCapabilities | nc.mUnwantedNetworkCapabilities; + if ((wantedCaps & unwantedCaps) != 0) { + throw new IllegalArgumentException( + "Cannot have the same capability in wanted and unwanted lists."); + } + this.mNetworkCapabilities = wantedCaps; + this.mUnwantedNetworkCapabilities = unwantedCaps; } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index cf131f0df6..23c92a52ac 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -305,11 +305,30 @@ public class NetworkRequest implements Parcelable { * * @hide */ + @NonNull + @SuppressLint("MissingGetterMatchingBuilder") + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addUnwantedCapability(capability); return this; } + /** + * Removes (if found) the given unwanted capability from this builder instance. + * + * @param capability The unwanted capability to remove. + * @return The builder to facilitate chaining. + * + * @hide + */ + @NonNull + @SuppressLint("BuilderSetStyle") + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder removeUnwantedCapability(@NetworkCapabilities.NetCapability int capability) { + mNetworkCapabilities.removeUnwantedCapability(capability); + return this; + } + /** * Completely clears all the {@code NetworkCapabilities} from this builder instance, * removing even the capabilities that are set by default when the object is constructed. @@ -567,6 +586,7 @@ public class NetworkRequest implements Parcelable { * * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public boolean hasUnwantedCapability(@NetCapability int capability) { return networkCapabilities.hasUnwantedCapability(capability); } From 5f26b19afdcc95a1c9e577fea9cbc985b769b992 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 12 Mar 2021 22:48:07 +0900 Subject: [PATCH 180/343] Support calling registerDefaultNetworkCallback for another UID. This is to be used by privileged components (e.g., JobScheduler) to request callbacks about the state of other UIDs on the system. Bug: 165835257 Test: new unit test coverage Change-Id: I29f155710394e58c14fcef488db6271d8d83033a --- .../src/android/net/ConnectivityManager.java | 49 +++++++++++++++++-- .../src/android/net/IConnectivityManager.aidl | 2 +- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index a5e9f31a5b..1a5299bb00 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -3695,8 +3695,9 @@ public class ConnectivityManager { private static final HashMap sCallbacks = new HashMap<>(); private static CallbackHandler sCallbackHandler; - private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback, - int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { + private NetworkRequest sendRequestForNetwork(int asUid, NetworkCapabilities need, + NetworkCallback callback, int timeoutMs, NetworkRequest.Type reqType, int legacyType, + CallbackHandler handler) { printStackTrace(); checkCallbackNotNull(callback); Preconditions.checkArgument( @@ -3721,8 +3722,8 @@ public class ConnectivityManager { getAttributionTag()); } else { request = mService.requestNetwork( - need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType, - callbackFlags, callingPackageName, getAttributionTag()); + asUid, need, reqType.ordinal(), messenger, timeoutMs, binder, + legacyType, callbackFlags, callingPackageName, getAttributionTag()); } if (request != null) { sCallbacks.put(request, callback); @@ -3737,6 +3738,12 @@ public class ConnectivityManager { return request; } + private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback, + int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) { + return sendRequestForNetwork(Process.INVALID_UID, need, callback, timeoutMs, reqType, + legacyType, handler); + } + /** * Helper function to request a network with a particular legacy type. * @@ -4220,8 +4227,40 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, @NonNull Handler handler) { + registerDefaultNetworkCallbackAsUid(Process.INVALID_UID, networkCallback, handler); + } + + /** + * Registers to receive notifications about changes in the default network for the specified + * UID. This may be a physical network or a virtual network, such as a VPN that applies to the + * UID. The callbacks will continue to be called until either the application exits or + * {@link #unregisterNetworkCallback(NetworkCallback)} is called. + * + *

    To avoid performance issues due to apps leaking callbacks, the system will limit the + * number of outstanding requests to 100 per app (identified by their UID), shared with + * all variants of this method, of {@link #requestNetwork} as well as + * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}. + * Requesting a network with this method will count toward this limit. If this limit is + * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources, + * make sure to unregister the callbacks with + * {@link #unregisterNetworkCallback(NetworkCallback)}. + * + * @param uid the UID for which to track default network changes. + * @param networkCallback The {@link NetworkCallback} that the system will call as the + * UID's default network changes. + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @throws RuntimeException if the app already has too many callbacks registered. + * @hide + */ + // TODO: @SystemApi(client=MODULE_LIBRARIES) + @SuppressLint({"ExecutorRegistration", "PairedRegistration"}) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + public void registerDefaultNetworkCallbackAsUid(int uid, + @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { CallbackHandler cbHandler = new CallbackHandler(handler); - sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0, + sendRequestForNetwork(uid, null /* need */, networkCallback, 0 /* timeoutMs */, TRACK_DEFAULT, TYPE_NONE, cbHandler); } diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl index 3300fa8fd1..0826922e21 100644 --- a/framework/src/android/net/IConnectivityManager.aidl +++ b/framework/src/android/net/IConnectivityManager.aidl @@ -142,7 +142,7 @@ interface IConnectivityManager in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, in int factorySerialNumber); - NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType, + NetworkRequest requestNetwork(int uid, in NetworkCapabilities networkCapabilities, int reqType, in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, int callbackFlags, String callingPackageName, String callingAttributionTag); From b90bdbdbf410fb7f01147d517f8add27e7b60629 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 22 Mar 2021 18:23:21 +0900 Subject: [PATCH 181/343] Expose registerDefaultNetworkCallbackAsUid. Bug: 165835257 Test: atest FrameworksNetTests Change-Id: I638ed5cd5273d456919630aba1e22f099df1b36c --- framework/api/module-lib-current.txt | 1 + framework/src/android/net/ConnectivityManager.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index aa7a0ac465..f32f08daf7 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -11,6 +11,7 @@ package android.net { method @Nullable public android.net.ProxyInfo getGlobalProxy(); method @NonNull public static android.util.Range getIpSecNetIdRange(); method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackAsUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean); diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java index 1a5299bb00..2e240f947d 100644 --- a/framework/src/android/net/ConnectivityManager.java +++ b/framework/src/android/net/ConnectivityManager.java @@ -4252,7 +4252,7 @@ public class ConnectivityManager { * @throws RuntimeException if the app already has too many callbacks registered. * @hide */ - // TODO: @SystemApi(client=MODULE_LIBRARIES) + @SystemApi(client = MODULE_LIBRARIES) @SuppressLint({"ExecutorRegistration", "PairedRegistration"}) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, From e76b5f70044375e0f9aa52eeb1d0d6962b309b17 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 16 Mar 2021 10:24:43 +0800 Subject: [PATCH 182/343] [VCN15] expose addUnwantedCapability and related APIs Test: m -j doc-comment-check-docs Bug: 175662146 Change-Id: I3f2e6a99e015f09cc4405f6804eac4ae33e3dcc7 --- framework/api/module-lib-current.txt | 7 ++++ .../src/android/net/NetworkCapabilities.java | 33 +++++++++++++++---- framework/src/android/net/NetworkRequest.java | 20 +++++++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 9ca6d8fedc..b179c6da29 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -45,6 +45,7 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); method @Nullable public java.util.Set> getUids(); + method public boolean hasUnwantedCapability(int); field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L @@ -57,7 +58,13 @@ package android.net { method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); } + public class NetworkRequest implements android.os.Parcelable { + method public boolean hasUnwantedCapability(int); + } + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder addUnwantedCapability(int); + method @NonNull public android.net.NetworkRequest.Builder removeUnwantedCapability(int); method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); } diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index c9c0940dfd..881fa8c270 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -639,19 +639,31 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Removes (if found) the given capability from this {@code NetworkCapability} instance. + * Removes (if found) the given capability from this {@code NetworkCapability} + * instance that were added via addCapability(int) or setCapabilities(int[], int[]). * * @param capability the capability to be removed. * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { - // Note that this method removes capabilities that were added via addCapability(int), - // addUnwantedCapability(int) or setCapabilities(int[], int[]). checkValidCapability(capability); final long mask = ~(1 << capability); mNetworkCapabilities &= mask; - mUnwantedNetworkCapabilities &= mask; + return this; + } + + /** + * Removes (if found) the given unwanted capability from this {@code NetworkCapability} + * instance that were added via addUnwantedCapability(int) or setCapabilities(int[], int[]). + * + * @param capability the capability to be removed. + * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide + */ + public @NonNull NetworkCapabilities removeUnwantedCapability(@NetCapability int capability) { + checkValidCapability(capability); + mUnwantedNetworkCapabilities &= ~(1 << capability); return this; } @@ -723,6 +735,7 @@ public final class NetworkCapabilities implements Parcelable { } /** @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public boolean hasUnwantedCapability(@NetCapability int capability) { return isValidCapability(capability) && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0); @@ -736,10 +749,16 @@ public final class NetworkCapabilities implements Parcelable { return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0); } - /** Note this method may result in having the same capability in wanted and unwanted lists. */ private void combineNetCapabilities(@NonNull NetworkCapabilities nc) { - this.mNetworkCapabilities |= nc.mNetworkCapabilities; - this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities; + final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities; + final long unwantedCaps = + this.mUnwantedNetworkCapabilities | nc.mUnwantedNetworkCapabilities; + if ((wantedCaps & unwantedCaps) != 0) { + throw new IllegalArgumentException( + "Cannot have the same capability in wanted and unwanted lists."); + } + this.mNetworkCapabilities = wantedCaps; + this.mUnwantedNetworkCapabilities = unwantedCaps; } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index cf131f0df6..23c92a52ac 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -305,11 +305,30 @@ public class NetworkRequest implements Parcelable { * * @hide */ + @NonNull + @SuppressLint("MissingGetterMatchingBuilder") + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) { mNetworkCapabilities.addUnwantedCapability(capability); return this; } + /** + * Removes (if found) the given unwanted capability from this builder instance. + * + * @param capability The unwanted capability to remove. + * @return The builder to facilitate chaining. + * + * @hide + */ + @NonNull + @SuppressLint("BuilderSetStyle") + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder removeUnwantedCapability(@NetworkCapabilities.NetCapability int capability) { + mNetworkCapabilities.removeUnwantedCapability(capability); + return this; + } + /** * Completely clears all the {@code NetworkCapabilities} from this builder instance, * removing even the capabilities that are set by default when the object is constructed. @@ -567,6 +586,7 @@ public class NetworkRequest implements Parcelable { * * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public boolean hasUnwantedCapability(@NetCapability int capability) { return networkCapabilities.hasUnwantedCapability(capability); } From 7625498617040503ddba026bff28613f2fe30b6c Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 22 Mar 2021 17:24:11 +0800 Subject: [PATCH 183/343] Add NetworkRequest.Builder creating from an existing instance Provide a formal way to construct a new NetworkRequest from an existing instance. The network capabilities inside the NetworkRequest is hidden. There is no way to pass a NetworkRequest and update its capabilities. Add NetworkRequest.Builder creating from an existing instance to allow to clone the network capabilities. Bug: 172183305 Test: make update-api Change-Id: I068462b2a1410daf67b0c95f2b643d396f079531 CTS-Coverage-Bug: 172183305 --- framework/api/current.txt | 1 + framework/src/android/net/NetworkRequest.java | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/framework/api/current.txt b/framework/api/current.txt index e415e01fea..ad44b27f6d 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -396,6 +396,7 @@ package android.net { public static class NetworkRequest.Builder { ctor public NetworkRequest.Builder(); + ctor public NetworkRequest.Builder(@NonNull android.net.NetworkRequest); method public android.net.NetworkRequest.Builder addCapability(int); method public android.net.NetworkRequest.Builder addTransportType(int); method public android.net.NetworkRequest build(); diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index cf131f0df6..f9b3db12c0 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -215,6 +215,14 @@ public class NetworkRequest implements Parcelable { mNetworkCapabilities.setSingleUid(Process.myUid()); } + /** + * Creates a new Builder of NetworkRequest from an existing instance. + */ + public Builder(@NonNull final NetworkRequest request) { + Objects.requireNonNull(request); + mNetworkCapabilities = request.networkCapabilities; + } + /** * Build {@link NetworkRequest} give the current set of capabilities. */ From f0fc6d7f68d5ff0c100b6e7616dec31d2e01a7de Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 19 Mar 2021 22:56:26 +0800 Subject: [PATCH 184/343] Move deduceRestrictedCapability to libs/net and rename it NetworkCapabilities is included in framework-connectivity, so external module cannot have dependencies on its hidden API. Move the method to libs/net so that external modules can use it by including the library. Bug: 178777253 Test: FrameworksNetTests Change-Id: I77970b3a5e5e0e9d263639694b1f06519169bf64 --- .../src/android/net/NetworkCapabilities.java | 66 +------------------ 1 file changed, 2 insertions(+), 64 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index c9c0940dfd..6572bbdee3 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -537,43 +537,6 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_NOT_VPN); - /** - * Capabilities that suggest that a network is restricted. - * {@see #maybeMarkCapabilitiesRestricted}, {@see #FORCE_RESTRICTED_CAPABILITIES} - */ - @VisibleForTesting - /* package */ static final long RESTRICTED_CAPABILITIES = - (1 << NET_CAPABILITY_CBS) - | (1 << NET_CAPABILITY_DUN) - | (1 << NET_CAPABILITY_EIMS) - | (1 << NET_CAPABILITY_FOTA) - | (1 << NET_CAPABILITY_IA) - | (1 << NET_CAPABILITY_IMS) - | (1 << NET_CAPABILITY_MCX) - | (1 << NET_CAPABILITY_RCS) - | (1 << NET_CAPABILITY_VEHICLE_INTERNAL) - | (1 << NET_CAPABILITY_XCAP) - | (1 << NET_CAPABILITY_ENTERPRISE); - - /** - * Capabilities that force network to be restricted. - * {@see #maybeMarkCapabilitiesRestricted}. - */ - private static final long FORCE_RESTRICTED_CAPABILITIES = - (1 << NET_CAPABILITY_OEM_PAID) - | (1 << NET_CAPABILITY_OEM_PRIVATE); - - /** - * Capabilities that suggest that a network is unrestricted. - * {@see #maybeMarkCapabilitiesRestricted}. - */ - @VisibleForTesting - /* package */ static final long UNRESTRICTED_CAPABILITIES = - (1 << NET_CAPABILITY_INTERNET) - | (1 << NET_CAPABILITY_MMS) - | (1 << NET_CAPABILITY_SUPL) - | (1 << NET_CAPABILITY_WIFI_P2P); - /** * Capabilities that are managed by ConnectivityService. */ @@ -792,37 +755,12 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Deduces that all the capabilities it provides are typically provided by restricted networks - * or not. - * - * @return {@code true} if the network should be restricted. - * @hide - */ - public boolean deduceRestrictedCapability() { - // Check if we have any capability that forces the network to be restricted. - final boolean forceRestrictedCapability = - (mNetworkCapabilities & FORCE_RESTRICTED_CAPABILITIES) != 0; - - // Verify there aren't any unrestricted capabilities. If there are we say - // the whole thing is unrestricted unless it is forced to be restricted. - final boolean hasUnrestrictedCapabilities = - (mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0; - - // Must have at least some restricted capabilities. - final boolean hasRestrictedCapabilities = - (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0; - - return forceRestrictedCapability - || (hasRestrictedCapabilities && !hasUnrestrictedCapabilities); - } - - /** - * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if deducing the network is restricted. + * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if inferring the network is restricted. * * @hide */ public void maybeMarkCapabilitiesRestricted() { - if (deduceRestrictedCapability()) { + if (NetworkCapabilitiesUtils.inferRestrictedCapability(this)) { removeCapability(NET_CAPABILITY_NOT_RESTRICTED); } } From 545aafdd16e35123f0c0aa3d93825d0153d6a642 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 22 Feb 2021 18:36:38 +0800 Subject: [PATCH 185/343] Replace the usage of UidRange UidRange is used in a shared way between ConnectivityService and VPN through the use of NetworkCapabilities. UidRange will be part of the ConnectivityService mainline but Vpn.java will stay in the framework. We need a way to replace the APIs using UidRange, or to make UidRange system API. The only really relevant surface here is NetworkCapabilities#{setUids, getUids}. The need for UidRange could be replaced by an integer Range, so replace the usage of UidRange by a integer Range in NetworkCapabilities#{setUids, getUids} and update the relevant callers. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCasesLatestSdk Merged-In: I4e5aec6ef1ea02e038fcd7ed117a3b67b69c5cb9 Change-Id: Idb7f353788c5779a4fbbd107595e9326b99fe0a8 --- .../src/android/net/NetworkCapabilities.java | 31 ++++++++++++------- framework/src/android/net/NetworkRequest.java | 5 +-- framework/src/android/net/UidRange.java | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index cbd6d6140b..fb4ef2b50e 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -33,6 +33,7 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; +import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -216,7 +217,7 @@ public final class NetworkCapabilities implements Parcelable { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - setUids(nc.mUids); // Will make the defensive copy + mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -1519,9 +1520,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - final ArraySet identity = new ArraySet<>(1); - identity.add(new UidRange(uid, uid)); - setUids(identity); + mUids = new ArraySet<>(1); + mUids.add(new UidRange(uid, uid)); return this; } @@ -1530,12 +1530,8 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(Set uids) { - if (null == uids) { - mUids = null; - } else { - mUids = new ArraySet<>(uids); - } + public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { + mUids = UidRange.fromIntRanges(uids); return this; } @@ -1544,8 +1540,19 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public @Nullable Set getUids() { - return null == mUids ? null : new ArraySet<>(mUids); + public @Nullable Set> getUids() { + return UidRange.toIntRanges(mUids); + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set getUidRanges() { + if (mUids == null) return null; + + return new ArraySet<>(mUids); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index dbe3ecc4d7..4ebbf06c51 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -45,6 +45,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; +import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -277,11 +278,11 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @param uids The watched UIDs as a set of {@code Range}, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(Set uids) { + public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; } diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java index 26518d32ed..bc67c745c9 100644 --- a/framework/src/android/net/UidRange.java +++ b/framework/src/android/net/UidRange.java @@ -20,8 +20,11 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Range; import java.util.Collection; +import java.util.Set; /** * An inclusive range of UIDs. @@ -149,4 +152,32 @@ public final class UidRange implements Parcelable { } return false; } + + /** + * Convert a set of {@code Range} to a set of {@link UidRange}. + */ + @Nullable + public static ArraySet fromIntRanges(@Nullable Set> ranges) { + if (null == ranges) return null; + + final ArraySet uids = new ArraySet<>(); + for (Range range : ranges) { + uids.add(new UidRange(range.getLower(), range.getUpper())); + } + return uids; + } + + /** + * Convert a set of {@link UidRange} to a set of {@code Range}. + */ + @Nullable + public static ArraySet> toIntRanges(@Nullable Set ranges) { + if (null == ranges) return null; + + final ArraySet> uids = new ArraySet<>(); + for (UidRange range : ranges) { + uids.add(new Range(range.start, range.stop)); + } + return uids; + } } From 14a86c3cbd43e1312a984e04f80d919a07053811 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 22 Feb 2021 18:36:38 +0800 Subject: [PATCH 186/343] Replace the usage of UidRange UidRange is used in a shared way between ConnectivityService and VPN through the use of NetworkCapabilities. UidRange will be part of the ConnectivityService mainline but Vpn.java will stay in the framework. We need a way to replace the APIs using UidRange, or to make UidRange system API. The only really relevant surface here is NetworkCapabilities#{setUids, getUids}. The need for UidRange could be replaced by an integer Range, so replace the usage of UidRange by a integer Range in NetworkCapabilities#{setUids, getUids} and update the relevant callers. Bug: 172183305 Test: atest FrameworksNetTests CtsNetTestCasesLatestSdk Merged-In: I4e5aec6ef1ea02e038fcd7ed117a3b67b69c5cb9 Merged-In: Idb7f353788c5779a4fbbd107595e9326b99fe0a8 Change-Id: Idb7f353788c5779a4fbbd107595e9326b99fe0a8 --- .../src/android/net/NetworkCapabilities.java | 31 ++++++++++++------- framework/src/android/net/NetworkRequest.java | 5 +-- framework/src/android/net/UidRange.java | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index cbd6d6140b..fb4ef2b50e 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -33,6 +33,7 @@ import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; import android.util.ArraySet; +import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -216,7 +217,7 @@ public final class NetworkCapabilities implements Parcelable { setTransportInfo(null); } mSignalStrength = nc.mSignalStrength; - setUids(nc.mUids); // Will make the defensive copy + mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids); setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; @@ -1519,9 +1520,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ public @NonNull NetworkCapabilities setSingleUid(int uid) { - final ArraySet identity = new ArraySet<>(1); - identity.add(new UidRange(uid, uid)); - setUids(identity); + mUids = new ArraySet<>(1); + mUids.add(new UidRange(uid, uid)); return this; } @@ -1530,12 +1530,8 @@ public final class NetworkCapabilities implements Parcelable { * This makes a copy of the set so that callers can't modify it after the call. * @hide */ - public @NonNull NetworkCapabilities setUids(Set uids) { - if (null == uids) { - mUids = null; - } else { - mUids = new ArraySet<>(uids); - } + public @NonNull NetworkCapabilities setUids(@Nullable Set> uids) { + mUids = UidRange.fromIntRanges(uids); return this; } @@ -1544,8 +1540,19 @@ public final class NetworkCapabilities implements Parcelable { * This returns a copy of the set so that callers can't modify the original object. * @hide */ - public @Nullable Set getUids() { - return null == mUids ? null : new ArraySet<>(mUids); + public @Nullable Set> getUids() { + return UidRange.toIntRanges(mUids); + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public @Nullable Set getUidRanges() { + if (mUids == null) return null; + + return new ArraySet<>(mUids); } /** diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index dbe3ecc4d7..4ebbf06c51 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -45,6 +45,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.text.TextUtils; +import android.util.Range; import android.util.proto.ProtoOutputStream; import java.util.Arrays; @@ -277,11 +278,11 @@ public class NetworkRequest implements Parcelable { * Set the watched UIDs for this request. This will be reset and wiped out unless * the calling app holds the CHANGE_NETWORK_STATE permission. * - * @param uids The watched UIDs as a set of UidRanges, or null for everything. + * @param uids The watched UIDs as a set of {@code Range}, or null for everything. * @return The builder to facilitate chaining. * @hide */ - public Builder setUids(Set uids) { + public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; } diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java index 26518d32ed..bc67c745c9 100644 --- a/framework/src/android/net/UidRange.java +++ b/framework/src/android/net/UidRange.java @@ -20,8 +20,11 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.ArraySet; +import android.util.Range; import java.util.Collection; +import java.util.Set; /** * An inclusive range of UIDs. @@ -149,4 +152,32 @@ public final class UidRange implements Parcelable { } return false; } + + /** + * Convert a set of {@code Range} to a set of {@link UidRange}. + */ + @Nullable + public static ArraySet fromIntRanges(@Nullable Set> ranges) { + if (null == ranges) return null; + + final ArraySet uids = new ArraySet<>(); + for (Range range : ranges) { + uids.add(new UidRange(range.getLower(), range.getUpper())); + } + return uids; + } + + /** + * Convert a set of {@link UidRange} to a set of {@code Range}. + */ + @Nullable + public static ArraySet> toIntRanges(@Nullable Set ranges) { + if (null == ranges) return null; + + final ArraySet> uids = new ArraySet<>(); + for (UidRange range : ranges) { + uids.add(new Range(range.start, range.stop)); + } + return uids; + } } From 32996ff68f68ed84e0c6301d5db9ca9e63c78db7 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 11 Mar 2021 16:13:13 +0800 Subject: [PATCH 187/343] Expose uids related APIs in NetworkRequest and NetworkCapabilities NetworkRequest is moving into the incoming connectivity mainline module. The hidden setUids becomes inaccessible outside the module. Shims for support cts in different API levels will need to use it to verify the behavior of NetworkRequest. Thus, expose it to the API surface. Also, VPN uses getUids and setUids to control network capabilities. Networkcapabilities is a part of incoming connectivity mainline module but VPN is not. Thus, exposing these two methods are needed to allow VPN to continue using it. Test: make update-api Bug: 172183305 Merged-In: I107c329d4d7130d488772166eae8b5e7aaa2ff04 Change-Id: If76877e6bde7abe3b5ddde078f87eefd027e675c --- framework/api/module-lib-current.txt | 9 ++++++++ .../src/android/net/NetworkCapabilities.java | 21 +++++++++++++++++++ framework/src/android/net/NetworkRequest.java | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 34dd149824..aa7a0ac465 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -38,6 +38,7 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); + method @Nullable public java.util.Set> getUids(); field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L @@ -46,6 +47,14 @@ package android.net { field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static final class NetworkCapabilities.Builder { + method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); + } + + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); + } + public class ParseException extends java.lang.RuntimeException { ctor public ParseException(@NonNull String); ctor public ParseException(@NonNull String, @NonNull Throwable); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index fb4ef2b50e..c9c0940dfd 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -23,6 +23,7 @@ import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -1538,8 +1539,13 @@ public final class NetworkCapabilities implements Parcelable { /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. + * + * @return the list of UIDs this network applies to. If {@code null}, then the network applies + * to all UIDs. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("NullableCollection") public @Nullable Set> getUids() { return UidRange.toIntRanges(mUids); } @@ -2741,6 +2747,21 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Set the list of UIDs this network applies to. + * + * @param uids the list of UIDs this network applies to, or {@code null} if this network + * applies to all UIDs. + * @return this builder + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder setUids(@Nullable Set> uids) { + mCaps.setUids(uids); + return this; + } + /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4ebbf06c51..cf131f0df6 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -282,6 +283,9 @@ public class NetworkRequest implements Parcelable { * @return The builder to facilitate chaining. * @hide */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("MissingGetterMatchingBuilder") public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; From 0ffaec3d501d112c4b972ad1f770fbf8664d43c8 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 11 Mar 2021 16:13:13 +0800 Subject: [PATCH 188/343] Expose uids related APIs in NetworkRequest and NetworkCapabilities NetworkRequest is moving into the incoming connectivity mainline module. The hidden setUids becomes inaccessible outside the module. Shims for support cts in different API levels will need to use it to verify the behavior of NetworkRequest. Thus, expose it to the API surface. Also, VPN uses getUids and setUids to control network capabilities. Networkcapabilities is a part of incoming connectivity mainline module but VPN is not. Thus, exposing these two methods are needed to allow VPN to continue using it. Test: make update-api Bug: 172183305 Merged-In: I107c329d4d7130d488772166eae8b5e7aaa2ff04 Merged-In: If76877e6bde7abe3b5ddde078f87eefd027e675c Change-Id: If76877e6bde7abe3b5ddde078f87eefd027e675c --- framework/api/module-lib-current.txt | 9 ++++++++ .../src/android/net/NetworkCapabilities.java | 21 +++++++++++++++++++ framework/src/android/net/NetworkRequest.java | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 34dd149824..aa7a0ac465 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -38,6 +38,7 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long); + method @Nullable public java.util.Set> getUids(); field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L @@ -46,6 +47,14 @@ package android.net { field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static final class NetworkCapabilities.Builder { + method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set>); + } + + public static class NetworkRequest.Builder { + method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set>); + } + public class ParseException extends java.lang.RuntimeException { ctor public ParseException(@NonNull String); ctor public ParseException(@NonNull String, @NonNull Throwable); diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index fb4ef2b50e..c9c0940dfd 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -23,6 +23,7 @@ import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; @@ -1538,8 +1539,13 @@ public final class NetworkCapabilities implements Parcelable { /** * Get the list of UIDs this network applies to. * This returns a copy of the set so that callers can't modify the original object. + * + * @return the list of UIDs this network applies to. If {@code null}, then the network applies + * to all UIDs. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("NullableCollection") public @Nullable Set> getUids() { return UidRange.toIntRanges(mUids); } @@ -2741,6 +2747,21 @@ public final class NetworkCapabilities implements Parcelable { return this; } + /** + * Set the list of UIDs this network applies to. + * + * @param uids the list of UIDs this network applies to, or {@code null} if this network + * applies to all UIDs. + * @return this builder + * @hide + */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder setUids(@Nullable Set> uids) { + mCaps.setUids(uids); + return this; + } + /** * Builds the instance of the capabilities. * diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java index 4ebbf06c51..cf131f0df6 100644 --- a/framework/src/android/net/NetworkRequest.java +++ b/framework/src/android/net/NetworkRequest.java @@ -36,6 +36,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; @@ -282,6 +283,9 @@ public class NetworkRequest implements Parcelable { * @return The builder to facilitate chaining. * @hide */ + @NonNull + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("MissingGetterMatchingBuilder") public Builder setUids(@Nullable Set> uids) { mNetworkCapabilities.setUids(uids); return this; From 974644dd3cf95b3db56271e5cd76a15b650370c3 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Mon, 22 Mar 2021 15:07:41 +0800 Subject: [PATCH 189/343] Have a new method in NetworkAgentConfig.Builder to set allowBypass Have a new method in NetworkAgentConfig.Builder for Vpn to set allowBypass. Bug: 182963397 Test: m Change-Id: I3f244464438325ee7f8a1b953d3fb28186293628 --- framework/api/module-lib-current.txt | 2 ++ .../src/android/net/NetworkAgentConfig.java | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 9ca6d8fedc..663a4ff9db 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -36,9 +36,11 @@ package android.net { public final class NetworkAgentConfig implements android.os.Parcelable { method @Nullable public String getSubscriberId(); + method public boolean isBypassableVpn(); } public static final class NetworkAgentConfig.Builder { + method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean); method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); } diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java index 5e50a6404a..0bd2371bfc 100644 --- a/framework/src/android/net/NetworkAgentConfig.java +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -63,6 +63,16 @@ public final class NetworkAgentConfig implements Parcelable { return explicitlySelected; } + /** + * @return whether this VPN connection can be bypassed by the apps. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public boolean isBypassableVpn() { + return allowBypass; + } + /** * Set if the user desires to use this network even if it is unvalidated. This field has meaning * only if {@link explicitlySelected} is true. If it is, this field must also be set to the @@ -346,6 +356,19 @@ public final class NetworkAgentConfig implements Parcelable { return this; } + /** + * Sets whether the apps can bypass the VPN connection. + * + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + @SystemApi(client = MODULE_LIBRARIES) + public Builder setBypassableVpn(boolean allowBypass) { + mConfig.allowBypass = allowBypass; + return this; + } + /** * Returns the constructed {@link NetworkAgentConfig} object. */ From 02da9189190c0b3bbb4847aee8209e82510dba80 Mon Sep 17 00:00:00 2001 From: Joshua Mccloskey Date: Mon, 22 Mar 2021 18:55:32 +0000 Subject: [PATCH 190/343] Revert "Have a new method in NetworkAgentConfig.Builder to set allowBypass" This reverts commit 974644dd3cf95b3db56271e5cd76a15b650370c3. Reason for revert: Broken build b/183416288 Change-Id: Id9ec9fb98b8f88eeb7db1d1442d76456aaf350d1 --- framework/api/module-lib-current.txt | 2 -- .../src/android/net/NetworkAgentConfig.java | 23 ------------------- 2 files changed, 25 deletions(-) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index 663a4ff9db..9ca6d8fedc 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -36,11 +36,9 @@ package android.net { public final class NetworkAgentConfig implements android.os.Parcelable { method @Nullable public String getSubscriberId(); - method public boolean isBypassableVpn(); } public static final class NetworkAgentConfig.Builder { - method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean); method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); } diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java index 0bd2371bfc..5e50a6404a 100644 --- a/framework/src/android/net/NetworkAgentConfig.java +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -63,16 +63,6 @@ public final class NetworkAgentConfig implements Parcelable { return explicitlySelected; } - /** - * @return whether this VPN connection can be bypassed by the apps. - * - * @hide - */ - @SystemApi(client = MODULE_LIBRARIES) - public boolean isBypassableVpn() { - return allowBypass; - } - /** * Set if the user desires to use this network even if it is unvalidated. This field has meaning * only if {@link explicitlySelected} is true. If it is, this field must also be set to the @@ -356,19 +346,6 @@ public final class NetworkAgentConfig implements Parcelable { return this; } - /** - * Sets whether the apps can bypass the VPN connection. - * - * @return this builder, to facilitate chaining. - * @hide - */ - @NonNull - @SystemApi(client = MODULE_LIBRARIES) - public Builder setBypassableVpn(boolean allowBypass) { - mConfig.allowBypass = allowBypass; - return this; - } - /** * Returns the constructed {@link NetworkAgentConfig} object. */ From 0e345e9b1a3b6115f24cdb5ed0ac54260d1e84a8 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Mon, 22 Mar 2021 15:07:41 +0800 Subject: [PATCH 191/343] Have a new method in NetworkAgentConfig.Builder to set allowBypass Have a new method in NetworkAgentConfig.Builder for Vpn to set allowBypass. Bug: 182963397 Test: m Change-Id: I3f244464438325ee7f8a1b953d3fb28186293628 --- framework/api/module-lib-current.txt | 2 ++ .../src/android/net/NetworkAgentConfig.java | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt index f32f08daf7..23a71798d7 100644 --- a/framework/api/module-lib-current.txt +++ b/framework/api/module-lib-current.txt @@ -31,9 +31,11 @@ package android.net { public final class NetworkAgentConfig implements android.os.Parcelable { method @Nullable public String getSubscriberId(); + method public boolean isBypassableVpn(); } public static final class NetworkAgentConfig.Builder { + method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean); method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String); } diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java index 5e50a6404a..0bd2371bfc 100644 --- a/framework/src/android/net/NetworkAgentConfig.java +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -63,6 +63,16 @@ public final class NetworkAgentConfig implements Parcelable { return explicitlySelected; } + /** + * @return whether this VPN connection can be bypassed by the apps. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public boolean isBypassableVpn() { + return allowBypass; + } + /** * Set if the user desires to use this network even if it is unvalidated. This field has meaning * only if {@link explicitlySelected} is true. If it is, this field must also be set to the @@ -346,6 +356,19 @@ public final class NetworkAgentConfig implements Parcelable { return this; } + /** + * Sets whether the apps can bypass the VPN connection. + * + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + @SystemApi(client = MODULE_LIBRARIES) + public Builder setBypassableVpn(boolean allowBypass) { + mConfig.allowBypass = allowBypass; + return this; + } + /** * Returns the constructed {@link NetworkAgentConfig} object. */ From 31f329e98732fb83210b982640a63eb0125db438 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 21 Mar 2021 14:30:38 +0000 Subject: [PATCH 192/343] Add NDK API for getprocnetwork The API is the getter couterpart for setprocnetwork. Use it in NetworkUtils so that the NDK API can be the source of truth for the process network. Bug: 171540887 Test: atest CtsNetTestCases Tests in change I311b58585033c2ca50ce5477ea9cd94b6f127507 Change-Id: Ie8f68cf1fa57deddb63324c1abf3d6fd5b0ef500 --- framework/Android.bp | 2 ++ framework/jni/android_net_NetworkUtils.cpp | 20 ++++++++++++++------ framework/src/android/net/NetworkUtils.java | 15 +++++++++++++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/framework/Android.bp b/framework/Android.bp index 657d5a3d2e..3553c1f053 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -128,6 +128,7 @@ cc_library_static { srcs: [ "jni/android_net_NetworkUtils.cpp", ], + shared_libs: ["libandroid_net"], apex_available: [ "//apex_available:platform", "com.android.tethering", @@ -140,6 +141,7 @@ cc_library_shared { srcs: [ "jni/onload.cpp", ], + shared_libs: ["libandroid"], static_libs: ["libconnectivityframeworkutils"], apex_available: [ "//apex_available:platform", diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp index 19ffe77c1f..89b058af69 100644 --- a/framework/jni/android_net_NetworkUtils.cpp +++ b/framework/jni/android_net_NetworkUtils.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -122,14 +123,21 @@ static void android_net_utils_detachBPFFilter(JNIEnv *env, jobject clazz, jobjec } } -static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId) +static jboolean android_net_utils_bindProcessToNetworkHandle(JNIEnv *env, jobject thiz, + jlong netHandle) { - return (jboolean) !setNetworkForProcess(netId); + return (jboolean) !android_setprocnetwork(netHandle); } -static jint android_net_utils_getBoundNetworkForProcess(JNIEnv *env, jobject thiz) +static jlong android_net_utils_getBoundNetworkHandleForProcess(JNIEnv *env, jobject thiz) { - return getNetworkForProcess(); + net_handle_t network; + if (android_getprocnetwork(&network) != 0) { + jniThrowExceptionFmt(env, "java/lang/IllegalStateException", + "android_getprocnetwork(): %s", strerror(errno)); + return NETWORK_UNSPECIFIED; + } + return (jlong) network; } static jboolean android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz, @@ -283,8 +291,8 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j // clang-format off static const JNINativeMethod gNetworkUtilMethods[] = { /* name, signature, funcPtr */ - { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork }, - { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess }, + { "bindProcessToNetworkHandle", "(J)Z", (void*) android_net_utils_bindProcessToNetworkHandle }, + { "getBoundNetworkHandleForProcess", "()J", (void*) android_net_utils_getBoundNetworkHandleForProcess }, { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, { "bindSocketToNetwork", "(Ljava/io/FileDescriptor;I)I", (void*) android_net_utils_bindSocketToNetwork }, { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess }, diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java index c0f262815b..4c61d4089d 100644 --- a/framework/src/android/net/NetworkUtils.java +++ b/framework/src/android/net/NetworkUtils.java @@ -16,6 +16,8 @@ package android.net; +import static android.net.ConnectivityManager.NETID_UNSET; + import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.system.ErrnoException; @@ -55,6 +57,8 @@ public class NetworkUtils { */ public static native void detachBPFFilter(FileDescriptor fd) throws SocketException; + private static native boolean bindProcessToNetworkHandle(long netHandle); + /** * Binds the current process to the network designated by {@code netId}. All sockets created * in the future (and not explicitly bound via a bound {@link SocketFactory} (see @@ -63,13 +67,20 @@ public class NetworkUtils { * is by design so an application doesn't accidentally use sockets it thinks are still bound to * a particular {@code Network}. Passing NETID_UNSET clears the binding. */ - public native static boolean bindProcessToNetwork(int netId); + public static boolean bindProcessToNetwork(int netId) { + return bindProcessToNetworkHandle(new Network(netId).getNetworkHandle()); + } + + private static native long getBoundNetworkHandleForProcess(); /** * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}. */ - public native static int getBoundNetworkForProcess(); + public static int getBoundNetworkForProcess() { + final long netHandle = getBoundNetworkHandleForProcess(); + return netHandle == 0L ? NETID_UNSET : Network.fromNetworkHandle(netHandle).getNetId(); + } /** * Binds host resolutions performed by this process to the network designated by {@code netId}. From c4fd62072b250a11c79cc786f84a129af8392089 Mon Sep 17 00:00:00 2001 From: lifr Date: Thu, 18 Mar 2021 01:11:30 +0800 Subject: [PATCH 193/343] [TL02]Remove hidden API usage of NetworkAgent The connection service will become the mainline module. Remove the hidden API usage of NetworkAgent. Bug: 170598012 CTS-Coverage-Bug: 170598012 Test: atest FrameworksNetTests FrameworksTelephonyTests atest FrameworksWifiTests Change-Id: I4e4040ae7f94bdf479c7df9ec2ffabafbe06331c --- framework/api/system-current.txt | 8 ++ framework/src/android/net/NetworkAgent.java | 7 +- .../src/android/net/NetworkAgentConfig.java | 45 +++++++++- .../src/android/net/SocketKeepalive.java | 84 ++++++++++++++----- 4 files changed, 119 insertions(+), 25 deletions(-) diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 358cea85a2..535ba384fa 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -216,6 +216,7 @@ package android.net { method public void markConnected(); method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData); method public void onAutomaticReconnectDisabled(); + method public void onBandwidthUpdateRequested(); method public void onNetworkUnwanted(); method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter); method public void onQosCallbackUnregistered(int); @@ -233,6 +234,7 @@ package android.net { method public final void sendQosSessionAvailable(int, int, @NonNull android.telephony.data.EpsBearerQosSessionAttributes); method public final void sendQosSessionLost(int, int); method public final void sendSocketKeepaliveEvent(int, int); + method @Deprecated public void setLegacySubtype(int, @NonNull String); method public final void setUnderlyingNetworks(@Nullable java.util.List); method public void unregister(); field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 @@ -253,7 +255,12 @@ package android.net { public static final class NetworkAgentConfig.Builder { ctor public NetworkAgentConfig.Builder(); method @NonNull public android.net.NetworkAgentConfig build(); + method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection(); + method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification(); method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyExtraInfo(@NonNull String); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubType(int); + method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubTypeName(@NonNull String); method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int); method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String); method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean); @@ -388,6 +395,7 @@ package android.net { } public abstract class SocketKeepalive implements java.lang.AutoCloseable { + field public static final int ERROR_NO_SUCH_SLOT = -33; // 0xffffffdf field public static final int SUCCESS = 0; // 0x0 } diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java index 3863ed1113..1ff0140006 100644 --- a/framework/src/android/net/NetworkAgent.java +++ b/framework/src/android/net/NetworkAgent.java @@ -362,9 +362,8 @@ public abstract class NetworkAgent { public static final int CMD_UNREGISTER_QOS_CALLBACK = BASE + 21; private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { - // The subtype can be changed with (TODO) setLegacySubtype, but it starts - // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description. - final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, ""); + final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType, + config.legacyTypeName, config.legacySubTypeName); ni.setIsAvailable(true); ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */, config.getLegacyExtraInfo()); @@ -829,6 +828,7 @@ public abstract class NetworkAgent { * @hide */ @Deprecated + @SystemApi public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); queueOrSendNetworkInfo(mNetworkInfo); @@ -962,6 +962,7 @@ public abstract class NetworkAgent { * shall try to overwrite this method and produce a bandwidth update if capable. * @hide */ + @SystemApi public void onBandwidthUpdateRequested() { pollLceData(); } diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java index 5e50a6404a..fb6fcc1274 100644 --- a/framework/src/android/net/NetworkAgentConfig.java +++ b/framework/src/android/net/NetworkAgentConfig.java @@ -164,6 +164,12 @@ public final class NetworkAgentConfig implements Parcelable { return legacyType; } + /** + * The legacy Sub type of this network agent, or TYPE_NONE if unset. + * @hide + */ + public int legacySubType = ConnectivityManager.TYPE_NONE; + /** * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. @@ -189,6 +195,13 @@ public final class NetworkAgentConfig implements Parcelable { return legacyTypeName; } + /** + * The name of the legacy Sub network type. It's a free-form string. + * @hide + */ + @NonNull + public String legacySubTypeName = ""; + /** * The legacy extra info of the agent. The extra info should only be : *