Merge "Reland: CaptivePortalData: use CharSequence in VenueFriendlyName API" into sc-dev
diff --git a/framework/Android.bp b/framework/Android.bp
index 017ff51..657d5a3 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -25,6 +25,7 @@
java_library {
name: "framework-connectivity-protos",
+ sdk_version: "module_current",
proto: {
type: "nano",
},
@@ -82,8 +83,7 @@
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,56 @@
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",
+ ],
}
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,12 +160,11 @@
],
},
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",
],
static_libs: [
"framework-connectivity-protos",
@@ -136,5 +173,5 @@
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/api/current.txt b/framework/api/current.txt
index f22d4b7..e415e01 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -291,6 +291,7 @@
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/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 7a91f64..5bd01a6 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -19,7 +19,11 @@
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 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";
@@ -36,9 +40,18 @@
}
public final class NetworkCapabilities implements android.os.Parcelable {
+ method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> 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<android.util.Range<java.lang.Integer>>);
+ }
+
+ public static class NetworkRequest.Builder {
+ method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
public class ParseException extends java.lang.RuntimeException {
ctor public ParseException(@NonNull String);
ctor public ParseException(@NonNull String, @NonNull Throwable);
diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp
new file mode 100644
index 0000000..19ffe77
--- /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 <vector>
+
+#include <android/file_descriptor_jni.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/JNIPlatformHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#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 <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 throwErrnoException(JNIEnv* env, const char* functionName, int error) {
+ ScopedLocalRef<jstring> 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,
+ "<init>", "(Ljava/lang/String;I)V");
+
+ jobject exception = env->NewObject(errnoExceptionClass,
+ errnoExceptionCtor,
+ detailMessage.get(),
+ error);
+ env->Throw(reinterpret_cast<jthrowable>(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<jbyte*>(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<char> 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<uint8_t> 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<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);
+ 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, "<init>", "(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, "<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 */
+ { "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 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/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 9f63abf..f8a0e4e 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -73,7 +73,6 @@
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;
@@ -424,7 +423,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
@@ -432,8 +432,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
@@ -442,8 +443,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.
@@ -4467,12 +4469,20 @@
/**
* Requests that the system open the captive portal app on the specified network.
*
+ * <p>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) {
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 98f3d40..3300fa8 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -20,6 +20,7 @@
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.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 94%
rename from framework/src/com/android/connectivity/aidl/INetworkAgent.aidl
rename to framework/src/android/net/INetworkAgent.aidl
index 64b5567..1f66e18 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 18d26a7..c5464d3 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 a127c6f..1416bb9 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -34,8 +34,6 @@
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;
diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java
index 664c265..5e50a64 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -50,7 +50,8 @@
* 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/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index c6dfcee..1466629 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -22,6 +22,7 @@
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;
@@ -32,6 +33,7 @@
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;
@@ -152,7 +154,7 @@
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;
@@ -608,10 +610,8 @@
* 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);
}
@@ -1457,9 +1457,8 @@
* @hide
*/
public @NonNull NetworkCapabilities setSingleUid(int uid) {
- final ArraySet<UidRange> identity = new ArraySet<>(1);
- identity.add(new UidRange(uid, uid));
- setUids(identity);
+ mUids = new ArraySet<>(1);
+ mUids.add(new UidRange(uid, uid));
return this;
}
@@ -1468,22 +1467,34 @@
* This makes a copy of the set so that callers can't modify it after the call.
* @hide
*/
- public @NonNull NetworkCapabilities setUids(Set<UidRange> uids) {
- if (null == uids) {
- mUids = null;
- } else {
- mUids = new ArraySet<>(uids);
- }
+ public @NonNull NetworkCapabilities setUids(@Nullable Set<Range<Integer>> uids) {
+ mUids = UidRange.fromIntRanges(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.
+ *
+ * @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<Range<Integer>> 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<UidRange> getUids() {
- return null == mUids ? null : new ArraySet<>(mUids);
+ public @Nullable Set<UidRange> getUidRanges() {
+ if (mUids == null) return null;
+
+ return new ArraySet<>(mUids);
}
/**
@@ -2656,6 +2667,21 @@
}
/**
+ * 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<Range<Integer>> uids) {
+ mCaps.setUids(uids);
+ return this;
+ }
+
+ /**
* Builds the instance of the capabilities.
*
* @return the built instance of NetworkCapabilities.
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index dbe3ecc..cf131f0 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -36,6 +36,7 @@
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;
@@ -45,6 +46,7 @@
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 +279,14 @@
* 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<Integer>}, or null for everything.
* @return The builder to facilitate chaining.
* @hide
*/
- public Builder setUids(Set<UidRange> uids) {
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public Builder setUids(@Nullable Set<Range<Integer>> uids) {
mNetworkCapabilities.setUids(uids);
return this;
}
diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java
index f478010..eadcb2d 100644
--- a/framework/src/android/net/NetworkScore.java
+++ b/framework/src/android/net/NetworkScore.java
@@ -20,6 +20,8 @@
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.
*
@@ -33,19 +35,39 @@
// a migration.
private final int mLegacyInt;
+ // Agent-managed policies
+ // TODO : add them here, starting from 1
/** @hide */
- NetworkScore(final int legacyInt) {
- this.mLegacyInt = legacyInt;
+ 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;
+
+ /** @hide */
+ 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() {
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 + ")";
@@ -54,6 +76,7 @@
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeInt(mLegacyInt);
+ dest.writeLong(mPolicies);
}
@Override
@@ -79,6 +102,7 @@
* 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 +126,7 @@
*/
@NonNull
public NetworkScore build() {
- return new NetworkScore(mLegacyInt);
+ return new NetworkScore(mLegacyInt, POLICY_NONE);
}
}
}
diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java
index 26518d3..bc67c74 100644
--- a/framework/src/android/net/UidRange.java
+++ b/framework/src/android/net/UidRange.java
@@ -20,8 +20,11 @@
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 @@
}
return false;
}
+
+ /**
+ * Convert a set of {@code Range<Integer>} to a set of {@link UidRange}.
+ */
+ @Nullable
+ public static ArraySet<UidRange> fromIntRanges(@Nullable Set<Range<Integer>> ranges) {
+ if (null == ranges) return null;
+
+ final ArraySet<UidRange> uids = new ArraySet<>();
+ for (Range<Integer> range : ranges) {
+ uids.add(new UidRange(range.getLower(), range.getUpper()));
+ }
+ return uids;
+ }
+
+ /**
+ * Convert a set of {@link UidRange} to a set of {@code Range<Integer>}.
+ */
+ @Nullable
+ public static ArraySet<Range<Integer>> toIntRanges(@Nullable Set<UidRange> ranges) {
+ if (null == ranges) return null;
+
+ final ArraySet<Range<Integer>> uids = new ArraySet<>();
+ for (UidRange range : ranges) {
+ uids.add(new Range<Integer>(range.start, range.stop));
+ }
+ return uids;
+ }
}