Merge "Fix testDeclareNetworkRequestUnfulfillable on R"
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..48e54da
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index cf5d4e5..540ea5c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2108,17 +2108,6 @@
// ignored
}
- /** {@hide} */
- @Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
- try {
- return mService.getActiveNetworkQuotaInfo();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/**
* @hide
* @deprecated Talk to TelephonyManager directly
@@ -3163,9 +3152,9 @@
}
/**
- * Set sign in error notification to visible or in visible
+ * Set sign in error notification to visible or invisible
*
- * {@hide}
+ * @hide
* @deprecated Doesn't properly deal with multiple connected networks of the same type.
*/
@Deprecated
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 4173200..95a2f2e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -25,13 +25,13 @@
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.ISocketKeepaliveCallback;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.INetworkActivityListener;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
@@ -76,7 +76,6 @@
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
NetworkState[] getAllNetworkState();
- NetworkQuotaInfo getActiveNetworkQuotaInfo();
boolean isActiveNetworkMetered();
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress,
@@ -235,4 +234,10 @@
in PersistableBundle extras);
void systemReady();
+
+ void registerNetworkActivityListener(in INetworkActivityListener l);
+
+ void unregisterNetworkActivityListener(in INetworkActivityListener l);
+
+ boolean isDefaultNetworkActive();
}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 0941e7d..486e2d7 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -20,12 +20,13 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.LinkPropertiesUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.net.module.util.LinkPropertiesUtils;
+
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 178183d..c7116b4 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -20,13 +20,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.MacAddressUtils;
import android.net.wifi.WifiInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.MacAddressUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 0676ad4..6780167 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -51,7 +51,7 @@
* An agent manages the life cycle of a network. A network starts its
* life cycle when {@link register} is called on NetworkAgent. The network
* is then connecting. When full L3 connectivity has been established,
- * the agent shoud call {@link markConnected} to inform the system that
+ * the agent should call {@link markConnected} to inform the system that
* this network is ready to use. When the network disconnects its life
* ends and the agent should call {@link unregister}, at which point the
* system will clean up and free resources.
@@ -94,12 +94,6 @@
@Nullable
private volatile Network mNetwork;
- // Whether this NetworkAgent is using the legacy (never unhidden) API. The difference is
- // that the legacy API uses NetworkInfo to convey the state, while the current API is
- // exposing methods to manage it and generate it internally instead.
- // TODO : remove this as soon as all agents have been converted.
- private final boolean mIsLegacy;
-
private final Handler mHandler;
private volatile AsyncChannel mAsyncChannel;
private final String LOG_TAG;
@@ -110,8 +104,6 @@
private static final long BW_REFRESH_MIN_WIN_MS = 500;
private boolean mBandwidthUpdateScheduled = false;
private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false);
- // Not used by legacy agents. Non-legacy agents use this to convert the NetworkAgent system API
- // into the internal API of ConnectivityService.
@NonNull
private NetworkInfo mNetworkInfo;
@NonNull
@@ -337,35 +329,6 @@
*/
public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
- /** @hide TODO: remove and replace usage with the public constructor. */
- public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score) {
- this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE);
- // Register done by the constructor called in the previous line
- }
-
- /** @hide TODO: remove and replace usage with the public constructor. */
- public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) {
- this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE);
- // Register done by the constructor called in the previous line
- }
-
- /** @hide TODO: remove and replace usage with the public constructor. */
- public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, int providerId) {
- this(looper, context, logTag, ni, nc, lp, score, null, providerId);
- // Register done by the constructor called in the previous line
- }
-
- /** @hide TODO: remove and replace usage with the public constructor. */
- public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
- NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config,
- int providerId) {
- this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */);
- register();
- }
-
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.
@@ -393,7 +356,7 @@
@NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
this(looper, context, logTag, nc, lp, score, config,
provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
- getLegacyNetworkInfo(config), false /* legacy */);
+ getLegacyNetworkInfo(config));
}
private static class InitialConfiguration {
@@ -418,11 +381,9 @@
private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
@NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
- @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni,
- boolean legacy) {
+ @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) {
mHandler = new NetworkAgentHandler(looper);
LOG_TAG = logTag;
- mIsLegacy = legacy;
mNetworkInfo = new NetworkInfo(ni);
this.providerId = providerId;
if (ni == null || nc == null || lp == null) {
@@ -696,11 +657,6 @@
* Call {@link #unregister} to disconnect.
*/
public void markConnected() {
- if (mIsLegacy) {
- throw new UnsupportedOperationException(
- "Legacy agents can't call markConnected.");
- }
- // |reason| cannot be used by the non-legacy agents
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */,
mNetworkInfo.getExtraInfo());
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
@@ -713,9 +669,6 @@
* the network is torn down and this agent can no longer be used.
*/
public void unregister() {
- if (mIsLegacy) {
- throw new UnsupportedOperationException("Legacy agents can't call unregister.");
- }
// When unregistering an agent nobody should use the extrainfo (or reason) any more.
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */,
null /* extraInfo */);
@@ -735,9 +688,6 @@
*/
@Deprecated
public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) {
- if (mIsLegacy) {
- throw new UnsupportedOperationException("Legacy agents can't call setLegacySubtype.");
- }
mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
}
@@ -760,9 +710,6 @@
*/
@Deprecated
public void setLegacyExtraInfo(@Nullable final String extraInfo) {
- if (mIsLegacy) {
- throw new UnsupportedOperationException("Legacy agents can't call setLegacyExtraInfo.");
- }
mNetworkInfo.setExtraInfo(extraInfo);
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
}
@@ -773,9 +720,6 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final void sendNetworkInfo(NetworkInfo networkInfo) {
- if (!mIsLegacy) {
- throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo.");
- }
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 8dad11f..1a37fb9 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -975,6 +975,10 @@
return mOwnerUid;
}
+ private boolean equalsOwnerUid(@NonNull final NetworkCapabilities nc) {
+ return mOwnerUid == nc.mOwnerUid;
+ }
+
/**
* UIDs of packages that are administrators of this network, or empty if none.
*
@@ -1684,6 +1688,7 @@
&& equalsTransportInfo(that)
&& equalsUids(that)
&& equalsSSID(that)
+ && equalsOwnerUid(that)
&& equalsPrivateDnsBroken(that)
&& equalsRequestor(that)
&& equalsAdministratorUids(that);
@@ -1697,17 +1702,18 @@
+ ((int) (mUnwantedNetworkCapabilities >> 32) * 7)
+ ((int) (mTransportTypes & 0xFFFFFFFF) * 11)
+ ((int) (mTransportTypes >> 32) * 13)
- + (mLinkUpBandwidthKbps * 17)
- + (mLinkDownBandwidthKbps * 19)
+ + mLinkUpBandwidthKbps * 17
+ + mLinkDownBandwidthKbps * 19
+ Objects.hashCode(mNetworkSpecifier) * 23
- + (mSignalStrength * 29)
- + Objects.hashCode(mUids) * 31
- + Objects.hashCode(mSSID) * 37
- + Objects.hashCode(mTransportInfo) * 41
- + Objects.hashCode(mPrivateDnsBroken) * 43
- + Objects.hashCode(mRequestorUid) * 47
- + Objects.hashCode(mRequestorPackageName) * 53
- + Arrays.hashCode(mAdministratorUids) * 59;
+ + mSignalStrength * 29
+ + mOwnerUid * 31
+ + Objects.hashCode(mUids) * 37
+ + Objects.hashCode(mSSID) * 41
+ + Objects.hashCode(mTransportInfo) * 43
+ + Objects.hashCode(mPrivateDnsBroken) * 47
+ + Objects.hashCode(mRequestorUid) * 53
+ + Objects.hashCode(mRequestorPackageName) * 59
+ + Arrays.hashCode(mAdministratorUids) * 61;
}
@Override
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index a0faafa..b5962c5 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,14 +16,9 @@
package android.net;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.system.ErrnoException;
-import android.system.Os;
import android.util.Log;
import android.util.Pair;
@@ -35,7 +30,6 @@
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
-import java.util.Collection;
import java.util.Locale;
import java.util.TreeSet;
@@ -156,14 +150,6 @@
public static native Network getDnsNetwork() throws ErrnoException;
/**
- * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process.
- *
- * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets
- * and DNS lookups.
- */
- public static native void setAllowNetworkingForProcess(boolean allowNetworking);
-
- /**
* Get the tcp repair window associated with the {@code fd}.
*
* @param fd the tcp socket's {@link FileDescriptor}.
@@ -342,20 +328,6 @@
}
/**
- * Create a string array of host addresses from a collection of InetAddresses
- * @param addrs a Collection of InetAddresses
- * @return an array of Strings containing their host addresses
- */
- public static String[] makeStrings(Collection<InetAddress> addrs) {
- String[] result = new String[addrs.size()];
- int i = 0;
- for (InetAddress addr : addrs) {
- result[i++] = addr.getHostAddress();
- }
- return result;
- }
-
- /**
* Trim leading zeros from IPv4 address strings
* Our base libraries will interpret that as octel..
* Must leave non v4 addresses and host names alone.
@@ -452,60 +424,4 @@
return routedIPCount;
}
- private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6};
-
- /**
- * Returns true if the hostname is weakly validated.
- * @param hostname Name of host to validate.
- * @return True if it's a valid-ish hostname.
- *
- * @hide
- */
- public static boolean isWeaklyValidatedHostname(@NonNull String hostname) {
- // TODO(b/34953048): Use a validation method that permits more accurate,
- // but still inexpensive, checking of likely valid DNS hostnames.
- final String weakHostnameRegex = "^[a-zA-Z0-9_.-]+$";
- if (!hostname.matches(weakHostnameRegex)) {
- return false;
- }
-
- for (int address_family : ADDRESS_FAMILIES) {
- if (Os.inet_pton(address_family, hostname) != null) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Safely multiple a value by a rational.
- * <p>
- * Internally it uses integer-based math whenever possible, but switches
- * over to double-based math if values would overflow.
- * @hide
- */
- public static long multiplySafeByRational(long value, long num, long den) {
- if (den == 0) {
- throw new ArithmeticException("Invalid Denominator");
- }
- long x = value;
- long y = num;
-
- // Logic shamelessly borrowed from Math.multiplyExact()
- long r = x * y;
- long ax = Math.abs(x);
- long ay = Math.abs(y);
- if (((ax | ay) >>> 31 != 0)) {
- // Some bits greater than 2^31 that might cause overflow
- // Check the result using the divide operator
- // and check for the special case of Long.MIN_VALUE * -1
- if (((y != 0) && (r / y != x)) ||
- (x == Long.MIN_VALUE && y == -1)) {
- // Use double math to avoid overflowing
- return (long) (((double) num / den) * value);
- }
- }
- return r / den;
- }
}
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 6166a75..94f849f 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -21,11 +21,12 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.NetUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.net.module.util.NetUtils;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.Inet4Address;
diff --git a/core/java/android/net/TcpKeepalivePacketData.java b/core/java/android/net/TcpKeepalivePacketData.java
new file mode 100644
index 0000000..ddb3a6a
--- /dev/null
+++ b/core/java/android/net/TcpKeepalivePacketData.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.InetAddress;
+import java.util.Objects;
+
+/**
+ * Represents the actual tcp keep alive packets which will be used for hardware offload.
+ * @hide
+ */
+@SystemApi
+public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
+ private static final String TAG = "TcpKeepalivePacketData";
+
+ /** TCP sequence number. */
+ public final int tcpSeq;
+
+ /** TCP ACK number. */
+ public final int tcpAck;
+
+ /** TCP RCV window. */
+ public final int tcpWindow;
+
+ /** TCP RCV window scale. */
+ public final int tcpWindowScale;
+
+ /** IP TOS. */
+ public final int ipTos;
+
+ /** IP TTL. */
+ public final int ipTtl;
+
+ public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort,
+ @NonNull final InetAddress dstAddress, int dstPort, @NonNull final byte[] data,
+ int tcpSeq, int tcpAck, int tcpWindow, int tcpWindowScale, int ipTos, int ipTtl)
+ throws InvalidPacketException {
+ super(srcAddress, srcPort, dstAddress, dstPort, data);
+ this.tcpSeq = tcpSeq;
+ this.tcpAck = tcpAck;
+ this.tcpWindow = tcpWindow;
+ this.tcpWindowScale = tcpWindowScale;
+ this.ipTos = ipTos;
+ this.ipTtl = ipTtl;
+ }
+
+ @Override
+ public boolean equals(@Nullable final Object o) {
+ if (!(o instanceof TcpKeepalivePacketData)) return false;
+ final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o;
+ final InetAddress srcAddress = getSrcAddress();
+ final InetAddress dstAddress = getDstAddress();
+ return srcAddress.equals(other.getSrcAddress())
+ && dstAddress.equals(other.getDstAddress())
+ && getSrcPort() == other.getSrcPort()
+ && getDstPort() == other.getDstPort()
+ && this.tcpAck == other.tcpAck
+ && this.tcpSeq == other.tcpSeq
+ && this.tcpWindow == other.tcpWindow
+ && this.tcpWindowScale == other.tcpWindowScale
+ && this.ipTos == other.ipTos
+ && this.ipTtl == other.ipTtl;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(),
+ tcpAck, tcpSeq, tcpWindow, tcpWindowScale, ipTos, ipTtl);
+ }
+
+ /**
+ * Parcelable Implementation.
+ * Note that this object implements parcelable (and needs to keep doing this as it inherits
+ * from a class that does), but should usually be parceled as a stable parcelable using
+ * the toStableParcelable() and fromStableParcelable() methods.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Write to parcel. */
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeString(getSrcAddress().getHostAddress());
+ out.writeString(getDstAddress().getHostAddress());
+ out.writeInt(getSrcPort());
+ out.writeInt(getDstPort());
+ out.writeByteArray(getPacket());
+ out.writeInt(tcpSeq);
+ out.writeInt(tcpAck);
+ out.writeInt(tcpWindow);
+ out.writeInt(tcpWindowScale);
+ out.writeInt(ipTos);
+ out.writeInt(ipTtl);
+ }
+
+ private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException {
+ InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString());
+ InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString());
+ int srcPort = in.readInt();
+ int dstPort = in.readInt();
+ byte[] packet = in.createByteArray();
+ int tcpSeq = in.readInt();
+ int tcpAck = in.readInt();
+ int tcpWnd = in.readInt();
+ int tcpWndScale = in.readInt();
+ int ipTos = in.readInt();
+ int ipTtl = in.readInt();
+ return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq,
+ tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl);
+ }
+
+ /** Parcelable Creator. */
+ public static final @NonNull Parcelable.Creator<TcpKeepalivePacketData> CREATOR =
+ new Parcelable.Creator<TcpKeepalivePacketData>() {
+ public TcpKeepalivePacketData createFromParcel(Parcel in) {
+ try {
+ return readFromParcel(in);
+ } catch (InvalidPacketException e) {
+ throw new IllegalArgumentException(
+ "Invalid TCP keepalive data: " + e.getError());
+ }
+ }
+
+ public TcpKeepalivePacketData[] newArray(int size) {
+ return new TcpKeepalivePacketData[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "saddr: " + getSrcAddress()
+ + " daddr: " + getDstAddress()
+ + " sport: " + getSrcPort()
+ + " dport: " + getDstPort()
+ + " seq: " + tcpSeq
+ + " ack: " + tcpAck
+ + " window: " + tcpWindow
+ + " windowScale: " + tcpWindowScale
+ + " tos: " + ipTos
+ + " ttl: " + ipTtl;
+ }
+}
diff --git a/core/java/android/net/TcpRepairWindow.java b/core/java/android/net/TcpRepairWindow.java
index 86034f0..f062fa9 100644
--- a/core/java/android/net/TcpRepairWindow.java
+++ b/core/java/android/net/TcpRepairWindow.java
@@ -16,12 +16,15 @@
package android.net;
+import android.annotation.SystemApi;
+
/**
* Corresponds to C's {@code struct tcp_repair_window} from
* include/uapi/linux/tcp.h
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TcpRepairWindow {
public final int sndWl1;
public final int sndWnd;
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 8d4c4e5..2155246 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008, The Android Open Source Project
+ * Copyright 2020, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
#include <netinet/udp.h>
#include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
-#include <android_runtime/AndroidRuntime.h>
#include <cutils/properties.h>
#include <nativehelper/JNIPlatformHelp.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -226,11 +225,6 @@
class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass);
}
-static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz,
- jboolean hasConnectivity) {
- setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE);
-}
-
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
if (javaFd == NULL) {
jniThrowNullPointerException(env, NULL);
@@ -288,7 +282,6 @@
{ "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 },
- { "setAllowNetworkingForProcess", "(Z)V", (void *)android_net_utils_setAllowNetworkingForProcess },
};
// clang-format on
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 58f1db3..2e1fbb7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -113,7 +113,6 @@
import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkProvider;
-import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
@@ -129,6 +128,7 @@
import android.net.SocketKeepalive;
import android.net.TetheringManager;
import android.net.UidRange;
+import android.net.UidRangeParcel;
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnService;
@@ -136,8 +136,6 @@
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
import android.net.shared.PrivateDnsConfig;
-import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
-import android.net.util.LinkPropertiesUtils.CompareResult;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.os.Binder;
@@ -146,6 +144,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.INetworkActivityListener;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
@@ -186,12 +185,13 @@
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.LocationPermissionChecker;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
+import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DataConnectionStats;
@@ -877,6 +877,10 @@
*/
@VisibleForTesting
public static class Dependencies {
+ public int getCallingUid() {
+ return Binder.getCallingUid();
+ }
+
/**
* Get system properties to use in ConnectivityService.
*/
@@ -1287,7 +1291,7 @@
if (network == null) {
return null;
}
- return getNetworkAgentInfoForNetId(network.netId);
+ return getNetworkAgentInfoForNetId(network.getNetId());
}
private NetworkAgentInfo getNetworkAgentInfoForNetId(int netId) {
@@ -1377,8 +1381,11 @@
return;
}
final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+ final NetworkRequest satisfiedRequest = nri.getSatisfiedRequest();
+ final int requestId = satisfiedRequest != null
+ ? satisfiedRequest.requestId : nri.mRequests.get(0).requestId;
mNetworkInfoBlockingLogs.log(String.format(
- "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.netId));
+ "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId()));
}
/**
@@ -1409,7 +1416,7 @@
@Override
public NetworkInfo getActiveNetworkInfo() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final NetworkState state = getUnfilteredActiveNetworkState(uid);
filterNetworkStateForUid(state, uid, false);
maybeLogBlockedNetworkInfo(state.networkInfo, uid);
@@ -1419,7 +1426,7 @@
@Override
public Network getActiveNetwork() {
enforceAccessPermission();
- return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
+ return getActiveNetworkForUidInternal(mDeps.getCallingUid(), false);
}
@Override
@@ -1459,7 +1466,7 @@
// Public because it's used by mLockdownTracker.
public NetworkInfo getActiveNetworkInfoUnfiltered() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
NetworkState state = getUnfilteredActiveNetworkState(uid);
return state.networkInfo;
}
@@ -1475,7 +1482,7 @@
@Override
public NetworkInfo getNetworkInfo(int networkType) {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
if (getVpnUnderlyingNetworks(uid) != null) {
// A VPN is active, so we may need to return one of its underlying networks. This
// information is not available in LegacyTypeTracker, so we have to get it from
@@ -1520,7 +1527,7 @@
@Override
public Network getNetworkForType(int networkType) {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
NetworkState state = getFilteredNetworkState(networkType, uid);
if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
return state.network;
@@ -1567,7 +1574,7 @@
result.put(
nai.network,
maybeSanitizeLocationInfoForCaller(
- nc, Binder.getCallingUid(), callingPackageName));
+ nc, mDeps.getCallingUid(), callingPackageName));
}
synchronized (mVpns) {
@@ -1582,7 +1589,7 @@
result.put(
network,
maybeSanitizeLocationInfoForCaller(
- nc, Binder.getCallingUid(), callingPackageName));
+ nc, mDeps.getCallingUid(), callingPackageName));
}
}
}
@@ -1612,7 +1619,7 @@
@Override
public LinkProperties getActiveLinkProperties() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
NetworkState state = getUnfilteredActiveNetworkState(uid);
if (state.linkProperties == null) return null;
return linkPropertiesRestrictedForCallerPermissions(state.linkProperties,
@@ -1626,7 +1633,7 @@
final LinkProperties lp = getLinkProperties(nai);
if (lp == null) return null;
return linkPropertiesRestrictedForCallerPermissions(
- lp, Binder.getCallingPid(), Binder.getCallingUid());
+ lp, Binder.getCallingPid(), mDeps.getCallingUid());
}
// TODO - this should be ALL networks
@@ -1636,7 +1643,7 @@
final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
if (lp == null) return null;
return linkPropertiesRestrictedForCallerPermissions(
- lp, Binder.getCallingPid(), Binder.getCallingUid());
+ lp, Binder.getCallingPid(), mDeps.getCallingUid());
}
@Nullable
@@ -1658,17 +1665,17 @@
synchronized (nai) {
if (nai.networkCapabilities == null) return null;
return networkCapabilitiesRestrictedForCallerPermissions(
- nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid());
+ nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid());
}
}
@Override
public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
- mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
+ mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName);
enforceAccessPermission();
return maybeSanitizeLocationInfoForCaller(
getNetworkCapabilitiesInternal(network),
- Binder.getCallingUid(), callingPackageName);
+ mDeps.getCallingUid(), callingPackageName);
}
@VisibleForTesting
@@ -1706,16 +1713,17 @@
return newNc;
}
- Binder.withCleanCallingIdentity(
- () -> {
- if (!mLocationPermissionChecker.checkLocationPermission(
- callerPkgName, null /* featureId */, callerUid, null /* message */)) {
- // Caller does not have the requisite location permissions. Reset the
- // owner's UID in the NetworkCapabilities.
- newNc.setOwnerUid(INVALID_UID);
- }
- }
- );
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!mLocationPermissionChecker.checkLocationPermission(
+ callerPkgName, null /* featureId */, callerUid, null /* message */)) {
+ // Caller does not have the requisite location permissions. Reset the
+ // owner's UID in the NetworkCapabilities.
+ newNc.setOwnerUid(INVALID_UID);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
return newNc;
}
@@ -1756,7 +1764,7 @@
}
private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
- if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
+ if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(mDeps.getCallingUid())) {
nc.addCapability(NET_CAPABILITY_FOREGROUND);
}
}
@@ -1781,14 +1789,6 @@
}
@Override
- @Deprecated
- public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
- Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
- + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
- return new NetworkQuotaInfo();
- }
-
- @Override
public boolean isActiveNetworkMetered() {
enforceAccessPermission();
@@ -1817,7 +1817,7 @@
// requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
// for devices launched with Q and above. However, existing devices upgrading to Q and
// above must continued to be supported for few more releases.
- if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
+ if (isSystem(mDeps.getCallingUid()) && SystemProperties.getInt(
"ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
log("This method exists only for app backwards compatibility"
+ " and must not be called by system services.");
@@ -1883,14 +1883,14 @@
return false;
}
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
LinkProperties lp;
int netId;
synchronized (nai) {
lp = nai.linkProperties;
- netId = nai.network.netId;
+ netId = nai.network.getNetId();
}
boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
if (DBG) log("requestRouteToHostAddress ok=" + ok);
@@ -2303,7 +2303,7 @@
*/
@Override
public void systemReady() {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Calling Uid is not system uid.");
}
systemReadyInternal();
@@ -2341,6 +2341,31 @@
}
/**
+ * Start listening for default data network activity state changes.
+ */
+ @Override
+ public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
+ // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+ }
+
+ /**
+ * Stop listening for default data network activity state changes.
+ */
+ @Override
+ public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
+ // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+ }
+
+ /**
+ * Check whether the default network radio is currently active.
+ */
+ @Override
+ public boolean isDefaultNetworkActive() {
+ // TODO: Replace isNetworkActive() in NMS.
+ return false;
+ }
+
+ /**
* Setup data activity tracking for the given network.
*
* Every {@code setupDataActivityTracking} should be paired with a
@@ -2525,9 +2550,21 @@
PriorityDump.dump(mPriorityDumper, fd, writer, args);
}
+ private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) {
+ if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump " + tag + " from from pid="
+ + Binder.getCallingPid() + ", uid=" + mDeps.getCallingUid()
+ + " due to missing android.permission.DUMP permission");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
- if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ if (!checkDumpPermission(mContext, TAG, pw)) return;
if (asProto) return;
if (ArrayUtils.contains(args, DIAG_ARG)) {
@@ -2553,7 +2590,7 @@
if (defaultNai == null) {
pw.println("none");
} else {
- pw.println(defaultNai.network.netId);
+ pw.println(defaultNai.network.getNetId());
}
pw.println();
@@ -2690,7 +2727,7 @@
private NetworkAgentInfo[] networksSortedById() {
NetworkAgentInfo[] networks = new NetworkAgentInfo[0];
networks = mNetworkAgentInfos.values().toArray(networks);
- Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.netId));
+ Arrays.sort(networks, Comparator.comparingInt(nai -> nai.network.getNetId()));
return networks;
}
@@ -2698,7 +2735,7 @@
* Return an array of all current NetworkRequest sorted by request id.
*/
@VisibleForTesting
- protected NetworkRequestInfo[] requestsSortedById() {
+ NetworkRequestInfo[] requestsSortedById() {
NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
requests = mNetworkRequests.values().toArray(requests);
// Sort the array based off the NRI containing the min requestId in its requests.
@@ -2811,6 +2848,7 @@
break;
}
case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
+ // TODO: prevent loops, e.g., if a network declares itself as underlying.
if (!nai.supportsUnderlyingNetworks()) {
Log.wtf(TAG, "Non-virtual networks cannot have underlying networks");
break;
@@ -2831,7 +2869,7 @@
log(nai.toShortString() + " changed underlying networks to "
+ Arrays.toString(nai.declaredUnderlyingNetworks));
}
- updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ updateCapabilitiesForNetwork(nai);
notifyIfacesChangedForNetworkStats();
}
}
@@ -2855,8 +2893,7 @@
if (probePrivateDnsCompleted) {
if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) {
nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken);
- final int oldScore = nai.getCurrentScore();
- updateCapabilities(oldScore, nai, nai.networkCapabilities);
+ updateCapabilitiesForNetwork(nai);
}
// Only show the notification when the private DNS is broken and the
// PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
@@ -2871,8 +2908,7 @@
// done yet. In either case, the networkCapabilities should be updated to
// reflect the new status.
nai.networkCapabilities.setPrivateDnsBroken(false);
- final int oldScore = nai.getCurrentScore();
- updateCapabilities(oldScore, nai, nai.networkCapabilities);
+ updateCapabilitiesForNetwork(nai);
nai.networkAgentConfig.hasShownBroken = false;
}
break;
@@ -2893,7 +2929,6 @@
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
// If captive portal status has changed, update capabilities or disconnect.
if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
- final int oldScore = nai.getCurrentScore();
nai.lastCaptivePortalDetected = visible;
nai.everCaptivePortalDetected |= visible;
if (nai.lastCaptivePortalDetected &&
@@ -2904,7 +2939,7 @@
teardownUnneededNetwork(nai);
break;
}
- updateCapabilities(oldScore, nai, nai.networkCapabilities);
+ updateCapabilitiesForNetwork(nai);
}
if (!visible) {
// Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other
@@ -2974,13 +3009,13 @@
handleFreshlyValidatedNetwork(nai);
// Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and
// LOST_INTERNET notifications if network becomes valid.
- mNotifier.clearNotification(nai.network.netId,
+ mNotifier.clearNotification(nai.network.getNetId(),
NotificationType.NO_INTERNET);
- mNotifier.clearNotification(nai.network.netId,
+ mNotifier.clearNotification(nai.network.getNetId(),
NotificationType.LOST_INTERNET);
- mNotifier.clearNotification(nai.network.netId,
+ mNotifier.clearNotification(nai.network.getNetId(),
NotificationType.PARTIAL_CONNECTIVITY);
- mNotifier.clearNotification(nai.network.netId,
+ mNotifier.clearNotification(nai.network.getNetId(),
NotificationType.PRIVATE_DNS_BROKEN);
// If network becomes valid, the hasShownBroken should be reset for
// that network so that the notification will be fired when the private
@@ -2988,7 +3023,7 @@
nai.networkAgentConfig.hasShownBroken = false;
}
} else if (partialConnectivityChanged) {
- updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ updateCapabilitiesForNetwork(nai);
}
updateInetCondition(nai);
// Let the NetworkAgent know the state of its network
@@ -3051,7 +3086,7 @@
private final AutodestructReference<NetworkAgentInfo> mNai;
private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
- mNetId = nai.network.netId;
+ mNetId = nai.network.getNetId();
mNai = new AutodestructReference<>(nai);
}
@@ -3201,7 +3236,7 @@
// in order to restart a validation pass from within netd.
final PrivateDnsConfig cfg = mDnsManager.getPrivateDnsConfig();
if (cfg.useTls && TextUtils.isEmpty(cfg.hostname)) {
- updateDnses(nai.linkProperties, null, nai.network.netId);
+ updateDnses(nai.linkProperties, null, nai.network.getNetId());
}
}
@@ -3234,7 +3269,7 @@
private void updatePrivateDns(NetworkAgentInfo nai, PrivateDnsConfig newCfg) {
mDnsManager.updatePrivateDns(nai.network, newCfg);
- updateDnses(nai.linkProperties, null, nai.network.netId);
+ updateDnses(nai.linkProperties, null, nai.network.getNetId());
}
private void handlePrivateDnsValidationUpdate(PrivateDnsValidationUpdate update) {
@@ -3330,9 +3365,9 @@
if (nai != null) {
final boolean wasDefault = isDefaultNetwork(nai);
synchronized (mNetworkForNetId) {
- mNetworkForNetId.remove(nai.network.netId);
+ mNetworkForNetId.remove(nai.network.getNetId());
}
- mNetIdManager.releaseNetId(nai.network.netId);
+ mNetIdManager.releaseNetId(nai.network.getNetId());
// Just in case.
mLegacyTypeTracker.remove(nai, wasDefault);
}
@@ -3362,7 +3397,7 @@
log(nai.toShortString() + " disconnected, was satisfying " + nai.numNetworkRequests());
}
// Clear all notifications of this network.
- mNotifier.clearNotification(nai.network.netId);
+ mNotifier.clearNotification(nai.network.getNetId());
// A network agent has disconnected.
// TODO - if we move the logic to the network agent (have them disconnect
// because they lost all their requests or because their score isn't good)
@@ -3399,19 +3434,21 @@
synchronized (mNetworkForNetId) {
// Remove the NetworkAgent, but don't mark the netId as
// available until we've told netd to delete it below.
- mNetworkForNetId.remove(nai.network.netId);
+ mNetworkForNetId.remove(nai.network.getNetId());
}
// Remove all previously satisfied requests.
for (int i = 0; i < nai.numNetworkRequests(); i++) {
NetworkRequest request = nai.requestAt(i);
final NetworkRequestInfo nri = mNetworkRequests.get(request);
final NetworkAgentInfo currentNetwork = nri.mSatisfier;
- if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
+ if (currentNetwork != null
+ && currentNetwork.network.getNetId() == nai.network.getNetId()) {
nri.mSatisfier = null;
sendUpdatedScoreToFactories(request, null);
}
}
nai.clearLingerState();
+ propagateUnderlyingNetworkCapabilities(nai.network);
if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
mDefaultNetworkNai = null;
updateDataActivityTracking(null /* newNetwork */, nai);
@@ -3419,9 +3456,6 @@
ensureNetworkTransitionWakelock(nai.toShortString());
}
mLegacyTypeTracker.remove(nai, wasDefault);
- if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
- propagateUnderlyingNetworkCapabilities();
- }
rematchAllNetworksAndRequests();
mLingerMonitor.noteDisconnect(nai);
if (nai.created) {
@@ -3436,26 +3470,26 @@
destroyNativeNetwork(nai);
mDnsManager.removeNetwork(nai.network);
}
- mNetIdManager.releaseNetId(nai.network.netId);
+ mNetIdManager.releaseNetId(nai.network.getNetId());
}
private boolean createNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
try {
// This should never fail. Specifying an already in use NetID will cause failure.
if (networkAgent.isVPN()) {
- mNetd.networkCreateVpn(networkAgent.network.netId,
+ mNetd.networkCreateVpn(networkAgent.network.getNetId(),
(networkAgent.networkAgentConfig == null
|| !networkAgent.networkAgentConfig.allowBypass));
} else {
- mNetd.networkCreatePhysical(networkAgent.network.netId,
+ mNetd.networkCreatePhysical(networkAgent.network.getNetId(),
getNetworkPermission(networkAgent.networkCapabilities));
}
- mDnsResolver.createNetworkCache(networkAgent.network.netId);
- mDnsManager.updateTransportsForNetwork(networkAgent.network.netId,
+ mDnsResolver.createNetworkCache(networkAgent.network.getNetId());
+ mDnsManager.updateTransportsForNetwork(networkAgent.network.getNetId(),
networkAgent.networkCapabilities.getTransportTypes());
return true;
} catch (RemoteException | ServiceSpecificException e) {
- loge("Error creating network " + networkAgent.network.netId + ": "
+ loge("Error creating network " + networkAgent.network.getNetId() + ": "
+ e.getMessage());
return false;
}
@@ -3463,8 +3497,8 @@
private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
try {
- mNetd.networkDestroy(networkAgent.network.netId);
- mDnsResolver.destroyNetworkCache(networkAgent.network.netId);
+ mNetd.networkDestroy(networkAgent.network.getNetId());
+ mDnsResolver.destroyNetworkCache(networkAgent.network.getNetId());
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception destroying network: " + e);
}
@@ -3551,30 +3585,58 @@
return false;
}
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
+ if (reason == UnneededFor.LINGER
+ && !nri.isMultilayerRequest()
+ && nri.mRequests.get(0).isBackgroundRequest()) {
// Background requests don't affect lingering.
continue;
}
- // If this Network is already the highest scoring Network for a request, or if
- // there is hope for it to become one if it validated, then it is needed.
- if (nri.request.isRequest() && nai.satisfies(nri.request) &&
- (nai.isSatisfyingRequest(nri.request.requestId) ||
- // Note that this catches two important cases:
- // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
- // is currently satisfying the request. This is desirable when
- // cellular ends up validating but WiFi does not.
- // 2. Unvalidated WiFi will not be reaped when validated cellular
- // is currently satisfying the request. This is desirable when
- // WiFi ends up validating and out scoring cellular.
- nri.mSatisfier.getCurrentScore()
- < nai.getCurrentScoreAsValidated())) {
+ if (isNetworkPotentialSatisfier(nai, nri)) {
return false;
}
}
return true;
}
+ private boolean isNetworkPotentialSatisfier(
+ @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) {
+ // listen requests won't keep up a network satisfying it. If this is not a multilayer
+ // request, we can return immediately. For multilayer requests, we have to check to see if
+ // any of the multilayer requests may have a potential satisfier.
+ if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+ return false;
+ }
+ for (final NetworkRequest req : nri.mRequests) {
+ // As non-multilayer listen requests have already returned, the below would only happen
+ // for a multilayer request therefore continue to the next request if available.
+ if (req.isListen()) {
+ continue;
+ }
+ // If this Network is already the highest scoring Network for a request, or if
+ // there is hope for it to become one if it validated, then it is needed.
+ if (candidate.satisfies(req)) {
+ // As soon as a network is found that satisfies a request, return. Specifically for
+ // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
+ // is important so as to not evaluate lower priority requests further in
+ // nri.mRequests.
+ final boolean isNetworkNeeded = candidate.isSatisfyingRequest(req.requestId)
+ // Note that this catches two important cases:
+ // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
+ // is currently satisfying the request. This is desirable when
+ // cellular ends up validating but WiFi does not.
+ // 2. Unvalidated WiFi will not be reaped when validated cellular
+ // is currently satisfying the request. This is desirable when
+ // WiFi ends up validating and out scoring cellular.
+ || nri.mSatisfier.getCurrentScore()
+ < candidate.getCurrentScoreAsValidated();
+ return isNetworkNeeded;
+ }
+ }
+
+ return false;
+ }
+
private NetworkRequestInfo getNriForAppRequest(
NetworkRequest request, int callingUid, String requestedOperation) {
final NetworkRequestInfo nri = mNetworkRequests.get(request);
@@ -3656,7 +3718,7 @@
nri.mSatisfier = null;
if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
// Went from foreground to background.
- updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ updateCapabilitiesForNetwork(nai);
}
}
@@ -3871,8 +3933,12 @@
new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
- Binder.withCleanCallingIdentity(() ->
- mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mContext.startActivityAsUser(appIntent, UserHandle.CURRENT);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
private class CaptivePortalImpl extends ICaptivePortal.Stub {
@@ -3900,7 +3966,7 @@
if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
checkNetworkStackPermission();
- nm.forceReevaluation(Binder.getCallingUid());
+ nm.forceReevaluation(mDeps.getCallingUid());
}
}
@@ -4026,7 +4092,7 @@
Intent intent = new Intent(action);
if (type != NotificationType.PRIVATE_DNS_BROKEN) {
- intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
+ intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.getNetId()), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Some OEMs have their own Settings package. Thus, need to get the current using
// Settings package name instead of just use default name "com.android.settings".
@@ -4041,7 +4107,8 @@
intent,
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority);
+ mNotifier.showNotification(
+ nai.network.getNetId(), type, nai, null, pendingIntent, highPriority);
}
private boolean shouldPromptUnvalidated(NetworkAgentInfo nai) {
@@ -4366,7 +4433,7 @@
public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
enforceAccessPermission();
enforceInternetPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final int connectivityInfo = encodeBool(hasConnectivity);
// Handle ConnectivityDiagnostics event before attempting to revalidate the network. This
@@ -4407,7 +4474,7 @@
return;
}
if (DBG) {
- int netid = nai.network.netId;
+ int netid = nai.network.getNetId();
log("reportNetworkConnectivity(" + netid + ", " + hasConnectivity + ") by " + uid);
}
// Validating a network that has not yet connected could result in a call to
@@ -4436,13 +4503,13 @@
if (globalProxy != null) return globalProxy;
if (network == null) {
// Get the network associated with the calling UID.
- final Network activeNetwork = getActiveNetworkForUidInternal(Binder.getCallingUid(),
+ final Network activeNetwork = getActiveNetworkForUidInternal(mDeps.getCallingUid(),
true);
if (activeNetwork == null) {
return null;
}
return getLinkPropertiesProxyInfo(activeNetwork);
- } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.netId)) {
+ } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network.getNetId())) {
// Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
// caller may not have.
return getLinkPropertiesProxyInfo(network);
@@ -4611,7 +4678,7 @@
*/
@Override
public ParcelFileDescriptor establishVpn(VpnConfig config) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).establish(config);
@@ -4632,7 +4699,7 @@
*/
@Override
public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore);
}
@@ -4650,7 +4717,7 @@
*/
@Override
public void deleteVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
mVpns.get(user).deleteVpnProfile(packageName, mKeyStore);
}
@@ -4667,7 +4734,7 @@
*/
@Override
public void startVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
mVpns.get(user).startVpnProfile(packageName, mKeyStore);
@@ -4684,7 +4751,7 @@
*/
@Override
public void stopVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
mVpns.get(user).stopVpnProfile(packageName);
}
@@ -4696,7 +4763,7 @@
*/
@Override
public void startLegacyVpn(VpnProfile profile) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
final LinkProperties egress = getActiveLinkProperties();
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
@@ -4809,25 +4876,43 @@
}
}
+ private Network[] underlyingNetworksOrDefault(Network[] underlyingNetworks) {
+ final Network defaultNetwork = getNetwork(getDefaultNetwork());
+ if (underlyingNetworks == null && defaultNetwork != null) {
+ // null underlying networks means to track the default.
+ underlyingNetworks = new Network[] { defaultNetwork };
+ }
+ return underlyingNetworks;
+ }
+
+ // Returns true iff |network| is an underlying network of |nai|.
+ private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) {
+ // TODO: support more than one level of underlying networks, either via a fixed-depth search
+ // (e.g., 2 levels of underlying networks), or via loop detection, or....
+ if (!nai.supportsUnderlyingNetworks()) return false;
+ final Network[] underlying = underlyingNetworksOrDefault(nai.declaredUnderlyingNetworks);
+ return ArrayUtils.contains(underlying, network);
+ }
+
/**
- * Ask all networks with underlying networks to recompute and update their capabilities.
+ * Recompute the capabilities for any networks that had a specific network as underlying.
*
* When underlying networks change, such networks may have to update capabilities to reflect
* things like the metered bit, their transports, and so on. The capabilities are calculated
* immediately. This method runs on the ConnectivityService thread.
*/
- private void propagateUnderlyingNetworkCapabilities() {
+ private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) {
ensureRunningOnConnectivityServiceThread();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- if (nai.supportsUnderlyingNetworks()) {
- updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) {
+ updateCapabilitiesForNetwork(nai);
}
}
}
@Override
public boolean updateLockdownVpn() {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
logw("Lockdown VPN only available to AID_SYSTEM");
return false;
}
@@ -4849,7 +4934,7 @@
setLockdownTracker(null);
return true;
}
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
Vpn vpn = mVpns.get(user);
if (vpn == null) {
logw("VPN for user " + user + " not ready yet. Skipping lockdown");
@@ -5142,7 +5227,7 @@
loge("Starting user already has a VPN");
return;
}
- userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
+ userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore);
mVpns.put(userId, userVpn);
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
updateLockdownVpn();
@@ -5414,7 +5499,7 @@
messenger = null;
mBinder = null;
mPid = getCallingPid();
- mUid = getCallingUid();
+ mUid = mDeps.getCallingUid();
enforceRequestCountLimit();
}
@@ -5426,7 +5511,7 @@
ensureAllNetworkRequestsHaveType(mRequests);
mBinder = binder;
mPid = getCallingPid();
- mUid = getCallingUid();
+ mUid = mDeps.getCallingUid();
mPendingIntent = null;
enforceRequestCountLimit();
@@ -5441,6 +5526,10 @@
this(r, null);
}
+ boolean isMultilayerRequest() {
+ return mRequests.size() > 1;
+ }
+
private List<NetworkRequest> initializeRequests(NetworkRequest r) {
final ArrayList<NetworkRequest> tempRequests = new ArrayList<>();
tempRequests.add(new NetworkRequest(r));
@@ -5482,7 +5571,7 @@
public void binderDied() {
log("ConnectivityService NetworkRequestInfo binderDied(" +
mRequests + ", " + mBinder + ")");
- releaseNetworkRequest(mRequests);
+ releaseNetworkRequests(mRequests);
}
@Override
@@ -5515,13 +5604,15 @@
mAppOpsManager.checkPackage(callerUid, callerPackageName);
}
- private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
+ private ArrayList<Integer> getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
final SortedSet<Integer> thresholds = new TreeSet<>();
synchronized (nai) {
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.request.networkCapabilities.hasSignalStrength() &&
- nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
- thresholds.add(nri.request.networkCapabilities.getSignalStrength());
+ for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
+ for (final NetworkRequest req : nri.mRequests) {
+ if (req.networkCapabilities.hasSignalStrength()
+ && nai.satisfiesImmutableCapabilitiesOf(req)) {
+ thresholds.add(req.networkCapabilities.getSignalStrength());
+ }
}
}
}
@@ -5569,11 +5660,12 @@
}
private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) {
- final PackageManager pm = mContext.getPackageManager();
- final int userId = UserHandle.getCallingUserId();
+ final UserHandle user = UserHandle.getUserHandleForUid(mDeps.getCallingUid());
+ final PackageManager pm =
+ mContext.createContextAsUser(user, 0 /* flags */).getPackageManager();
try {
- final int callingVersion = pm.getApplicationInfoAsUser(
- callingPackageName, 0 /* flags */, userId).targetSdkVersion;
+ final int callingVersion = pm.getApplicationInfo(
+ callingPackageName, 0 /* flags */).targetSdkVersion;
if (callingVersion < version) return false;
} catch (PackageManager.NameNotFoundException e) { }
return true;
@@ -5588,7 +5680,7 @@
throw new SecurityException("Insufficient permissions to specify legacy type");
}
}
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
final NetworkRequest.Type type = (networkCapabilities == null)
? NetworkRequest.Type.TRACK_DEFAULT
: NetworkRequest.Type.REQUEST;
@@ -5653,12 +5745,12 @@
return false;
}
synchronized (mNetworkForNetId) {
- nai = mNetworkForNetId.get(network.netId);
+ nai = mNetworkForNetId.get(network.getNetId());
}
if (nai != null) {
nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
synchronized (mBandwidthRequests) {
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
Integer uidReqs = mBandwidthRequests.get(uid);
if (uidReqs == null) {
uidReqs = 0;
@@ -5675,7 +5767,7 @@
}
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
if (isSystem(uid)) {
// Exemption for system uid.
return;
@@ -5695,7 +5787,7 @@
PendingIntent operation, @NonNull String callingPackageName,
@Nullable String callingAttributionTag) {
Objects.requireNonNull(operation, "PendingIntent cannot be null.");
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
networkCapabilities = new NetworkCapabilities(networkCapabilities);
enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
callingAttributionTag);
@@ -5754,7 +5846,7 @@
@Override
public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, IBinder binder, @NonNull String callingPackageName) {
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
@@ -5784,7 +5876,7 @@
public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
PendingIntent operation, @NonNull String callingPackageName) {
Objects.requireNonNull(operation, "PendingIntent cannot be null.");
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
@@ -5807,7 +5899,7 @@
return mNextNetworkProviderId.getAndIncrement();
}
- private void releaseNetworkRequest(List<NetworkRequest> networkRequests) {
+ private void releaseNetworkRequests(List<NetworkRequest> networkRequests) {
for (int i = 0; i < networkRequests.size(); i++) {
releaseNetworkRequest(networkRequests.get(i));
}
@@ -5885,7 +5977,7 @@
} else {
enforceNetworkFactoryPermission();
}
- mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
+ mHandler.post(() -> handleReleaseNetworkRequest(request, mDeps.getCallingUid(), true));
}
// NOTE: Accessed on multiple threads, must be synchronized on itself.
@@ -5979,7 +6071,7 @@
enforceNetworkFactoryPermission();
}
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
return registerNetworkAgentInternal(messenger, networkInfo, linkProperties,
@@ -6033,7 +6125,7 @@
if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(nai.messenger, nai);
synchronized (mNetworkForNetId) {
- mNetworkForNetId.put(nai.network.netId, nai);
+ mNetworkForNetId.put(nai.network.getNetId(), nai);
}
try {
@@ -6052,6 +6144,7 @@
* Stores into |nai| any data coming from the agent that might also be written to the network's
* LinkProperties by ConnectivityService itself. This ensures that the data provided by the
* agent is not lost when updateLinkProperties is called.
+ * This method should never alter the agent's LinkProperties, only store data in |nai|.
*/
private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) {
lp.ensureDirectlyConnectedRoutes();
@@ -6060,7 +6153,7 @@
private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp,
@NonNull LinkProperties oldLp) {
- int netId = networkAgent.network.netId;
+ int netId = networkAgent.network.getNetId();
// The NetworkAgent does not know whether clatd is running on its network or not, or whether
// a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure
@@ -6341,7 +6434,7 @@
final int newPermission = getNetworkPermission(newNc);
if (oldPermission != newPermission && nai.created && !nai.isVPN()) {
try {
- mNetd.networkSetPermissionForNetwork(nai.network.netId, newPermission);
+ mNetd.networkSetPermissionForNetwork(nai.network.getNetId(), newPermission);
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception in networkSetPermissionForNetwork: " + e);
}
@@ -6353,24 +6446,31 @@
* Stores into |nai| any data coming from the agent that might also be written to the network's
* NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the
* agent is not lost when updateCapabilities is called.
+ * This method should never alter the agent's NetworkCapabilities, only store data in |nai|.
*/
private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) {
- nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
+ // Note: resetting the owner UID before storing the agent capabilities in NAI means that if
+ // the agent attempts to change the owner UID, then nai.declaredCapabilities will not
+ // actually be the same as the capabilities sent by the agent. Still, it is safer to reset
+ // the owner UID here and behave as if the agent had never tried to change it.
+ if (nai.networkCapabilities.getOwnerUid() != nc.getOwnerUid()) {
+ Log.e(TAG, nai.toShortString() + ": ignoring attempt to change owner from "
+ + nai.networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid());
+ nc.setOwnerUid(nai.networkCapabilities.getOwnerUid());
+ }
+ nai.declaredCapabilities = new NetworkCapabilities(nc);
}
- /** Modifies |caps| based on the capabilities of the specified underlying networks. */
+ /** Modifies |newNc| based on the capabilities of |underlyingNetworks| and |agentCaps|. */
@VisibleForTesting
void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
- @NonNull NetworkCapabilities caps, boolean declaredMetered) {
- final Network defaultNetwork = getNetwork(getDefaultNetwork());
- if (underlyingNetworks == null && defaultNetwork != null) {
- // null underlying networks means to track the default.
- underlyingNetworks = new Network[] { defaultNetwork };
- }
- int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
+ @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) {
+ underlyingNetworks = underlyingNetworksOrDefault(underlyingNetworks);
+ int[] transportTypes = agentCaps.getTransportTypes();
int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
- boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered
+ // metered if any underlying is metered, or originally declared metered by the agent.
+ boolean metered = !agentCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
boolean roaming = false; // roaming if any underlying is roaming
boolean congested = false; // congested if any underlying is congested
boolean suspended = true; // suspended if all underlying are suspended
@@ -6416,13 +6516,13 @@
suspended = false;
}
- caps.setTransportTypes(transportTypes);
- caps.setLinkDownstreamBandwidthKbps(downKbps);
- caps.setLinkUpstreamBandwidthKbps(upKbps);
- caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
- caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
- caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
- caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
+ newNc.setTransportTypes(transportTypes);
+ newNc.setLinkDownstreamBandwidthKbps(downKbps);
+ newNc.setLinkUpstreamBandwidthKbps(upKbps);
+ newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
+ newNc.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
+ newNc.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
+ newNc.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
}
/**
@@ -6479,7 +6579,8 @@
}
if (nai.supportsUnderlyingNetworks()) {
- applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered);
+ applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, nai.declaredCapabilities,
+ newNc);
}
return newNc;
@@ -6558,17 +6659,20 @@
}
}
- if (!newNc.hasTransport(TRANSPORT_VPN)) {
- // Tell VPNs about updated capabilities, since they may need to
- // bubble those changes through.
- propagateUnderlyingNetworkCapabilities();
- }
+ // This network might have been underlying another network. Propagate its capabilities.
+ propagateUnderlyingNetworkCapabilities(nai.network);
if (!newNc.equalsTransportTypes(prevNc)) {
- mDnsManager.updateTransportsForNetwork(nai.network.netId, newNc.getTransportTypes());
+ mDnsManager.updateTransportsForNetwork(
+ nai.network.getNetId(), newNc.getTransportTypes());
}
}
+ /** Convenience method to update the capabilities for a given network. */
+ private void updateCapabilitiesForNetwork(NetworkAgentInfo nai) {
+ updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ }
+
/**
* Returns whether VPN isolation (ingress interface filtering) should be applied on the given
* network.
@@ -6598,6 +6702,16 @@
&& (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
}
+ private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
+ final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()];
+ int index = 0;
+ for (UidRange range : ranges) {
+ stableRanges[index] = new UidRangeParcel(range.start, range.stop);
+ index++;
+ }
+ return stableRanges;
+ }
+
private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
NetworkCapabilities newNc) {
Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
@@ -6617,14 +6731,11 @@
// removing old range works because, unlike the filtering rules below, it's possible to
// add duplicate UID routing rules.
if (!newRanges.isEmpty()) {
- final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
- newRanges.toArray(addedRangesArray);
- mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray);
+ mNetd.networkAddUidRanges(nai.network.netId, toUidRangeStableParcels(newRanges));
}
if (!prevRanges.isEmpty()) {
- final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
- prevRanges.toArray(removedRangesArray);
- mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray);
+ mNetd.networkRemoveUidRanges(
+ nai.network.netId, toUidRangeStableParcels(prevRanges));
}
final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);
@@ -6655,7 +6766,7 @@
public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) {
ensureRunningOnConnectivityServiceThread();
- if (getNetworkAgentInfoForNetId(nai.network.netId) != nai) {
+ if (getNetworkAgentInfoForNetId(nai.network.getNetId()) != nai) {
// Ignore updates for disconnected networks
return;
}
@@ -6854,8 +6965,7 @@
teardownUnneededNetwork(oldNetwork);
} else {
// Put the network in the background.
- updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
- oldNetwork.networkCapabilities);
+ updateCapabilitiesForNetwork(oldNetwork);
}
}
@@ -6866,7 +6976,7 @@
try {
if (null != newNetwork) {
- mNetd.networkSetDefault(newNetwork.network.netId);
+ mNetd.networkSetDefault(newNetwork.network.getNetId());
} else {
mNetd.networkClearDefault();
}
@@ -6880,8 +6990,10 @@
updateTcpBufferSizes(null != newNetwork
? newNetwork.linkProperties.getTcpBufferSizes() : null);
notifyIfacesChangedForNetworkStats();
- // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
- propagateUnderlyingNetworkCapabilities();
+ // Fix up the NetworkCapabilities of any networks that have this network as underlying.
+ if (newNetwork != null) {
+ propagateUnderlyingNetworkCapabilities(newNetwork.network);
+ }
}
private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
@@ -6929,8 +7041,8 @@
public String toString() {
return mRequest.mRequests.get(0).requestId + " : "
- + (null != mOldNetwork ? mOldNetwork.network.netId : "null")
- + " → " + (null != mNewNetwork ? mNewNetwork.network.netId : "null");
+ + (null != mOldNetwork ? mOldNetwork.network.getNetId() : "null")
+ + " → " + (null != mNewNetwork ? mNewNetwork.network.getNetId() : "null");
}
}
@@ -7337,13 +7449,11 @@
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
if (!createNativeNetwork(networkAgent)) return;
- if (networkAgent.isVPN()) {
- // Initialize the VPN capabilities to their starting values according to the
- // underlying networks. This will avoid a spurious callback to
- // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as
- // the VPN would switch from its default, blank capabilities to those
- // that reflect the capabilities of its underlying networks.
- propagateUnderlyingNetworkCapabilities();
+ if (networkAgent.supportsUnderlyingNetworks()) {
+ // Initialize the network's capabilities to their starting values according to the
+ // underlying networks. This ensures that the capabilities are correct before
+ // anything happens to the network.
+ updateCapabilitiesForNetwork(networkAgent);
}
networkAgent.created = true;
}
@@ -7385,10 +7495,6 @@
// doing.
updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
- if (networkAgent.supportsUnderlyingNetworks()) {
- propagateUnderlyingNetworkCapabilities();
- }
-
// Consider network even though it is not yet validated.
rematchAllNetworksAndRequests();
@@ -7619,7 +7725,7 @@
@Override
public boolean addVpnAddress(String address, int prefixLength) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).addAddress(address, prefixLength);
@@ -7628,7 +7734,7 @@
@Override
public boolean removeVpnAddress(String address, int prefixLength) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).removeAddress(address, prefixLength);
@@ -7637,7 +7743,7 @@
@Override
public boolean setUnderlyingNetworksForVpn(Network[] networks) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
final boolean success;
synchronized (mVpns) {
throwIfLockdownEnabled();
@@ -7725,10 +7831,13 @@
final int userId = UserHandle.getCallingUserId();
- Binder.withCleanCallingIdentity(() -> {
+ final long token = Binder.clearCallingIdentity();
+ try {
final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
ipMemoryStore.factoryReset();
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
// Turn airplane mode off
setAirplaneMode(false);
@@ -7794,7 +7903,7 @@
private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
int[] transports = nai.networkCapabilities.getTransportTypes();
- mMetricsLog.log(nai.network.netId, transports, new NetworkEvent(evtype));
+ mMetricsLog.log(nai.network.getNetId(), transports, new NetworkEvent(evtype));
}
private static boolean toBool(int encodedBoolean) {
@@ -7864,7 +7973,7 @@
@GuardedBy("mVpns")
private Vpn getVpnIfOwner() {
- return getVpnIfOwner(Binder.getCallingUid());
+ return getVpnIfOwner(mDeps.getCallingUid());
}
@GuardedBy("mVpns")
@@ -8342,7 +8451,7 @@
throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
+ " Please use NetworkCapabilities instead.");
}
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
mAppOpsManager.checkPackage(callingUid, callingPackageName);
// This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
@@ -8377,7 +8486,7 @@
mConnectivityDiagnosticsHandler.obtainMessage(
ConnectivityDiagnosticsHandler
.EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
- Binder.getCallingUid(),
+ mDeps.getCallingUid(),
0,
callback));
}
@@ -8393,7 +8502,7 @@
}
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai == null || nai.creatorUid != Binder.getCallingUid()) {
+ if (nai == null || nai.creatorUid != mDeps.getCallingUid()) {
throw new SecurityException("Data Stall simulation is only possible for network "
+ "creators");
}
@@ -8416,6 +8525,6 @@
KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
}
- notifyDataStallSuspected(p, network.netId);
+ notifyDataStallSuspected(p, network.getNetId());
}
}
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index a45466d..e8687e5 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -61,9 +61,8 @@
/** @hide */
class TestNetworkService extends ITestNetworkManager.Stub {
- @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
@NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent";
- @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = TAG;
+ @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = "TestNetworkProvider";
@NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
@NonNull private final Context mContext;
@@ -108,23 +107,23 @@
String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
- return Binder.withCleanCallingIdentity(
- () -> {
- try {
- ParcelFileDescriptor tunIntf =
- ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
- for (LinkAddress addr : linkAddrs) {
- mNetd.interfaceAddAddress(
- iface,
- addr.getAddress().getHostAddress(),
- addr.getPrefixLength());
- }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ ParcelFileDescriptor tunIntf =
+ ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
+ for (LinkAddress addr : linkAddrs) {
+ mNetd.interfaceAddAddress(
+ iface,
+ addr.getAddress().getHostAddress(),
+ addr.getPrefixLength());
+ }
- return new TestNetworkInterface(tunIntf, iface);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- });
+ return new TestNetworkInterface(tunIntf, iface);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
/**
@@ -168,17 +167,15 @@
private TestNetworkAgent(
@NonNull Context context,
@NonNull Looper looper,
- @NonNull NetworkAgentConfig config,
@NonNull NetworkCapabilities nc,
@NonNull LinkProperties lp,
+ @NonNull NetworkAgentConfig config,
int uid,
@NonNull IBinder binder,
@NonNull NetworkProvider np)
throws RemoteException {
super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np);
-
mUid = uid;
-
synchronized (mBinderLock) {
mBinder = binder; // Binder null-checks in create()
@@ -220,7 +217,7 @@
// Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
// resources, even for binder death or unwanted calls.
synchronized (mTestNetworkTracker) {
- mTestNetworkTracker.remove(getNetwork().netId);
+ mTestNetworkTracker.remove(getNetwork().getNetId());
}
}
}
@@ -286,8 +283,8 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
}
- final TestNetworkAgent agent = new TestNetworkAgent(context, looper,
- new NetworkAgentConfig.Builder().build(), nc, lp, callingUid, binder,
+ final TestNetworkAgent agent = new TestNetworkAgent(context, looper, nc, lp,
+ new NetworkAgentConfig.Builder().build(), callingUid, binder,
mNetworkProvider);
agent.register();
agent.markConnected();
@@ -320,7 +317,12 @@
try {
// This requires NETWORK_STACK privileges.
- Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNMS.setInterfaceUp(iface);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
// Synchronize all accesses to mTestNetworkTracker to prevent the case where:
// 1. TestNetworkAgent successfully binds to death of binder
@@ -339,7 +341,7 @@
administratorUids,
binder);
- mTestNetworkTracker.put(agent.getNetwork().netId, agent);
+ mTestNetworkTracker.put(agent.getNetwork().getNetId(), agent);
}
} catch (SocketException e) {
throw new UncheckedIOException(e);
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 1f0fb5e..c70bb08 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -34,7 +34,6 @@
import android.net.IDnsResolver;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkUtils;
import android.net.ResolverOptionsParcel;
import android.net.ResolverParamsParcel;
import android.net.Uri;
@@ -50,6 +49,7 @@
import java.net.InetAddress;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,7 +59,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-
/**
* Encapsulate the management of DNS settings for networks.
*
@@ -266,23 +265,23 @@
}
public void removeNetwork(Network network) {
- mPrivateDnsMap.remove(network.netId);
- mPrivateDnsValidationMap.remove(network.netId);
- mTransportsMap.remove(network.netId);
- mLinkPropertiesMap.remove(network.netId);
+ mPrivateDnsMap.remove(network.getNetId());
+ mPrivateDnsValidationMap.remove(network.getNetId());
+ mTransportsMap.remove(network.getNetId());
+ mLinkPropertiesMap.remove(network.getNetId());
}
// This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which
// is not on the ConnectivityService handler thread.
public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) {
- return mPrivateDnsMap.getOrDefault(network.netId, PRIVATE_DNS_OFF);
+ return mPrivateDnsMap.getOrDefault(network.getNetId(), PRIVATE_DNS_OFF);
}
public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
Log.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
return (cfg != null)
- ? mPrivateDnsMap.put(network.netId, cfg)
- : mPrivateDnsMap.remove(network.netId);
+ ? mPrivateDnsMap.put(network.getNetId(), cfg)
+ : mPrivateDnsMap.remove(network.getNetId());
}
public void updatePrivateDnsStatus(int netId, LinkProperties lp) {
@@ -309,8 +308,7 @@
}
public void updatePrivateDnsValidation(PrivateDnsValidationUpdate update) {
- final PrivateDnsValidationStatuses statuses =
- mPrivateDnsValidationMap.get(update.netId);
+ final PrivateDnsValidationStatuses statuses = mPrivateDnsValidationMap.get(update.netId);
if (statuses == null) return;
statuses.updateStatus(update);
}
@@ -364,12 +362,11 @@
paramsParcel.successThreshold = mSuccessThreshold;
paramsParcel.minSamples = mMinSamples;
paramsParcel.maxSamples = mMaxSamples;
- paramsParcel.servers =
- NetworkUtils.makeStrings(lp.getDnsServers());
+ paramsParcel.servers = makeStrings(lp.getDnsServers());
paramsParcel.domains = getDomainStrings(lp.getDomains());
paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
paramsParcel.tlsServers =
- strictMode ? NetworkUtils.makeStrings(
+ strictMode ? makeStrings(
Arrays.stream(privateDnsCfg.ips)
.filter((ip) -> lp.isReachable(ip))
.collect(Collectors.toList()))
@@ -460,6 +457,21 @@
return Settings.Global.getInt(mContentResolver, which, dflt);
}
+ /**
+ * Create a string array of host addresses from a collection of InetAddresses
+ *
+ * @param addrs a Collection of InetAddresses
+ * @return an array of Strings containing their host addresses
+ */
+ private String[] makeStrings(Collection<InetAddress> addrs) {
+ String[] result = new String[addrs.size()];
+ int i = 0;
+ for (InetAddress addr : addrs) {
+ result[i++] = addr.getHostAddress();
+ }
+ return result;
+ }
+
private static String getPrivateDnsMode(ContentResolver cr) {
String mode = getStringSetting(cr, PRIVATE_DNS_MODE);
if (TextUtils.isEmpty(mode)) mode = getStringSetting(cr, PRIVATE_DNS_DEFAULT_MODE);
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 8625a6f..96cbfde 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -40,11 +40,11 @@
import android.annotation.Nullable;
import android.content.Context;
import android.net.ISocketKeepaliveCallback;
+import android.net.InetAddresses;
import android.net.InvalidPacketException;
import android.net.KeepalivePacketData;
import android.net.NattKeepalivePacketData;
import android.net.NetworkAgent;
-import android.net.NetworkUtils;
import android.net.SocketKeepalive.InvalidSocketException;
import android.net.TcpKeepalivePacketData;
import android.net.util.KeepaliveUtils;
@@ -625,8 +625,8 @@
InetAddress srcAddress, dstAddress;
try {
- srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
- dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
+ srcAddress = InetAddresses.parseNumericAddress(srcAddrString);
+ dstAddress = InetAddresses.parseNumericAddress(dstAddrString);
} catch (IllegalArgumentException e) {
notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
return;
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java
index f99f4c6..adec7ad 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java
@@ -114,7 +114,7 @@
private int getNotificationSource(NetworkAgentInfo toNai) {
for (int i = 0; i < mNotifications.size(); i++) {
- if (mNotifications.valueAt(i) == toNai.network.netId) {
+ if (mNotifications.valueAt(i) == toNai.network.getNetId()) {
return mNotifications.keyAt(i);
}
}
@@ -122,7 +122,7 @@
}
private boolean everNotified(NetworkAgentInfo nai) {
- return mEverNotified.get(nai.network.netId, false);
+ return mEverNotified.get(nai.network.getNetId(), false);
}
@VisibleForTesting
@@ -153,7 +153,7 @@
}
private void showNotification(NetworkAgentInfo fromNai, NetworkAgentInfo toNai) {
- mNotifier.showNotification(fromNai.network.netId, NotificationType.NETWORK_SWITCH,
+ mNotifier.showNotification(fromNai.network.getNetId(), NotificationType.NETWORK_SWITCH,
fromNai, toNai, createNotificationIntent(), true);
}
@@ -208,8 +208,8 @@
+ " type=" + sNotifyTypeNames.get(notifyType, "unknown(" + notifyType + ")"));
}
- mNotifications.put(fromNai.network.netId, toNai.network.netId);
- mEverNotified.put(fromNai.network.netId, true);
+ mNotifications.put(fromNai.network.getNetId(), toNai.network.getNetId());
+ mEverNotified.put(fromNai.network.getNetId(), true);
}
/**
@@ -295,8 +295,8 @@
}
public void noteDisconnect(NetworkAgentInfo nai) {
- mNotifications.delete(nai.network.netId);
- mEverNotified.delete(nai.network.netId);
+ mNotifications.delete(nai.network.getNetId());
+ mEverNotified.delete(nai.network.getNetId());
maybeStopNotifying(nai);
// No need to cancel notifications on nai: NetworkMonitor does that on disconnect.
}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index d9c2e80..c1b1b6a 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -528,6 +528,6 @@
@VisibleForTesting
protected int getNetId() {
- return mNetwork.network.netId;
+ return mNetwork.network.getNetId();
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 3270dd5..52b9f5c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -138,9 +138,10 @@
// not guaranteed to be current or correct, or even to exist.
public @Nullable Network[] declaredUnderlyingNetworks;
- // Whether this network is always metered even if its underlying networks are unmetered.
- // Only relevant if #supportsUnderlyingNetworks is true.
- public boolean declaredMetered;
+ // The capabilities originally announced by the NetworkAgent, regardless of any capabilities
+ // that were added or removed due to this network's underlying networks.
+ // Only set if #supportsUnderlyingNetworks is true.
+ public @Nullable NetworkCapabilities declaredCapabilities;
// Indicates if netd has been told to create this Network. From this point on the appropriate
// routing rules are setup and routes are added so packets can begin flowing over the Network.
@@ -610,7 +611,7 @@
if (newExpiry > 0) {
mLingerMessage = new WakeupMessage(
mContext, mHandler,
- "NETWORK_LINGER_COMPLETE." + network.netId /* cmdName */,
+ "NETWORK_LINGER_COMPLETE." + network.getNetId() /* cmdName */,
EVENT_NETWORK_LINGER_COMPLETE /* cmd */,
0 /* arg1 (unused) */, 0 /* arg2 (unused) */,
this /* obj (NetworkAgentInfo) */);
@@ -701,7 +702,7 @@
* This represents the network with something like "[100 WIFI|VPN]" or "[108 MOBILE]".
*/
public String toShortString() {
- return "[" + network.netId + " "
+ return "[" + network.getNetId() + " "
+ transportNamesOf(networkCapabilities.getTransportTypes()) + "]";
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 49c16ad..a7be657 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -20,10 +20,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.InetAddresses;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.TrafficStats;
import android.net.shared.PrivateDnsConfig;
@@ -97,8 +97,8 @@
public class NetworkDiagnostics {
private static final String TAG = "NetworkDiagnostics";
- private static final InetAddress TEST_DNS4 = NetworkUtils.numericToInetAddress("8.8.8.8");
- private static final InetAddress TEST_DNS6 = NetworkUtils.numericToInetAddress(
+ private static final InetAddress TEST_DNS4 = InetAddresses.parseNumericAddress("8.8.8.8");
+ private static final InetAddress TEST_DNS6 = InetAddresses.parseNumericAddress(
"2001:4860:4860::8888");
// For brevity elsewhere.
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 7795ed3..3d71b0a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -334,7 +334,13 @@
*/
public void setProvNotificationVisible(boolean visible, int id, String action) {
if (visible) {
- Intent intent = new Intent(action);
+ // For legacy purposes, action is sent as the action + the phone ID from DcTracker.
+ // Split the string here and send the phone ID as an extra instead.
+ String[] splitAction = action.split(":");
+ Intent intent = new Intent(splitAction[0]);
+ try {
+ intent.putExtra("provision.phone.id", Integer.parseInt(splitAction[1]));
+ } catch (NumberFormatException ignored) { }
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false);
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 4c63eb4..d507b5f 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -35,7 +35,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
-import android.content.pm.UserInfo;
import android.net.INetd;
import android.net.UidRange;
import android.os.Build;
@@ -174,11 +173,9 @@
netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
}
- List<UserInfo> users = mUserManager.getAliveUsers();
- if (users != null) {
- for (UserInfo user : users) {
- mUsers.add(user.id);
- }
+ final List<UserHandle> users = mUserManager.getUserHandles(true /* excludeDying */);
+ for (UserHandle user : users) {
+ mUsers.add(user.getIdentifier());
}
final SparseArray<ArraySet<String>> systemPermission =
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 1129899..b5f20d7 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -36,6 +36,7 @@
import android.net.TcpKeepalivePacketData;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.TcpRepairWindow;
+import android.net.util.KeepalivePacketDataUtil;
import android.os.Handler;
import android.os.MessageQueue;
import android.os.Messenger;
@@ -112,7 +113,7 @@
throws InvalidPacketException, InvalidSocketException {
try {
final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd);
- return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails);
+ return KeepalivePacketDataUtil.fromStableParcelable(tcpDetails);
} catch (InvalidPacketException | InvalidSocketException e) {
switchOutOfRepairMode(fd);
throw e;
@@ -122,7 +123,7 @@
* Switch the tcp socket to repair mode and query detail tcp information.
*
* @param fd the fd of socket on which to use keepalive offload.
- * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current
+ * @return a {@link TcpKeepalivePacketDataParcelable} object for current
* tcp/ip information.
*/
private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd)
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index 60308e3..1eaf30c 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -68,8 +68,8 @@
private static final String V4 = "192.0.2.1";
private static final String V6 = "2001:db8::1";
- private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
- private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
+ private static final InetAddress V4_ADDRESS = InetAddresses.parseNumericAddress(V4);
+ private static final InetAddress V6_ADDRESS = InetAddresses.parseNumericAddress(V6);
@Test
public void testConstants() {
@@ -131,10 +131,10 @@
ipv6Loopback = new LinkAddress(addrs.get(0));
}
- assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
+ assertEquals(InetAddresses.parseNumericAddress("127.0.0.1"), ipv4Loopback.getAddress());
assertEquals(8, ipv4Loopback.getPrefixLength());
- assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
+ assertEquals(InetAddresses.parseNumericAddress("::1"), ipv6Loopback.getAddress());
assertEquals(128, ipv6Loopback.getPrefixLength());
// Null addresses are rejected.
diff --git a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
new file mode 100644
index 0000000..6770066
--- /dev/null
+++ b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.InetAddresses.parseNumericAddress
+import android.os.Build
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertFieldCountEquals
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.net.InetAddress
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+import kotlin.test.assertTrue
+
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) // TcpKeepalivePacketData added to SDK in S
+class TcpKeepalivePacketDataTest {
+ private fun makeData(
+ srcAddress: InetAddress = parseNumericAddress("192.0.2.123"),
+ srcPort: Int = 1234,
+ dstAddress: InetAddress = parseNumericAddress("192.0.2.231"),
+ dstPort: Int = 4321,
+ data: ByteArray = byteArrayOf(1, 2, 3),
+ tcpSeq: Int = 135,
+ tcpAck: Int = 246,
+ tcpWnd: Int = 1234,
+ tcpWndScale: Int = 2,
+ ipTos: Int = 0x12,
+ ipTtl: Int = 10
+ ) = TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data, tcpSeq, tcpAck,
+ tcpWnd, tcpWndScale, ipTos, ipTtl)
+
+ @Test
+ fun testEquals() {
+ val data1 = makeData()
+ val data2 = makeData()
+ assertEquals(data1, data2)
+ assertEquals(data1.hashCode(), data2.hashCode())
+ }
+
+ @Test
+ fun testNotEquals() {
+ assertNotEquals(makeData(srcAddress = parseNumericAddress("192.0.2.124")), makeData())
+ assertNotEquals(makeData(srcPort = 1235), makeData())
+ assertNotEquals(makeData(dstAddress = parseNumericAddress("192.0.2.232")), makeData())
+ assertNotEquals(makeData(dstPort = 4322), makeData())
+ // .equals does not test .packet, as it should be generated from the other fields
+ assertNotEquals(makeData(tcpSeq = 136), makeData())
+ assertNotEquals(makeData(tcpAck = 247), makeData())
+ assertNotEquals(makeData(tcpWnd = 1235), makeData())
+ assertNotEquals(makeData(tcpWndScale = 3), makeData())
+ assertNotEquals(makeData(ipTos = 0x14), makeData())
+ assertNotEquals(makeData(ipTtl = 11), makeData())
+
+ // Update above assertions if field is added
+ assertFieldCountEquals(5, KeepalivePacketData::class.java)
+ assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
+ }
+
+ @Test
+ fun testParcelUnparcel() {
+ assertParcelSane(makeData(), fieldCount = 6) { a, b ->
+ // .equals() does not verify .packet
+ a == b && a.packet contentEquals b.packet
+ }
+ }
+
+ @Test
+ fun testToString() {
+ val data = makeData()
+ val str = data.toString()
+
+ assertTrue(str.contains(data.srcAddress.hostAddress))
+ assertTrue(str.contains(data.srcPort.toString()))
+ assertTrue(str.contains(data.dstAddress.hostAddress))
+ assertTrue(str.contains(data.dstPort.toString()))
+ // .packet not included in toString()
+ assertTrue(str.contains(data.tcpSeq.toString()))
+ assertTrue(str.contains(data.tcpAck.toString()))
+ assertTrue(str.contains(data.tcpWindow.toString()))
+ assertTrue(str.contains(data.tcpWindowScale.toString()))
+ assertTrue(str.contains(data.ipTos.toString()))
+ assertTrue(str.contains(data.ipTtl.toString()))
+
+ // Update above assertions if field is added
+ assertFieldCountEquals(5, KeepalivePacketData::class.java)
+ assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
+ }
+}
\ No newline at end of file
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 2a24d1a..3d4dc4d 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -29,7 +29,7 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.fail;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -38,7 +38,6 @@
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
import android.net.NetworkProvider;
import android.net.NetworkSpecifier;
import android.net.SocketKeepalive;
@@ -53,9 +52,9 @@
import com.android.testutils.TestableNetworkCallback;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
- private final NetworkInfo mNetworkInfo;
private final NetworkCapabilities mNetworkCapabilities;
private final HandlerThread mHandlerThread;
private final Context mContext;
@@ -63,6 +62,7 @@
private final ConditionVariable mDisconnected = new ConditionVariable();
private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
+ private final AtomicBoolean mConnected = new AtomicBoolean(false);
private int mScore;
private NetworkAgent mNetworkAgent;
private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
@@ -76,7 +76,6 @@
NetworkCapabilities ncTemplate, Context context) throws Exception {
final int type = transportToLegacyType(transport);
final String typeName = ConnectivityManager.getNetworkTypeName(type);
- mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities();
mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
mNetworkCapabilities.addTransportType(transport);
@@ -108,22 +107,29 @@
mHandlerThread = new HandlerThread(mLogTag);
mHandlerThread.start();
- mNetworkAgent = makeNetworkAgent(linkProperties);
+ mNetworkAgent = makeNetworkAgent(linkProperties, type, typeName);
}
- protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
+ protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
+ final int type, final String typeName)
throws Exception {
- return new InstrumentedNetworkAgent(this, linkProperties);
+ return new InstrumentedNetworkAgent(this, linkProperties, type, typeName);
}
public static class InstrumentedNetworkAgent extends NetworkAgent {
private final NetworkAgentWrapper mWrapper;
+ private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider";
- public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) {
- super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag,
- wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore,
- new NetworkAgentConfig(), NetworkProvider.ID_NONE);
+ public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
+ final int type, final String typeName) {
+ super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag,
+ wrapper.mNetworkCapabilities, lp, wrapper.mScore,
+ new NetworkAgentConfig.Builder()
+ .setLegacyType(type).setLegacyTypeName(typeName).build(),
+ new NetworkProvider(wrapper.mContext, wrapper.mHandlerThread.getLooper(),
+ PROVIDER_NAME));
mWrapper = wrapper;
+ register();
}
@Override
@@ -212,10 +218,12 @@
}
public void connect() {
- assertNotEquals("MockNetworkAgents can only be connected once",
- mNetworkInfo.getDetailedState(), NetworkInfo.DetailedState.CONNECTED);
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ if (!mConnected.compareAndSet(false /* expect */, true /* update */)) {
+ // compareAndSet returns false when the value couldn't be updated because it did not
+ // match the expected value.
+ fail("Test NetworkAgents can only be connected once");
+ }
+ mNetworkAgent.markConnected();
}
public void suspend() {
@@ -227,8 +235,7 @@
}
public void disconnect() {
- mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
- mNetworkAgent.sendNetworkInfo(mNetworkInfo);
+ mNetworkAgent.unregister();
}
@Override
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
similarity index 65%
rename from tests/net/java/android/net/TcpKeepalivePacketDataTest.java
rename to tests/net/java/android/net/KeepalivePacketDataUtilTest.java
index c5b25bd..fc739fb 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,11 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.net.util.KeepalivePacketDataUtil;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,7 +34,7 @@
import java.nio.ByteBuffer;
@RunWith(JUnit4.class)
-public final class TcpKeepalivePacketDataTest {
+public final class KeepalivePacketDataUtilTest {
private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
@@ -39,7 +42,7 @@
public void setUp() {}
@Test
- public void testV4TcpKeepalivePacket() throws Exception {
+ public void testFromTcpKeepaliveStableParcelable() throws Exception {
final int srcPort = 1234;
final int dstPort = 4321;
final int seq = 0x11111111;
@@ -61,7 +64,7 @@
testInfo.tos = tos;
testInfo.ttl = ttl;
try {
- resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
+ resultData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
} catch (InvalidPacketException e) {
fail("InvalidPacketException: " + e);
}
@@ -72,8 +75,8 @@
assertEquals(testInfo.dstPort, resultData.getDstPort());
assertEquals(testInfo.seq, resultData.tcpSeq);
assertEquals(testInfo.ack, resultData.tcpAck);
- assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
- assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
+ assertEquals(testInfo.rcvWnd, resultData.tcpWindow);
+ assertEquals(testInfo.rcvWndScale, resultData.tcpWindowScale);
assertEquals(testInfo.tos, resultData.ipTos);
assertEquals(testInfo.ttl, resultData.ipTtl);
@@ -113,7 +116,7 @@
//TODO: add ipv6 test when ipv6 supported
@Test
- public void testParcel() throws Exception {
+ public void testToTcpKeepaliveStableParcelable() throws Exception {
final int srcPort = 1234;
final int dstPort = 4321;
final int sequence = 0x11111111;
@@ -135,8 +138,8 @@
testInfo.ttl = ttl;
TcpKeepalivePacketData testData = null;
TcpKeepalivePacketDataParcelable resultData = null;
- testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
- resultData = testData.toStableParcelable();
+ testData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
+ resultData = KeepalivePacketDataUtil.toStableParcelable(testData);
assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR);
assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR);
assertEquals(resultData.srcPort, srcPort);
@@ -154,4 +157,49 @@
+ " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}";
assertEquals(expected, resultData.toString());
}
+
+ @Test
+ public void testParseTcpKeepalivePacketData() throws Exception {
+ final int srcPort = 1234;
+ final int dstPort = 4321;
+ final int sequence = 0x11111111;
+ final int ack = 0x22222222;
+ final int wnd = 4800;
+ final int wndScale = 2;
+ final int tos = 4;
+ final int ttl = 64;
+ final TcpKeepalivePacketDataParcelable testParcel = new TcpKeepalivePacketDataParcelable();
+ testParcel.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+ testParcel.srcPort = srcPort;
+ testParcel.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+ testParcel.dstPort = dstPort;
+ testParcel.seq = sequence;
+ testParcel.ack = ack;
+ testParcel.rcvWnd = wnd;
+ testParcel.rcvWndScale = wndScale;
+ testParcel.tos = tos;
+ testParcel.ttl = ttl;
+
+ final KeepalivePacketData testData =
+ KeepalivePacketDataUtil.fromStableParcelable(testParcel);
+ final TcpKeepalivePacketDataParcelable parsedParcelable =
+ KeepalivePacketDataUtil.parseTcpKeepalivePacketData(testData);
+ final TcpKeepalivePacketData roundTripData =
+ KeepalivePacketDataUtil.fromStableParcelable(parsedParcelable);
+
+ // Generated packet is the same, but rcvWnd / wndScale will differ if scale is non-zero
+ assertTrue(testData.getPacket().length > 0);
+ assertArrayEquals(testData.getPacket(), roundTripData.getPacket());
+
+ testParcel.rcvWndScale = 0;
+ final KeepalivePacketData noScaleTestData =
+ KeepalivePacketDataUtil.fromStableParcelable(testParcel);
+ final TcpKeepalivePacketDataParcelable noScaleParsedParcelable =
+ KeepalivePacketDataUtil.parseTcpKeepalivePacketData(noScaleTestData);
+ final TcpKeepalivePacketData noScaleRoundTripData =
+ KeepalivePacketDataUtil.fromStableParcelable(noScaleParsedParcelable);
+ assertEquals(noScaleTestData, noScaleRoundTripData);
+ assertTrue(noScaleTestData.getPacket().length > 0);
+ assertArrayEquals(noScaleTestData.getPacket(), noScaleRoundTripData.getPacket());
+ }
}
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 91c9a2a..6de31f6 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -22,11 +22,11 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.net.util.MacAddressUtils;
-
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.MacAddressUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 3158cc8..7748288 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -16,24 +16,10 @@
package android.net;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.AF_UNIX;
-import static android.system.OsConstants.EPERM;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_STREAM;
-
import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.system.ErrnoException;
-import android.system.Os;
-
import androidx.test.runner.AndroidJUnit4;
-import libcore.io.IoUtils;
-
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -139,50 +125,4 @@
assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
NetworkUtils.routedIPv6AddressCount(set));
}
-
- private static void expectSocketSuccess(String msg, int domain, int type) {
- try {
- IoUtils.closeQuietly(Os.socket(domain, type, 0));
- } catch (ErrnoException e) {
- fail(msg + e.getMessage());
- }
- }
-
- private static void expectSocketPemissionError(String msg, int domain, int type) {
- try {
- IoUtils.closeQuietly(Os.socket(domain, type, 0));
- fail(msg);
- } catch (ErrnoException e) {
- assertEquals(msg, e.errno, EPERM);
- }
- }
-
- private static void expectHasNetworking() {
- expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
- AF_UNIX, SOCK_STREAM);
- expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
- AF_INET, SOCK_DGRAM);
- expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
- AF_INET6, SOCK_DGRAM);
- }
-
- private static void expectNoNetworking() {
- expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
- AF_UNIX, SOCK_STREAM);
- expectSocketPemissionError(
- "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
- AF_INET, SOCK_DGRAM);
- expectSocketPemissionError(
- "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
- AF_INET6, SOCK_DGRAM);
- }
-
- @Test
- public void testSetAllowNetworkingForProcess() {
- expectHasNetworking();
- NetworkUtils.setAllowNetworkingForProcess(false);
- expectNoNetworking();
- NetworkUtils.setAllowNetworkingForProcess(true);
- expectHasNetworking();
- }
}
diff --git a/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java b/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
new file mode 100644
index 0000000..3cfecd5
--- /dev/null
+++ b/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.EPERM;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.fail;
+
+import android.system.ErrnoException;
+import android.system.Os;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import libcore.io.IoUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@androidx.test.filters.SmallTest
+public class NetworkUtilsInternalTest {
+
+ private static void expectSocketSuccess(String msg, int domain, int type) {
+ try {
+ IoUtils.closeQuietly(Os.socket(domain, type, 0));
+ } catch (ErrnoException e) {
+ fail(msg + e.getMessage());
+ }
+ }
+
+ private static void expectSocketPemissionError(String msg, int domain, int type) {
+ try {
+ IoUtils.closeQuietly(Os.socket(domain, type, 0));
+ fail(msg);
+ } catch (ErrnoException e) {
+ assertEquals(msg, e.errno, EPERM);
+ }
+ }
+
+ private static void expectHasNetworking() {
+ expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+ AF_UNIX, SOCK_STREAM);
+ expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
+ AF_INET, SOCK_DGRAM);
+ expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
+ AF_INET6, SOCK_DGRAM);
+ }
+
+ private static void expectNoNetworking() {
+ expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+ AF_UNIX, SOCK_STREAM);
+ expectSocketPemissionError(
+ "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
+ AF_INET, SOCK_DGRAM);
+ expectSocketPemissionError(
+ "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
+ AF_INET6, SOCK_DGRAM);
+ }
+
+ @Test
+ public void testSetAllowNetworkingForProcess() {
+ expectHasNetworking();
+ NetworkUtilsInternal.setAllowNetworkingForProcess(false);
+ expectNoNetworking();
+ NetworkUtilsInternal.setAllowNetworkingForProcess(true);
+ expectHasNetworking();
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 7a1cb25..a68044a 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Intent.ACTION_USER_ADDED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
@@ -38,6 +39,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
@@ -100,6 +102,8 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
@@ -131,6 +135,7 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -139,6 +144,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.location.LocationManager;
@@ -175,19 +182,20 @@
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStackClient;
import android.net.NetworkState;
import android.net.NetworkTestResultParcelable;
-import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.ResolverParamsParcel;
import android.net.RouteInfo;
import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.UidRange;
+import android.net.UidRangeParcel;
import android.net.Uri;
import android.net.VpnManager;
import android.net.metrics.IpConnectivityLog;
@@ -331,12 +339,13 @@
private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
private static final String VPN_IFNAME = "tun10042";
private static final String TEST_PACKAGE_NAME = "com.android.test.package";
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
private static final String INTERFACE_NAME = "interface";
private MockContext mServiceContext;
private HandlerThread mCsHandlerThread;
+ private ConnectivityService.Dependencies mDeps;
private ConnectivityService mService;
private WrappedConnectivityManager mCm;
private TestNetworkAgentWrapper mWiFiNetworkAgent;
@@ -352,6 +361,7 @@
@Mock IIpConnectivityMetrics mIpConnectivityMetrics;
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+ @Mock DeviceIdleInternal mDeviceIdleInternal;
@Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
@Mock IBatteryStats mBatteryStatsService;
@@ -449,6 +459,15 @@
}
@Override
+ public ComponentName startService(Intent service) {
+ final String action = service.getAction();
+ if (!VpnConfig.SERVICE_INTERFACE.equals(action)) {
+ fail("Attempt to start unknown service, action=" + action);
+ }
+ return new ComponentName(service.getPackage(), "com.android.test.Service");
+ }
+
+ @Override
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
@@ -646,8 +665,8 @@
}
@Override
- protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties)
- throws Exception {
+ protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
+ final int type, final String typeName) throws Exception {
mNetworkMonitor = mock(INetworkMonitor.class);
final Answer validateAnswer = inv -> {
@@ -666,7 +685,8 @@
any() /* name */,
nmCbCaptor.capture());
- final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) {
+ final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties,
+ type, typeName) {
@Override
public void networkStatus(int status, String redirectUrl) {
mRedirectUrl = redirectUrl;
@@ -1053,9 +1073,19 @@
private VpnInfo mVpnInfo;
public MockVpn(int userId) {
- super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
- userId, mock(KeyStore.class));
- mConfig = new VpnConfig();
+ super(startHandlerThreadAndReturnLooper(), mServiceContext,
+ new Dependencies() {
+ @Override
+ public boolean isCallerSystem() {
+ return true;
+ }
+
+ @Override
+ public DeviceIdleInternal getDeviceIdleInternal() {
+ return mDeviceIdleInternal;
+ }
+ },
+ mNetworkManagementService, mMockNetd, userId, mock(KeyStore.class));
}
public void setUids(Set<UidRange> uids) {
@@ -1084,26 +1114,35 @@
return mVpnType;
}
+ private LinkProperties makeLinkProperties() {
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(VPN_IFNAME);
+ return lp;
+ }
+
private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
throws Exception {
if (mAgentRegistered) throw new IllegalStateException("already registered");
+ mConfig = new VpnConfig();
setUids(uids);
if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME;
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
- verify(mNetworkManagementService, times(1))
- .addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0])));
- verify(mNetworkManagementService, never())
- .removeVpnUidRanges(eq(mMockVpn.getNetId()), any());
+
+ verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetId()),
+ eq(toUidRangeStableParcels(uids)));
+ verify(mMockNetd, never())
+ .networkRemoveUidRanges(eq(mMockVpn.getNetId()), any());
mAgentRegistered = true;
+ updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
}
private void registerAgent(Set<UidRange> uids) throws Exception {
- registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties());
+ registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
}
private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
@@ -1139,12 +1178,12 @@
public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
throws Exception {
final int uid = Process.myUid();
- establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
+ establish(makeLinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
isStrictMode);
}
public void establishForMyUid() throws Exception {
- establishForMyUid(new LinkProperties());
+ establishForMyUid(makeLinkProperties());
}
public void sendLinkProperties(LinkProperties lp) {
@@ -1152,7 +1191,10 @@
}
public void disconnect() {
- if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect();
+ if (mMockNetworkAgent != null) {
+ mMockNetworkAgent.disconnect();
+ updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect");
+ }
mAgentRegistered = false;
}
@@ -1168,6 +1210,11 @@
}
}
+ private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
+ return ranges.stream().map(
+ r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
+ }
+
private void mockVpn(int uid) {
synchronized (mService.mVpns) {
int userId = UserHandle.getUserId(uid);
@@ -1221,6 +1268,17 @@
fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
}
+ private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
+ int uid) {
+ when(mDeps.getCallingUid()).thenReturn(uid);
+ try {
+ mCm.registerNetworkCallback(request, callback);
+ waitForIdle();
+ } finally {
+ returnRealCallingUid();
+ }
+ }
+
private static final int VPN_USER = 0;
private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
@@ -1263,7 +1321,8 @@
initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
mCsHandlerThread = new HandlerThread("TestConnectivityService");
- final ConnectivityService.Dependencies deps = makeDependencies();
+ mDeps = makeDependencies();
+ returnRealCallingUid();
mService = new ConnectivityService(mServiceContext,
mNetworkManagementService,
mStatsService,
@@ -1271,9 +1330,9 @@
mMockDnsResolver,
mock(IpConnectivityLog.class),
mMockNetd,
- deps);
+ mDeps);
mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
- verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
+ verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any());
final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
ArgumentCaptor.forClass(INetworkPolicyListener.class);
@@ -1293,6 +1352,10 @@
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
+ private void returnRealCallingUid() {
+ doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid();
+ }
+
private ConnectivityService.Dependencies makeDependencies() {
doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties)
.getInt("net.tcp.default_init_rwnd", 0);
@@ -1368,13 +1431,13 @@
}
private void mockDefaultPackages() throws Exception {
- final String testPackageName = mContext.getPackageName();
- final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
- testPackageName, PackageManager.GET_PERMISSIONS);
+ final String myPackageName = mContext.getPackageName();
+ final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
+ myPackageName, PackageManager.GET_PERMISSIONS);
when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
- new String[] {testPackageName});
- when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
- eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+ new String[] {myPackageName});
+ when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(),
+ eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo);
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
Arrays.asList(new PackageInfo[] {
@@ -1382,6 +1445,25 @@
buildPackageInfo(/* SYSTEM */ false, APP2_UID),
buildPackageInfo(/* SYSTEM */ false, VPN_UID)
}));
+
+ // Create a fake always-on VPN package.
+ final int userId = UserHandle.getCallingUserId();
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; // Always-on supported in N+.
+ when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(),
+ eq(userId))).thenReturn(applicationInfo);
+
+ // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
+ ResolveInfo rInfo = new ResolveInfo();
+ rInfo.serviceInfo = new ServiceInfo();
+ rInfo.serviceInfo.metaData = new Bundle();
+ final List<ResolveInfo> services = Arrays.asList(new ResolveInfo[]{rInfo});
+ when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA),
+ eq(userId))).thenReturn(services);
+ when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId))
+ .thenReturn(Process.myUid());
+ when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId))
+ .thenReturn(VPN_UID);
}
private void verifyActiveNetwork(int transport) {
@@ -1958,6 +2040,37 @@
}
@Test
+ public void testOwnerUidCannotChange() throws Exception {
+ // Owner UIDs are not visible without location permission.
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
+
+ final NetworkCapabilities ncTemplate = new NetworkCapabilities();
+ final int originalOwnerUid = Process.myUid();
+ ncTemplate.setOwnerUid(originalOwnerUid);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(),
+ ncTemplate);
+ mWiFiNetworkAgent.connect(false);
+ waitForIdle();
+
+ // Send ConnectivityService an update to the mWiFiNetworkAgent's capabilities that changes
+ // the owner UID and an unrelated capability.
+ NetworkCapabilities agentCapabilities = mWiFiNetworkAgent.getNetworkCapabilities();
+ assertEquals(originalOwnerUid, agentCapabilities.getOwnerUid());
+ agentCapabilities.setOwnerUid(42);
+ assertFalse(agentCapabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+ agentCapabilities.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+ mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
+ waitForIdle();
+
+ // Check that the capability change has been applied but the owner UID is not modified.
+ NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
+ assertEquals(originalOwnerUid, nc.getOwnerUid());
+ assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
+ }
+
+ @Test
public void testMultipleLingering() throws Exception {
// This test would be flaky with the default 120ms timer: that is short enough that
// lingered networks are torn down before assertions can be run. We don't want to mock the
@@ -2213,10 +2326,10 @@
}
private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
- final String testPackageName = mContext.getPackageName();
- when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
+ final String myPackageName = mContext.getPackageName();
+ when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS)))
.thenReturn(buildPackageInfo(true, uid));
- mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
+ mService.mPermissionMonitor.onPackageAdded(myPackageName, uid);
}
@Test
@@ -2517,7 +2630,8 @@
@Test
public void testNoMutableNetworkRequests() throws Exception {
- PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE);
NetworkRequest request1 = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_VALIDATED)
.build();
@@ -3179,7 +3293,7 @@
assertThrows(SecurityException.class, () ->
mCm.registerNetworkCallback(r, PendingIntent.getService(
- mServiceContext, 0, new Intent(), 0)));
+ mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
// Requesting a Network with signal strength should get IllegalArgumentException.
assertThrows(IllegalArgumentException.class, () ->
@@ -3187,7 +3301,7 @@
assertThrows(IllegalArgumentException.class, () ->
mCm.requestNetwork(r, PendingIntent.getService(
- mServiceContext, 0, new Intent(), 0)));
+ mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE)));
}
@Test
@@ -4651,12 +4765,14 @@
}
j = 0;
while (j++ < INTENTS / 2) {
- PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), 0);
+ final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("a" + j), FLAG_IMMUTABLE);
mCm.requestNetwork(networkRequest, pi);
registered.add(pi);
}
while (j++ < INTENTS) {
- PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), 0);
+ final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("b" + j), FLAG_IMMUTABLE);
mCm.registerNetworkCallback(networkRequest, pi);
registered.add(pi);
}
@@ -4670,11 +4786,13 @@
);
assertThrows(TooManyRequestsException.class, () ->
mCm.requestNetwork(networkRequest,
- PendingIntent.getBroadcast(mContext, 0, new Intent("c"), 0))
+ PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("c"), FLAG_IMMUTABLE))
);
assertThrows(TooManyRequestsException.class, () ->
mCm.registerNetworkCallback(networkRequest,
- PendingIntent.getBroadcast(mContext, 0, new Intent("d"), 0))
+ PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("d"), FLAG_IMMUTABLE))
);
for (Object o : registered) {
@@ -4703,16 +4821,16 @@
waitForIdle();
for (int i = 0; i < MAX_REQUESTS; i++) {
- PendingIntent pendingIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), 0);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE);
mCm.requestNetwork(networkRequest, pendingIntent);
mCm.unregisterNetworkCallback(pendingIntent);
}
waitForIdle();
for (int i = 0; i < MAX_REQUESTS; i++) {
- PendingIntent pendingIntent =
- PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), 0);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE);
mCm.registerNetworkCallback(networkRequest, pendingIntent);
mCm.unregisterNetworkCallback(pendingIntent);
}
@@ -4790,7 +4908,7 @@
lp.setInterfaceName(WIFI_IFNAME);
LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
- NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
+ InetAddresses.parseNumericAddress("192.168.12.1"), lp.getInterfaceName());
lp.addLinkAddress(myIpv4Address);
lp.addRoute(myIpv4DefaultRoute);
@@ -4910,8 +5028,8 @@
expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
reset(mStatsService);
- // Captive portal change shouldn't update ifaces
- mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+ // Temp metered change shouldn't update ifaces
+ mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED);
waitForIdle();
verify(mStatsService, never())
.forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
@@ -5427,6 +5545,7 @@
final Network wifi = mWiFiNetworkAgent.getNetwork();
final NetworkCapabilities initialCaps = new NetworkCapabilities();
+ initialCaps.addTransportType(TRANSPORT_VPN);
initialCaps.addCapability(NET_CAPABILITY_INTERNET);
initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
@@ -5458,44 +5577,45 @@
withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
+ final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
+ initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
+
NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
- final boolean notDeclaredMetered = false;
- mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
assertEquals(withNoUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
assertEquals(withNoUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
assertEquals(withMobileUnderlying, caps);
- mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
assertEquals(withWifiUnderlying, caps);
- final boolean isDeclaredMetered = true;
withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
assertEquals(withWifiUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
assertEquals(withWifiAndMobileUnderlying, caps);
withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
caps = new NetworkCapabilities(initialCaps);
mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
- caps, notDeclaredMetered);
+ initialCapsNotMetered, caps);
assertEquals(withWifiAndMobileUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
- caps, notDeclaredMetered);
+ initialCapsNotMetered, caps);
assertEquals(withWifiAndMobileUnderlying, caps);
- mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
assertEquals(withWifiUnderlying, caps);
}
@@ -5785,10 +5905,21 @@
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
}
+ private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
+ final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
+ userId, "com.android.calling.package");
+ final String defaultCapsString = Arrays.toString(defaultCaps);
+ assertEquals(defaultCapsString, defaultCaps.length, networks.length);
+ final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
+ for (NetworkAgentWrapper network : networks) {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
+ final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
+ assertTrue(msg, defaultCapsSet.contains(nc));
+ }
+ }
+
@Test
public void testVpnSetUnderlyingNetworks() throws Exception {
- final int uid = Process.myUid();
-
final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_NOT_VPN)
@@ -5811,6 +5942,9 @@
// A VPN without underlying networks is not suspended.
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ final int userId = UserHandle.getUserId(Process.myUid());
+ assertDefaultNetworkCapabilities(userId /* no networks */);
+
// Connect cell and use it as an underlying network.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5824,6 +5958,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
@@ -5838,6 +5973,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Don't disconnect, but note the VPN is not using wifi any more.
mService.setUnderlyingNetworksForVpn(
@@ -5848,6 +5984,9 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
+ // network (wifi) as well as the underlying networks (cell).
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5876,6 +6015,7 @@
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
// Use both again.
mService.setUnderlyingNetworksForVpn(
@@ -5886,6 +6026,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Cell is suspended again. As WiFi is not, this should not cause a callback.
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5903,6 +6044,7 @@
// a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never
// been public and are deprecated and slated for removal, there is no sense in spending
// resources fixing this bug now.
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Use both again.
mService.setUnderlyingNetworksForVpn(
@@ -5915,6 +6057,7 @@
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
// As above, the RESUMED callback not being sent here is a bug, but not a bug that's
// worth anybody's time to fix.
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks – it's dead anyway. Not metered any more.
@@ -5923,6 +6066,7 @@
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
// Disconnect wifi too. No underlying networks means this is now metered.
mWiFiNetworkAgent.disconnect();
@@ -5930,6 +6074,11 @@
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ // When a network disconnects, the callbacks are fired before all state is updated, so for a
+ // short time, synchronous calls will behave as if the network is still connected. Wait for
+ // things to settle.
+ waitForIdle();
+ assertDefaultNetworkCapabilities(userId /* no networks */);
mMockVpn.disconnect();
}
@@ -6230,6 +6379,7 @@
// Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
assertTrue(mCm.isActiveNetworkMetered());
+
// VPN explicitly declares WiFi as its underlying network.
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork() });
@@ -6343,6 +6493,189 @@
mCm.unregisterNetworkCallback(defaultCallback);
}
+ private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
+ UidRangeParcel... expected) throws Exception {
+ inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
+ }
+
+ private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
+ assertNotNull(ni);
+ assertEquals(type, ni.getType());
+ assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
+ }
+
+ private void assertActiveNetworkInfo(int type, DetailedState state) {
+ checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
+ }
+ private void assertNetworkInfo(int type, DetailedState state) {
+ checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
+ }
+
+ @Test
+ public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
+ mServiceContext.setPermission(
+ Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
+ mServiceContext.setPermission(
+ Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
+ mServiceContext.setPermission(
+ Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .build();
+ mCm.registerNetworkCallback(request, callback);
+
+ final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+
+ final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
+ final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
+ registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
+
+ final int uid = Process.myUid();
+ final int userId = UserHandle.getUserId(uid);
+ final ArrayList<String> allowList = new ArrayList<>();
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+
+ UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
+ UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999);
+ InOrder inOrder = inOrder(mMockNetd);
+ expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+
+ // Connect a network when lockdown is active, expect to see it blocked.
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false /* validated */);
+ callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertNull(mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ // Mobile is BLOCKED even though it's not actually connected.
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+ // Disable lockdown, expect to see the network unblocked.
+ // There are no callbacks because they are not implemented yet.
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
+ allowList.add(TEST_PACKAGE_NAME);
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+ callback.assertNoCallback();
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.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
+ // 200 packages installed.
+ final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1);
+ final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1);
+ final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999);
+ expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Connect a new network, expect it to be unblocked.
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(false /* validated */);
+ callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
+ // Everything should now be blocked.
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
+ allowList.clear();
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+ expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertNull(mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+ // Disable lockdown. Everything is unblocked.
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Enable and disable an always-on VPN package without lockdown. Expect no changes.
+ reset(mMockNetd);
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList);
+ inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
+ callback.assertNoCallback();
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
+ callback.assertNoCallback();
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Enable lockdown and connect a VPN. The VPN is not blocked.
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertNull(mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+ mMockVpn.establishForMyUid();
+ defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+ vpnUidCallback.assertNoCallback(); // vpnUidCallback has NOT_VPN capability.
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(null, mCm.getActiveNetworkForUid(VPN_UID)); // BUG?
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ mMockVpn.disconnect();
+ defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
+ defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ assertNull(mCm.getActiveNetwork());
+
+ mCm.unregisterNetworkCallback(callback);
+ mCm.unregisterNetworkCallback(defaultCallback);
+ mCm.unregisterNetworkCallback(vpnUidCallback);
+ }
+
@Test
public final void testLoseTrusted() throws Exception {
final NetworkRequest trustedRequest = new NetworkRequest.Builder()
@@ -7776,7 +8109,16 @@
@Test
public void testDumpDoesNotCrash() {
- StringWriter stringWriter = new StringWriter();
+ // Filing a couple requests prior to testing the dump.
+ final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+ final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest genericRequest = new NetworkRequest.Builder()
+ .clearCapabilities().build();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+ mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+ final StringWriter stringWriter = new StringWriter();
mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
@@ -7798,11 +8140,11 @@
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
- ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
+ final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
assertTrue(nriOutput.length > 1);
for (int i = 0; i < nriOutput.length - 1; i++) {
- boolean isRequestIdInOrder =
+ final boolean isRequestIdInOrder =
nriOutput[i].mRequests.get(0).requestId
< nriOutput[i + 1].mRequests.get(0).requestId;
assertTrue(isRequestIdInOrder);
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 529d03c..799bcc8 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -34,6 +34,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.INetd;
+import android.net.InetAddresses;
import android.net.IpSecAlgorithm;
import android.net.IpSecConfig;
import android.net.IpSecManager;
@@ -44,7 +45,6 @@
import android.net.IpSecUdpEncapResponse;
import android.net.LinkAddress;
import android.net.Network;
-import android.net.NetworkUtils;
import android.os.Binder;
import android.os.INetworkManagementService;
import android.os.ParcelFileDescriptor;
@@ -272,7 +272,7 @@
IpSecSpiResponse spi =
mIpSecService.allocateSecurityParameterIndex(
- NetworkUtils.numericToInetAddress(remoteAddress).getHostAddress(),
+ InetAddresses.parseNumericAddress(remoteAddress).getHostAddress(),
IpSecManager.INVALID_SECURITY_PARAMETER_INDEX,
new Binder());
return spi.resourceId;
diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
index c53462c..950d716 100644
--- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
+++ b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
@@ -130,6 +130,7 @@
when(mContext.getResources()).thenReturn(mResources);
when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ // Mock user id to all users that Context#registerReceiver will register with all users too.
doReturn(UserHandle.ALL.getIdentifier()).when(mUserAllContext).getUserId();
when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt()))
.thenReturn(mUserAllContext);
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index de35f91..3556c72 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -58,7 +58,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
-import android.content.pm.UserInfo;
import android.net.INetd;
import android.net.UidRange;
import android.os.Build;
@@ -123,10 +122,10 @@
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
- when(mUserManager.getAliveUsers()).thenReturn(
- Arrays.asList(new UserInfo[] {
- new UserInfo(MOCK_USER1, "", 0),
- new UserInfo(MOCK_USER2, "", 0),
+ when(mUserManager.getUserHandles(eq(true))).thenReturn(
+ Arrays.asList(new UserHandle[] {
+ new UserHandle(MOCK_USER1),
+ new UserHandle(MOCK_USER2),
}));
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 337507a..cc47317 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -58,6 +58,7 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.net.INetd;
import android.net.Ikev2VpnProfile;
import android.net.InetAddresses;
import android.net.IpPrefix;
@@ -70,6 +71,7 @@
import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo;
import android.net.UidRange;
+import android.net.UidRangeParcel;
import android.net.VpnManager;
import android.net.VpnService;
import android.net.ipsec.ike.IkeSessionCallback;
@@ -172,11 +174,13 @@
mPackages.put(PKGS[i], PKG_UIDS[i]);
}
}
+ private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id);
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@Mock private PackageManager mPackageManager;
@Mock private INetworkManagementService mNetService;
+ @Mock private INetd mNetd;
@Mock private AppOpsManager mAppOps;
@Mock private NotificationManager mNotificationManager;
@Mock private Vpn.SystemServices mSystemServices;
@@ -224,7 +228,6 @@
R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
.thenReturn(true);
- when(mSystemServices.isCallerSystem()).thenReturn(true);
// Used by {@link Notification.Builder}
ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -256,8 +259,7 @@
null, null);
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- UidRange.createForUser(primaryUser.id),
- UidRange.createForUser(restrictedProfileA.id)
+ PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id)
})), ranges);
}
@@ -269,9 +271,7 @@
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- UidRange.createForUser(primaryUser.id)
- })), ranges);
+ assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
}
@Test
@@ -282,15 +282,13 @@
final Set<UidRange> ranges = new ArraySet<>();
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- UidRange.createForUser(primaryUser.id)
- })), ranges);
+ assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
}
@Test
public void testUidAllowAndDenylist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = UidRange.createForUser(primaryUser.id);
+ final UidRange user = PRI_USER_RANGE;
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
// Allowed list
@@ -339,62 +337,67 @@
@Test
public void testLockdownChangingPackage() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = UidRange.createForUser(primaryUser.id);
+ final UidRange user = PRI_USER_RANGE;
// Default state.
- assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+ assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
+ user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
// Set always-on without lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore));
- assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+ assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
+ user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
// Set always-on with lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
}));
- assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
+
+ assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2],
+ user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[1]);
// Switch to another app.
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
}));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
- new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
}));
- assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
+ assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
+ user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[3]);
}
@Test
public void testLockdownAllowlist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = UidRange.createForUser(primaryUser.id);
+ final UidRange user = PRI_USER_RANGE;
// Set always-on with lockdown and allow app PKGS[2] from lockdown.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
}));
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
-
// Change allowed app list to PKGS[3].
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
}));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
- new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
}));
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
@@ -402,25 +405,25 @@
// Change the VPN app.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
}));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[0] - 1),
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
}));
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
// Remove the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
- new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
}));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[0] + 1, user.stop),
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop),
}));
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2],
user.start + PKG_UIDS[3]);
@@ -429,12 +432,12 @@
// Add the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[0] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop)
}));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
}));
assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
@@ -447,13 +450,13 @@
// allowed package should change from PGKS[1] to PKGS[2].
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[]{
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
}));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
- new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[]{
+ new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
}));
}
@@ -467,86 +470,86 @@
restrictedProfileA.flags);
tempProfile.restrictedProfileParentId = primaryUser.id;
- final UidRange user = UidRange.createForUser(primaryUser.id);
+ final UidRange user = PRI_USER_RANGE;
final UidRange profile = UidRange.createForUser(tempProfile.id);
// Set lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
- new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
+ new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
}));
-
// Verify restricted user isn't affected at first.
assertUnblocked(vpn, profile.start + PKG_UIDS[0]);
// Add the restricted user.
setMockedUsers(primaryUser, tempProfile);
vpn.onUserAdded(tempProfile.id);
- verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
- new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1),
- new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
+ new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
}));
// Remove the restricted user.
tempProfile.partial = true;
vpn.onUserRemoved(tempProfile.id);
- verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
- new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1),
- new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop)
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
+ new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
+ new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
}));
}
@Test
public void testLockdownRuleRepeatability() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
-
+ final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
+ new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
// Given legacy lockdown is already enabled,
vpn.setLockdown(true);
- verify(mNetService, times(1)).setAllowOnlyVpnForUids(
- eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
+
+ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(primaryUserRangeParcel));
// Enabling legacy lockdown twice should do nothing.
vpn.setLockdown(true);
- verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
+ verify(mNetd, times(1))
+ .networkRejectNonSecureVpn(anyBoolean(), any(UidRangeParcel[].class));
// And disabling should remove the rules exactly once.
vpn.setLockdown(false);
- verify(mNetService, times(1)).setAllowOnlyVpnForUids(
- eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
+ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(primaryUserRangeParcel));
// Removing the lockdown again should have no effect.
vpn.setLockdown(false);
- verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class));
+ verify(mNetd, times(2)).networkRejectNonSecureVpn(
+ anyBoolean(), any(UidRangeParcel[].class));
}
@Test
public void testLockdownRuleReversibility() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
-
- final UidRange[] entireUser = {
- UidRange.createForUser(primaryUser.id)
+ final UidRangeParcel[] entireUser = {
+ new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
};
- final UidRange[] exceptPkg0 = {
- new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
- new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
+ final UidRangeParcel[] exceptPkg0 = {
+ new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
+ new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
};
- final InOrder order = inOrder(mNetService);
+ final InOrder order = inOrder(mNetd);
// Given lockdown is enabled with no package (legacy VPN),
vpn.setLockdown(true);
- order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
+ order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
// When a new VPN package is set the rules should change to cover that package.
vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE);
- order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser));
- order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0));
+ order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(entireUser));
+ order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(exceptPkg0));
// When that VPN package is unset, everything should be undone again in reverse.
vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE);
- order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0));
- order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser));
+ order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(exceptPkg0));
+ order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
}
@Test
@@ -1098,6 +1101,11 @@
}
@Override
+ public boolean isCallerSystem() {
+ return true;
+ }
+
+ @Override
public void startService(final String serviceName) {
mRunningServices.put(serviceName, true);
}
@@ -1186,7 +1194,7 @@
.thenReturn(asUserContext);
final TestLooper testLooper = new TestLooper();
final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
- userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
+ mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat(
provider -> provider.getName().contains("VpnNetworkProvider")
));
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index fb0cfc0..89146f9 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -23,11 +23,11 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.NetworkUtils.multiplySafeByRational;
import static android.os.Process.myUid;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
import static com.android.testutils.MiscAsserts.assertThrows;
import static org.junit.Assert.assertArrayEquals;