[automerger skipped] Merge "Add network disconnected callback" am: c1657fb7f8 am: edca52ab74 am: 7b978c5cd7 -s ours
am skip reason: skip tag Change-Id I602ff2c688909473b03b72c9407d4286608cff4c with SHA-1 9affe28062 is already in history
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1652259
Change-Id: I7a5a9589eaa8ef0022d5f9ee5f857bbe70fa38ad
diff --git a/framework/Android.bp b/framework/Android.bp
index 017ff51..74cecdd 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -25,6 +25,8 @@
java_library {
name: "framework-connectivity-protos",
+ sdk_version: "module_current",
+ min_sdk_version: "30",
proto: {
type: "nano",
},
@@ -33,7 +35,6 @@
":framework-javastream-protos",
],
apex_available: [
- "//apex_available:platform",
"com.android.tethering",
],
jarjar_rules: "jarjar-rules-proto.txt",
@@ -80,12 +81,13 @@
java_sdk_library {
name: "framework-connectivity",
- api_only: true,
+ sdk_version: "module_current",
+ min_sdk_version: "30",
defaults: ["framework-module-defaults"],
- // TODO: build against module API
- platform_apis: true,
+ installable: true,
srcs: [
":framework-connectivity-sources",
+ ":net-utils-framework-common-srcs",
],
aidl: {
include_dirs: [
@@ -97,44 +99,80 @@
"frameworks/native/aidl/binder", // For PersistableBundle.aidl
],
},
- libs: [
- "unsupportedappusage",
- ],
- 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
+ impl_only_libs: [
+ // TODO (b/183097033) remove once module_current includes core_platform
+ "stable.core.platform.api.stubs",
"framework-tethering.stubs.module_lib",
"framework-wifi.stubs.module_lib",
+ "net-utils-device-common",
+ ],
+ libs: [
"unsupportedappusage",
- "ServiceConnectivityResources",
],
static_libs: [
"framework-connectivity-protos",
- "net-utils-device-common",
],
jarjar_rules: "jarjar-rules.txt",
- apex_available: ["com.android.tethering"],
- installable: true,
- permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+ permitted_packages: ["android.net"],
+ impl_library_visibility: [
+ "//packages/modules/Connectivity/Tethering/apex",
+ // In preparation for future move
+ "//packages/modules/Connectivity/apex",
+ "//packages/modules/Connectivity/service",
+ "//frameworks/base/packages/Connectivity/service",
+ "//frameworks/base",
+ "//packages/modules/Connectivity/Tethering/tests/unit",
+ ],
+ apex_available: [
+ "com.android.tethering",
+ ],
+}
+
+cc_defaults {
+ name: "libframework-connectivity-defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ // Don't warn about S API usage even with
+ // min_sdk 30: the library is only loaded
+ // on S+ devices
+ "-Wno-unguarded-availability",
+ "-Wthread-safety",
+ ],
+ shared_libs: [
+ "liblog",
+ "libnativehelper",
+ ],
+ header_libs: [
+ "dnsproxyd_protocol_headers",
+ ],
+}
+
+cc_library_static {
+ name: "libconnectivityframeworkutils",
+ defaults: ["libframework-connectivity-defaults"],
+ srcs: [
+ "jni/android_net_NetworkUtils.cpp",
+ ],
+ shared_libs: ["libandroid_net"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ ],
+}
+
+cc_library_shared {
+ name: "libframework-connectivity-jni",
+ min_sdk_version: "30",
+ defaults: ["libframework-connectivity-defaults"],
+ srcs: [
+ "jni/android_net_NetworkUtils.cpp",
+ "jni/onload.cpp",
+ ],
+ shared_libs: ["libandroid"],
+ stl: "libc++_static",
+ apex_available: [
+ "com.android.tethering",
+ ],
}
diff --git a/framework/api/current.txt b/framework/api/current.txt
index ad44b27..0a9560a 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -68,6 +68,7 @@
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 @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public android.net.Network getActiveNetworkForUid(int);
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();
@@ -387,7 +388,9 @@
public class NetworkRequest implements android.os.Parcelable {
method public boolean canBeSatisfiedBy(@Nullable android.net.NetworkCapabilities);
method public int describeContents();
+ method @NonNull public int[] getCapabilities();
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+ method @NonNull public int[] getTransportTypes();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
method public void writeToParcel(android.os.Parcel, int);
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 35e45ec..970a236 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -26,6 +26,9 @@
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 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 int BLOCKED_METERED_REASON_ADMIN_DISABLED = 262144; // 0x40000
field public static final int BLOCKED_METERED_REASON_DATA_SAVER = 65536; // 0x10000
field public static final int BLOCKED_METERED_REASON_MASK = -65536; // 0xffff0000
@@ -120,6 +123,7 @@
}
public class NetworkRequest implements android.os.Parcelable {
+ method @NonNull public int[] getUnwantedCapabilities();
method public boolean hasUnwantedCapability(int);
}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 6f832c6..95df8b8 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -217,6 +217,7 @@
method public void markConnected();
method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
method public void onAutomaticReconnectDisabled();
+ method public void onBandwidthUpdateRequested();
method public void onNetworkCreated();
method public void onNetworkDisconnected();
method public void onNetworkUnwanted();
@@ -236,6 +237,7 @@
method public final void sendQosSessionAvailable(int, int, @NonNull android.net.QosSessionAttributes);
method public final void sendQosSessionLost(int, 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<android.net.Network>);
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
@@ -256,7 +258,12 @@
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);
@@ -265,15 +272,18 @@
public final class NetworkCapabilities implements android.os.Parcelable {
method @NonNull public int[] getAdministratorUids();
+ method @Nullable public static String getCapabilityCarrierName(int);
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_BIP = 31; // 0x1f
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
+ field public static final int NET_CAPABILITY_VSIM = 30; // 0x1e
}
public static final class NetworkCapabilities.Builder {
@@ -304,9 +314,16 @@
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);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void registerNetworkOffer(@NonNull android.net.NetworkScore, @NonNull android.net.NetworkCapabilities, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkProvider.NetworkOfferCallback);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkOffer(@NonNull android.net.NetworkProvider.NetworkOfferCallback);
field public static final int ID_NONE = -1; // 0xffffffff
}
+ public static interface NetworkProvider.NetworkOfferCallback {
+ method public void onNetworkNeeded(@NonNull android.net.NetworkRequest);
+ method public void onNetworkUnneeded(@NonNull android.net.NetworkRequest);
+ }
+
public class NetworkReleasedException extends java.lang.Exception {
}
@@ -321,14 +338,18 @@
public final class NetworkScore implements android.os.Parcelable {
method public int describeContents();
+ method public int getKeepConnectedReason();
method public int getLegacyInt();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkScore> CREATOR;
+ field public static final int KEEP_CONNECTED_FOR_HANDOVER = 1; // 0x1
+ field public static final int KEEP_CONNECTED_NONE = 0; // 0x0
}
public static final class NetworkScore.Builder {
ctor public NetworkScore.Builder();
method @NonNull public android.net.NetworkScore build();
+ method @NonNull public android.net.NetworkScore.Builder setKeepConnectedReason(int);
method @NonNull public android.net.NetworkScore.Builder setLegacyInt(int);
}
@@ -405,6 +426,7 @@
}
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/jarjar-rules.txt b/framework/jarjar-rules.txt
index 0959840..7474c24 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.**
diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp
new file mode 100644
index 0000000..e8bb42d
--- /dev/null
+++ b/framework/jni/android_net_NetworkUtils.cpp
@@ -0,0 +1,281 @@
+/*
+ * 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 <vector>
+
+#include <android/file_descriptor_jni.h>
+#include <android/multinetwork.h>
+#include <arpa/inet.h>
+#include <linux/filter.h>
+#include <linux/if_arp.h>
+#include <linux/tcp.h>
+#include <net/if.h>
+#include <netinet/ether.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+#include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
+#include <cutils/properties.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <utils/Log.h>
+#include <utils/misc.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;
+}
+
+template <typename T>
+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<T>(res);
+}
+
+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_bindProcessToNetworkHandle(JNIEnv *env, jobject thiz,
+ jlong netHandle)
+{
+ return (jboolean) !android_setprocnetwork(netHandle);
+}
+
+static jlong android_net_utils_getBoundNetworkHandleForProcess(JNIEnv *env, jobject thiz)
+{
+ 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,
+ jint netId, jlong netHandle)
+{
+ return (jboolean) !android_setprocdns(netHandle);
+}
+
+static jint android_net_utils_bindSocketToNetworkHandle(JNIEnv *env, jobject thiz, jobject javaFd,
+ jlong netHandle) {
+ return android_setsocknetwork(netHandle, AFileDescriptor_getFD(env, javaFd));
+}
+
+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<jbyte*>(dst));
+ return true;
+}
+
+static jobject android_net_utils_resNetworkQuery(JNIEnv *env, jobject thiz, jlong netHandle,
+ 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<char> queryname(byteCountUTF8 + 1, 0);
+
+ env->GetStringUTFRegion(dname, 0, javaCharsCount, queryname.data());
+
+ int fd = android_res_nquery(netHandle, queryname.data(), ns_class, ns_type, flags);
+
+ if (fd < 0) {
+ jniThrowErrnoException(env, "resNetworkQuery", -fd);
+ return nullptr;
+ }
+
+ return jniCreateFileDescriptor(env, fd);
+}
+
+static jobject android_net_utils_resNetworkSend(JNIEnv *env, jobject thiz, jlong netHandle,
+ jbyteArray msg, jint msgLen, jint flags) {
+ uint8_t data[MAXCMDSIZE];
+
+ checkLenAndCopy(env, msg, msgLen, data);
+ int fd = android_res_nsend(netHandle, data, msgLen, flags);
+
+ if (fd < 0) {
+ jniThrowErrnoException(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<uint8_t> buf(MAXPACKETSIZE, 0);
+
+ int res = android_res_nresult(fd, &rcode, buf.data(), MAXPACKETSIZE);
+ jniSetFileDescriptorOfFD(env, javaFd, -1);
+ if (res < 0) {
+ jniThrowErrnoException(env, "resNetworkResult", -res);
+ return nullptr;
+ }
+
+ jbyteArray answer = env->NewByteArray(res);
+ if (answer == nullptr) {
+ jniThrowErrnoException(env, "resNetworkResult", ENOMEM);
+ return nullptr;
+ } else {
+ env->SetByteArrayRegion(answer, 0, res,
+ reinterpret_cast<jbyte*>(buf.data()));
+ }
+
+ jclass class_DnsResponse = env->FindClass("android/net/DnsResolver$DnsResponse");
+ jmethodID ctor = env->GetMethodID(class_DnsResponse, "<init>", "([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);
+ android_res_cancel(fd);
+ jniSetFileDescriptorOfFD(env, javaFd, -1);
+}
+
+static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) {
+ net_handle_t dnsNetHandle = NETWORK_UNSPECIFIED;
+ if (int res = android_getprocdns(&dnsNetHandle) < 0) {
+ jniThrowErrnoException(env, "getDnsNetwork", -res);
+ return nullptr;
+ }
+
+ static jclass class_Network = MakeGlobalRefOrDie(
+ env, FindClassOrDie(env, "android/net/Network"));
+ static jmethodID method = env->GetStaticMethodID(class_Network, "fromNetworkHandle",
+ "(J)Landroid/net/Network;");
+ return env->CallStaticObjectMethod(class_Network, method, static_cast<jlong>(dnsNetHandle));
+}
+
+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) {
+ jniThrowErrnoException(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) {
+ jniThrowErrnoException(env, "getsockopt : TCP_INFO", errno);
+ return NULL;
+ }
+
+ jclass class_TcpRepairWindow = env->FindClass("android/net/TcpRepairWindow");
+ jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "<init>", "(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 */
+ { "bindProcessToNetworkHandle", "(J)Z", (void*) android_net_utils_bindProcessToNetworkHandle },
+ { "getBoundNetworkHandleForProcess", "()J", (void*) android_net_utils_getBoundNetworkHandleForProcess },
+ { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
+ { "bindSocketToNetworkHandle", "(Ljava/io/FileDescriptor;J)I", (void*) android_net_utils_bindSocketToNetworkHandle },
+ { "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", "(J[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
+ { "resNetworkQuery", "(JLjava/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 0000000..435f434
--- /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 <nativehelper/JNIHelp.h>
+#include <log/log.h>
+
+namespace android {
+
+int register_android_net_NetworkUtils(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&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
diff --git a/framework/src/android/net/CaptivePortalData.java b/framework/src/android/net/CaptivePortalData.java
index 82dbd0f..53aa1b9 100644
--- a/framework/src/android/net/CaptivePortalData.java
+++ b/framework/src/android/net/CaptivePortalData.java
@@ -42,7 +42,7 @@
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;
@@ -73,14 +73,14 @@
mByteLimit = byteLimit;
mExpiryTimeMillis = expiryTimeMillis;
mCaptive = captive;
- mVenueFriendlyName = venueFriendlyName;
+ mVenueFriendlyName = venueFriendlyName == null ? null : venueFriendlyName.toString();
mVenueInfoUrlSource = venueInfoUrlSource;
mUserPortalUrlSource = userPortalUrlSource;
}
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 @@
dest.writeLong(mByteLimit);
dest.writeLong(mExpiryTimeMillis);
dest.writeBoolean(mCaptive);
- dest.writeCharSequence(mVenueFriendlyName);
+ dest.writeString(mVenueFriendlyName);
dest.writeInt(mVenueInfoUrlSource);
dest.writeInt(mUserPortalUrlSource);
}
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index d196c1a..3939c7f 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -425,7 +425,8 @@
*
* @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 @@
*
* @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 @@
*
* @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.
@@ -1189,8 +1192,7 @@
*
* @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
+ * TODO: b/183465229 Cleanup getActiveNetworkForUid once b/165835257 is fixed
*/
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
@Nullable
@@ -2430,7 +2432,7 @@
@NonNull String callingPackage, @Nullable String callingAttributionTag,
boolean throwException) {
return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
- throwException);
+ callingAttributionTag, throwException);
}
/**
@@ -3341,7 +3343,61 @@
provider.setProviderId(NetworkProvider.ID_NONE);
}
+ /**
+ * Register or update a network offer with ConnectivityService.
+ *
+ * ConnectivityService keeps track of offers made by the various providers and matches
+ * them to networking requests made by apps or the system. A callback identifies an offer
+ * uniquely, and later calls with the same callback update the offer. The provider supplies a
+ * score and the capabilities of the network it might be able to bring up ; these act as
+ * filters used by ConnectivityService to only send those requests that can be fulfilled by the
+ * provider.
+ *
+ * The provider is under no obligation to be able to bring up the network it offers at any
+ * given time. Instead, this mechanism is meant to limit requests received by providers
+ * to those they actually have a chance to fulfill, as providers don't have a way to compare
+ * the quality of the network satisfying a given request to their own offer.
+ *
+ * An offer can be updated by calling this again with the same callback object. This is
+ * similar to calling unofferNetwork and offerNetwork again, but will only update the
+ * provider with the changes caused by the changes in the offer.
+ *
+ * @param provider The provider making this offer.
+ * @param score The prospective score of the network.
+ * @param caps The prospective capabilities of the network.
+ * @param callback The callback to call when this offer is needed or unneeded.
+ * @hide exposed via the NetworkProvider class.
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
+ public void offerNetwork(@NonNull final int providerId,
+ @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps,
+ @NonNull final INetworkOfferCallback callback) {
+ try {
+ mService.offerNetwork(providerId,
+ Objects.requireNonNull(score, "null score"),
+ Objects.requireNonNull(caps, "null caps"),
+ Objects.requireNonNull(callback, "null callback"));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ /**
+ * Withdraw a network offer made with {@link #offerNetwork}.
+ *
+ * @param callback The callback passed at registration time. This must be the same object
+ * that was passed to {@link #offerNetwork}
+ * @hide exposed via the NetworkProvider class.
+ */
+ public void unofferNetwork(@NonNull final INetworkOfferCallback callback) {
+ try {
+ mService.unofferNetwork(Objects.requireNonNull(callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/** @hide exposed via the NetworkProvider class. */
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 0826922..728f375 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -23,6 +23,7 @@
import android.net.INetworkAgent;
import android.net.IOnCompleteListener;
import android.net.INetworkActivityListener;
+import android.net.INetworkOfferCallback;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
import android.net.LinkProperties;
@@ -221,4 +222,8 @@
in IOnCompleteListener listener);
int getRestrictBackgroundStatusByCaller();
+
+ void offerNetwork(int providerId, in NetworkScore score,
+ in NetworkCapabilities caps, in INetworkOfferCallback callback);
+ void unofferNetwork(in INetworkOfferCallback callback);
}
diff --git a/framework/src/android/net/INetworkOfferCallback.aidl b/framework/src/android/net/INetworkOfferCallback.aidl
new file mode 100644
index 0000000..ecfba21
--- /dev/null
+++ b/framework/src/android/net/INetworkOfferCallback.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.net.NetworkRequest;
+
+/**
+ * A callback registered with connectivity by network providers together with
+ * a NetworkOffer.
+ *
+ * When the network for this offer is needed to satisfy some application or
+ * system component, connectivity will call onNetworkNeeded on this callback.
+ * When this happens, the provider should try and bring up the network.
+ *
+ * When the network for this offer is no longer needed, for example because
+ * the application has withdrawn the request or if the request is being
+ * satisfied by a network that this offer will never be able to beat,
+ * connectivity calls onNetworkUnneeded. When this happens, the provider
+ * should stop trying to bring up the network, or tear it down if it has
+ * already been brought up.
+ *
+ * When NetworkProvider#offerNetwork is called, the provider can expect to
+ * immediately receive all requests that can be fulfilled by that offer and
+ * are not already satisfied by a better network. It is possible no such
+ * request is currently outstanding, because no requests have been made that
+ * can be satisfied by this offer, or because all such requests are already
+ * satisfied by a better network.
+ * onNetworkNeeded can be called at any time after registration and until the
+ * offer is withdrawn with NetworkProvider#unofferNetwork is called. This
+ * typically happens when a new network request is filed by an application,
+ * or when the network satisfying a request disconnects and this offer now
+ * stands a chance to supply the best network for it.
+ *
+ * @hide
+ */
+oneway interface INetworkOfferCallback {
+ /**
+ * Called when a network for this offer is needed to fulfill this request.
+ * @param networkRequest the request to satisfy
+ */
+ void onNetworkNeeded(in NetworkRequest networkRequest);
+
+ /**
+ * Informs the registrant that the offer is no longer valuable to fulfill this request.
+ */
+ void onNetworkUnneeded(in NetworkRequest networkRequest);
+}
diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java
index 0741414..1f49033 100644
--- a/framework/src/android/net/Network.java
+++ b/framework/src/android/net/Network.java
@@ -27,7 +27,6 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -93,6 +92,7 @@
// value in the native/android/net.c NDK implementation.
private static final long HANDLE_MAGIC = 0xcafed00dL;
private static final int HANDLE_MAGIC_SIZE = 32;
+ private static final int USE_LOCAL_NAMESERVERS_FLAG = 0x80000000;
// A boolean to control how getAllByName()/getByName() behaves in the face
// of Private DNS.
@@ -190,7 +190,7 @@
*/
public int getNetIdForResolv() {
return mPrivateDnsBypass
- ? (int) (0x80000000L | (long) netId) // Non-portable DNS resolution flag.
+ ? (USE_LOCAL_NAMESERVERS_FLAG | netId) // Non-portable DNS resolution flag.
: netId;
}
@@ -453,12 +453,13 @@
throw new IllegalArgumentException(
"Network.fromNetworkHandle refusing to instantiate NETID_UNSET Network.");
}
- if ((networkHandle & ((1L << HANDLE_MAGIC_SIZE) - 1)) != HANDLE_MAGIC
- || networkHandle < 0) {
+ if ((networkHandle & ((1L << HANDLE_MAGIC_SIZE) - 1)) != HANDLE_MAGIC) {
throw new IllegalArgumentException(
"Value passed to fromNetworkHandle() is not a network handle.");
}
- return new Network((int) (networkHandle >> HANDLE_MAGIC_SIZE));
+ final int netIdForResolv = (int) (networkHandle >>> HANDLE_MAGIC_SIZE);
+ return new Network((netIdForResolv & ~USE_LOCAL_NAMESERVERS_FLAG),
+ ((netIdForResolv & USE_LOCAL_NAMESERVERS_FLAG) != 0) /* privateDnsBypass */);
}
/**
@@ -486,7 +487,7 @@
if (netId == 0) {
return 0L; // make this zero condition obvious for debugging
}
- return (((long) netId) << HANDLE_MAGIC_SIZE) | HANDLE_MAGIC;
+ return (((long) getNetIdForResolv()) << HANDLE_MAGIC_SIZE) | HANDLE_MAGIC;
}
// implement the Parcelable interface
@@ -526,11 +527,4 @@
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
index 01b88aa..6b55bb7 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -379,9 +379,8 @@
public static final int CMD_NETWORK_DISCONNECTED = BASE + 23;
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());
@@ -863,6 +862,7 @@
* @hide
*/
@Deprecated
+ @SystemApi
public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) {
mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName);
queueOrSendNetworkInfo(mNetworkInfo);
@@ -996,6 +996,7 @@
* 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 0bd2371..3f058d8 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -175,6 +175,12 @@
}
/**
+ * 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.
*
@@ -200,6 +206,13 @@
}
/**
+ * 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 :
* <ul>
* <li>For cellular agents, the APN name.</li>
@@ -235,6 +248,8 @@
skip464xlat = nac.skip464xlat;
legacyType = nac.legacyType;
legacyTypeName = nac.legacyTypeName;
+ legacySubType = nac.legacySubType;
+ legacySubTypeName = nac.legacySubTypeName;
mLegacyExtraInfo = nac.mLegacyExtraInfo;
}
}
@@ -300,7 +315,6 @@
* 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() {
@@ -313,7 +327,6 @@
* perform its own carrier-specific provisioning procedure.
*
* @return this builder, to facilitate chaining.
- * @hide
*/
@NonNull
public Builder disableProvisioningNotification() {
@@ -334,6 +347,18 @@
}
/**
+ * Sets the legacy sub-type for this network.
+ *
+ * @param legacySubType the type
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setLegacySubType(final int legacySubType) {
+ mConfig.legacySubType = legacySubType;
+ 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.
@@ -345,10 +370,20 @@
}
/**
+ * Sets the name of the legacy Sub-type of the agent. It's a free-form string.
+ * @param legacySubTypeName the name
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setLegacySubTypeName(@NonNull String legacySubTypeName) {
+ mConfig.legacySubTypeName = legacySubTypeName;
+ 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) {
@@ -435,6 +470,8 @@
out.writeInt(skip464xlat ? 1 : 0);
out.writeInt(legacyType);
out.writeString(legacyTypeName);
+ out.writeInt(legacySubType);
+ out.writeString(legacySubTypeName);
out.writeString(mLegacyExtraInfo);
}
@@ -452,6 +489,8 @@
networkAgentConfig.skip464xlat = in.readInt() != 0;
networkAgentConfig.legacyType = in.readInt();
networkAgentConfig.legacyTypeName = in.readString();
+ networkAgentConfig.legacySubType = in.readInt();
+ networkAgentConfig.legacySubTypeName = in.readString();
networkAgentConfig.mLegacyExtraInfo = in.readString();
return networkAgentConfig;
}
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 881fa8c..ca69f16 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -35,7 +35,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Range;
-import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.CollectionUtils;
@@ -274,6 +273,8 @@
NET_CAPABILITY_VEHICLE_INTERNAL,
NET_CAPABILITY_NOT_VCN_MANAGED,
NET_CAPABILITY_ENTERPRISE,
+ NET_CAPABILITY_VSIM,
+ NET_CAPABILITY_BIP,
})
public @interface NetCapability { }
@@ -493,8 +494,22 @@
*/
public static final int NET_CAPABILITY_ENTERPRISE = 29;
+ /**
+ * Indicates that this network has ability to access the carrier's Virtual Sim service.
+ * @hide
+ */
+ @SystemApi
+ public static final int NET_CAPABILITY_VSIM = 30;
+
+ /**
+ * Indicates that this network has ability to support Bearer Independent Protol.
+ * @hide
+ */
+ @SystemApi
+ public static final int NET_CAPABILITY_BIP = 31;
+
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_ENTERPRISE;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_BIP;
/**
* Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -538,43 +553,6 @@
| (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.
*/
private static final long CONNECTIVITY_MANAGED_CAPABILITIES =
@@ -749,6 +727,23 @@
return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0);
}
+ /**
+ * Get the name of the given capability that carriers use.
+ * If the capability does not have a carrier-name, returns null.
+ *
+ * @param capability The capability to get the carrier-name of.
+ * @return The carrier-name of the capability, or null if it doesn't exist.
+ * @hide
+ */
+ @SystemApi
+ public static @Nullable String getCapabilityCarrierName(@NetCapability int capability) {
+ if (capability == NET_CAPABILITY_ENTERPRISE) {
+ return capabilityNameOf(capability);
+ } else {
+ return null;
+ }
+ }
+
private void combineNetCapabilities(@NonNull NetworkCapabilities nc) {
final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities;
final long unwantedCaps =
@@ -811,37 +806,12 @@
}
/**
- * 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);
}
}
@@ -2087,34 +2057,6 @@
}
}
- /** @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
*/
@@ -2163,6 +2105,8 @@
case NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL";
case NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED";
case NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE";
+ case NET_CAPABILITY_VSIM: return "VSIM";
+ case NET_CAPABILITY_BIP: return "BIP";
default: return Integer.toString(capability);
}
}
diff --git a/framework/src/android/net/NetworkProvider.java b/framework/src/android/net/NetworkProvider.java
index 14cb51c..cfb7325 100644
--- a/framework/src/android/net/NetworkProvider.java
+++ b/framework/src/android/net/NetworkProvider.java
@@ -28,6 +28,11 @@
import android.os.Messenger;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+
/**
* 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
@@ -78,7 +83,9 @@
*/
@SystemApi
public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {
- Handler handler = new Handler(looper) {
+ // TODO (b/174636568) : this class should be able to cache an instance of
+ // ConnectivityManager so it doesn't have to fetch it again every time.
+ final Handler handler = new Handler(looper) {
@Override
public void handleMessage(Message m) {
switch (m.what) {
@@ -159,4 +166,159 @@
public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request);
}
+
+ /** @hide */
+ @SystemApi
+ public interface NetworkOfferCallback {
+ /**
+ * Called by the system when a network for this offer is needed to satisfy some
+ * networking request.
+ */
+ void onNetworkNeeded(@NonNull NetworkRequest request);
+ /**
+ * Called by the system when this offer is no longer valuable for this request.
+ */
+ void onNetworkUnneeded(@NonNull NetworkRequest request);
+ }
+
+ private class NetworkOfferCallbackProxy extends INetworkOfferCallback.Stub {
+ @NonNull public final NetworkOfferCallback callback;
+ @NonNull private final Executor mExecutor;
+
+ NetworkOfferCallbackProxy(@NonNull final NetworkOfferCallback callback,
+ @NonNull final Executor executor) {
+ this.callback = callback;
+ this.mExecutor = executor;
+ }
+
+ @Override
+ public void onNetworkNeeded(final @NonNull NetworkRequest request) {
+ mExecutor.execute(() -> callback.onNetworkNeeded(request));
+ }
+
+ @Override
+ public void onNetworkUnneeded(final @NonNull NetworkRequest request) {
+ mExecutor.execute(() -> callback.onNetworkUnneeded(request));
+ }
+ }
+
+ @GuardedBy("mProxies")
+ @NonNull private final ArrayList<NetworkOfferCallbackProxy> mProxies = new ArrayList<>();
+
+ // Returns the proxy associated with this callback, or null if none.
+ @Nullable
+ private NetworkOfferCallbackProxy findProxyForCallback(@NonNull final NetworkOfferCallback cb) {
+ synchronized (mProxies) {
+ for (final NetworkOfferCallbackProxy p : mProxies) {
+ if (p.callback == cb) return p;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Register or update an offer for network with the passed capabilities and score.
+ *
+ * A NetworkProvider's role is to provide networks. This method is how a provider tells the
+ * connectivity stack what kind of network it may provide. The score and caps arguments act
+ * as filters that the connectivity stack uses to tell when the offer is valuable. When an
+ * offer might be preferred over existing networks, the provider will receive a call to
+ * the associated callback's {@link NetworkOfferCallback#onNetworkNeeded} method. The provider
+ * should then try to bring up this network. When an offer is no longer useful, the stack
+ * will inform the provider by calling {@link NetworkOfferCallback#onNetworkUnneeded}. The
+ * provider should stop trying to bring up such a network, or disconnect it if it already has
+ * one.
+ *
+ * The stack determines what offers are valuable according to what networks are currently
+ * available to the system, and what networking requests are made by applications. If an
+ * offer looks like it could connect a better network than any existing network for any
+ * particular request, that's when the stack decides the network is needed. If the current
+ * networking requests are all satisfied by networks that this offer couldn't possibly be a
+ * better match for, that's when the offer is no longer valuable. An offer starts out as
+ * unneeded ; the provider should not try to bring up the network until
+ * {@link NetworkOfferCallback#onNetworkNeeded} is called.
+ *
+ * Note that the offers are non-binding to the providers, in particular because providers
+ * often don't know if they will be able to bring up such a network at any given time. For
+ * example, no wireless network may be in range when the offer would be valuable. This is fine
+ * and expected ; the provider should simply continue to try to bring up the network and do so
+ * if/when it becomes possible. In the mean time, the stack will continue to satisfy requests
+ * with the best network currently available, or if none, keep the apps informed that no
+ * network can currently satisfy this request. When/if the provider can bring up the network,
+ * the connectivity stack will match it against requests, and inform interested apps of the
+ * availability of this network. This may, in turn, render the offer of some other provider
+ * low-value if all requests it used to satisfy are now better served by this network.
+ *
+ * A network can become unneeded for a reason like the above : whether the provider managed
+ * to bring up the offered network after it became needed or not, some other provider may
+ * bring up a better network than this one, making this network unneeded. A network may also
+ * become unneeded if the application making the request withdrew it (for example, after it
+ * is done transferring data, or if the user canceled an operation).
+ *
+ * The capabilities and score act as filters as to what requests the provider will see.
+ * They are not promises, but for best performance, the providers should strive to put
+ * as much known information as possible in the offer. For the score, it should put as
+ * strong a score as the networks will have, since this will filter what requests the
+ * provider sees – it's not a promise, it only serves to avoid sending requests that
+ * the provider can't ever hope to satisfy better than any current network. For capabilities,
+ * it should put all NetworkAgent-managed capabilities a network may have, even if it doesn't
+ * have them at first. This applies to INTERNET, for example ; if a provider thinks the
+ * network it can bring up for this offer may offer Internet access it should include the
+ * INTERNET bit. It's fine if the brought up network ends up not actually having INTERNET.
+ *
+ * TODO : in the future, to avoid possible infinite loops, there should be constraints on
+ * what can be put in capabilities of networks brought up for an offer. If a provider might
+ * bring up a network with or without INTERNET, then it should file two offers : this will
+ * let it know precisely what networks are needed, so it can avoid bringing up networks that
+ * won't actually satisfy requests and remove the risk for bring-up-bring-down loops.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void registerNetworkOffer(@NonNull final NetworkScore score,
+ @NonNull final NetworkCapabilities caps, @NonNull final Executor executor,
+ @NonNull final NetworkOfferCallback callback) {
+ // Can't offer a network with a provider that is not yet registered or already unregistered.
+ final int providerId = mProviderId;
+ if (providerId == ID_NONE) return;
+ NetworkOfferCallbackProxy proxy = null;
+ synchronized (mProxies) {
+ for (final NetworkOfferCallbackProxy existingProxy : mProxies) {
+ if (existingProxy.callback == callback) {
+ proxy = existingProxy;
+ break;
+ }
+ }
+ if (null == proxy) {
+ proxy = new NetworkOfferCallbackProxy(callback, executor);
+ mProxies.add(proxy);
+ }
+ }
+ mContext.getSystemService(ConnectivityManager.class)
+ .offerNetwork(providerId, score, caps, proxy);
+ }
+
+ /**
+ * Withdraw a network offer previously made to the networking stack.
+ *
+ * If a provider can no longer provide a network they offered, it should call this method.
+ * An example of usage could be if the hardware necessary to bring up the network was turned
+ * off in UI by the user. Note that because offers are never binding, the provider might
+ * alternatively decide not to withdraw this offer and simply refuse to bring up the network
+ * even when it's needed. However, withdrawing the request is slightly more resource-efficient
+ * because the networking stack won't have to compare this offer to exiting networks to see
+ * if it could beat any of them, and may be advantageous to the provider's implementation that
+ * can rely on no longer receiving callbacks for a network that they can't bring up anyways.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void unregisterNetworkOffer(final @NonNull NetworkOfferCallback callback) {
+ final NetworkOfferCallbackProxy proxy = findProxyForCallback(callback);
+ if (null == proxy) return;
+ mProxies.remove(proxy);
+ mContext.getSystemService(ConnectivityManager.class).unofferNetwork(proxy);
+ }
}
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index bcbc04f7..5313f08 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -47,7 +47,6 @@
import android.os.Process;
import android.text.TextUtils;
import android.util.Range;
-import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
import java.util.List;
@@ -675,18 +674,6 @@
}
}
- /** @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(@Nullable Object obj) {
if (obj instanceof NetworkRequest == false) return false;
NetworkRequest that = (NetworkRequest)obj;
@@ -699,4 +686,43 @@
public int hashCode() {
return Objects.hash(requestId, legacyType, networkCapabilities, type);
}
+
+ /**
+ * Gets all the capabilities set on this {@code NetworkRequest} instance.
+ *
+ * @return an array of capability values for this instance.
+ */
+ @NonNull
+ public @NetCapability int[] getCapabilities() {
+ // No need to make a defensive copy here as NC#getCapabilities() already returns
+ // a new array.
+ return networkCapabilities.getCapabilities();
+ }
+
+ /**
+ * Gets all the unwanted capabilities set on this {@code NetworkRequest} instance.
+ *
+ * @return an array of unwanted capability values for this instance.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public @NetCapability int[] getUnwantedCapabilities() {
+ // No need to make a defensive copy here as NC#getUnwantedCapabilities() already returns
+ // a new array.
+ return networkCapabilities.getUnwantedCapabilities();
+ }
+
+ /**
+ * Gets all the transports set on this {@code NetworkRequest} instance.
+ *
+ * @return an array of transport type values for this instance.
+ */
+ @NonNull
+ public @Transport int[] getTransportTypes() {
+ // No need to make a defensive copy here as NC#getTransportTypes() already returns
+ // a new array.
+ return networkCapabilities.getTransportTypes();
+ }
}
diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java
index 6584993..9786b09 100644
--- a/framework/src/android/net/NetworkScore.java
+++ b/framework/src/android/net/NetworkScore.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
@@ -23,6 +24,9 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Object representing the quality of a network as perceived by the user.
*
@@ -36,6 +40,17 @@
// a migration.
private final int mLegacyInt;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ KEEP_CONNECTED_NONE,
+ KEEP_CONNECTED_FOR_HANDOVER
+ })
+ public @interface KeepConnectedReason { }
+
+ public static final int KEEP_CONNECTED_NONE = 0;
+ public static final int KEEP_CONNECTED_FOR_HANDOVER = 1;
+
// Agent-managed policies
// TODO : add them here, starting from 1
/** @hide */
@@ -46,15 +61,20 @@
// Bitmask of all the policies applied to this score.
private final long mPolicies;
+ private final int mKeepConnectedReason;
+
/** @hide */
- NetworkScore(final int legacyInt, final long policies) {
+ NetworkScore(final int legacyInt, final long policies,
+ @KeepConnectedReason final int keepConnectedReason) {
mLegacyInt = legacyInt;
mPolicies = policies;
+ mKeepConnectedReason = keepConnectedReason;
}
private NetworkScore(@NonNull final Parcel in) {
mLegacyInt = in.readInt();
mPolicies = in.readLong();
+ mKeepConnectedReason = in.readInt();
}
public int getLegacyInt() {
@@ -62,6 +82,13 @@
}
/**
+ * Returns the keep-connected reason, or KEEP_CONNECTED_NONE.
+ */
+ public int getKeepConnectedReason() {
+ return mKeepConnectedReason;
+ }
+
+ /**
* @return whether this score has a particular policy.
*
* @hide
@@ -80,6 +107,7 @@
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeInt(mLegacyInt);
dest.writeLong(mPolicies);
+ dest.writeInt(mKeepConnectedReason);
}
@Override
@@ -108,6 +136,7 @@
private static final long POLICY_NONE = 0L;
private static final int INVALID_LEGACY_INT = Integer.MIN_VALUE;
private int mLegacyInt = INVALID_LEGACY_INT;
+ private int mKeepConnectedReason = KEEP_CONNECTED_NONE;
/**
* Sets the legacy int for this score.
@@ -124,12 +153,23 @@
}
/**
+ * Set the keep-connected reason.
+ *
+ * This can be reset by calling it again with {@link KEEP_CONNECTED_NONE}.
+ */
+ @NonNull
+ public Builder setKeepConnectedReason(@KeepConnectedReason final int reason) {
+ mKeepConnectedReason = reason;
+ return this;
+ }
+
+ /**
* Builds this NetworkScore.
* @return The built NetworkScore object.
*/
@NonNull
public NetworkScore build() {
- return new NetworkScore(mLegacyInt, POLICY_NONE);
+ return new NetworkScore(mLegacyInt, POLICY_NONE, mKeepConnectedReason);
}
}
}
diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java
index c4bebc0..2679b62 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;
@@ -40,6 +42,9 @@
* {@hide}
*/
public class NetworkUtils {
+ static {
+ System.loadLibrary("framework-connectivity-jni");
+ }
private static final String TAG = "NetworkUtils";
@@ -55,6 +60,8 @@
*/
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 +70,20 @@
* 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}.
@@ -81,18 +95,28 @@
@Deprecated
public native static boolean bindProcessToNetworkForHostResolution(int netId);
+ private static native int bindSocketToNetworkHandle(FileDescriptor fd, long netHandle);
+
/**
* 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);
+ public static int bindSocketToNetwork(FileDescriptor fd, int netId) {
+ return bindSocketToNetworkHandle(fd, new Network(netId).getNetworkHandle());
+ }
/**
* 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);
+ public static boolean queryUserAccess(int uid, int netId) {
+ // TODO (b/183485986): remove this method
+ return false;
+ }
+
+ private static native FileDescriptor resNetworkSend(
+ long netHandle, byte[] msg, int msglen, int flags) throws ErrnoException;
/**
* DNS resolver series jni method.
@@ -100,8 +124,13 @@
* {@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;
+ public static FileDescriptor resNetworkSend(
+ int netId, byte[] msg, int msglen, int flags) throws ErrnoException {
+ return resNetworkSend(new Network(netId).getNetworkHandle(), msg, msglen, flags);
+ }
+
+ private static native FileDescriptor resNetworkQuery(
+ long netHandle, String dname, int nsClass, int nsType, int flags) throws ErrnoException;
/**
* DNS resolver series jni method.
@@ -110,8 +139,11 @@
* {@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;
+ public static FileDescriptor resNetworkQuery(
+ int netId, String dname, int nsClass, int nsType, int flags) throws ErrnoException {
+ return resNetworkQuery(new Network(netId).getNetworkHandle(), dname, nsClass, nsType,
+ flags);
+ }
/**
* DNS resolver series jni method.
diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java
index d007a95..f6cae72 100644
--- a/framework/src/android/net/SocketKeepalive.java
+++ b/framework/src/android/net/SocketKeepalive.java
@@ -55,36 +55,68 @@
static final String TAG = "SocketKeepalive";
/**
- * No errors.
+ * Success. It indicates there is no error.
* @hide
*/
@SystemApi
public static final int SUCCESS = 0;
- /** @hide */
+ /**
+ * No keepalive. This should only be internally as it indicates There is no keepalive.
+ * It should not propagate to applications.
+ * @hide
+ */
public static final int NO_KEEPALIVE = -1;
- /** @hide */
+ /**
+ * Data received.
+ * @hide
+ */
public static final int DATA_RECEIVED = -2;
- /** @hide */
+ /**
+ * The binder died.
+ * @hide
+ */
public static final int BINDER_DIED = -10;
- /** The specified {@code Network} is not connected. */
+ /**
+ * The invalid network. It indicates 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}. */
+
+ /**
+ * The invalid IP addresses. Indicates 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. */
+
+ /**
+ * The port is invalid.
+ */
public static final int ERROR_INVALID_PORT = -22;
- /** The packet length is invalid (e.g., too long). */
+
+ /**
+ * The 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). */
+
+ /**
+ * The interval is invalid (e.g. too short).
+ */
public static final int ERROR_INVALID_INTERVAL = -24;
- /** The target socket is invalid. */
+
+ /**
+ * The socket is invalid.
+ */
public static final int ERROR_INVALID_SOCKET = -25;
- /** The target socket is not idle. */
+
+ /**
+ * The 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.
@@ -92,15 +124,29 @@
*/
public static final int ERROR_STOP_REASON_UNINITIALIZED = -27;
- /** The device does not support this request. */
+ /**
+ * The request is unsupported.
+ */
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. */
+
+ /**
+ * There was a hardware error.
+ */
public static final int ERROR_HARDWARE_ERROR = -31;
- /** The limitation of resource is reached. */
+
+ /**
+ * Resources are insufficient (e.g. all hardware slots are in use).
+ */
public static final int ERROR_INSUFFICIENT_RESOURCES = -32;
+ /**
+ * There was no such slot. This should only be internally as it indicates
+ * a programming error in the system server. It should not propagate to
+ * applications.
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_NO_SUCH_SLOT = -33;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -111,7 +157,8 @@
ERROR_INVALID_LENGTH,
ERROR_INVALID_INTERVAL,
ERROR_INVALID_SOCKET,
- ERROR_SOCKET_NOT_IDLE
+ ERROR_SOCKET_NOT_IDLE,
+ ERROR_NO_SUCH_SLOT
})
public @interface ErrorCode {}
@@ -122,7 +169,6 @@
ERROR_INVALID_LENGTH,
ERROR_UNSUPPORTED,
ERROR_INSUFFICIENT_RESOURCES,
- ERROR_HARDWARE_UNSUPPORTED
})
public @interface KeepaliveEvent {}
diff --git a/service/Android.bp b/service/Android.bp
index 1330e71..b44128b 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -25,7 +25,7 @@
cc_library_shared {
name: "libservice-connectivity",
- // TODO: build against the NDK (sdk_version: "30" for example)
+ min_sdk_version: "30",
cflags: [
"-Wall",
"-Werror",
@@ -36,13 +36,13 @@
"jni/com_android_server_TestNetworkService.cpp",
"jni/onload.cpp",
],
+ stl: "libc++_static",
+ header_libs: [
+ "libbase_headers",
+ ],
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",
],
apex_available: [
"com.android.tethering",
@@ -51,33 +51,46 @@
java_library {
name: "service-connectivity-pre-jarjar",
+ sdk_version: "system_server_current",
+ min_sdk_version: "30",
srcs: [
- ":framework-connectivity-shared-srcs",
":connectivity-service-srcs",
+ ":framework-connectivity-shared-srcs",
+ ":services-connectivity-shared-srcs",
+ // TODO: move to net-utils-device-common, enable shrink optimization to avoid extra classes
+ ":net-module-utils-srcs",
],
libs: [
- "android.net.ipsec.ike",
- "services.core",
- "services.net",
+ // TODO (b/183097033) remove once system_server_current includes core_current
+ "stable.core.platform.api.stubs",
+ "android_system_server_stubs_current",
+ "framework-annotations-lib",
+ "framework-connectivity.impl",
+ "framework-tethering.stubs.module_lib",
+ "framework-wifi.stubs.module_lib",
"unsupportedappusage",
"ServiceConnectivityResources",
],
static_libs: [
+ "dnsresolver_aidl_interface-V7-java",
"modules-utils-os",
"net-utils-device-common",
"net-utils-framework-common",
"netd-client",
+ "netlink-client",
+ "networkstack-client",
"PlatformProperties",
"service-connectivity-protos",
],
apex_available: [
- "//apex_available:platform",
"com.android.tethering",
],
}
java_library {
name: "service-connectivity-protos",
+ sdk_version: "system_current",
+ min_sdk_version: "30",
proto: {
type: "nano",
},
@@ -86,20 +99,21 @@
],
libs: ["libprotobuf-java-nano"],
apex_available: [
- "//apex_available:platform",
"com.android.tethering",
],
}
java_library {
name: "service-connectivity",
+ sdk_version: "system_server_current",
+ min_sdk_version: "30",
installable: true,
static_libs: [
"service-connectivity-pre-jarjar",
],
jarjar_rules: "jarjar-rules.txt",
apex_available: [
- "//apex_available:platform",
+ "//apex_available:platform", // For arc-services
"com.android.tethering",
],
}
diff --git a/service/ServiceConnectivityResources/Android.bp b/service/ServiceConnectivityResources/Android.bp
index fa4501a..d783738 100644
--- a/service/ServiceConnectivityResources/Android.bp
+++ b/service/ServiceConnectivityResources/Android.bp
@@ -22,6 +22,7 @@
android_app {
name: "ServiceConnectivityResources",
sdk_version: "module_current",
+ min_sdk_version: "30",
resource_dirs: [
"res",
],
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index 71674e4..9ff2a22 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -78,6 +78,11 @@
<item>1,3</item>
</string-array>
+ <!-- Reserved privileged keepalive slots per transport. -->
+ <integer translatable="false" name="config_reservedPrivilegedKeepaliveSlots">2</integer>
+
+ <!-- Allowed unprivileged keepalive slots per uid. -->
+ <integer translatable="false" name="config_allowedUnprivilegedKeepalivePerUid">2</integer>
<!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
device behaviour is controlled by the metered multipath preference in
@@ -89,4 +94,33 @@
Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
<integer translatable="false" name="config_networkAvoidBadWifi">1</integer>
+ <!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only
+ be controlled by systemOrSignature apps. -->
+ <integer-array translatable="false" name="config_protectedNetworks">
+ <item>10</item>
+ <item>11</item>
+ <item>12</item>
+ <item>14</item>
+ <item>15</item>
+ </integer-array>
+
+ <!-- Whether the internal vehicle network should remain active even when no
+ apps requested it. -->
+ <bool name="config_vehicleInternalNetworkAlwaysRequested">false</bool>
+
+
+ <!-- If the hardware supports specially marking packets that caused a wakeup of the
+ main CPU, set this value to the mark used. -->
+ <integer name="config_networkWakeupPacketMark">0</integer>
+
+ <!-- Mask to use when checking skb mark defined in config_networkWakeupPacketMark above. -->
+ <integer name="config_networkWakeupPacketMask">0</integer>
+
+ <!-- Whether/how to notify the user on network switches. See LingerMonitor.java. -->
+ <integer translatable="false" name="config_networkNotifySwitchType">0</integer>
+
+ <!-- What types of network switches to notify. See LingerMonitor.java. -->
+ <string-array translatable="false" name="config_networkNotifySwitches">
+ </string-array>
+
</resources>
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index 25e19ce..717d08e 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -26,6 +26,12 @@
<item type="integer" name="config_networkMeteredMultipathPreference"/>
<item type="array" name="config_networkSupportedKeepaliveCount"/>
<item type="integer" name="config_networkAvoidBadWifi"/>
+ <item type="array" name="config_protectedNetworks"/>
+ <item type="bool" name="config_vehicleInternalNetworkAlwaysRequested"/>
+ <item type="integer" name="config_networkWakeupPacketMark"/>
+ <item type="integer" name="config_networkWakeupPacketMask"/>
+ <item type="integer" name="config_networkNotifySwitchType"/>
+ <item type="array" name="config_networkNotifySwitches"/>
</policy>
</overlayable>
diff --git a/service/jni/com_android_server_TestNetworkService.cpp b/service/jni/com_android_server_TestNetworkService.cpp
index 36a6fde..e7a40e5 100644
--- a/service/jni/com_android_server_TestNetworkService.cpp
+++ b/service/jni/com_android_server_TestNetworkService.cpp
@@ -35,8 +35,6 @@
#include <log/log.h>
-#include "netutils/ifc.h"
-
#include "jni.h"
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
@@ -48,9 +46,8 @@
//------------------------------------------------------------------------------
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));
-
+ const std::string& msg = "Error: " + std::string(action) + " " + std::string(iface) + ": "
+ + std::string(strerror(error));
jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
}