Merge "Move BLOCKED_REASON_* constants from NPMS into ConnectivityManager." into sc-dev
diff --git a/framework/Android.bp b/framework/Android.bp
index 657d5a3..80c68f2 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -26,6 +26,7 @@
java_library {
name: "framework-connectivity-protos",
sdk_version: "module_current",
+ min_sdk_version: "30",
proto: {
type: "nano",
},
@@ -109,13 +110,15 @@
"-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: [
- "libbase",
"liblog",
"libnativehelper",
- "libnetd_client",
],
header_libs: [
"dnsproxyd_protocol_headers",
@@ -128,6 +131,7 @@
srcs: [
"jni/android_net_NetworkUtils.cpp",
],
+ shared_libs: ["libandroid_net"],
apex_available: [
"//apex_available:platform",
"com.android.tethering",
@@ -136,11 +140,14 @@
cc_library_shared {
name: "libframework-connectivity-jni",
+ min_sdk_version: "30",
defaults: ["libframework-connectivity-defaults"],
srcs: [
+ "jni/android_net_NetworkUtils.cpp",
"jni/onload.cpp",
],
- static_libs: ["libconnectivityframeworkutils"],
+ shared_libs: ["libandroid"],
+ stl: "libc++_static",
apex_available: [
"//apex_available:platform",
"com.android.tethering",
@@ -150,6 +157,7 @@
java_library {
name: "framework-connectivity.impl",
sdk_version: "module_current",
+ min_sdk_version: "30",
srcs: [
":framework-connectivity-sources",
],
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 c184f9b..2bf807c 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -11,6 +11,7 @@
method @Nullable public android.net.ProxyInfo getGlobalProxy();
method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange();
method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerDefaultNetworkCallbackAsUid(int, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
method @Deprecated public boolean requestRouteToHostAddress(int, java.net.InetAddress);
@@ -44,15 +45,18 @@
public final class NetworkAgentConfig implements android.os.Parcelable {
method @Nullable public String getSubscriberId();
+ method public boolean isBypassableVpn();
}
public static final class NetworkAgentConfig.Builder {
+ method @NonNull public android.net.NetworkAgentConfig.Builder setBypassableVpn(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
}
public final class NetworkCapabilities implements android.os.Parcelable {
ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long);
method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids();
+ method public boolean hasUnwantedCapability(int);
field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL
field public static final long REDACT_FOR_ACCESS_FINE_LOCATION = 1L; // 0x1L
field public static final long REDACT_FOR_LOCAL_MAC_ADDRESS = 2L; // 0x2L
@@ -65,7 +69,14 @@
method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
}
+ public class NetworkRequest implements android.os.Parcelable {
+ method @NonNull public int[] getUnwantedCapabilities();
+ method public boolean hasUnwantedCapability(int);
+ }
+
public static class NetworkRequest.Builder {
+ method @NonNull public android.net.NetworkRequest.Builder addUnwantedCapability(int);
+ method @NonNull public android.net.NetworkRequest.Builder removeUnwantedCapability(int);
method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 703fca4..9dcc391 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -212,10 +212,12 @@
public abstract class NetworkAgent {
ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, int, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
+ ctor public NetworkAgent(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkScore, @NonNull android.net.NetworkAgentConfig, @Nullable android.net.NetworkProvider);
method @Nullable public android.net.Network getNetwork();
method public void markConnected();
method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
method public void onAutomaticReconnectDisabled();
+ method public void onBandwidthUpdateRequested();
method public void onNetworkUnwanted();
method public void onQosCallbackRegistered(int, @NonNull android.net.QosFilter);
method public void onQosCallbackUnregistered(int);
@@ -233,6 +235,7 @@
method public final void sendQosSessionAvailable(int, int, @NonNull android.telephony.data.EpsBearerQosSessionAttributes);
method public final void sendQosSessionLost(int, int);
method public final void sendSocketKeepaliveEvent(int, int);
+ method @Deprecated public void setLegacySubtype(int, @NonNull String);
method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>);
method public void unregister();
field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
@@ -253,7 +256,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);
@@ -262,6 +270,7 @@
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();
@@ -316,6 +325,19 @@
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int);
}
+ public final class NetworkScore implements android.os.Parcelable {
+ method public int describeContents();
+ 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;
+ }
+
+ public static final class NetworkScore.Builder {
+ ctor public NetworkScore.Builder();
+ method @NonNull public android.net.NetworkScore build();
+ method @NonNull public android.net.NetworkScore.Builder setLegacyInt(int);
+ }
+
public final class OemNetworkPreferences implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getNetworkPreferences();
@@ -388,6 +410,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/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp
index c5b1ff8..e8bb42d 100644
--- a/framework/jni/android_net_NetworkUtils.cpp
+++ b/framework/jni/android_net_NetworkUtils.cpp
@@ -19,6 +19,7 @@
#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>
@@ -36,7 +37,6 @@
#include <utils/Log.h>
#include <utils/misc.h>
-#include "NetdClient.h"
#include "jni.h"
extern "C" {
@@ -94,30 +94,32 @@
}
}
-static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
+static jboolean android_net_utils_bindProcessToNetworkHandle(JNIEnv *env, jobject thiz,
+ jlong netHandle)
{
- return (jboolean) !setNetworkForProcess(netId);
+ return (jboolean) !android_setprocnetwork(netHandle);
}
-static jint android_net_utils_getBoundNetworkForProcess(JNIEnv *env, jobject thiz)
+static jlong android_net_utils_getBoundNetworkHandleForProcess(JNIEnv *env, jobject thiz)
{
- return getNetworkForProcess();
+ net_handle_t network;
+ if (android_getprocnetwork(&network) != 0) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "android_getprocnetwork(): %s", strerror(errno));
+ return NETWORK_UNSPECIFIED;
+ }
+ return (jlong) network;
}
static jboolean android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz,
- jint netId)
+ jint netId, jlong netHandle)
{
- return (jboolean) !setNetworkForResolv(netId);
+ return (jboolean) !android_setprocdns(netHandle);
}
-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 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)
@@ -129,7 +131,7 @@
return true;
}
-static jobject android_net_utils_resNetworkQuery(JNIEnv *env, jobject thiz, jint netId,
+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);
@@ -139,7 +141,8 @@
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);
+
+ int fd = android_res_nquery(netHandle, queryname.data(), ns_class, ns_type, flags);
if (fd < 0) {
jniThrowErrnoException(env, "resNetworkQuery", -fd);
@@ -149,12 +152,12 @@
return jniCreateFileDescriptor(env, fd);
}
-static jobject android_net_utils_resNetworkSend(JNIEnv *env, jobject thiz, jint netId,
+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 = resNetworkSend(netId, data, msgLen, flags);
+ int fd = android_res_nsend(netHandle, data, msgLen, flags);
if (fd < 0) {
jniThrowErrnoException(env, "resNetworkSend", -fd);
@@ -169,7 +172,7 @@
int rcode;
std::vector<uint8_t> buf(MAXPACKETSIZE, 0);
- int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE);
+ int res = android_res_nresult(fd, &rcode, buf.data(), MAXPACKETSIZE);
jniSetFileDescriptorOfFD(env, javaFd, -1);
if (res < 0) {
jniThrowErrnoException(env, "resNetworkResult", -res);
@@ -193,23 +196,22 @@
static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) {
int fd = AFileDescriptor_getFD(env, javaFd);
- resNetworkCancel(fd);
+ android_res_cancel(fd);
jniSetFileDescriptorOfFD(env, javaFd, -1);
}
static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) {
- unsigned dnsNetId = 0;
- if (int res = getNetworkForDns(&dnsNetId) < 0) {
- jniThrowErrnoException(env, "getDnsNetId", -res);
+ net_handle_t dnsNetHandle = NETWORK_UNSPECIFIED;
+ if (int res = android_getprocdns(&dnsNetHandle) < 0) {
+ jniThrowErrnoException(env, "getDnsNetwork", -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 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) {
@@ -255,16 +257,15 @@
// clang-format off
static const JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
- { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
- { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess },
+ { "bindProcessToNetworkHandle", "(J)Z", (void*) android_net_utils_bindProcessToNetworkHandle },
+ { "getBoundNetworkHandleForProcess", "()J", (void*) android_net_utils_getBoundNetworkHandleForProcess },
{ "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
- { "bindSocketToNetwork", "(Ljava/io/FileDescriptor;I)I", (void*) android_net_utils_bindSocketToNetwork },
- { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
+ { "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", "(I[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
- { "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
+ { "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 },
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 861dbbb..a73d76e 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -1171,8 +1171,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
@@ -3323,7 +3322,60 @@
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. 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
+ */
+ @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
+ */
+ 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,
@@ -3793,8 +3845,9 @@
private static final HashMap<NetworkRequest, NetworkCallback> sCallbacks = new HashMap<>();
private static CallbackHandler sCallbackHandler;
- private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
- int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
+ private NetworkRequest sendRequestForNetwork(int asUid, NetworkCapabilities need,
+ NetworkCallback callback, int timeoutMs, NetworkRequest.Type reqType, int legacyType,
+ CallbackHandler handler) {
printStackTrace();
checkCallbackNotNull(callback);
if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) {
@@ -3819,8 +3872,8 @@
getAttributionTag());
} else {
request = mService.requestNetwork(
- need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType,
- callbackFlags, callingPackageName, getAttributionTag());
+ asUid, need, reqType.ordinal(), messenger, timeoutMs, binder,
+ legacyType, callbackFlags, callingPackageName, getAttributionTag());
}
if (request != null) {
sCallbacks.put(request, callback);
@@ -3835,6 +3888,12 @@
return request;
}
+ private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
+ int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
+ return sendRequestForNetwork(Process.INVALID_UID, need, callback, timeoutMs, reqType,
+ legacyType, handler);
+ }
+
/**
* Helper function to request a network with a particular legacy type.
*
@@ -4320,8 +4379,40 @@
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
@NonNull Handler handler) {
+ registerDefaultNetworkCallbackAsUid(Process.INVALID_UID, networkCallback, handler);
+ }
+
+ /**
+ * Registers to receive notifications about changes in the default network for the specified
+ * UID. This may be a physical network or a virtual network, such as a VPN that applies to the
+ * UID. The callbacks will continue to be called until either the application exits or
+ * {@link #unregisterNetworkCallback(NetworkCallback)} is called.
+ *
+ * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
+ * number of outstanding requests to 100 per app (identified by their UID), shared with
+ * all variants of this method, of {@link #requestNetwork} as well as
+ * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}.
+ * Requesting a network with this method will count toward this limit. If this limit is
+ * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources,
+ * make sure to unregister the callbacks with
+ * {@link #unregisterNetworkCallback(NetworkCallback)}.
+ *
+ * @param uid the UID for which to track default network changes.
+ * @param networkCallback The {@link NetworkCallback} that the system will call as the
+ * UID's default network changes.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @throws RuntimeException if the app already has too many callbacks registered.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @SuppressLint({"ExecutorRegistration", "PairedRegistration"})
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_SETTINGS})
+ public void registerDefaultNetworkCallbackAsUid(int uid,
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
CallbackHandler cbHandler = new CallbackHandler(handler);
- sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0,
+ sendRequestForNetwork(uid, null /* need */, networkCallback, 0 /* timeoutMs */,
TRACK_DEFAULT, TYPE_NONE, cbHandler);
}
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 3300fa8..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;
@@ -142,7 +143,7 @@
in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config,
in int factorySerialNumber);
- NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType,
+ NetworkRequest requestNetwork(int uid, in NetworkCapabilities networkCapabilities, int reqType,
in Messenger messenger, int timeoutSec, in IBinder binder, int legacy,
int callbackFlags, String callingPackageName, String callingAttributionTag);
@@ -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..67d2d40
--- /dev/null
+++ b/framework/src/android/net/INetworkOfferCallback.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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 offer is needed to satisfy some application or system component,
+ * connectivity will call onOfferNeeded on this callback. When this happens,
+ * the provider should try and bring up the network.
+ *
+ * When the 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
+ * onOfferUnneeded. 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.
+ * onOfferNeeded 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 be the best network for it.
+ *
+ * @hide
+ */
+oneway interface INetworkOfferCallback {
+ /**
+ * Informs the registrant that the offer is needed to fulfill this request.
+ * @param networkRequest the request to satisfy
+ * @param providerId the ID of the provider currently satisfying
+ * this request, or NetworkProvider.ID_NONE if none.
+ */
+ void onOfferNeeded(in NetworkRequest networkRequest, int providerId);
+
+ /**
+ * Informs the registrant that the offer is no longer needed to fulfill this request.
+ */
+ void onOfferUnneeded(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 3863ed1..b3d9616 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -362,9 +362,8 @@
public static final int CMD_UNREGISTER_QOS_CALLBACK = BASE + 21;
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
- // The subtype can be changed with (TODO) setLegacySubtype, but it starts
- // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description.
- final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, "");
+ final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
+ config.legacyTypeName, config.legacySubTypeName);
ni.setIsAvailable(true);
ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */,
config.getLegacyExtraInfo());
@@ -390,7 +389,6 @@
* @param score the initial score of this network. Update with sendNetworkScore.
* @param config an immutable {@link NetworkAgentConfig} for this agent.
* @param provider the {@link NetworkProvider} managing this agent.
- * @hide TODO : unhide when impl is complete
*/
public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
@NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
@@ -829,6 +827,7 @@
* @hide
*/
@Deprecated
+ @SystemApi
public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) {
mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName);
queueOrSendNetworkInfo(mNetworkInfo);
@@ -962,6 +961,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 5e50a64..3f058d8 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -64,6 +64,16 @@
}
/**
+ * @return whether this VPN connection can be bypassed by the apps.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public boolean isBypassableVpn() {
+ return allowBypass;
+ }
+
+ /**
* Set if the user desires to use this network even if it is unvalidated. This field has meaning
* only if {@link explicitlySelected} is true. If it is, this field must also be set to the
* appropriate value based on previous user choice.
@@ -165,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.
*
@@ -190,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>
@@ -225,6 +248,8 @@
skip464xlat = nac.skip464xlat;
legacyType = nac.legacyType;
legacyTypeName = nac.legacyTypeName;
+ legacySubType = nac.legacySubType;
+ legacySubTypeName = nac.legacySubTypeName;
mLegacyExtraInfo = nac.mLegacyExtraInfo;
}
}
@@ -290,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() {
@@ -303,7 +327,6 @@
* perform its own carrier-specific provisioning procedure.
*
* @return this builder, to facilitate chaining.
- * @hide
*/
@NonNull
public Builder disableProvisioningNotification() {
@@ -324,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.
@@ -335,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) {
@@ -347,6 +392,19 @@
}
/**
+ * Sets whether the apps can bypass the VPN connection.
+ *
+ * @return this builder, to facilitate chaining.
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = MODULE_LIBRARIES)
+ public Builder setBypassableVpn(boolean allowBypass) {
+ mConfig.allowBypass = allowBypass;
+ return this;
+ }
+
+ /**
* Returns the constructed {@link NetworkAgentConfig} object.
*/
@NonNull
@@ -412,6 +470,8 @@
out.writeInt(skip464xlat ? 1 : 0);
out.writeInt(legacyType);
out.writeString(legacyTypeName);
+ out.writeInt(legacySubType);
+ out.writeString(legacySubTypeName);
out.writeString(mLegacyExtraInfo);
}
@@ -429,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 c9c0940..f50b018 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;
@@ -538,43 +537,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 =
@@ -639,19 +601,31 @@
}
/**
- * Removes (if found) the given capability from this {@code NetworkCapability} instance.
+ * Removes (if found) the given capability from this {@code NetworkCapability}
+ * instance that were added via addCapability(int) or setCapabilities(int[], int[]).
*
* @param capability the capability to be removed.
* @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) {
- // Note that this method removes capabilities that were added via addCapability(int),
- // addUnwantedCapability(int) or setCapabilities(int[], int[]).
checkValidCapability(capability);
final long mask = ~(1 << capability);
mNetworkCapabilities &= mask;
- mUnwantedNetworkCapabilities &= mask;
+ return this;
+ }
+
+ /**
+ * Removes (if found) the given unwanted capability from this {@code NetworkCapability}
+ * instance that were added via addUnwantedCapability(int) or setCapabilities(int[], int[]).
+ *
+ * @param capability the capability to be removed.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
+ * @hide
+ */
+ public @NonNull NetworkCapabilities removeUnwantedCapability(@NetCapability int capability) {
+ checkValidCapability(capability);
+ mUnwantedNetworkCapabilities &= ~(1 << capability);
return this;
}
@@ -723,6 +697,7 @@
}
/** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public boolean hasUnwantedCapability(@NetCapability int capability) {
return isValidCapability(capability)
&& ((mUnwantedNetworkCapabilities & (1 << capability)) != 0);
@@ -736,10 +711,33 @@
return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0);
}
- /** Note this method may result in having the same capability in wanted and unwanted lists. */
+ /**
+ * 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) {
- this.mNetworkCapabilities |= nc.mNetworkCapabilities;
- this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities;
+ final long wantedCaps = this.mNetworkCapabilities | nc.mNetworkCapabilities;
+ final long unwantedCaps =
+ this.mUnwantedNetworkCapabilities | nc.mUnwantedNetworkCapabilities;
+ if ((wantedCaps & unwantedCaps) != 0) {
+ throw new IllegalArgumentException(
+ "Cannot have the same capability in wanted and unwanted lists.");
+ }
+ this.mNetworkCapabilities = wantedCaps;
+ this.mUnwantedNetworkCapabilities = unwantedCaps;
}
/**
@@ -792,37 +790,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);
}
}
@@ -2068,34 +2041,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
*/
diff --git a/framework/src/android/net/NetworkProvider.java b/framework/src/android/net/NetworkProvider.java
index 14cb51c..d5b5c9b 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,152 @@
public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request);
}
+
+ /** @hide */
+ // TODO : make @SystemApi when the impl is complete
+ public interface NetworkOfferCallback {
+ /** Called by the system when this offer is needed to satisfy some networking request. */
+ void onOfferNeeded(@NonNull NetworkRequest request, int providerId);
+ /** Called by the system when this offer is no longer needed. */
+ void onOfferUnneeded(@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 onOfferNeeded(final @NonNull NetworkRequest request,
+ final int providerId) {
+ mExecutor.execute(() -> callback.onOfferNeeded(request, providerId));
+ }
+
+ @Override
+ public void onOfferUnneeded(final @NonNull NetworkRequest request) {
+ mExecutor.execute(() -> callback.onOfferUnneeded(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 caps and score.
+ *
+ * A NetworkProvider's job is to provide networks. This function 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 necessary. When an
+ * offer might be advantageous over existing networks, the provider will receive a call to
+ * the associated callback's {@link NetworkOfferCallback#onOfferNeeded} method. The provider
+ * should then try to bring up this network. When an offer is no longer needed, the stack
+ * will inform the provider by calling {@link NetworkOfferCallback#onOfferUnneeded}. 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 needed 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 be a better choice than any existing network for any particular
+ * request, that's when the stack decides the offer is needed. If the current networking
+ * requests are all satisfied by networks that this offer can't possibly be a better match
+ * for, that's when the offer is unneeded. An offer starts off as unneeded ; the provider
+ * should not try to bring up the network until {@link NetworkOfferCallback#onOfferNeeded}
+ * 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 is needed. 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
+ * unneeded 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 offer 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 capabilities in particular, 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
+ */
+ // TODO : make @SystemApi when the impl is complete
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void offerNetwork(@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
+ */
+ // TODO : make @SystemApi when the impl is complete
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void unofferNetwork(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 f9b3db1..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;
@@ -313,12 +312,31 @@
*
* @hide
*/
+ @NonNull
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
mNetworkCapabilities.addUnwantedCapability(capability);
return this;
}
/**
+ * Removes (if found) the given unwanted capability from this builder instance.
+ *
+ * @param capability The unwanted capability to remove.
+ * @return The builder to facilitate chaining.
+ *
+ * @hide
+ */
+ @NonNull
+ @SuppressLint("BuilderSetStyle")
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public Builder removeUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
+ mNetworkCapabilities.removeUnwantedCapability(capability);
+ return this;
+ }
+
+ /**
* Completely clears all the {@code NetworkCapabilities} from this builder instance,
* removing even the capabilities that are set by default when the object is constructed.
*
@@ -575,6 +593,7 @@
*
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public boolean hasUnwantedCapability(@NetCapability int capability) {
return networkCapabilities.hasUnwantedCapability(capability);
}
@@ -655,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;
@@ -679,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 eadcb2d..6584993 100644
--- a/framework/src/android/net/NetworkScore.java
+++ b/framework/src/android/net/NetworkScore.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,7 +30,7 @@
* network is considered for a particular use.
* @hide
*/
-// TODO : @SystemApi when the implementation is complete
+@SystemApi
public final class NetworkScore implements Parcelable {
// This will be removed soon. Do *NOT* depend on it for any new code that is not part of
// a migration.
@@ -62,6 +63,8 @@
/**
* @return whether this score has a particular policy.
+ *
+ * @hide
*/
@VisibleForTesting
public boolean hasPolicy(final int policy) {
diff --git a/framework/src/android/net/NetworkUtils.java b/framework/src/android/net/NetworkUtils.java
index c4bebc0..16a49bc 100644
--- a/framework/src/android/net/NetworkUtils.java
+++ b/framework/src/android/net/NetworkUtils.java
@@ -16,6 +16,8 @@
package android.net;
+import static android.net.ConnectivityManager.NETID_UNSET;
+
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.system.ErrnoException;
@@ -55,6 +57,8 @@
*/
public static native void detachBPFFilter(FileDescriptor fd) throws SocketException;
+ private static native boolean bindProcessToNetworkHandle(long netHandle);
+
/**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
@@ -63,13 +67,20 @@
* 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 +92,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 +121,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 +136,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..9d1bb0f 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,22 +51,34 @@
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",
],
@@ -78,6 +90,8 @@
java_library {
name: "service-connectivity-protos",
+ sdk_version: "system_current",
+ min_sdk_version: "30",
proto: {
type: "nano",
},
@@ -93,6 +107,8 @@
java_library {
name: "service-connectivity",
+ sdk_version: "system_server_current",
+ min_sdk_version: "30",
installable: true,
static_libs: [
"service-connectivity-pre-jarjar",
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/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());
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6abec71..8f56842 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -15,7 +15,6 @@
*/
package com.android.server;
-
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_WATCH;
@@ -122,6 +121,7 @@
import android.net.INetworkAgent;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
+import android.net.INetworkOfferCallback;
import android.net.IOnCompleteListener;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
@@ -145,7 +145,6 @@
import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
-import android.net.NetworkStackClient;
import android.net.NetworkState;
import android.net.NetworkStateSnapshot;
import android.net.NetworkTestResultParcelable;
@@ -172,13 +171,14 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
+import android.net.networkstack.ModuleNetworkStackClient;
+import android.net.networkstack.NetworkStackClientBase;
import android.net.resolv.aidl.DnsHealthEventParcel;
import android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener;
import android.net.resolv.aidl.Nat64PrefixEventParcel;
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
-import android.net.util.NetdService;
import android.os.BatteryStatsManager;
import android.os.Binder;
import android.os.Build;
@@ -229,6 +229,7 @@
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
+import com.android.server.connectivity.FullScore;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
import com.android.server.connectivity.MockableSystemProperties;
@@ -236,6 +237,7 @@
import com.android.server.connectivity.NetworkDiagnostics;
import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import com.android.server.connectivity.NetworkOffer;
import com.android.server.connectivity.NetworkRanker;
import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.ProfileNetworkPreferences;
@@ -593,6 +595,18 @@
private static final int EVENT_UID_BLOCKED_REASON_CHANGED = 51;
/**
+ * Event to register a new network offer
+ * obj = NetworkOffer
+ */
+ private static final int EVENT_REGISTER_NETWORK_OFFER = 52;
+
+ /**
+ * Event to unregister an existing network offer
+ * obj = INetworkOfferCallback
+ */
+ private static final int EVENT_UNREGISTER_NETWORK_OFFER = 53;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -1121,10 +1135,10 @@
}
/**
- * Get a reference to the NetworkStackClient.
+ * Get a reference to the ModuleNetworkStackClient.
*/
- public NetworkStackClient getNetworkStack() {
- return NetworkStackClient.getInstance();
+ public NetworkStackClientBase getNetworkStack() {
+ return ModuleNetworkStackClient.getInstance(null);
}
/**
@@ -1145,8 +1159,8 @@
/**
* @see NetworkUtils#queryUserAccess(int, int)
*/
- public boolean queryUserAccess(int uid, int netId) {
- return NetworkUtils.queryUserAccess(uid, netId);
+ public boolean queryUserAccess(int uid, Network network, ConnectivityService cs) {
+ return cs.queryUserAccess(uid, network);
}
/**
@@ -1183,7 +1197,8 @@
public ConnectivityService(Context context) {
this(context, getDnsResolver(context), new IpConnectivityLog(),
- NetdService.getInstance(), new Dependencies());
+ INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
+ new Dependencies());
}
@VisibleForTesting
@@ -1202,7 +1217,7 @@
mNetworkRanker = new NetworkRanker();
final NetworkRequest defaultInternetRequest = createDefaultRequest();
mDefaultRequest = new NetworkRequestInfo(
- defaultInternetRequest, null,
+ Process.myUid(), defaultInternetRequest, null,
new Binder(), NetworkCallback.FLAG_INCLUDE_LOCATION_INFO,
null /* attributionTags */);
mNetworkRequests.put(defaultInternetRequest, mDefaultRequest);
@@ -1408,8 +1423,7 @@
if (enable) {
handleRegisterNetworkRequest(new NetworkRequestInfo(
- networkRequest, null,
- new Binder(),
+ Process.myUid(), networkRequest, null, new Binder(),
NetworkCallback.FLAG_INCLUDE_LOCATION_INFO,
null /* attributionTags */));
} else {
@@ -1562,7 +1576,7 @@
final int requestId = nri.getActiveRequest() != null
? nri.getActiveRequest().requestId : nri.mRequests.get(0).requestId;
mNetworkInfoBlockingLogs.log(String.format(
- "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId()));
+ "%s %d(%d) on netId %d", action, nri.mAsUid, requestId, net.getNetId()));
}
/**
@@ -2077,6 +2091,8 @@
private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc,
int callerUid, String callerPackageName) {
if (!checkSettingsPermission()) {
+ // There is no need to track the effective UID of the request here. If the caller lacks
+ // the settings permission, the effective UID is the same as the calling ID.
nc.setSingleUid(callerUid);
}
nc.setRequestorUidAndPackageName(callerUid, callerPackageName);
@@ -2904,10 +2920,6 @@
}
pw.println();
- pw.println("NetworkStackClient logs:");
- pw.increaseIndent();
- NetworkStackClient.getInstance().dump(pw);
- pw.decreaseIndent();
pw.println();
pw.println("Permission Monitor:");
@@ -4567,6 +4579,18 @@
handleUnregisterNetworkProvider((Messenger) msg.obj);
break;
}
+ case EVENT_REGISTER_NETWORK_OFFER: {
+ handleRegisterNetworkOffer((NetworkOffer) msg.obj);
+ break;
+ }
+ case EVENT_UNREGISTER_NETWORK_OFFER: {
+ final NetworkOfferInfo offer =
+ findNetworkOfferInfoByCallback((INetworkOfferCallback) msg.obj);
+ if (null != offer) {
+ handleUnregisterNetworkOffer(offer);
+ }
+ break;
+ }
case EVENT_REGISTER_NETWORK_AGENT: {
final Pair<NetworkAgentInfo, INetworkMonitor> arg =
(Pair<NetworkAgentInfo, INetworkMonitor>) msg.obj;
@@ -4842,6 +4866,42 @@
nai.networkMonitor().forceReevaluation(uid);
}
+ // TODO: call into netd.
+ private boolean queryUserAccess(int uid, Network network) {
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+ if (nai == null) return false;
+
+ // Any UID can use its default network.
+ if (nai == getDefaultNetworkForUid(uid)) return true;
+
+ // Privileged apps can use any network.
+ if (mPermissionMonitor.hasRestrictedNetworksPermission(uid)) {
+ return true;
+ }
+
+ // An unprivileged UID can use a VPN iff the VPN applies to it.
+ if (nai.isVPN()) {
+ return nai.networkCapabilities.appliesToUid(uid);
+ }
+
+ // An unprivileged UID can bypass the VPN that applies to it only if it can protect its
+ // sockets, i.e., if it is the owner.
+ final NetworkAgentInfo vpn = getVpnForUid(uid);
+ if (vpn != null && !vpn.networkAgentConfig.allowBypass
+ && uid != vpn.networkCapabilities.getOwnerUid()) {
+ return false;
+ }
+
+ // The UID's permission must be at least sufficient for the network. Since the restricted
+ // permission was already checked above, that just leaves background networks.
+ if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
+ return mPermissionMonitor.hasUseBackgroundNetworksPermission(uid);
+ }
+
+ // Unrestricted network. Anyone gets to use it.
+ return true;
+ }
+
/**
* Returns information about the proxy a certain network is using. If given a null network, it
* it will return the proxy for the bound network for the caller app or the default proxy if
@@ -4862,7 +4922,7 @@
return null;
}
return getLinkPropertiesProxyInfo(activeNetwork);
- } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network.getNetId())) {
+ } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network, this)) {
// Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
// caller may not have.
return getLinkPropertiesProxyInfo(network);
@@ -5367,6 +5427,8 @@
boolean mPendingIntentSent;
@Nullable
final Messenger mMessenger;
+
+ // Information about the caller that caused this object to be created.
@Nullable
private final IBinder mBinder;
final int mPid;
@@ -5374,6 +5436,13 @@
final @NetworkCallback.Flag int mCallbackFlags;
@Nullable
final String mCallingAttributionTag;
+
+ // Effective UID of this request. This is different from mUid when a privileged process
+ // files a request on behalf of another UID. This UID is used to determine blocked status,
+ // UID matching, and so on. mUid above is used for permission checks and to enforce the
+ // maximum limit of registered callbacks per UID.
+ final int mAsUid;
+
// In order to preserve the mapping of NetworkRequest-to-callback when apps register
// callbacks using a returned NetworkRequest, the original NetworkRequest needs to be
// maintained for keying off of. This is only a concern when the original nri
@@ -5401,12 +5470,12 @@
return (null == uids) ? new ArraySet<>() : uids;
}
- NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final PendingIntent pi,
- @Nullable String callingAttributionTag) {
- this(Collections.singletonList(r), r, pi, callingAttributionTag);
+ NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r,
+ @Nullable final PendingIntent pi, @Nullable String callingAttributionTag) {
+ this(asUid, Collections.singletonList(r), r, pi, callingAttributionTag);
}
- NetworkRequestInfo(@NonNull final List<NetworkRequest> r,
+ NetworkRequestInfo(int asUid, @NonNull final List<NetworkRequest> r,
@NonNull final NetworkRequest requestForCallback, @Nullable final PendingIntent pi,
@Nullable String callingAttributionTag) {
ensureAllNetworkRequestsHaveType(r);
@@ -5417,6 +5486,7 @@
mBinder = null;
mPid = getCallingPid();
mUid = mDeps.getCallingUid();
+ mAsUid = asUid;
mNetworkRequestCounter.incrementCountOrThrow(mUid);
/**
* Location sensitive data not included in pending intent. Only included in
@@ -5426,14 +5496,15 @@
mCallingAttributionTag = callingAttributionTag;
}
- NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final Messenger m,
+ NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r, @Nullable final Messenger m,
@Nullable final IBinder binder,
@NetworkCallback.Flag int callbackFlags,
@Nullable String callingAttributionTag) {
- this(Collections.singletonList(r), r, m, binder, callbackFlags, callingAttributionTag);
+ this(asUid, Collections.singletonList(r), r, m, binder, callbackFlags,
+ callingAttributionTag);
}
- NetworkRequestInfo(@NonNull final List<NetworkRequest> r,
+ NetworkRequestInfo(int asUid, @NonNull final List<NetworkRequest> r,
@NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m,
@Nullable final IBinder binder,
@NetworkCallback.Flag int callbackFlags,
@@ -5446,6 +5517,7 @@
mBinder = binder;
mPid = getCallingPid();
mUid = mDeps.getCallingUid();
+ mAsUid = asUid;
mPendingIntent = null;
mNetworkRequestCounter.incrementCountOrThrow(mUid);
mCallbackFlags = callbackFlags;
@@ -5488,18 +5560,19 @@
mBinder = nri.mBinder;
mPid = nri.mPid;
mUid = nri.mUid;
+ mAsUid = nri.mAsUid;
mPendingIntent = nri.mPendingIntent;
mNetworkRequestCounter.incrementCountOrThrow(mUid);
mCallbackFlags = nri.mCallbackFlags;
mCallingAttributionTag = nri.mCallingAttributionTag;
}
- NetworkRequestInfo(@NonNull final NetworkRequest r) {
- this(Collections.singletonList(r));
+ NetworkRequestInfo(int asUid, @NonNull final NetworkRequest r) {
+ this(asUid, Collections.singletonList(r));
}
- NetworkRequestInfo(@NonNull final List<NetworkRequest> r) {
- this(r, r.get(0), null /* pi */, null /* callingAttributionTag */);
+ NetworkRequestInfo(int asUid, @NonNull final List<NetworkRequest> r) {
+ this(asUid, r, r.get(0), null /* pi */, null /* callingAttributionTag */);
}
// True if this NRI is being satisfied. It also accounts for if the nri has its satisifer
@@ -5535,9 +5608,10 @@
@Override
public String toString() {
- return "uid/pid:" + mUid + "/" + mPid + " active request Id: "
+ final String asUidString = (mAsUid == mUid) ? "" : " asUid: " + mAsUid;
+ return "uid/pid:" + mUid + "/" + mPid + asUidString + " activeRequest: "
+ (mActiveRequest == null ? null : mActiveRequest.requestId)
- + " callback request Id: "
+ + " callbackRequest: "
+ mNetworkRequestForCallback.requestId
+ " " + mRequests
+ (mPendingIntent == null ? "" : " to trigger " + mPendingIntent)
@@ -5638,7 +5712,7 @@
}
@Override
- public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
+ public NetworkRequest requestNetwork(int asUid, NetworkCapabilities networkCapabilities,
int reqTypeInt, Messenger messenger, int timeoutMs, IBinder binder,
int legacyType, int callbackFlags, @NonNull String callingPackageName,
@Nullable String callingAttributionTag) {
@@ -5650,6 +5724,12 @@
}
final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities;
final int callingUid = mDeps.getCallingUid();
+ // Privileged callers can track the default network of another UID by passing in a UID.
+ if (asUid != Process.INVALID_UID) {
+ enforceSettingsPermission();
+ } else {
+ asUid = callingUid;
+ }
final NetworkRequest.Type reqType;
try {
reqType = NetworkRequest.Type.values()[reqTypeInt];
@@ -5659,10 +5739,10 @@
switch (reqType) {
case TRACK_DEFAULT:
// If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
- // is unused and will be replaced by ones appropriate for the caller.
- // This allows callers to keep track of the default network for their app.
+ // is unused and will be replaced by ones appropriate for the UID (usually, the
+ // calling app). This allows callers to keep track of the default network.
networkCapabilities = copyDefaultNetworkCapabilitiesForUid(
- defaultNc, callingUid, callingPackageName);
+ defaultNc, asUid, callingUid, callingPackageName);
enforceAccessPermission();
break;
case TRACK_SYSTEM_DEFAULT:
@@ -5714,7 +5794,8 @@
final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId(), reqType);
final NetworkRequestInfo nri = getNriToRegister(
- networkRequest, messenger, binder, callbackFlags, callingAttributionTag);
+ asUid, networkRequest, messenger, binder, callbackFlags,
+ callingAttributionTag);
if (DBG) log("requestNetwork for " + nri);
// For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were
@@ -5741,25 +5822,27 @@
* requests registered to track the default request. If there is currently a per-app default
* tracking the app requestor, then we need to create a version of this nri that mirrors that of
* the tracking per-app default so that callbacks are sent to the app requestor appropriately.
+ * @param asUid the uid on behalf of which to file the request. Different from requestorUid
+ * when a privileged caller is tracking the default network for another uid.
* @param nr the network request for the nri.
* @param msgr the messenger for the nri.
* @param binder the binder for the nri.
* @param callingAttributionTag the calling attribution tag for the nri.
* @return the nri to register.
*/
- private NetworkRequestInfo getNriToRegister(@NonNull final NetworkRequest nr,
+ private NetworkRequestInfo getNriToRegister(final int asUid, @NonNull final NetworkRequest nr,
@Nullable final Messenger msgr, @Nullable final IBinder binder,
@NetworkCallback.Flag int callbackFlags,
@Nullable String callingAttributionTag) {
final List<NetworkRequest> requests;
if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) {
requests = copyDefaultNetworkRequestsForUid(
- nr.getRequestorUid(), nr.getRequestorPackageName());
+ asUid, nr.getRequestorUid(), nr.getRequestorPackageName());
} else {
requests = Collections.singletonList(nr);
}
return new NetworkRequestInfo(
- requests, nr, msgr, binder, callbackFlags, callingAttributionTag);
+ asUid, requests, nr, msgr, binder, callbackFlags, callingAttributionTag);
}
private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities,
@@ -5840,8 +5923,8 @@
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
- NetworkRequestInfo nri =
- new NetworkRequestInfo(networkRequest, operation, callingAttributionTag);
+ NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, networkRequest, operation,
+ callingAttributionTag);
if (DBG) log("pendingRequest for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
nri));
@@ -5908,7 +5991,7 @@
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
NetworkRequestInfo nri =
- new NetworkRequestInfo(networkRequest, messenger, binder, callbackFlags,
+ new NetworkRequestInfo(callingUid, networkRequest, messenger, binder, callbackFlags,
callingAttributionTag);
if (VDBG) log("listenForNetwork for " + nri);
@@ -5933,8 +6016,8 @@
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
- NetworkRequestInfo nri =
- new NetworkRequestInfo(networkRequest, operation, callingAttributionTag);
+ NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, networkRequest, operation,
+ callingAttributionTag);
if (VDBG) log("pendingListenForNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
@@ -5989,12 +6072,37 @@
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger));
}
+ @Override
+ public void offerNetwork(final int providerId,
+ @NonNull final NetworkScore score, @NonNull final NetworkCapabilities caps,
+ @NonNull final INetworkOfferCallback callback) {
+ final NetworkOffer offer = new NetworkOffer(
+ FullScore.makeProspectiveScore(score, caps), caps, callback, providerId);
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_OFFER, offer));
+ }
+
+ @Override
+ public void unofferNetwork(@NonNull final INetworkOfferCallback callback) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_OFFER, callback));
+ }
+
private void handleUnregisterNetworkProvider(Messenger messenger) {
NetworkProviderInfo npi = mNetworkProviderInfos.remove(messenger);
if (npi == null) {
loge("Failed to find Messenger in unregisterNetworkProvider");
return;
}
+ // Unregister all the offers from this provider
+ final ArrayList<NetworkOfferInfo> toRemove = new ArrayList<>();
+ for (final NetworkOfferInfo noi : mNetworkOffers) {
+ if (noi.offer.providerId == npi.providerId) {
+ // Can't call handleUnregisterNetworkOffer here because iteration is in progress
+ toRemove.add(noi);
+ }
+ }
+ for (NetworkOfferInfo noi : toRemove) {
+ handleUnregisterNetworkOffer(noi);
+ }
if (DBG) log("unregisterNetworkProvider for " + npi.name);
}
@@ -6033,6 +6141,10 @@
// (on the handler thread).
private volatile List<UidRange> mVpnBlockedUidRanges = new ArrayList<>();
+ // Must only be accessed on the handler thread
+ @NonNull
+ private final ArrayList<NetworkOfferInfo> mNetworkOffers = new ArrayList<>();
+
@GuardedBy("mBlockedAppUids")
private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
@@ -6084,33 +6196,37 @@
/**
* Get a copy of the network requests of the default request that is currently tracking the
* given uid.
+ * @param asUid the uid on behalf of which to file the request. Different from requestorUid
+ * when a privileged caller is tracking the default network for another uid.
* @param requestorUid the uid to check the default for.
* @param requestorPackageName the requestor's package name.
* @return a copy of the default's NetworkRequest that is tracking the given uid.
*/
@NonNull
private List<NetworkRequest> copyDefaultNetworkRequestsForUid(
- @NonNull final int requestorUid, @NonNull final String requestorPackageName) {
+ final int asUid, final int requestorUid, @NonNull final String requestorPackageName) {
return copyNetworkRequestsForUid(
- getDefaultRequestTrackingUid(requestorUid).mRequests,
- requestorUid, requestorPackageName);
+ getDefaultRequestTrackingUid(asUid).mRequests,
+ asUid, requestorUid, requestorPackageName);
}
/**
* Copy the given nri's NetworkRequest collection.
* @param requestsToCopy the NetworkRequest collection to be copied.
+ * @param asUid the uid on behalf of which to file the request. Different from requestorUid
+ * when a privileged caller is tracking the default network for another uid.
* @param requestorUid the uid to set on the copied collection.
* @param requestorPackageName the package name to set on the copied collection.
* @return the copied NetworkRequest collection.
*/
@NonNull
private List<NetworkRequest> copyNetworkRequestsForUid(
- @NonNull final List<NetworkRequest> requestsToCopy, @NonNull final int requestorUid,
- @NonNull final String requestorPackageName) {
+ @NonNull final List<NetworkRequest> requestsToCopy, final int asUid,
+ final int requestorUid, @NonNull final String requestorPackageName) {
final List<NetworkRequest> requests = new ArrayList<>();
for (final NetworkRequest nr : requestsToCopy) {
requests.add(new NetworkRequest(copyDefaultNetworkCapabilitiesForUid(
- nr.networkCapabilities, requestorUid, requestorPackageName),
+ nr.networkCapabilities, asUid, requestorUid, requestorPackageName),
nr.legacyType, nextNetworkRequestId(), nr.type));
}
return requests;
@@ -6118,17 +6234,17 @@
@NonNull
private NetworkCapabilities copyDefaultNetworkCapabilitiesForUid(
- @NonNull final NetworkCapabilities netCapToCopy, @NonNull final int requestorUid,
- @NonNull final String requestorPackageName) {
+ @NonNull final NetworkCapabilities netCapToCopy, final int asUid,
+ final int requestorUid, @NonNull final String requestorPackageName) {
// These capabilities are for a TRACK_DEFAULT callback, so:
// 1. Remove NET_CAPABILITY_VPN, because it's (currently!) the only difference between
// mDefaultRequest and a per-UID default request.
// TODO: stop depending on the fact that these two unrelated things happen to be the same
- // 2. Always set the UIDs to mAsUid. restrictRequestUidsForCallerAndSetRequestorInfo will
+ // 2. Always set the UIDs to asUid. restrictRequestUidsForCallerAndSetRequestorInfo will
// not do this in the case of a privileged application.
final NetworkCapabilities netCap = new NetworkCapabilities(netCapToCopy);
netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
- netCap.setSingleUid(requestorUid);
+ netCap.setSingleUid(asUid);
restrictRequestUidsForCallerAndSetRequestorInfo(
netCap, requestorUid, requestorPackageName);
return netCap;
@@ -6338,6 +6454,71 @@
updateUids(nai, null, nai.networkCapabilities);
}
+ private class NetworkOfferInfo implements IBinder.DeathRecipient {
+ @NonNull public final NetworkOffer offer;
+
+ NetworkOfferInfo(@NonNull final NetworkOffer offer) {
+ this.offer = offer;
+ }
+
+ @Override
+ public void binderDied() {
+ mHandler.post(() -> handleUnregisterNetworkOffer(this));
+ }
+ }
+
+ private boolean isNetworkProviderWithIdRegistered(final int providerId) {
+ for (final NetworkProviderInfo npi : mNetworkProviderInfos.values()) {
+ if (npi.providerId == providerId) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Register or update a network offer.
+ * @param newOffer The new offer. If the callback member is the same as an existing
+ * offer, it is an update of that offer.
+ */
+ private void handleRegisterNetworkOffer(@NonNull final NetworkOffer newOffer) {
+ ensureRunningOnConnectivityServiceThread();
+ if (!isNetworkProviderWithIdRegistered(newOffer.providerId)) {
+ // This may actually happen if a provider updates its score or registers and then
+ // immediately unregisters. The offer would still be in the handler queue, but the
+ // provider would have been removed.
+ if (DBG) log("Received offer from an unregistered provider");
+ return;
+ }
+ final NetworkOfferInfo existingOffer = findNetworkOfferInfoByCallback(newOffer.callback);
+ if (null != existingOffer) {
+ handleUnregisterNetworkOffer(existingOffer);
+ newOffer.migrateFrom(existingOffer.offer);
+ }
+ final NetworkOfferInfo noi = new NetworkOfferInfo(newOffer);
+ try {
+ noi.offer.callback.asBinder().linkToDeath(noi, 0 /* flags */);
+ } catch (RemoteException e) {
+ noi.binderDied();
+ return;
+ }
+ mNetworkOffers.add(noi);
+ // TODO : send requests to the provider.
+ }
+
+ private void handleUnregisterNetworkOffer(@NonNull final NetworkOfferInfo noi) {
+ ensureRunningOnConnectivityServiceThread();
+ mNetworkOffers.remove(noi);
+ noi.offer.callback.asBinder().unlinkToDeath(noi, 0 /* flags */);
+ }
+
+ @Nullable private NetworkOfferInfo findNetworkOfferInfoByCallback(
+ @NonNull final INetworkOfferCallback callback) {
+ ensureRunningOnConnectivityServiceThread();
+ for (final NetworkOfferInfo noi : mNetworkOffers) {
+ if (noi.offer.callback.equals(callback)) return noi;
+ }
+ return null;
+ }
+
/**
* Called when receiving LinkProperties directly from a NetworkAgent.
* Stores into |nai| any data coming from the agent that might also be written to the network's
@@ -8034,9 +8215,9 @@
final boolean metered = nai.networkCapabilities.isMetered();
boolean blocked;
- blocked = isUidBlockedByVpn(nri.mUid, mVpnBlockedUidRanges);
+ blocked = isUidBlockedByVpn(nri.mAsUid, mVpnBlockedUidRanges);
blocked |= NetworkPolicyManager.isUidBlocked(
- mUidBlockedReasons.get(nri.mUid, BLOCKED_REASON_NONE), metered);
+ mUidBlockedReasons.get(nri.mAsUid, BLOCKED_REASON_NONE), metered);
callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_AVAILABLE, blocked ? 1 : 0);
}
@@ -8064,12 +8245,12 @@
NetworkRequestInfo nri = mNetworkRequests.get(nr);
final boolean oldBlocked, newBlocked, oldVpnBlocked, newVpnBlocked;
- oldVpnBlocked = isUidBlockedByVpn(nri.mUid, oldBlockedUidRanges);
+ oldVpnBlocked = isUidBlockedByVpn(nri.mAsUid, oldBlockedUidRanges);
newVpnBlocked = (oldBlockedUidRanges != newBlockedUidRanges)
- ? isUidBlockedByVpn(nri.mUid, newBlockedUidRanges)
+ ? isUidBlockedByVpn(nri.mAsUid, newBlockedUidRanges)
: oldVpnBlocked;
- final int blockedReasons = mUidBlockedReasons.get(nri.mUid, BLOCKED_REASON_NONE);
+ final int blockedReasons = mUidBlockedReasons.get(nri.mAsUid, BLOCKED_REASON_NONE);
oldBlocked = oldVpnBlocked || NetworkPolicyManager.isUidBlocked(
blockedReasons, oldMetered);
newBlocked = newVpnBlocked || NetworkPolicyManager.isUidBlocked(
@@ -8104,7 +8285,7 @@
for (int i = 0; i < nai.numNetworkRequests(); i++) {
NetworkRequest nr = nai.requestAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
- if (nri != null && nri.mUid == uid) {
+ if (nri != null && nri.mAsUid == uid) {
callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_BLK_CHANGED, arg);
}
}
@@ -8869,7 +9050,7 @@
// nri is not bound to the death of callback. Instead, callback.bindToDeath() is set in
// handleRegisterConnectivityDiagnosticsCallback(). nri will be cleaned up as part of the
// callback's binder death.
- final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId);
+ final NetworkRequestInfo nri = new NetworkRequestInfo(callingUid, requestWithId);
final ConnectivityDiagnosticsCallbackInfo cbInfo =
new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName);
@@ -9353,7 +9534,7 @@
nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities));
nrs.add(createDefaultRequest());
setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids()));
- final NetworkRequestInfo nri = new NetworkRequestInfo(nrs);
+ final NetworkRequestInfo nri = new NetworkRequestInfo(Process.myUid(), nrs);
result.add(nri);
}
return result;
@@ -9524,7 +9705,7 @@
}
// Include this nri if it will be tracked by the new per-app default requests.
final boolean isNriGoingToBeTracked =
- getDefaultRequestTrackingUid(nri.mUid) != mDefaultRequest;
+ getDefaultRequestTrackingUid(nri.mAsUid) != mDefaultRequest;
if (isNriGoingToBeTracked) {
defaultCallbackRequests.add(nri);
}
@@ -9546,7 +9727,7 @@
final ArraySet<NetworkRequestInfo> callbackRequestsToRegister = new ArraySet<>();
for (final NetworkRequestInfo callbackRequest : perAppCallbackRequestsForUpdate) {
final NetworkRequestInfo trackingNri =
- getDefaultRequestTrackingUid(callbackRequest.mUid);
+ getDefaultRequestTrackingUid(callbackRequest.mAsUid);
// If this nri is not being tracked, the change it back to an untracked nri.
if (trackingNri == mDefaultRequest) {
@@ -9556,12 +9737,12 @@
continue;
}
- final String requestorPackageName =
- callbackRequest.mRequests.get(0).getRequestorPackageName();
+ final NetworkRequest request = callbackRequest.mRequests.get(0);
callbackRequestsToRegister.add(new NetworkRequestInfo(
callbackRequest,
copyNetworkRequestsForUid(
- trackingNri.mRequests, callbackRequest.mUid, requestorPackageName)));
+ trackingNri.mRequests, callbackRequest.mAsUid,
+ callbackRequest.mUid, request.getRequestorPackageName())));
}
return callbackRequestsToRegister;
}
@@ -9665,7 +9846,7 @@
ranges.add(new UidRange(uid, uid));
}
setNetworkRequestUids(requests, ranges);
- return new NetworkRequestInfo(requests);
+ return new NetworkRequestInfo(Process.myUid(), requests);
}
private NetworkRequest createUnmeteredNetworkRequest() {
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index f566277..09873f4 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -35,7 +35,6 @@
import android.net.RouteInfo;
import android.net.TestNetworkInterface;
import android.net.TestNetworkSpecifier;
-import android.net.util.NetdService;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -86,7 +85,9 @@
mHandler = new Handler(mHandlerThread.getLooper());
mContext = Objects.requireNonNull(context, "missing Context");
- mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance");
+ mNetd = Objects.requireNonNull(
+ INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
+ "could not get netd instance");
mCm = mContext.getSystemService(ConnectivityManager.class);
mNetworkProvider = new NetworkProvider(mContext, mHandler.getLooper(),
TEST_NETWORK_PROVIDER_NAME);
diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/services/core/java/com/android/server/connectivity/FullScore.java
index 028cfee..9326d69 100644
--- a/services/core/java/com/android/server/connectivity/FullScore.java
+++ b/services/core/java/com/android/server/connectivity/FullScore.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
@@ -116,6 +117,33 @@
}
/**
+ * Given a score supplied by the NetworkAgent, produce a prospective score for an offer.
+ *
+ * NetworkOffers have score filters that are compared to the scores of actual networks
+ * to see if they could possibly beat the current satisfier. Some things the agent can't
+ * know in advance ; a good example is the validation bit – some networks will validate,
+ * others won't. For comparison purposes, assume the best, so all possibly beneficial
+ * networks will be brought up.
+ *
+ * @param score the score supplied by the agent for this offer
+ * @param caps the capabilities supplied by the agent for this offer
+ * @return a FullScore appropriate for comparing to actual network's scores.
+ */
+ public static FullScore makeProspectiveScore(@NonNull final NetworkScore score,
+ @NonNull final NetworkCapabilities caps) {
+ // If the network offers Internet access, it may validate.
+ final boolean mayValidate = caps.hasCapability(NET_CAPABILITY_INTERNET);
+ // VPN transports are known in advance.
+ final boolean vpn = caps.hasTransport(TRANSPORT_VPN);
+ // The network hasn't been chosen by the user (yet, at least).
+ final boolean everUserSelected = false;
+ // Don't assume the user will accept unvalidated connectivity.
+ final boolean acceptUnvalidated = false;
+ return withPolicies(score.getLegacyInt(), mayValidate, vpn, everUserSelected,
+ acceptUnvalidated);
+ }
+
+ /**
* Return a new score given updated caps and config.
*
* @param caps the NetworkCapabilities of the network
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 74e4ae7..acf39f0 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -26,6 +26,7 @@
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
+import static android.net.SocketKeepalive.ERROR_NO_SUCH_SLOT;
import static android.net.SocketKeepalive.ERROR_STOP_REASON_UNINITIALIZED;
import static android.net.SocketKeepalive.ERROR_UNSUPPORTED;
import static android.net.SocketKeepalive.MAX_INTERVAL_SEC;
@@ -528,6 +529,8 @@
}
} else if (reason == ERROR_STOP_REASON_UNINITIALIZED) {
throw new IllegalStateException("Unexpected stop reason: " + reason);
+ } else if (reason == ERROR_NO_SUCH_SLOT) {
+ throw new IllegalStateException("No such slot: " + reason);
} else {
notifyErrorCallback(ki.mCallback, reason);
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkOffer.java b/services/core/java/com/android/server/connectivity/NetworkOffer.java
new file mode 100644
index 0000000..548db6b
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/NetworkOffer.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.android.server.connectivity;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.INetworkOfferCallback;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+
+import java.util.Objects;
+
+
+/**
+ * Represents an offer made by a NetworkProvider to create a network if a need arises.
+ *
+ * This class contains the prospective score and capabilities of the network. The provider
+ * is not obligated to caps able to create a network satisfying this, nor to build a network
+ * with the exact score and/or capabilities passed ; after all, not all providers know in
+ * advance what a network will look like after it's connected. Instead, this is meant as a
+ * filter to limit requests sent to the provider by connectivity to those that this offer stands
+ * a chance to fulfill.
+ *
+ * @see NetworkProvider#offerNetwork.
+ *
+ * @hide
+ */
+public class NetworkOffer {
+ @NonNull public final FullScore score;
+ @NonNull public final NetworkCapabilities caps;
+ @NonNull public final INetworkOfferCallback callback;
+ @NonNull public final int providerId;
+
+ private static NetworkCapabilities emptyCaps() {
+ final NetworkCapabilities nc = new NetworkCapabilities();
+ return nc;
+ }
+
+ // Ideally the caps argument would be non-null, but null has historically meant no filter
+ // and telephony passes null. Keep backward compatibility.
+ public NetworkOffer(@NonNull final FullScore score,
+ @Nullable final NetworkCapabilities caps,
+ @NonNull final INetworkOfferCallback callback,
+ @NonNull final int providerId) {
+ this.score = Objects.requireNonNull(score);
+ this.caps = null != caps ? caps : emptyCaps();
+ this.callback = Objects.requireNonNull(callback);
+ this.providerId = providerId;
+ }
+
+ /**
+ * Migrate from, and take over, a previous offer.
+ *
+ * When an updated offer is sent from a provider, call this method on the new offer, passing
+ * the old one, to take over the state.
+ *
+ * @param previousOffer
+ */
+ public void migrateFrom(@NonNull final NetworkOffer previousOffer) {
+ if (!callback.equals(previousOffer.callback)) {
+ throw new IllegalArgumentException("Can only migrate from a previous version of"
+ + " the same offer");
+ }
+ }
+
+ /**
+ * Returns whether an offer can satisfy a NetworkRequest, according to its capabilities.
+ * @param request The request to test against.
+ * @return Whether this offer can satisfy the request.
+ */
+ public final boolean canSatisfy(@NonNull final NetworkRequest request) {
+ return request.networkCapabilities.satisfiedByNetworkCapabilities(caps);
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkOffer [ Score " + score + " ]";
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/OsCompat.java b/services/core/java/com/android/server/connectivity/OsCompat.java
new file mode 100644
index 0000000..57e3dcd
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/OsCompat.java
@@ -0,0 +1,75 @@
+/*
+ * 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 com.android.server.connectivity;
+
+import android.system.ErrnoException;
+import android.system.Os;
+
+import java.io.FileDescriptor;
+
+/**
+ * Compatibility utility for android.system.Os core platform APIs.
+ *
+ * Connectivity has access to such APIs, but they are not part of the module_current stubs yet
+ * (only core_current). Most stable core platform APIs are included manually in the connectivity
+ * build rules, but because Os is also part of the base java SDK that is earlier on the
+ * classpath, the extra core platform APIs are not seen.
+ *
+ * TODO (b/157639992, b/183097033): remove as soon as core_current is part of system_server_current
+ * @hide
+ */
+public class OsCompat {
+ // This value should be correct on all architectures supported by Android, but hardcoding ioctl
+ // numbers should be avoided.
+ /**
+ * @see android.system.OsConstants#TIOCOUTQ
+ */
+ public static final int TIOCOUTQ = 0x5411;
+
+ /**
+ * @see android.system.Os#getsockoptInt(FileDescriptor, int, int)
+ */
+ public static int getsockoptInt(FileDescriptor fd, int level, int option) throws
+ ErrnoException {
+ try {
+ return (int) Os.class.getMethod(
+ "getsockoptInt", FileDescriptor.class, int.class, int.class)
+ .invoke(null, fd, level, option);
+ } catch (ReflectiveOperationException e) {
+ if (e.getCause() instanceof ErrnoException) {
+ throw (ErrnoException) e.getCause();
+ }
+ throw new IllegalStateException("Error calling getsockoptInt", e);
+ }
+ }
+
+ /**
+ * @see android.system.Os#ioctlInt(FileDescriptor, int)
+ */
+ public static int ioctlInt(FileDescriptor fd, int cmd) throws
+ ErrnoException {
+ try {
+ return (int) Os.class.getMethod(
+ "ioctlInt", FileDescriptor.class, int.class).invoke(null, fd, cmd);
+ } catch (ReflectiveOperationException e) {
+ if (e.getCause() instanceof ErrnoException) {
+ throw (ErrnoException) e.getCause();
+ }
+ throw new IllegalStateException("Error calling ioctlInt", e);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 488677a..3711679 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -271,6 +271,13 @@
return mApps.containsKey(uid);
}
+ /**
+ * Returns whether the given uid has permission to use restricted networks.
+ */
+ public synchronized boolean hasRestrictedNetworksPermission(int uid) {
+ return Boolean.TRUE.equals(mApps.get(uid));
+ }
+
private void update(Set<UserHandle> users, Map<Integer, Boolean> apps, boolean add) {
List<Integer> network = new ArrayList<>();
List<Integer> system = new ArrayList<>();
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index c480594..73f3475 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -27,7 +27,8 @@
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IP_TOS;
import static android.system.OsConstants.IP_TTL;
-import static android.system.OsConstants.TIOCOUTQ;
+
+import static com.android.server.connectivity.OsCompat.TIOCOUTQ;
import android.annotation.NonNull;
import android.net.InvalidPacketException;
@@ -175,10 +176,10 @@
}
// Query write sequence number from SEND_QUEUE.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE);
- tcpDetails.seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+ tcpDetails.seq = OsCompat.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
// Query read sequence number from RECV_QUEUE.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE);
- tcpDetails.ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+ tcpDetails.ack = OsCompat.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
// Switch to NO_QUEUE to prevent illegal socket read/write in repair mode.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE);
// Finally, check if socket is still idle. TODO : this check needs to move to
@@ -198,9 +199,9 @@
tcpDetails.rcvWndScale = trw.rcvWndScale;
if (tcpDetails.srcAddress.length == 4 /* V4 address length */) {
// Query TOS.
- tcpDetails.tos = Os.getsockoptInt(fd, IPPROTO_IP, IP_TOS);
+ tcpDetails.tos = OsCompat.getsockoptInt(fd, IPPROTO_IP, IP_TOS);
// Query TTL.
- tcpDetails.ttl = Os.getsockoptInt(fd, IPPROTO_IP, IP_TTL);
+ tcpDetails.ttl = OsCompat.getsockoptInt(fd, IPPROTO_IP, IP_TTL);
}
} catch (ErrnoException e) {
Log.e(TAG, "Exception reading TCP state from socket", e);
@@ -305,7 +306,7 @@
private static boolean isReceiveQueueEmpty(FileDescriptor fd)
throws ErrnoException {
- final int result = Os.ioctlInt(fd, SIOCINQ);
+ final int result = OsCompat.ioctlInt(fd, SIOCINQ);
if (result != 0) {
Log.e(TAG, "Read queue has data");
return false;
@@ -315,7 +316,7 @@
private static boolean isSendQueueEmpty(FileDescriptor fd)
throws ErrnoException {
- final int result = Os.ioctlInt(fd, SIOCOUTQ);
+ final int result = OsCompat.ioctlInt(fd, SIOCOUTQ);
if (result != 0) {
Log.e(TAG, "Write queue has data");
return false;
diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
index a4d8353..1e54093 100644
--- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
@@ -19,6 +19,7 @@
import android.os.Build
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
+import com.android.modules.utils.build.SdkLevel.isAtLeastS
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.assertParcelSane
@@ -44,7 +45,13 @@
setPartialConnectivityAcceptable(false)
setUnvalidatedConnectivityAcceptable(true)
}.build()
- assertParcelSane(config, 10)
+ if (isAtLeastS()) {
+ // From S, the config will have 12 items
+ assertParcelSane(config, 12)
+ } else {
+ // For R or below, the config will have 10 items
+ assertParcelSane(config, 10)
+ }
}
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index d40b88c..e7718b5 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -38,14 +38,12 @@
import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
-import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
import static android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
-import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
import static android.os.Process.INVALID_UID;
import static com.android.modules.utils.build.SdkLevel.isAtLeastR;
@@ -103,20 +101,6 @@
@Test
public void testMaybeMarkCapabilitiesRestricted() {
- // verify EIMS is restricted
- assertEquals((1 << NET_CAPABILITY_EIMS) & RESTRICTED_CAPABILITIES,
- (1 << NET_CAPABILITY_EIMS));
-
- // verify CBS is also restricted
- assertEquals((1 << NET_CAPABILITY_CBS) & RESTRICTED_CAPABILITIES,
- (1 << NET_CAPABILITY_CBS));
-
- // verify default is not restricted
- assertEquals((1 << NET_CAPABILITY_INTERNET) & RESTRICTED_CAPABILITIES, 0);
-
- // just to see
- assertEquals(RESTRICTED_CAPABILITIES & UNRESTRICTED_CAPABILITIES, 0);
-
// check that internet does not get restricted
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addCapability(NET_CAPABILITY_INTERNET);
@@ -329,7 +313,8 @@
if (isAtLeastS()) {
netCap.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2));
netCap.setUids(uids);
- } else if (isAtLeastR()) {
+ }
+ if (isAtLeastR()) {
netCap.setOwnerUid(123);
netCap.setAdministratorUids(new int[] {5, 11});
}
@@ -531,11 +516,22 @@
assertFalse(nc1.equalsNetCapabilities(nc2));
nc2.addUnwantedCapability(NET_CAPABILITY_INTERNET);
assertTrue(nc1.equalsNetCapabilities(nc2));
+ if (isAtLeastS()) {
+ // Remove a required capability doesn't affect unwanted capabilities.
+ // This is a behaviour change from S.
+ nc1.removeCapability(NET_CAPABILITY_INTERNET);
+ assertTrue(nc1.equalsNetCapabilities(nc2));
- nc1.removeCapability(NET_CAPABILITY_INTERNET);
- assertFalse(nc1.equalsNetCapabilities(nc2));
- nc2.removeCapability(NET_CAPABILITY_INTERNET);
- assertTrue(nc1.equalsNetCapabilities(nc2));
+ nc1.removeUnwantedCapability(NET_CAPABILITY_INTERNET);
+ assertFalse(nc1.equalsNetCapabilities(nc2));
+ nc2.removeUnwantedCapability(NET_CAPABILITY_INTERNET);
+ assertTrue(nc1.equalsNetCapabilities(nc2));
+ } else {
+ nc1.removeCapability(NET_CAPABILITY_INTERNET);
+ assertFalse(nc1.equalsNetCapabilities(nc2));
+ nc2.removeCapability(NET_CAPABILITY_INTERNET);
+ assertTrue(nc1.equalsNetCapabilities(nc2));
+ }
}
@Test
@@ -596,11 +592,21 @@
// This will effectively move NOT_ROAMING capability from required to unwanted for nc1.
nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
- nc2.combineCapabilities(nc1);
- // We will get this capability in both requested and unwanted lists thus this request
- // will never be satisfied.
- assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
- assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+ if (isAtLeastS()) {
+ // From S, it is not allowed to have the same capability in both wanted and
+ // unwanted list.
+ assertThrows(IllegalArgumentException.class, () -> nc2.combineCapabilities(nc1));
+ // Remove unwanted capability to continue other tests.
+ nc1.removeUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
+ } else {
+ nc2.combineCapabilities(nc1);
+ // We will get this capability in both requested and unwanted lists thus this request
+ // will never be satisfied.
+ assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+ assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+ // For R or below, remove unwanted capability via removeCapability.
+ nc1.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+ }
nc1.setSSID(TEST_SSID);
nc2.combineCapabilities(nc1);
@@ -963,26 +969,6 @@
assertNotEquals(-50, nc.getSignalStrength());
}
- @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
- public void testDeduceRestrictedCapability() {
- final NetworkCapabilities nc = new NetworkCapabilities();
- // Default capabilities don't have restricted capability.
- assertFalse(nc.deduceRestrictedCapability());
- // If there is a force restricted capability, then the network capabilities is restricted.
- nc.addCapability(NET_CAPABILITY_OEM_PAID);
- nc.addCapability(NET_CAPABILITY_INTERNET);
- assertTrue(nc.deduceRestrictedCapability());
- // Except for the force restricted capability, if there is any unrestricted capability in
- // capabilities, then the network capabilities is not restricted.
- nc.removeCapability(NET_CAPABILITY_OEM_PAID);
- nc.addCapability(NET_CAPABILITY_CBS);
- assertFalse(nc.deduceRestrictedCapability());
- // Except for the force restricted capability, the network capabilities will only be treated
- // as restricted when there is no any unrestricted capability.
- nc.removeCapability(NET_CAPABILITY_INTERNET);
- assertTrue(nc.deduceRestrictedCapability());
- }
-
private void assertNoTransport(NetworkCapabilities nc) {
for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
assertFalse(nc.hasTransport(i));
diff --git a/tests/net/common/java/android/net/NetworkTest.java b/tests/net/common/java/android/net/NetworkTest.java
index 11d44b8..cd9da8e 100644
--- a/tests/net/common/java/android/net/NetworkTest.java
+++ b/tests/net/common/java/android/net/NetworkTest.java
@@ -22,11 +22,16 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.os.Build;
import android.platform.test.annotations.AppModeFull;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,6 +48,9 @@
public class NetworkTest {
final Network mNetwork = new Network(99);
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
@Test
public void testBindSocketOfInvalidFdThrows() throws Exception {
@@ -151,6 +159,23 @@
}
@Test
+ public void testFromNetworkHandle() {
+ final Network network = new Network(1234);
+ assertEquals(network.getNetId(),
+ Network.fromNetworkHandle(network.getNetworkHandle()).getNetId());
+ }
+
+ // Parsing private DNS bypassing handle was not supported until S
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testFromNetworkHandle_S() {
+ final Network network = new Network(1234, true);
+
+ final Network recreatedNetwork = Network.fromNetworkHandle(network.getNetworkHandle());
+ assertEquals(network.netId, recreatedNetwork.netId);
+ assertEquals(network.getNetIdForResolv(), recreatedNetwork.getNetIdForResolv());
+ }
+
+ @Test
public void testGetPrivateDnsBypassingCopy() {
final Network copy = mNetwork.getPrivateDnsBypassingCopy();
assertEquals(mNetwork.netId, copy.netId);
diff --git a/tests/net/integration/src/android/net/TestNetworkStackClient.kt b/tests/net/integration/src/android/net/TestNetworkStackClient.kt
index 01eb514..61ef5bd 100644
--- a/tests/net/integration/src/android/net/TestNetworkStackClient.kt
+++ b/tests/net/integration/src/android/net/TestNetworkStackClient.kt
@@ -19,6 +19,7 @@
import android.content.ComponentName
import android.content.Context
import android.content.Intent
+import android.net.networkstack.NetworkStackClientBase
import android.os.IBinder
import com.android.server.net.integrationtests.TestNetworkStackService
import org.mockito.Mockito.any
@@ -29,28 +30,22 @@
const val TEST_ACTION_SUFFIX = ".Test"
-class TestNetworkStackClient(context: Context) : NetworkStackClient(TestDependencies(context)) {
+class TestNetworkStackClient(private val context: Context) : NetworkStackClientBase() {
// TODO: consider switching to TrackRecord for more expressive checks
private val lastCallbacks = HashMap<Network, INetworkMonitorCallbacks>()
+ private val moduleConnector = ConnectivityModuleConnector { _, action, _, _ ->
+ val intent = Intent(action)
+ val serviceName = TestNetworkStackService::class.qualifiedName
+ ?: fail("TestNetworkStackService name not found")
+ intent.component = ComponentName(context.packageName, serviceName)
+ return@ConnectivityModuleConnector intent
+ }.also { it.init(context) }
- private class TestDependencies(private val context: Context) : Dependencies {
- override fun addToServiceManager(service: IBinder) = Unit
- override fun checkCallerUid() = Unit
-
- override fun getConnectivityModuleConnector(): ConnectivityModuleConnector {
- return ConnectivityModuleConnector { _, _, _, inSystemProcess ->
- getNetworkStackIntent(inSystemProcess)
- }.also { it.init(context) }
- }
-
- private fun getNetworkStackIntent(inSystemProcess: Boolean): Intent? {
- // Simulate out-of-system-process config: in-process service not found (null intent)
- if (inSystemProcess) return null
- val intent = Intent(INetworkStackConnector::class.qualifiedName + TEST_ACTION_SUFFIX)
- val serviceName = TestNetworkStackService::class.qualifiedName
- ?: fail("TestNetworkStackService name not found")
- intent.component = ComponentName(context.packageName, serviceName)
- return intent
+ fun start() {
+ moduleConnector.startModuleService(
+ INetworkStackConnector::class.qualifiedName + TEST_ACTION_SUFFIX,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) { connector ->
+ onNetworkStackConnected(INetworkStackConnector.Stub.asInterface(connector))
}
}
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index db49e0b..14dddcb 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -157,7 +157,6 @@
doReturn(IntArray(0)).`when`(systemConfigManager).getSystemPermissionUids(anyString())
networkStackClient = TestNetworkStackClient(realContext)
- networkStackClient.init()
networkStackClient.start()
service = TestConnectivityService(makeDependencies())
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index 6fc605e..36f205b 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -64,6 +64,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
+import android.os.Process;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -219,8 +220,8 @@
ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
// register callback
- when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
- anyInt(), any(), nullable(String.class))).thenReturn(request);
+ when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
+ anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(request);
manager.requestNetwork(request, callback, handler);
// callback triggers
@@ -247,8 +248,8 @@
ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
// register callback
- when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
- anyInt(), any(), nullable(String.class))).thenReturn(req1);
+ when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
+ anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req1);
manager.requestNetwork(req1, callback, handler);
// callback triggers
@@ -265,8 +266,8 @@
verify(callback, timeout(100).times(0)).onLosing(any(), anyInt());
// callback can be registered again
- when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
- anyInt(), any(), nullable(String.class))).thenReturn(req2);
+ when(mService.requestNetwork(anyInt(), any(), anyInt(), captor.capture(), anyInt(), any(),
+ anyInt(), anyInt(), any(), nullable(String.class))).thenReturn(req2);
manager.requestNetwork(req2, callback, handler);
// callback triggers
@@ -289,8 +290,8 @@
info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
when(mCtx.getApplicationInfo()).thenReturn(info);
- when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), anyInt(),
- any(), nullable(String.class))).thenReturn(request);
+ when(mService.requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(), anyInt(),
+ anyInt(), any(), nullable(String.class))).thenReturn(request);
Handler handler = new Handler(Looper.getMainLooper());
manager.requestNetwork(request, callback, handler);
@@ -357,34 +358,40 @@
final NetworkCallback callback = new ConnectivityManager.NetworkCallback();
manager.requestNetwork(request, callback);
- verify(mService).requestNetwork(eq(request.networkCapabilities),
+ verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
eq(testPkgName), eq(testAttributionTag));
reset(mService);
// Verify that register network callback does not calls requestNetwork at all.
manager.registerNetworkCallback(request, callback);
- verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(),
- anyInt(), any(), any());
+ verify(mService, never()).requestNetwork(anyInt(), any(), anyInt(), any(), anyInt(), any(),
+ anyInt(), anyInt(), any(), any());
verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(), anyInt(),
eq(testPkgName), eq(testAttributionTag));
reset(mService);
+ Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
+
manager.registerDefaultNetworkCallback(callback);
- verify(mService).requestNetwork(eq(null),
+ verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
eq(testPkgName), eq(testAttributionTag));
reset(mService);
- Handler handler = new Handler(ConnectivityThread.getInstanceLooper());
+ manager.registerDefaultNetworkCallbackAsUid(42, callback, handler);
+ verify(mService).requestNetwork(eq(42), eq(null),
+ eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
+ eq(testPkgName), eq(testAttributionTag));
+
manager.requestBackgroundNetwork(request, handler, callback);
- verify(mService).requestNetwork(eq(request.networkCapabilities),
+ verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(request.networkCapabilities),
eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
eq(testPkgName), eq(testAttributionTag));
reset(mService);
manager.registerSystemDefaultNetworkCallback(callback, handler);
- verify(mService).requestNetwork(eq(null),
+ verify(mService).requestNetwork(eq(Process.INVALID_UID), eq(null),
eq(TRACK_SYSTEM_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE), anyInt(),
eq(testPkgName), eq(testAttributionTag));
reset(mService);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 625627b..fd37652 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -37,7 +37,6 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
-import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
@@ -216,7 +215,6 @@
import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
-import android.net.NetworkStackClient;
import android.net.NetworkStateSnapshot;
import android.net.NetworkTestResultParcelable;
import android.net.OemNetworkPreferences;
@@ -236,6 +234,7 @@
import android.net.VpnManager;
import android.net.VpnTransportInfo;
import android.net.metrics.IpConnectivityLog;
+import android.net.networkstack.NetworkStackClientBase;
import android.net.resolv.aidl.Nat64PrefixEventParcel;
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
import android.net.shared.NetworkMonitorUtils;
@@ -446,7 +445,7 @@
@Mock NetworkStatsManager mStatsManager;
@Mock IDnsResolver mMockDnsResolver;
@Mock INetd mMockNetd;
- @Mock NetworkStackClient mNetworkStack;
+ @Mock NetworkStackClientBase mNetworkStack;
@Mock PackageManager mPackageManager;
@Mock UserManager mUserManager;
@Mock NotificationManager mNotificationManager;
@@ -1201,12 +1200,10 @@
mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
- final int expectedNetId = mMockVpn.getNetwork() == null ? NETID_UNSET
- : mMockVpn.getNetwork().getNetId();
- verify(mMockNetd, times(1)).networkAddUidRanges(eq(expectedNetId),
+ verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetwork().getNetId()),
eq(toUidRangeStableParcels(uids)));
verify(mMockNetd, never())
- .networkRemoveUidRanges(eq(expectedNetId), any());
+ .networkRemoveUidRanges(eq(mMockVpn.getNetwork().getNetId()), any());
mAgentRegistered = true;
updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
@@ -1448,6 +1445,23 @@
});
}
+ private interface ExceptionalRunnable {
+ void run() throws Exception;
+ }
+
+ private void withPermission(String permission, ExceptionalRunnable r) throws Exception {
+ if (mServiceContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
+ r.run();
+ return;
+ }
+ try {
+ mServiceContext.setPermission(permission, PERMISSION_GRANTED);
+ r.run();
+ } finally {
+ mServiceContext.setPermission(permission, PERMISSION_DENIED);
+ }
+ }
+
private static final int PRIMARY_USER = 0;
private static final UidRange PRIMARY_UIDRANGE =
UidRange.createForUser(UserHandle.of(PRIMARY_USER));
@@ -1556,7 +1570,7 @@
doReturn(mNetworkStack).when(deps).getNetworkStack();
doReturn(mSystemProperties).when(deps).getSystemProperties();
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
- doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
+ doReturn(true).when(deps).queryUserAccess(anyInt(), any(), any());
doAnswer(inv -> {
mPolicyTracker = new WrappedMultinetworkPolicyTracker(
inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
@@ -3811,8 +3825,9 @@
NetworkCapabilities networkCapabilities = new NetworkCapabilities();
networkCapabilities.addTransportType(TRANSPORT_WIFI)
.setNetworkSpecifier(new MatchAllNetworkSpecifier());
- mService.requestNetwork(networkCapabilities, NetworkRequest.Type.REQUEST.ordinal(),
- null, 0, null, ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
+ mService.requestNetwork(Process.INVALID_UID, networkCapabilities,
+ NetworkRequest.Type.REQUEST.ordinal(), null, 0, null,
+ ConnectivityManager.TYPE_WIFI, NetworkCallback.FLAG_NONE,
mContext.getPackageName(), getAttributionTag());
});
@@ -4041,7 +4056,7 @@
}
@Test
- public void testRegisterSystemDefaultCallbackRequiresNetworkSettings() throws Exception {
+ public void testRegisterPrivilegedDefaultCallbacksRequireNetworkSettings() throws Exception {
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false /* validated */);
@@ -4050,12 +4065,19 @@
assertThrows(SecurityException.class,
() -> mCm.registerSystemDefaultNetworkCallback(callback, handler));
callback.assertNoCallback();
+ assertThrows(SecurityException.class,
+ () -> mCm.registerDefaultNetworkCallbackAsUid(APP1_UID, callback, handler));
+ callback.assertNoCallback();
mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
PERMISSION_GRANTED);
mCm.registerSystemDefaultNetworkCallback(callback, handler);
callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
mCm.unregisterNetworkCallback(callback);
+
+ mCm.registerDefaultNetworkCallbackAsUid(APP1_UID, callback, handler);
+ callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ mCm.unregisterNetworkCallback(callback);
}
private void setCaptivePortalMode(int mode) {
@@ -7488,6 +7510,10 @@
final TestNetworkCallback vpnUidDefaultCallback = new TestNetworkCallback();
registerDefaultNetworkCallbackAsUid(vpnUidDefaultCallback, VPN_UID);
+ final TestNetworkCallback vpnDefaultCallbackAsUid = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallbackAsUid(VPN_UID, vpnDefaultCallbackAsUid,
+ new Handler(ConnectivityThread.getInstanceLooper()));
+
final int uid = Process.myUid();
final int userId = UserHandle.getUserId(uid);
final ArrayList<String> allowList = new ArrayList<>();
@@ -7507,6 +7533,7 @@
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
vpnUidDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ vpnDefaultCallbackAsUid.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
@@ -7520,6 +7547,7 @@
defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -7535,6 +7563,7 @@
defaultCallback.assertNoCallback();
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
// The following requires that the UID of this test package is greater than VPN_UID. This
// is always true in practice because a plain AOSP build with no apps installed has almost
@@ -7556,6 +7585,7 @@
defaultCallback.assertNoCallback();
vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7577,6 +7607,7 @@
assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
@@ -7589,6 +7620,7 @@
assertBlockedCallbackInAnyOrder(callback, false, mWiFiNetworkAgent, mCellNetworkAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7604,6 +7636,7 @@
defaultCallback.assertNoCallback();
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7616,6 +7649,7 @@
defaultCallback.assertNoCallback();
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7629,6 +7663,7 @@
assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertNull(mCm.getActiveNetwork());
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
@@ -7640,6 +7675,7 @@
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
vpnUidCallback.assertNoCallback(); // vpnUidCallback has NOT_VPN capability.
vpnUidDefaultCallback.assertNoCallback(); // VPN does not apply to VPN_UID
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -7652,12 +7688,14 @@
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
vpnUidCallback.assertNoCallback();
vpnUidDefaultCallback.assertNoCallback();
+ vpnDefaultCallbackAsUid.assertNoCallback();
assertNull(mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultCallback);
mCm.unregisterNetworkCallback(vpnUidCallback);
mCm.unregisterNetworkCallback(vpnUidDefaultCallback);
+ mCm.unregisterNetworkCallback(vpnDefaultCallbackAsUid);
}
private void setupLegacyLockdownVpn() {
@@ -9758,14 +9796,13 @@
exemptUidCaptor.capture());
assertContainsExactly(exemptUidCaptor.getValue(), Process.VPN_UID, exemptUid);
- final int expectedNetId = mMockVpn.getNetwork() == null ? NETID_UNSET
- : mMockVpn.getNetwork().getNetId();
-
if (add) {
- inOrder.verify(mMockNetd, times(1)).networkAddUidRanges(eq(expectedNetId),
+ inOrder.verify(mMockNetd, times(1))
+ .networkAddUidRanges(eq(mMockVpn.getNetwork().getNetId()),
eq(toUidRangeStableParcels(vpnRanges)));
} else {
- inOrder.verify(mMockNetd, times(1)).networkRemoveUidRanges(eq(expectedNetId),
+ inOrder.verify(mMockNetd, times(1))
+ .networkRemoveUidRanges(eq(mMockVpn.getNetwork().getNetId()),
eq(toUidRangeStableParcels(vpnRanges)));
}
@@ -9806,8 +9843,8 @@
for (int reqTypeInt : invalidReqTypeInts) {
assertThrows("Expect throws for invalid request type " + reqTypeInt,
IllegalArgumentException.class,
- () -> mService.requestNetwork(nc, reqTypeInt, null, 0, null,
- ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
+ () -> mService.requestNetwork(Process.INVALID_UID, nc, reqTypeInt, null, 0,
+ null, ConnectivityManager.TYPE_NONE, NetworkCallback.FLAG_NONE,
mContext.getPackageName(), getAttributionTag())
);
}
@@ -10378,6 +10415,7 @@
mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
TEST_WORK_PROFILE_APP_UID);
+ // TODO: test using ConnectivityManager#registerDefaultNetworkCallbackAsUid as well.
mServiceContext.setPermission(
Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
}
@@ -10397,7 +10435,7 @@
private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
@OemNetworkPreferences.OemNetworkPreference final int networkPrefToSetup)
throws Exception {
- final int testPackageNameUid = 123;
+ final int testPackageNameUid = TEST_PACKAGE_UID;
final String testPackageName = "per.app.defaults.package";
setupMultipleDefaultNetworksForOemNetworkPreferenceTest(
networkPrefToSetup, testPackageNameUid, testPackageName);
@@ -10533,6 +10571,11 @@
mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
defaultNetworkCallback.assertNoCallback();
+ final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
+ withPermission(Manifest.permission.NETWORK_SETTINGS, () ->
+ mCm.registerDefaultNetworkCallbackAsUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
+ new Handler(ConnectivityThread.getInstanceLooper())));
+
// Setup the test process to use networkPref for their default network.
setupMultipleDefaultNetworksForOemNetworkPreferenceCurrentUidTest(networkPref);
@@ -10543,19 +10586,22 @@
null,
mEthernetNetworkAgent.getNetwork());
- // At this point with a restricted network used, the available callback should trigger
+ // At this point with a restricted network used, the available callback should trigger.
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
mEthernetNetworkAgent.getNetwork());
+ otherUidDefaultCallback.assertNoCallback();
// Now bring down the default network which should trigger a LOST callback.
setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
// At this point, with no network is available, the lost callback should trigger
defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+ otherUidDefaultCallback.assertNoCallback();
// Confirm we can unregister without issues.
mCm.unregisterNetworkCallback(defaultNetworkCallback);
+ mCm.unregisterNetworkCallback(otherUidDefaultCallback);
}
@Test
@@ -10573,6 +10619,11 @@
mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
defaultNetworkCallback.assertNoCallback();
+ final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
+ withPermission(Manifest.permission.NETWORK_SETTINGS, () ->
+ mCm.registerDefaultNetworkCallbackAsUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
+ new Handler(ConnectivityThread.getInstanceLooper())));
+
// Bring up ethernet with OEM_PAID. This will satisfy NET_CAPABILITY_OEM_PAID.
// The active nai for the default is null at this point as this is a restricted network.
setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, true);
@@ -10584,15 +10635,19 @@
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
mEthernetNetworkAgent.getNetwork());
+ otherUidDefaultCallback.assertNoCallback();
// Now bring down the default network which should trigger a LOST callback.
setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
+ otherUidDefaultCallback.assertNoCallback();
// At this point, with no network is available, the lost callback should trigger
defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+ otherUidDefaultCallback.assertNoCallback();
// Confirm we can unregister without issues.
mCm.unregisterNetworkCallback(defaultNetworkCallback);
+ mCm.unregisterNetworkCallback(otherUidDefaultCallback);
}
@Test
@@ -10606,6 +10661,11 @@
mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
defaultNetworkCallback.assertNoCallback();
+ final TestNetworkCallback otherUidDefaultCallback = new TestNetworkCallback();
+ withPermission(Manifest.permission.NETWORK_SETTINGS, () ->
+ mCm.registerDefaultNetworkCallbackAsUid(TEST_PACKAGE_UID, otherUidDefaultCallback,
+ new Handler(ConnectivityThread.getInstanceLooper())));
+
// Setup a process different than the test process to use the default network. This means
// that the defaultNetworkCallback won't be tracked by the per-app policy.
setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(networkPref);
@@ -10621,6 +10681,9 @@
defaultNetworkCallback.assertNoCallback();
assertDefaultNetworkCapabilities(userId /* no networks */);
+ // The other UID does have access, and gets a callback.
+ otherUidDefaultCallback.expectAvailableThenValidatedCallbacks(mEthernetNetworkAgent);
+
// Bring up unrestricted cellular. This should now satisfy the default network.
setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, true);
verifyMultipleDefaultNetworksTracksCorrectly(expectedOemPrefRequestSize,
@@ -10628,25 +10691,31 @@
mEthernetNetworkAgent.getNetwork());
// At this point with an unrestricted network used, the available callback should trigger
+ // The other UID is unaffected and remains on the paid network.
defaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(),
mCellNetworkAgent.getNetwork());
assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
+ otherUidDefaultCallback.assertNoCallback();
// Now bring down the per-app network.
setOemNetworkPreferenceAgentConnected(TRANSPORT_ETHERNET, false);
- // Since the callback didn't use the per-app network, no callback should fire.
+ // Since the callback didn't use the per-app network, only the other UID gets a callback.
+ // Because the preference specifies no fallback, it does not switch to cellular.
defaultNetworkCallback.assertNoCallback();
+ otherUidDefaultCallback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
// Now bring down the default network.
setOemNetworkPreferenceAgentConnected(TRANSPORT_CELLULAR, false);
// As this callback was tracking the default, this should now trigger.
defaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+ otherUidDefaultCallback.assertNoCallback();
// Confirm we can unregister without issues.
mCm.unregisterNetworkCallback(defaultNetworkCallback);
+ mCm.unregisterNetworkCallback(otherUidDefaultCallback);
}
/**
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 8c5d1d6..97c65eb 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -22,7 +22,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -56,6 +58,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -80,6 +83,12 @@
IpConnectivityMetrics mService;
NetdEventListenerService mNetdListener;
+ final NetworkCapabilities mNcWifi = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ final NetworkCapabilities mNcCell = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .build();
@Before
public void setUp() {
@@ -263,14 +272,6 @@
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
- NetworkCapabilities ncWifi = new NetworkCapabilities();
- NetworkCapabilities ncCell = new NetworkCapabilities();
- ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-
- when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
- when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
-
ApfStats apfStats = new ApfStats.Builder()
.setDurationMs(45000)
.setReceivedRas(10)
@@ -584,11 +585,21 @@
return buffer.toString();
}
- void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
- mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
+ private void setCapabilities(int netId) {
+ final ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallback =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ verify(mCm).registerNetworkCallback(any(), networkCallback.capture());
+ networkCallback.getValue().onCapabilitiesChanged(new Network(netId),
+ netId == 100 ? mNcWifi : mNcCell);
+ }
+
+ void connectEvent(int netId, int error, int latencyMs, String ipAddr) throws Exception {
+ setCapabilities(netId);
+ mNetdListener.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
}
void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+ setCapabilities(netId);
mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
}
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 8ccea1a..52975e4 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -23,8 +23,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -42,6 +43,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import java.io.FileOutputStream;
import java.io.PrintWriter;
@@ -61,18 +63,16 @@
NetdEventListenerService mService;
ConnectivityManager mCm;
+ final NetworkCapabilities mNcWifi = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ final NetworkCapabilities mNcCell = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .build();
@Before
public void setUp() {
- NetworkCapabilities ncWifi = new NetworkCapabilities();
- NetworkCapabilities ncCell = new NetworkCapabilities();
- ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-
mCm = mock(ConnectivityManager.class);
- when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
- when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
-
mService = new NetdEventListenerService(mCm);
}
@@ -470,7 +470,16 @@
assertEquals(want, got);
}
+ private void setCapabilities(int netId) {
+ final ArgumentCaptor<ConnectivityManager.NetworkCallback> networkCallback =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ verify(mCm).registerNetworkCallback(any(), networkCallback.capture());
+ networkCallback.getValue().onCapabilitiesChanged(new Network(netId),
+ netId == 100 ? mNcWifi : mNcCell);
+ }
+
Thread connectEventAction(int netId, int error, int latencyMs, String ipAddr) {
+ setCapabilities(netId);
return new Thread(() -> {
try {
mService.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
@@ -481,6 +490,7 @@
}
void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+ setCapabilities(netId);
mService.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
}
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index dde77b0..2f3ee68 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -50,9 +50,7 @@
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import org.junit.After;
-import org.junit.AfterClass;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -104,17 +102,6 @@
NetworkNotificationManager mManager;
-
- @BeforeClass
- public static void setUpClass() {
- Notification.DevFlags.sForceDefaults = true;
- }
-
- @AfterClass
- public static void tearDownClass() {
- Notification.DevFlags.sForceDefaults = false;
- }
-
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);