Merge "Remove redundant connected notification"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index cb31404..d8a97de 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -53,7 +53,6 @@
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
-import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -808,7 +807,7 @@
private INetworkManagementService mNMService;
private INetworkPolicyManager mNPManager;
- private TetheringManager mTetheringManager;
+ private final TetheringManager mTetheringManager;
/**
* Tests if a given integer represents a valid network type.
@@ -1279,7 +1278,8 @@
@UnsupportedAppUsage
public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
try {
- return mService.getDefaultNetworkCapabilitiesForUser(userId);
+ return mService.getDefaultNetworkCapabilitiesForUser(
+ userId, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1361,7 +1361,7 @@
@Nullable
public NetworkCapabilities getNetworkCapabilities(@Nullable Network network) {
try {
- return mService.getNetworkCapabilities(network);
+ return mService.getNetworkCapabilities(network, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2274,6 +2274,7 @@
public ConnectivityManager(Context context, IConnectivityManager service) {
mContext = Preconditions.checkNotNull(context, "missing context");
mService = Preconditions.checkNotNull(service, "missing IConnectivityManager");
+ mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE);
sInstance = this;
}
@@ -2347,28 +2348,6 @@
return getInstanceOrNull();
}
- private static final int TETHERING_TIMEOUT_MS = 60_000;
- private final Object mTetheringLock = new Object();
-
- private TetheringManager getTetheringManager() {
- synchronized (mTetheringLock) {
- if (mTetheringManager != null) {
- return mTetheringManager;
- }
- final long before = System.currentTimeMillis();
- while ((mTetheringManager = (TetheringManager) mContext.getSystemService(
- Context.TETHERING_SERVICE)) == null) {
- if (System.currentTimeMillis() - before > TETHERING_TIMEOUT_MS) {
- Log.e(TAG, "Timeout waiting tethering service not ready yet");
- throw new IllegalStateException("No tethering service yet");
- }
- SystemClock.sleep(100);
- }
-
- return mTetheringManager;
- }
- }
-
/**
* Get the set of tetherable, available interfaces. This list is limited by
* device configuration and current interface existence.
@@ -2382,7 +2361,7 @@
@UnsupportedAppUsage
@Deprecated
public String[] getTetherableIfaces() {
- return getTetheringManager().getTetherableIfaces();
+ return mTetheringManager.getTetherableIfaces();
}
/**
@@ -2397,7 +2376,7 @@
@UnsupportedAppUsage
@Deprecated
public String[] getTetheredIfaces() {
- return getTetheringManager().getTetheredIfaces();
+ return mTetheringManager.getTetheredIfaces();
}
/**
@@ -2418,20 +2397,20 @@
@UnsupportedAppUsage
@Deprecated
public String[] getTetheringErroredIfaces() {
- return getTetheringManager().getTetheringErroredIfaces();
+ return mTetheringManager.getTetheringErroredIfaces();
}
/**
* Get the set of tethered dhcp ranges.
*
- * @return an array of 0 or more {@code String} of tethered dhcp ranges.
- * @deprecated This API just return the default value which is not used in DhcpServer.
+ * @deprecated This method is not supported.
+ * TODO: remove this function when all of clients are removed.
* {@hide}
*/
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
@Deprecated
public String[] getTetheredDhcpRanges() {
- return getTetheringManager().getTetheredDhcpRanges();
+ throw new UnsupportedOperationException("getTetheredDhcpRanges is not supported");
}
/**
@@ -2462,7 +2441,7 @@
@UnsupportedAppUsage
@Deprecated
public int tether(String iface) {
- return getTetheringManager().tether(iface);
+ return mTetheringManager.tether(iface);
}
/**
@@ -2486,7 +2465,7 @@
@UnsupportedAppUsage
@Deprecated
public int untether(String iface) {
- return getTetheringManager().untether(iface);
+ return mTetheringManager.untether(iface);
}
/**
@@ -2512,7 +2491,7 @@
@RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS})
public boolean isTetheringSupported() {
- return getTetheringManager().isTetheringSupported();
+ return mTetheringManager.isTetheringSupported();
}
/**
@@ -2605,7 +2584,7 @@
final TetheringRequest request = new TetheringRequest.Builder(type)
.setSilentProvisioning(!showProvisioningUi).build();
- getTetheringManager().startTethering(request, executor, tetheringCallback);
+ mTetheringManager.startTethering(request, executor, tetheringCallback);
}
/**
@@ -2624,7 +2603,7 @@
@Deprecated
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void stopTethering(int type) {
- getTetheringManager().stopTethering(type);
+ mTetheringManager.stopTethering(type);
}
/**
@@ -2682,7 +2661,7 @@
synchronized (mTetheringEventCallbacks) {
mTetheringEventCallbacks.put(callback, tetherCallback);
- getTetheringManager().registerTetheringEventCallback(executor, tetherCallback);
+ mTetheringManager.registerTetheringEventCallback(executor, tetherCallback);
}
}
@@ -2704,7 +2683,7 @@
synchronized (mTetheringEventCallbacks) {
final TetheringEventCallback tetherCallback =
mTetheringEventCallbacks.remove(callback);
- getTetheringManager().unregisterTetheringEventCallback(tetherCallback);
+ mTetheringManager.unregisterTetheringEventCallback(tetherCallback);
}
}
@@ -2724,7 +2703,7 @@
@UnsupportedAppUsage
@Deprecated
public String[] getTetherableUsbRegexs() {
- return getTetheringManager().getTetherableUsbRegexs();
+ return mTetheringManager.getTetherableUsbRegexs();
}
/**
@@ -2742,7 +2721,7 @@
@UnsupportedAppUsage
@Deprecated
public String[] getTetherableWifiRegexs() {
- return getTetheringManager().getTetherableWifiRegexs();
+ return mTetheringManager.getTetherableWifiRegexs();
}
/**
@@ -2761,7 +2740,7 @@
@UnsupportedAppUsage
@Deprecated
public String[] getTetherableBluetoothRegexs() {
- return getTetheringManager().getTetherableBluetoothRegexs();
+ return mTetheringManager.getTetherableBluetoothRegexs();
}
/**
@@ -2785,7 +2764,7 @@
@UnsupportedAppUsage
@Deprecated
public int setUsbTethering(boolean enable) {
- return getTetheringManager().setUsbTethering(enable);
+ return mTetheringManager.setUsbTethering(enable);
}
/**
@@ -2902,7 +2881,7 @@
@UnsupportedAppUsage
@Deprecated
public int getLastTetherError(String iface) {
- return getTetheringManager().getLastTetherError(iface);
+ return mTetheringManager.getLastTetherError(iface);
}
/** @hide */
@@ -2973,7 +2952,7 @@
}
};
- getTetheringManager().requestLatestTetheringEntitlementResult(type, wrappedListener,
+ mTetheringManager.requestLatestTetheringEntitlementResult(type, wrappedListener,
showEntitlementUi);
}
@@ -3243,7 +3222,9 @@
/** {@hide} - returns the factory serial number */
@UnsupportedAppUsage
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public int registerNetworkFactory(Messenger messenger, String name) {
try {
return mService.registerNetworkFactory(messenger, name);
@@ -3254,7 +3235,9 @@
/** {@hide} */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public void unregisterNetworkFactory(Messenger messenger) {
try {
mService.unregisterNetworkFactory(messenger);
@@ -3274,7 +3257,9 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public int registerNetworkProvider(@NonNull NetworkProvider provider) {
if (provider.getProviderId() != NetworkProvider.ID_NONE) {
throw new IllegalStateException("NetworkProviders can only be registered once");
@@ -3297,7 +3282,9 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public void unregisterNetworkProvider(@NonNull NetworkProvider provider) {
try {
mService.unregisterNetworkProvider(provider.getMessenger());
@@ -3309,7 +3296,9 @@
/** @hide exposed via the NetworkProvider class. */
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
try {
mService.declareNetworkRequestUnfulfillable(request);
@@ -3327,7 +3316,9 @@
* Register a NetworkAgent with ConnectivityService.
* @return Network corresponding to NetworkAgent.
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config) {
return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
@@ -3338,9 +3329,12 @@
* Register a NetworkAgent with ConnectivityService.
* @return Network corresponding to NetworkAgent.
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_FACTORY})
public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
+
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId);
} catch (RemoteException e) {
@@ -4035,10 +4029,9 @@
@NonNull PendingIntent operation) {
printStackTrace();
checkPendingIntentNotNull(operation);
- final String callingPackageName = mContext.getOpPackageName();
try {
mService.pendingRequestForNetwork(
- request.networkCapabilities, operation, callingPackageName);
+ request.networkCapabilities, operation, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
@@ -4150,10 +4143,9 @@
@NonNull PendingIntent operation) {
printStackTrace();
checkPendingIntentNotNull(operation);
- final String callingPackageName = mContext.getOpPackageName();
try {
mService.pendingListenForNetwork(
- request.networkCapabilities, operation, callingPackageName);
+ request.networkCapabilities, operation, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
@@ -4470,7 +4462,7 @@
public void factoryReset() {
try {
mService.factoryReset();
- getTetheringManager().stopAllTethering();
+ mTetheringManager.stopAllTethering();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4716,19 +4708,19 @@
/**
* Returns the {@code uid} of the owner of a network connection.
*
- * @param protocol The protocol of the connection. Only {@code IPPROTO_TCP} and
- * {@code IPPROTO_UDP} currently supported.
+ * @param protocol The protocol of the connection. Only {@code IPPROTO_TCP} and {@code
+ * IPPROTO_UDP} currently supported.
* @param local The local {@link InetSocketAddress} of a connection.
* @param remote The remote {@link InetSocketAddress} of a connection.
- *
* @return {@code uid} if the connection is found and the app has permission to observe it
- * (e.g., if it is associated with the calling VPN app's tunnel) or
- * {@link android.os.Process#INVALID_UID} if the connection is not found.
- * Throws {@link SecurityException} if the caller is not the active VPN for the current user.
- * Throws {@link IllegalArgumentException} if an unsupported protocol is requested.
+ * (e.g., if it is associated with the calling VPN app's VpnService tunnel) or {@link
+ * android.os.Process#INVALID_UID} if the connection is not found.
+ * @throws {@link SecurityException} if the caller is not the active VpnService for the current
+ * user.
+ * @throws {@link IllegalArgumentException} if an unsupported protocol is requested.
*/
- public int getConnectionOwnerUid(int protocol, @NonNull InetSocketAddress local,
- @NonNull InetSocketAddress remote) {
+ public int getConnectionOwnerUid(
+ int protocol, @NonNull InetSocketAddress local, @NonNull InetSocketAddress remote) {
ConnectionInfo connectionInfo = new ConnectionInfo(protocol, local, remote);
try {
return mService.getConnectionOwnerUid(connectionInfo);
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 3a55461..1434560 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -59,7 +59,8 @@
NetworkInfo[] getAllNetworkInfo();
Network getNetworkForType(int networkType);
Network[] getAllNetworks();
- NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId);
+ NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(
+ int userId, String callingPackageName);
boolean isNetworkSupported(int networkType);
@@ -68,7 +69,7 @@
LinkProperties getLinkPropertiesForType(int networkType);
LinkProperties getLinkProperties(in Network network);
- NetworkCapabilities getNetworkCapabilities(in Network network);
+ NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName);
@UnsupportedAppUsage
NetworkState[] getAllNetworkState();
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index d25ee0e..732ceb5 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -21,6 +21,8 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.util.LinkPropertiesUtils;
+import android.net.util.LinkPropertiesUtils.CompareResult;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -93,36 +95,6 @@
/**
* @hide
*/
- public static class CompareResult<T> {
- public final List<T> removed = new ArrayList<>();
- public final List<T> added = new ArrayList<>();
-
- public CompareResult() {}
-
- public CompareResult(Collection<T> oldItems, Collection<T> newItems) {
- if (oldItems != null) {
- removed.addAll(oldItems);
- }
- if (newItems != null) {
- for (T newItem : newItems) {
- if (!removed.remove(newItem)) {
- added.add(newItem);
- }
- }
- }
- }
-
- @Override
- public String toString() {
- return "removed=[" + TextUtils.join(",", removed)
- + "] added=[" + TextUtils.join(",", added)
- + "]";
- }
- }
-
- /**
- * @hide
- */
@UnsupportedAppUsage(implicitMember =
"values()[Landroid/net/LinkProperties$ProvisioningChange;")
public enum ProvisioningChange {
@@ -1326,7 +1298,7 @@
*/
@UnsupportedAppUsage
public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) {
- return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
+ return LinkPropertiesUtils.isIdenticalInterfaceName(target, this);
}
/**
@@ -1349,10 +1321,7 @@
*/
@UnsupportedAppUsage
public boolean isIdenticalAddresses(@NonNull LinkProperties target) {
- Collection<InetAddress> targetAddresses = target.getAddresses();
- Collection<InetAddress> sourceAddresses = getAddresses();
- return (sourceAddresses.size() == targetAddresses.size()) ?
- sourceAddresses.containsAll(targetAddresses) : false;
+ return LinkPropertiesUtils.isIdenticalAddresses(target, this);
}
/**
@@ -1364,15 +1333,7 @@
*/
@UnsupportedAppUsage
public boolean isIdenticalDnses(@NonNull LinkProperties target) {
- Collection<InetAddress> targetDnses = target.getDnsServers();
- String targetDomains = target.getDomains();
- if (mDomains == null) {
- if (targetDomains != null) return false;
- } else {
- if (!mDomains.equals(targetDomains)) return false;
- }
- return (mDnses.size() == targetDnses.size()) ?
- mDnses.containsAll(targetDnses) : false;
+ return LinkPropertiesUtils.isIdenticalDnses(target, this);
}
/**
@@ -1425,9 +1386,7 @@
*/
@UnsupportedAppUsage
public boolean isIdenticalRoutes(@NonNull LinkProperties target) {
- Collection<RouteInfo> targetRoutes = target.getRoutes();
- return (mRoutes.size() == targetRoutes.size()) ?
- mRoutes.containsAll(targetRoutes) : false;
+ return LinkPropertiesUtils.isIdenticalRoutes(target, this);
}
/**
@@ -1439,8 +1398,7 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) {
- return getHttpProxy() == null ? target.getHttpProxy() == null :
- getHttpProxy().equals(target.getHttpProxy());
+ return LinkPropertiesUtils.isIdenticalHttpProxy(target, this);
}
/**
@@ -1663,26 +1621,6 @@
}
/**
- * Compares the addresses in this LinkProperties with another
- * LinkProperties, examining only addresses on the base link.
- *
- * @param target a LinkProperties with the new list of addresses
- * @return the differences between the addresses.
- * @hide
- */
- public @NonNull CompareResult<LinkAddress> compareAddresses(@Nullable LinkProperties target) {
- /*
- * Duplicate the LinkAddresses into removed, we will be removing
- * address which are common between mLinkAddresses and target
- * leaving the addresses that are different. And address which
- * are in target but not in mLinkAddresses are placed in the
- * addedAddresses.
- */
- return new CompareResult<>(mLinkAddresses,
- target != null ? target.getLinkAddresses() : null);
- }
-
- /**
* Compares the DNS addresses in this LinkProperties with another
* LinkProperties, examining only DNS addresses on the base link.
*
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 74c9aac..0e10c42 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -20,11 +20,11 @@
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.Parcel;
import android.os.Parcelable;
-import com.android.internal.util.BitUtils;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -33,7 +33,6 @@
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.Arrays;
-import java.util.Random;
/**
* Representation of a MAC address.
@@ -109,21 +108,13 @@
if (equals(BROADCAST_ADDRESS)) {
return TYPE_BROADCAST;
}
- if (isMulticastAddress()) {
+ if ((mAddr & MULTICAST_MASK) != 0) {
return TYPE_MULTICAST;
}
return TYPE_UNICAST;
}
/**
- * @return true if this MacAddress is a multicast address.
- * @hide
- */
- public boolean isMulticastAddress() {
- return (mAddr & MULTICAST_MASK) != 0;
- }
-
- /**
* @return true if this MacAddress is a locally assigned address.
*/
public boolean isLocallyAssigned() {
@@ -192,7 +183,7 @@
* @hide
*/
public static boolean isMacAddress(byte[] addr) {
- return addr != null && addr.length == ETHER_ADDR_LEN;
+ return MacAddressUtils.isMacAddress(addr);
}
/**
@@ -261,26 +252,11 @@
}
private static byte[] byteAddrFromLongAddr(long addr) {
- byte[] bytes = new byte[ETHER_ADDR_LEN];
- int index = ETHER_ADDR_LEN;
- while (index-- > 0) {
- bytes[index] = (byte) addr;
- addr = addr >> 8;
- }
- return bytes;
+ return MacAddressUtils.byteAddrFromLongAddr(addr);
}
private static long longAddrFromByteAddr(byte[] addr) {
- Preconditions.checkNotNull(addr);
- if (!isMacAddress(addr)) {
- throw new IllegalArgumentException(
- Arrays.toString(addr) + " was not a valid MAC address");
- }
- long longAddr = 0;
- for (byte b : addr) {
- longAddr = (longAddr << 8) + BitUtils.uint8(b);
- }
- return longAddr;
+ return MacAddressUtils.longAddrFromByteAddr(addr);
}
// Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr))
@@ -350,50 +326,7 @@
* @hide
*/
public static @NonNull MacAddress createRandomUnicastAddressWithGoogleBase() {
- return createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom());
- }
-
- /**
- * Returns a generated MAC address whose 46 bits, excluding the locally assigned bit and the
- * unicast bit, are randomly selected.
- *
- * The locally assigned bit is always set to 1. The multicast bit is always set to 0.
- *
- * @return a random locally assigned, unicast MacAddress.
- *
- * @hide
- */
- public static @NonNull MacAddress createRandomUnicastAddress() {
- return createRandomUnicastAddress(null, new SecureRandom());
- }
-
- /**
- * Returns a randomly generated MAC address using the given Random object and the same
- * OUI values as the given MacAddress.
- *
- * The locally assigned bit is always set to 1. The multicast bit is always set to 0.
- *
- * @param base a base MacAddress whose OUI is used for generating the random address.
- * If base == null then the OUI will also be randomized.
- * @param r a standard Java Random object used for generating the random address.
- * @return a random locally assigned MacAddress.
- *
- * @hide
- */
- public static @NonNull MacAddress createRandomUnicastAddress(MacAddress base, Random r) {
- long addr;
- if (base == null) {
- addr = r.nextLong() & VALID_LONG_MASK;
- } else {
- addr = (base.mAddr & OUI_MASK) | (NIC_MASK & r.nextLong());
- }
- addr |= LOCALLY_ASSIGNED_MASK;
- addr &= ~MULTICAST_MASK;
- MacAddress mac = new MacAddress(addr);
- if (mac.equals(DEFAULT_MAC_ADDRESS)) {
- return createRandomUnicastAddress(base, r);
- }
- return mac;
+ return MacAddressUtils.createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom());
}
// Convenience function for working around the lack of byte literals.
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 8d1ab33..c145b2b 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -61,6 +61,7 @@
public class Network implements Parcelable {
/**
+ * The unique id of the network.
* @hide
*/
@SystemApi
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 61a1484..fef353f 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -33,6 +33,7 @@
import com.android.internal.util.Protocol;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -50,20 +51,29 @@
/**
* The {@link Network} corresponding to this object.
*/
- @NonNull
- public final Network network;
+ @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;
private static final boolean DBG = true;
private static final boolean VDBG = false;
- private final Context mContext;
private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
private volatile long mLastBwRefreshTime = 0;
private static final long BW_REFRESH_MIN_WIN_MS = 500;
private boolean mBandwidthUpdateScheduled = false;
private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false);
+ // 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;
/**
* The ID of the {@link NetworkProvider} that created this object, or
@@ -116,7 +126,7 @@
/**
* Sent by the NetworkAgent to ConnectivityService to pass the current
* network score.
- * obj = network score Integer
+ * arg1 = network score int
* @hide
*/
public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
@@ -266,31 +276,38 @@
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);
+ 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 the type and an empty description.
- return new NetworkInfo(config.legacyType, config.legacyType, config.legacyTypeName, "");
+ final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacyType,
+ config.legacyTypeName, "");
+ ni.setIsAvailable(true);
+ return ni;
}
/**
@@ -310,26 +327,44 @@
@NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
this(looper, context, logTag, nc, lp, score, config,
provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
- getLegacyNetworkInfo(config));
+ getLegacyNetworkInfo(config), false /* legacy */);
}
- private NetworkAgent(Looper looper, Context context, String logTag, NetworkCapabilities nc,
- LinkProperties lp, int score, NetworkAgentConfig config, int providerId,
- NetworkInfo ni) {
+ private static class InitialConfiguration {
+ public final Context context;
+ public final NetworkCapabilities capabilities;
+ public final LinkProperties properties;
+ public final int score;
+ public final NetworkAgentConfig config;
+ public final NetworkInfo info;
+ InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities,
+ @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config,
+ @NonNull NetworkInfo info) {
+ this.context = context;
+ this.capabilities = capabilities;
+ this.properties = properties;
+ this.score = score;
+ this.config = config;
+ this.info = info;
+ }
+ }
+ private volatile InitialConfiguration mInitialConfiguration;
+
+ private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
+ @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
+ @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni,
+ boolean legacy) {
mHandler = new NetworkAgentHandler(looper);
LOG_TAG = logTag;
- mContext = context;
+ mIsLegacy = legacy;
+ mNetworkInfo = new NetworkInfo(ni);
this.providerId = providerId;
if (ni == null || nc == null || lp == null) {
throw new IllegalArgumentException();
}
- if (VDBG) log("Registering NetworkAgent");
- ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni),
- new LinkProperties(lp), new NetworkCapabilities(nc), score, config,
- providerId);
+ mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc),
+ new LinkProperties(lp), score, config, ni);
}
private class NetworkAgentHandler extends Handler {
@@ -451,6 +486,32 @@
}
}
+ /**
+ * Register this network agent with ConnectivityService.
+ * @return the Network associated with this network agent (which can also be obtained later
+ * by calling getNetwork() on this agent).
+ */
+ @NonNull
+ public Network register() {
+ if (VDBG) log("Registering NetworkAgent");
+ final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ mNetwork = cm.registerNetworkAgent(new Messenger(mHandler),
+ new NetworkInfo(mInitialConfiguration.info),
+ mInitialConfiguration.properties, mInitialConfiguration.capabilities,
+ mInitialConfiguration.score, mInitialConfiguration.config, providerId);
+ mInitialConfiguration = null; // All this memory can now be GC'd
+ return mNetwork;
+ }
+
+ /**
+ * @return The Network associated with this agent, or null if it's not registered yet.
+ */
+ @Nullable
+ public Network getNetwork() {
+ return mNetwork;
+ }
+
private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, 0, 0, obj);
}
@@ -483,15 +544,89 @@
* @param linkProperties the new LinkProperties.
*/
public void sendLinkProperties(@NonNull LinkProperties linkProperties) {
+ Objects.requireNonNull(linkProperties);
queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
}
/**
+ * Inform ConnectivityService that this agent has now connected.
+ */
+ public void setConnected() {
+ if (mIsLegacy) {
+ throw new UnsupportedOperationException(
+ "Legacy agents can't call setConnected.");
+ }
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
+ queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
+ }
+
+ /**
+ * Unregister this network agent.
+ *
+ * This signals the network has disconnected and ends its lifecycle. After this is called,
+ * the network is torn down and this agent can no longer be used.
+ */
+ public void unregister() {
+ if (mIsLegacy) {
+ throw new UnsupportedOperationException(
+ "Legacy agents can't call unregister.");
+ }
+ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+ queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);
+ }
+
+ /**
+ * Change the legacy subtype of this network agent.
+ *
+ * This is only for backward compatibility and should not be used by non-legacy network agents,
+ * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use
+ * this and others will be thrown an exception if they try.
+ *
+ * @deprecated this is for backward compatibility only.
+ * @param legacySubtype the legacy subtype.
+ */
+ @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);
+ }
+
+ /**
+ * Set the ExtraInfo of this network agent.
+ *
+ * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the
+ * broadcasts about the corresponding Network.
+ * This is only for backward compatibility and should not be used by non-legacy network agents,
+ * who will be thrown an exception if they try. The extra info should only be :
+ * <ul>
+ * <li>For cellular agents, the APN name.</li>
+ * <li>For ethernet agents, the interface name.</li>
+ * </ul>
+ *
+ * @deprecated this is for backward compatibility only.
+ * @param extraInfo the ExtraInfo.
+ */
+ @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);
+ }
+
+ /**
* Must be called by the agent when it has a new NetworkInfo object.
* @hide TODO: expose something better.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void sendNetworkInfo(NetworkInfo networkInfo) {
+ if (!mIsLegacy) {
+ throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo.");
+ }
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
}
@@ -500,6 +635,7 @@
* @param networkCapabilities the new NetworkCapabilities.
*/
public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
+ Objects.requireNonNull(networkCapabilities);
mBandwidthUpdatePending.set(false);
mLastBwRefreshTime = System.currentTimeMillis();
queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
@@ -514,18 +650,7 @@
if (score < 0) {
throw new IllegalArgumentException("Score must be >= 0");
}
- final NetworkScore ns = new NetworkScore();
- ns.putIntExtension(NetworkScore.LEGACY_SCORE, score);
- updateScore(ns);
- }
-
- /**
- * Must be called by the agent when it has a new {@link NetworkScore} for this network.
- * @param ns the new score.
- * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore.
- */
- public void updateScore(@NonNull NetworkScore ns) {
- queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns));
+ queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score, 0);
}
/**
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
index 2c5a113..7e2db4a 100644
--- a/core/java/android/net/NetworkAgentConfig.java
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -22,6 +22,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
+
/**
* Allows a network transport to provide the system with policy and configuration information about
* a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered.
@@ -52,23 +54,47 @@
public boolean explicitlySelected;
/**
+ * @return whether this network was explicitly selected by the user.
+ */
+ public boolean isExplicitlySelected() {
+ return explicitlySelected;
+ }
+
+ /**
* Set if the user desires to use this network even if it is unvalidated. This field has meaning
* only if {@link explicitlySelected} is true. If it is, this field must also be set to the
* appropriate value based on previous user choice.
*
+ * TODO : rename this field to match its accessor
* @hide
*/
public boolean acceptUnvalidated;
/**
+ * @return whether the system should accept this network even if it doesn't validate.
+ */
+ public boolean isUnvalidatedConnectivityAcceptable() {
+ return acceptUnvalidated;
+ }
+
+ /**
* Whether the user explicitly set that this network should be validated even if presence of
* only partial internet connectivity.
*
+ * TODO : rename this field to match its accessor
* @hide
*/
public boolean acceptPartialConnectivity;
/**
+ * @return whether the system should validate this network even if it only offers partial
+ * Internet connectivity.
+ */
+ public boolean isPartialConnectivityAcceptable() {
+ return acceptPartialConnectivity;
+ }
+
+ /**
* Set to avoid surfacing the "Sign in to network" notification.
* if carrier receivers/apps are registered to handle the carrier-specific provisioning
* procedure, a carrier specific provisioning notification will be placed.
@@ -134,9 +160,11 @@
* Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
* Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
*
+ * This is not parceled, because it would not make sense.
+ *
* @hide
*/
- public boolean hasShownBroken;
+ public transient boolean hasShownBroken;
/**
* The name of the legacy network type. It's a free-form string used in logging.
@@ -163,6 +191,7 @@
allowBypass = nac.allowBypass;
explicitlySelected = nac.explicitlySelected;
acceptUnvalidated = nac.acceptUnvalidated;
+ acceptPartialConnectivity = nac.acceptPartialConnectivity;
subscriberId = nac.subscriberId;
provisioningNotificationDisabled = nac.provisioningNotificationDisabled;
skip464xlat = nac.skip464xlat;
@@ -178,6 +207,43 @@
private final NetworkAgentConfig mConfig = new NetworkAgentConfig();
/**
+ * Sets whether the network was explicitly selected by the user.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setExplicitlySelected(final boolean explicitlySelected) {
+ mConfig.explicitlySelected = explicitlySelected;
+ return this;
+ }
+
+ /**
+ * Sets whether the system should validate this network even if it is found not to offer
+ * Internet connectivity.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setUnvalidatedConnectivityAcceptable(
+ final boolean unvalidatedConnectivityAcceptable) {
+ mConfig.acceptUnvalidated = unvalidatedConnectivityAcceptable;
+ return this;
+ }
+
+ /**
+ * Sets whether the system should validate this network even if it is found to only offer
+ * partial Internet connectivity.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setPartialConnectivityAcceptable(
+ final boolean partialConnectivityAcceptable) {
+ mConfig.acceptPartialConnectivity = partialConnectivityAcceptable;
+ return this;
+ }
+
+ /**
* Sets the subscriber ID for this network.
*
* @return this builder, to facilitate chaining.
@@ -245,6 +311,45 @@
}
@Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final NetworkAgentConfig that = (NetworkAgentConfig) o;
+ return allowBypass == that.allowBypass
+ && explicitlySelected == that.explicitlySelected
+ && acceptUnvalidated == that.acceptUnvalidated
+ && acceptPartialConnectivity == that.acceptPartialConnectivity
+ && provisioningNotificationDisabled == that.provisioningNotificationDisabled
+ && skip464xlat == that.skip464xlat
+ && legacyType == that.legacyType
+ && Objects.equals(subscriberId, that.subscriberId)
+ && Objects.equals(legacyTypeName, that.legacyTypeName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated,
+ acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId,
+ skip464xlat, legacyType, legacyTypeName);
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkAgentConfig {"
+ + " allowBypass = " + allowBypass
+ + ", explicitlySelected = " + explicitlySelected
+ + ", acceptUnvalidated = " + acceptUnvalidated
+ + ", acceptPartialConnectivity = " + acceptPartialConnectivity
+ + ", provisioningNotificationDisabled = " + provisioningNotificationDisabled
+ + ", subscriberId = '" + subscriberId + '\''
+ + ", skip464xlat = " + skip464xlat
+ + ", legacyType = " + legacyType
+ + ", hasShownBroken = " + hasShownBroken
+ + ", legacyTypeName = '" + legacyTypeName + '\''
+ + "}";
+ }
+
+ @Override
public int describeContents() {
return 0;
}
@@ -254,9 +359,12 @@
out.writeInt(allowBypass ? 1 : 0);
out.writeInt(explicitlySelected ? 1 : 0);
out.writeInt(acceptUnvalidated ? 1 : 0);
+ out.writeInt(acceptPartialConnectivity ? 1 : 0);
out.writeString(subscriberId);
out.writeInt(provisioningNotificationDisabled ? 1 : 0);
out.writeInt(skip464xlat ? 1 : 0);
+ out.writeInt(legacyType);
+ out.writeString(legacyTypeName);
}
public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
@@ -267,9 +375,12 @@
networkAgentConfig.allowBypass = in.readInt() != 0;
networkAgentConfig.explicitlySelected = in.readInt() != 0;
networkAgentConfig.acceptUnvalidated = in.readInt() != 0;
+ networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0;
networkAgentConfig.subscriberId = in.readString();
networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0;
networkAgentConfig.skip464xlat = in.readInt() != 0;
+ networkAgentConfig.legacyType = in.readInt();
+ networkAgentConfig.legacyTypeName = in.readString();
return networkAgentConfig;
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index ef4a9e5..873d6e9 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -830,6 +830,23 @@
* <p>This field keeps track of the UID of the app that created this network and is in charge of
* its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
* VPN, or Carrier Service app managing a cellular data connection.
+ *
+ * <p>For NetworkCapability instances being sent from ConnectivityService, this value MUST be
+ * reset to Process.INVALID_UID unless all the following conditions are met:
+ *
+ * <ol>
+ * <li>The destination app is the network owner
+ * <li>The destination app has the ACCESS_FINE_LOCATION permission granted
+ * <li>The user's location toggle is on
+ * </ol>
+ *
+ * This is because the owner UID is location-sensitive. The apps that request a network could
+ * know where the device is if they can tell for sure the system has connected to the network
+ * they requested.
+ *
+ * <p>This is populated by the network agents and for the NetworkCapabilities instance sent by
+ * an app to the System Server, the value MUST be reset to Process.INVALID_UID by the system
+ * server.
*/
private int mOwnerUid = Process.INVALID_UID;
@@ -842,7 +859,16 @@
}
/**
- * Retrieves the UID of the owner app.
+ * Retrieves the UID of the app that owns this network.
+ *
+ * <p>For user privacy reasons, this field will only be populated if:
+ *
+ * <ol>
+ * <li>The calling app is the network owner
+ * <li>The calling app has the ACCESS_FINE_LOCATION permission granted
+ * <li>The user's location toggle is on
+ * </ol>
+ *
*/
public int getOwnerUid() {
return mOwnerUid;
@@ -880,8 +906,9 @@
* @param administratorUids the UIDs to be set as administrators of this Network.
* @hide
*/
+ @NonNull
@SystemApi
- public @NonNull NetworkCapabilities setAdministratorUids(
+ public NetworkCapabilities setAdministratorUids(
@NonNull final List<Integer> administratorUids) {
mAdministratorUids.clear();
mAdministratorUids.addAll(administratorUids);
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index d0c5363..08fe159 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -17,9 +17,11 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
import com.android.internal.annotations.VisibleForTesting;
@@ -150,10 +152,19 @@
private boolean mIsRoaming;
/**
- * @hide
+ * Create a new instance of NetworkInfo.
+ *
+ * This may be useful for apps to write unit tests.
+ *
+ * @param type the legacy type of the network, as one of the ConnectivityManager.TYPE_*
+ * constants.
+ * @param subtype the subtype if applicable, as one of the TelephonyManager.NETWORK_TYPE_*
+ * constants.
+ * @param typeName a human-readable string for the network type, or an empty string or null.
+ * @param subtypeName a human-readable string for the subtype, or an empty string or null.
*/
- @UnsupportedAppUsage
- public NetworkInfo(int type, int subtype, String typeName, String subtypeName) {
+ public NetworkInfo(int type, @NetworkType int subtype,
+ @Nullable String typeName, @Nullable String subtypeName) {
if (!ConnectivityManager.isNetworkTypeValid(type)
&& type != ConnectivityManager.TYPE_NONE) {
throw new IllegalArgumentException("Invalid network type: " + type);
@@ -462,17 +473,19 @@
/**
* Sets the fine-grained state of the network.
+ *
+ * This is only useful for testing.
+ *
* @param detailedState the {@link DetailedState}.
* @param reason a {@code String} indicating the reason for the state change,
* if one was supplied. May be {@code null}.
* @param extraInfo an optional {@code String} providing addditional network state
* information passed up from the lower networking layers.
* @deprecated Use {@link NetworkCapabilities} instead.
- * @hide
*/
@Deprecated
- @UnsupportedAppUsage
- public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) {
+ public void setDetailedState(@NonNull DetailedState detailedState, @Nullable String reason,
+ @Nullable String extraInfo) {
synchronized (this) {
this.mDetailedState = detailedState;
this.mState = stateMap.get(detailedState);
diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java
deleted file mode 100644
index 13f2994..0000000
--- a/core/java/android/net/NetworkScore.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Object representing the quality of a network as perceived by the user.
- *
- * A NetworkScore object represents the characteristics of a network that affects how good the
- * network is considered for a particular use.
- * @hide
- */
-public final class NetworkScore implements Parcelable {
-
- // The key of bundle which is used to get the legacy network score of NetworkAgentInfo.
- // TODO: Remove this when the transition to NetworkScore is over.
- public static final String LEGACY_SCORE = "LEGACY_SCORE";
- @NonNull
- private final Bundle mExtensions;
-
- public NetworkScore() {
- mExtensions = new Bundle();
- }
-
- public NetworkScore(@NonNull NetworkScore source) {
- mExtensions = new Bundle(source.mExtensions);
- }
-
- /**
- * Put the value of parcelable inside the bundle by key.
- */
- public void putExtension(@Nullable String key, @Nullable Parcelable value) {
- mExtensions.putParcelable(key, value);
- }
-
- /**
- * Put the value of int inside the bundle by key.
- */
- public void putIntExtension(@Nullable String key, int value) {
- mExtensions.putInt(key, value);
- }
-
- /**
- * Get the value of non primitive type by key.
- */
- public <T extends Parcelable> T getExtension(@Nullable String key) {
- return mExtensions.getParcelable(key);
- }
-
- /**
- * Get the value of int by key.
- */
- public int getIntExtension(@Nullable String key) {
- return mExtensions.getInt(key);
- }
-
- /**
- * Remove the entry by given key.
- */
- public void removeExtension(@Nullable String key) {
- mExtensions.remove(key);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- synchronized (this) {
- dest.writeBundle(mExtensions);
- }
- }
-
- public static final @NonNull Creator<NetworkScore> CREATOR = new Creator<NetworkScore>() {
- @Override
- public NetworkScore createFromParcel(@NonNull Parcel in) {
- return new NetworkScore(in);
- }
-
- @Override
- public NetworkScore[] newArray(int size) {
- return new NetworkScore[size];
- }
- };
-
- private NetworkScore(@NonNull Parcel in) {
- mExtensions = in.readBundle();
- }
-
- // TODO: Modify this method once new fields are added into this class.
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof NetworkScore)) {
- return false;
- }
- final NetworkScore other = (NetworkScore) obj;
- return bundlesEqual(mExtensions, other.mExtensions);
- }
-
- @Override
- public int hashCode() {
- int result = 29;
- for (String key : mExtensions.keySet()) {
- final Object value = mExtensions.get(key);
- // The key may be null, so call Objects.hash() is safer.
- result += 31 * value.hashCode() + 37 * Objects.hash(key);
- }
- return result;
- }
-
- // mExtensions won't be null since the constructor will create it.
- private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) {
- if (bundle1 == bundle2) {
- return true;
- }
-
- // This is unlikely but it's fine to add this clause here.
- if (null == bundle1 || null == bundle2) {
- return false;
- }
-
- if (bundle1.size() != bundle2.size()) {
- return false;
- }
-
- for (String key : bundle1.keySet()) {
- final Object value1 = bundle1.get(key);
- final Object value2 = bundle2.get(key);
- if (!Objects.equals(value1, value2)) {
- return false;
- }
- }
- return true;
- }
-
- /** Convert to a string */
- public String toString() {
- return "NetworkScore[" + mExtensions.toString() + "]";
- }
-}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 08cc4e2..779f7bc 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -31,7 +31,6 @@
import java.io.FileDescriptor;
import java.math.BigInteger;
import java.net.Inet4Address;
-import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
@@ -313,15 +312,6 @@
}
/**
- * Check if IP address type is consistent between two InetAddress.
- * @return true if both are the same type. False otherwise.
- */
- public static boolean addressTypeMatches(InetAddress left, InetAddress right) {
- return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) ||
- ((left instanceof Inet6Address) && (right instanceof Inet6Address)));
- }
-
- /**
* Convert a 32 char hex string into a Inet6Address.
* throws a runtime exception if the string isn't 32 chars, isn't hex or can't be
* made into an Inet6Address
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 67bad53..2b9e9fe 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -22,6 +22,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.util.NetUtils;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -483,21 +484,7 @@
@UnsupportedAppUsage
@Nullable
public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
- if ((routes == null) || (dest == null)) return null;
-
- RouteInfo bestRoute = null;
- // pick a longest prefix match under same address type
- for (RouteInfo route : routes) {
- if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
- if ((bestRoute != null) &&
- (bestRoute.mDestination.getPrefixLength() >=
- route.mDestination.getPrefixLength())) {
- continue;
- }
- if (route.matches(dest)) bestRoute = route;
- }
- }
- return bestRoute;
+ return NetUtils.selectBestRoute(routes, dest);
}
/**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 78aa24d..5f0a53c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -89,7 +89,6 @@
import android.net.IpMemoryStore;
import android.net.IpPrefix;
import android.net.LinkProperties;
-import android.net.LinkProperties.CompareResult;
import android.net.MatchAllNetworkSpecifier;
import android.net.NattSocketKeepalive;
import android.net.Network;
@@ -104,7 +103,6 @@
import android.net.NetworkProvider;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
-import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStackClient;
@@ -124,6 +122,7 @@
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.LinkPropertiesUtils.CompareResult;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
import android.os.Binder;
@@ -1528,7 +1527,8 @@
}
@Override
- public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
+ public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(
+ int userId, String callingPackageName) {
// The basic principle is: if an app's traffic could possibly go over a
// network, without the app doing anything multinetwork-specific,
// (hence, by "default"), then include that network's capabilities in
@@ -1550,7 +1550,10 @@
NetworkAgentInfo nai = getDefaultNetwork();
NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
if (nc != null) {
- result.put(nai.network, nc);
+ result.put(
+ nai.network,
+ maybeSanitizeLocationInfoForCaller(
+ nc, Binder.getCallingUid(), callingPackageName));
}
synchronized (mVpns) {
@@ -1560,10 +1563,12 @@
Network[] networks = vpn.getUnderlyingNetworks();
if (networks != null) {
for (Network network : networks) {
- nai = getNetworkAgentInfoForNetwork(network);
- nc = getNetworkCapabilitiesInternal(nai);
+ nc = getNetworkCapabilitiesInternal(network);
if (nc != null) {
- result.put(network, nc);
+ result.put(
+ network,
+ maybeSanitizeLocationInfoForCaller(
+ nc, Binder.getCallingUid(), callingPackageName));
}
}
}
@@ -1630,20 +1635,26 @@
}
}
+ private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) {
+ return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
+ }
+
private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
if (nai == null) return null;
synchronized (nai) {
if (nai.networkCapabilities == null) return null;
return networkCapabilitiesRestrictedForCallerPermissions(
- nai.networkCapabilities,
- Binder.getCallingPid(), Binder.getCallingUid());
+ nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid());
}
}
@Override
- public NetworkCapabilities getNetworkCapabilities(Network network) {
+ public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
+ mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
enforceAccessPermission();
- return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
+ return maybeSanitizeLocationInfoForCaller(
+ getNetworkCapabilitiesInternal(network),
+ Binder.getCallingUid(), callingPackageName);
}
@VisibleForTesting
@@ -1659,20 +1670,34 @@
}
newNc.setAdministratorUids(Collections.EMPTY_LIST);
- maybeSanitizeLocationInfoForCaller(newNc, callerUid);
-
return newNc;
}
- private void maybeSanitizeLocationInfoForCaller(
- NetworkCapabilities nc, int callerUid) {
- // TODO(b/142072839): Conditionally reset the owner UID if the following
- // conditions are not met:
- // 1. The destination app is the network owner
- // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted
- // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted
- // 3. The user's location toggle is on
- nc.setOwnerUid(INVALID_UID);
+ @VisibleForTesting
+ @Nullable
+ NetworkCapabilities maybeSanitizeLocationInfoForCaller(
+ @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) {
+ if (nc == null) {
+ return null;
+ }
+ final NetworkCapabilities newNc = new NetworkCapabilities(nc);
+ if (callerUid != newNc.getOwnerUid()) {
+ newNc.setOwnerUid(INVALID_UID);
+ 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);
+ }
+ }
+ );
+
+ return newNc;
}
private LinkProperties linkPropertiesRestrictedForCallerPermissions(
@@ -1747,7 +1772,7 @@
public boolean isActiveNetworkMetered() {
enforceAccessPermission();
- final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
+ final NetworkCapabilities caps = getNetworkCapabilitiesInternal(getActiveNetwork());
if (caps != null) {
return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
} else {
@@ -2060,9 +2085,9 @@
}
private void enforceNetworkFactoryPermission() {
- mContext.enforceCallingOrSelfPermission(
+ enforceAnyPermissionOf(
android.Manifest.permission.NETWORK_FACTORY,
- "ConnectivityService");
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private boolean checkSettingsPermission() {
@@ -2690,8 +2715,7 @@
break;
}
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
- final NetworkScore ns = (NetworkScore) msg.obj;
- updateNetworkScore(nai, ns);
+ updateNetworkScore(nai, msg.arg1);
break;
}
case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
@@ -3254,7 +3278,6 @@
for (int i = 0; i < nai.numNetworkRequests(); i++) {
NetworkRequest request = nai.requestAt(i);
final NetworkRequestInfo nri = mNetworkRequests.get(request);
- ensureRunningOnConnectivityServiceThread();
final NetworkAgentInfo currentNetwork = nri.mSatisfier;
if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
nri.mSatisfier = null;
@@ -3406,7 +3429,6 @@
// 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.
- ensureRunningOnConnectivityServiceThread();
if (nri.request.isRequest() && nai.satisfies(nri.request) &&
(nai.isSatisfyingRequest(nri.request.requestId) ||
// Note that this catches two important cases:
@@ -3445,7 +3467,6 @@
if (mNetworkRequests.get(nri.request) == null) {
return;
}
- ensureRunningOnConnectivityServiceThread();
if (nri.mSatisfier != null) {
return;
}
@@ -3483,7 +3504,6 @@
mNetworkRequestInfoLogs.log("RELEASE " + nri);
if (nri.request.isRequest()) {
boolean wasKept = false;
- ensureRunningOnConnectivityServiceThread();
final NetworkAgentInfo nai = nri.mSatisfier;
if (nai != null) {
boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
@@ -4751,7 +4771,7 @@
return false;
}
- return vpn.startAlwaysOnVpn();
+ return vpn.startAlwaysOnVpn(mKeyStore);
}
}
@@ -4766,7 +4786,7 @@
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
return false;
}
- return vpn.isAlwaysOnPackageSupported(packageName);
+ return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore);
}
}
@@ -4787,11 +4807,11 @@
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
return false;
}
- if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist)) {
+ if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist, mKeyStore)) {
return false;
}
if (!startAlwaysOnVpn(userId)) {
- vpn.setAlwaysOnPackage(null, false, null);
+ vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
return false;
}
}
@@ -4977,7 +4997,7 @@
loge("Starting user already has a VPN");
return;
}
- userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId);
+ userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
mVpns.put(userId, userVpn);
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
updateLockdownVpn();
@@ -5048,7 +5068,7 @@
if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
+ userId);
- vpn.startAlwaysOnVpn();
+ vpn.startAlwaysOnVpn(mKeyStore);
}
}
}
@@ -5070,7 +5090,7 @@
if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
+ userId);
- vpn.setAlwaysOnPackage(null, false, null);
+ vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
}
}
}
@@ -5290,8 +5310,8 @@
}
public String toString() {
- return "uid/pid:" + mUid + "/" + mPid + " " + request +
- (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
+ return "uid/pid:" + mUid + "/" + mPid + " " + request
+ + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
}
}
@@ -5758,12 +5778,10 @@
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
- final NetworkScore ns = new NetworkScore();
- ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
- ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this,
- mNetd, mDnsResolver, mNMS, providerId);
+ currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
+ this, mNetd, mDnsResolver, mNMS, providerId);
// Make sure the network capabilities reflect what the agent info says.
nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));
final String extraInfo = networkInfo.getExtraInfo();
@@ -6384,8 +6402,13 @@
}
switch (notificationType) {
case ConnectivityManager.CALLBACK_AVAILABLE: {
- putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions(
- networkAgent.networkCapabilities, nri.mPid, nri.mUid));
+ final NetworkCapabilities nc =
+ networkCapabilitiesRestrictedForCallerPermissions(
+ networkAgent.networkCapabilities, nri.mPid, nri.mUid);
+ putParcelable(
+ bundle,
+ maybeSanitizeLocationInfoForCaller(
+ nc, nri.mUid, nri.request.getRequestorPackageName()));
putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
networkAgent.linkProperties, nri.mPid, nri.mUid));
// For this notification, arg1 contains the blocked status.
@@ -6398,9 +6421,13 @@
}
case ConnectivityManager.CALLBACK_CAP_CHANGED: {
// networkAgent can't be null as it has been accessed a few lines above.
- final NetworkCapabilities nc = networkCapabilitiesRestrictedForCallerPermissions(
- networkAgent.networkCapabilities, nri.mPid, nri.mUid);
- putParcelable(bundle, nc);
+ final NetworkCapabilities netCap =
+ networkCapabilitiesRestrictedForCallerPermissions(
+ networkAgent.networkCapabilities, nri.mPid, nri.mUid);
+ putParcelable(
+ bundle,
+ maybeSanitizeLocationInfoForCaller(
+ netCap, nri.mUid, nri.request.getRequestorPackageName()));
break;
}
case ConnectivityManager.CALLBACK_IP_CHANGED: {
@@ -7012,9 +7039,9 @@
}
}
- private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) {
- if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + ns);
- nai.setNetworkScore(ns);
+ private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final int score) {
+ if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score);
+ nai.setScore(score);
rematchAllNetworksAndRequests();
sendUpdatedScoreToFactories(nai);
}
@@ -7496,6 +7523,13 @@
*/
public int getConnectionOwnerUid(ConnectionInfo connectionInfo) {
final Vpn vpn = enforceActiveVpnOrNetworkStackPermission();
+
+ // Only VpnService based VPNs should be able to get this information.
+ if (vpn != null && vpn.getActiveAppVpnType() != VpnManager.TYPE_VPN_SERVICE) {
+ throw new SecurityException(
+ "getConnectionOwnerUid() not allowed for non-VpnService VPNs");
+ }
+
if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) {
throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol);
}
@@ -7762,12 +7796,15 @@
private void handleNetworkTestedWithExtras(
@NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) {
final NetworkAgentInfo nai = reportEvent.mNai;
+ final NetworkCapabilities networkCapabilities =
+ new NetworkCapabilities(nai.networkCapabilities);
+ clearNetworkCapabilitiesUids(networkCapabilities);
final ConnectivityReport report =
new ConnectivityReport(
reportEvent.mNai.network,
reportEvent.mTimestampMillis,
nai.linkProperties,
- nai.networkCapabilities,
+ networkCapabilities,
extras);
final List<IConnectivityDiagnosticsCallback> results =
getMatchingPermissionedCallbacks(nai);
@@ -7783,13 +7820,16 @@
private void handleDataStallSuspected(
@NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod,
@NonNull PersistableBundle extras) {
+ final NetworkCapabilities networkCapabilities =
+ new NetworkCapabilities(nai.networkCapabilities);
+ clearNetworkCapabilitiesUids(networkCapabilities);
final DataStallReport report =
new DataStallReport(
nai.network,
timestampMillis,
detectionMethod,
nai.linkProperties,
- nai.networkCapabilities,
+ networkCapabilities,
extras);
final List<IConnectivityDiagnosticsCallback> results =
getMatchingPermissionedCallbacks(nai);
@@ -7815,6 +7855,12 @@
}
}
+ private void clearNetworkCapabilitiesUids(@NonNull NetworkCapabilities nc) {
+ nc.setUids(null);
+ nc.setAdministratorUids(Collections.EMPTY_LIST);
+ nc.setOwnerUid(Process.INVALID_UID);
+ }
+
private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks(
@NonNull NetworkAgentInfo nai) {
final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index a7e36b2..95ac900 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -219,7 +219,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(network.netId);
+ mTestNetworkTracker.remove(getNetwork().netId);
}
}
}
@@ -338,7 +338,7 @@
callingUid,
binder);
- mTestNetworkTracker.put(agent.network.netId, agent);
+ mTestNetworkTracker.put(agent.getNetwork().netId, agent);
}
} catch (SocketException e) {
throw new UncheckedIOException(e);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 3ed2a1a..2f04715 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -32,7 +32,6 @@
import android.net.NetworkInfo;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
-import android.net.NetworkScore;
import android.net.NetworkState;
import android.os.Handler;
import android.os.INetworkManagementService;
@@ -232,10 +231,8 @@
// validated).
private boolean mLingering;
- // This represents the characteristics of a network that affects how good the network is
- // considered for a particular use.
- @NonNull
- private NetworkScore mNetworkScore;
+ // This represents the quality of the network with no clear scale.
+ private int mScore;
// The list of NetworkRequests being satisfied by this Network.
private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
@@ -264,7 +261,7 @@
private final Handler mHandler;
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
- LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context,
+ LinkProperties lp, NetworkCapabilities nc, int score, Context context,
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
this.messenger = messenger;
@@ -273,7 +270,7 @@
networkInfo = info;
linkProperties = lp;
networkCapabilities = nc;
- mNetworkScore = ns;
+ mScore = score;
clatd = new Nat464Xlat(this, netd, dnsResolver, nms);
mConnService = connService;
mContext = context;
@@ -487,7 +484,7 @@
return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
}
- int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE);
+ int score = mScore;
if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
}
@@ -516,13 +513,8 @@
return getCurrentScore(true);
}
- public void setNetworkScore(@NonNull NetworkScore ns) {
- mNetworkScore = ns;
- }
-
- @NonNull
- public NetworkScore getNetworkScore() {
- return mNetworkScore;
+ public void setScore(final int score) {
+ mScore = score;
}
public NetworkState getNetworkState() {
diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java
index ca4ba63..7a60cc1 100644
--- a/tests/net/common/java/android/net/CaptivePortalTest.java
+++ b/tests/net/common/java/android/net/CaptivePortalTest.java
@@ -18,19 +18,26 @@
import static org.junit.Assert.assertEquals;
+import android.os.Build;
import android.os.RemoteException;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class CaptivePortalTest {
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
private static final int DEFAULT_TIMEOUT_MS = 5000;
private static final String TEST_PACKAGE_NAME = "com.google.android.test";
@@ -84,6 +91,7 @@
assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS);
}
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
@Test
public void testReevaluateNetwork() {
final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.reevaluateNetwork());
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index 06c6301..c74c112 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -28,8 +28,8 @@
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import static com.android.testutils.MiscAssertsKt.assertEqualBothWays;
+import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static com.android.testutils.MiscAssertsKt.assertNotEqualEitherWay;
-import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
import static org.junit.Assert.assertEquals;
@@ -38,11 +38,17 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.os.Build;
import android.os.SystemClock;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,6 +63,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LinkAddressTest {
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
private static final String V4 = "192.0.2.1";
private static final String V6 = "2001:db8::1";
@@ -318,15 +326,29 @@
l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
assertParcelingIsLossless(l);
- l = new LinkAddress(V6_ADDRESS, 64, 123, 456,
- 1L, 3600000L);
- assertParcelingIsLossless(l);
l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
- assertParcelSane(l, 6);
+ assertParcelingIsLossless(l);
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testLifetimeParceling() {
+ final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, 456, 1L, 3600000L);
+ assertParcelingIsLossless(l);
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.Q)
+ public void testFieldCount_Q() {
+ assertFieldCountEquals(4, LinkAddress.class);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testFieldCount() {
+ // Make sure any new field is covered by the above parceling tests when changing this number
+ assertFieldCountEquals(6, LinkAddress.class);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testDeprecationTime() {
try {
new LinkAddress(V6_ADDRESS, 64, 0, 456,
@@ -345,9 +367,12 @@
-2, 100000L);
fail("negative deprecation time should cause exception");
} catch (IllegalArgumentException expected) { }
+
+ LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L);
+ assertEquals(100000L, addr.getDeprecationTime());
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testExpirationTime() {
try {
new LinkAddress(V6_ADDRESS, 64, 0, 456,
@@ -360,16 +385,22 @@
100000L, -2);
fail("negative expiration time should cause exception");
} catch (IllegalArgumentException expected) { }
+
+ LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L);
+ assertEquals(200000L, addr.getExpirationTime());
}
@Test
public void testGetFlags() {
LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST);
assertEquals(123, l.getFlags());
+ }
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testGetFlags_Deprecation() {
// Test if deprecated bit was added/remove automatically based on the provided deprecation
// time
- l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
+ LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
1L, LinkAddress.LIFETIME_PERMANENT);
// Check if the flag is added automatically.
assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0);
@@ -458,8 +489,11 @@
(IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
RT_SCOPE_UNIVERSE);
assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
+ }
- l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testIsGlobalPreferred_DeprecatedInFuture() {
+ final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000,
SystemClock.elapsedRealtime() + 200000);
// Although the deprecated bit is set, but the deprecation time is in the future, test
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 3f311c9..48b65e5 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -27,8 +27,8 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.net.LinkProperties.CompareResult;
import android.net.LinkProperties.ProvisioningChange;
+import android.net.util.LinkPropertiesUtils.CompareResult;
import android.system.OsConstants;
import android.util.ArraySet;
@@ -315,7 +315,7 @@
source.addDnsServer(DNS1);
source.addDnsServer(DNS2);
// set 2 gateways
- source.addRoute(new RouteInfo(GATEWAY1));
+ source.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1));
source.addRoute(new RouteInfo(GATEWAY2));
source.setMtu(MTU);
@@ -327,7 +327,7 @@
target.addDnsServer(DNS2);
target.addDnsServer(DNS1);
target.addRoute(new RouteInfo(GATEWAY2));
- target.addRoute(new RouteInfo(GATEWAY1));
+ target.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1));
target.setMtu(MTU);
assertLinkPropertiesEqual(source, target);
@@ -364,12 +364,13 @@
@Test
public void testRouteInterfaces() {
- LinkAddress prefix = new LinkAddress(address("2001:db8::"), 32);
+ LinkAddress prefix1 = new LinkAddress(address("2001:db8:1::"), 48);
+ LinkAddress prefix2 = new LinkAddress(address("2001:db8:2::"), 48);
InetAddress address = ADDRV6;
// Add a route with no interface to a LinkProperties with no interface. No errors.
LinkProperties lp = new LinkProperties();
- RouteInfo r = new RouteInfo(prefix, address, null);
+ RouteInfo r = new RouteInfo(prefix1, address, null);
assertTrue(lp.addRoute(r));
assertEquals(1, lp.getRoutes().size());
assertAllRoutesHaveInterface(null, lp);
@@ -379,7 +380,7 @@
assertEquals(1, lp.getRoutes().size());
// Add a route with an interface. Expect an exception.
- r = new RouteInfo(prefix, address, "wlan0");
+ r = new RouteInfo(prefix2, address, "wlan0");
try {
lp.addRoute(r);
fail("Adding wlan0 route to LP with no interface, expect exception");
@@ -398,7 +399,7 @@
} catch (IllegalArgumentException expected) {}
// If the interface name matches, the route is added.
- r = new RouteInfo(prefix, null, "wlan0");
+ r = new RouteInfo(prefix2, null, "wlan0");
lp.setInterfaceName("wlan0");
lp.addRoute(r);
assertEquals(2, lp.getRoutes().size());
@@ -423,10 +424,12 @@
assertEquals(3, lp.compareAllRoutes(lp2).added.size());
assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
- // Check remove works
- lp.removeRoute(new RouteInfo(prefix, address, null));
+ // Remove route with incorrect interface, no route removed.
+ lp.removeRoute(new RouteInfo(prefix2, null, null));
assertEquals(3, lp.getRoutes().size());
- lp.removeRoute(new RouteInfo(prefix, address, "wlan0"));
+
+ // Check remove works when interface is correct.
+ lp.removeRoute(new RouteInfo(prefix2, null, "wlan0"));
assertEquals(2, lp.getRoutes().size());
assertAllRoutesHaveInterface("wlan0", lp);
assertAllRoutesNotHaveInterface("p2p0", lp);
diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
new file mode 100644
index 0000000..de65ba2
--- /dev/null
+++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.os.Build
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.assertParcelSane
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NetworkAgentConfigTest {
+ @Rule @JvmField
+ val ignoreRule = DevSdkIgnoreRule()
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testParcelNetworkAgentConfig() {
+ val config = NetworkAgentConfig.Builder().apply {
+ setExplicitlySelected(true)
+ setLegacyType(ConnectivityManager.TYPE_ETHERNET)
+ setSubscriberId("MySubId")
+ setPartialConnectivityAcceptable(false)
+ setUnvalidatedConnectivityAcceptable(true)
+ }.build()
+ assertParcelSane(config, 9)
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testBuilder() {
+ val config = NetworkAgentConfig.Builder().apply {
+ setExplicitlySelected(true)
+ setLegacyType(ConnectivityManager.TYPE_ETHERNET)
+ setSubscriberId("MySubId")
+ setPartialConnectivityAcceptable(false)
+ setUnvalidatedConnectivityAcceptable(true)
+ setLegacyTypeName("TEST_NETWORK")
+ disableNat64Detection()
+ disableProvisioningNotification()
+ }.build()
+
+ assertTrue(config.isExplicitlySelected())
+ assertEquals(ConnectivityManager.TYPE_ETHERNET, config.getLegacyType())
+ assertEquals("MySubId", config.getSubscriberId())
+ assertFalse(config.isPartialConnectivityAcceptable())
+ assertTrue(config.isUnvalidatedConnectivityAcceptable())
+ assertEquals("TEST_NETWORK", config.getLegacyTypeName())
+ assertFalse(config.isNat64DetectionEnabled())
+ assertFalse(config.isProvisioningNotificationEnabled())
+ }
+}
diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java
index fe51b3a..1658262 100644
--- a/tests/net/common/java/android/net/RouteInfoTest.java
+++ b/tests/net/common/java/android/net/RouteInfoTest.java
@@ -19,19 +19,40 @@
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static com.android.testutils.MiscAssertsKt.assertEqualBothWays;
+import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
import static com.android.testutils.MiscAssertsKt.assertNotEqualEitherWay;
-import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
-import android.test.suitebuilder.annotation.SmallTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
-import junit.framework.TestCase;
+import android.os.Build;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-public class RouteInfoTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RouteInfoTest {
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
+ private static final int INVALID_ROUTE_TYPE = -1;
private InetAddress Address(String addr) {
return InetAddress.parseNumericAddress(addr);
@@ -41,15 +62,32 @@
return new IpPrefix(prefix);
}
- @SmallTest
+ @Test
public void testConstructor() {
RouteInfo r;
-
// Invalid input.
try {
r = new RouteInfo((IpPrefix) null, null, "rmnet0");
fail("Expected RuntimeException: destination and gateway null");
- } catch(RuntimeException e) {}
+ } catch (RuntimeException e) { }
+
+ try {
+ r = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "rmnet0",
+ INVALID_ROUTE_TYPE);
+ fail("Invalid route type should cause exception");
+ } catch (IllegalArgumentException e) { }
+
+ try {
+ r = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("192.0.2.1"), "rmnet0",
+ RTN_UNREACHABLE);
+ fail("Address family mismatch should cause exception");
+ } catch (IllegalArgumentException e) { }
+
+ try {
+ r = new RouteInfo(Prefix("0.0.0.0/0"), Address("2001:db8::1"), "rmnet0",
+ RTN_UNREACHABLE);
+ fail("Address family mismatch should cause exception");
+ } catch (IllegalArgumentException e) { }
// Null destination is default route.
r = new RouteInfo((IpPrefix) null, Address("2001:db8::1"), null);
@@ -74,6 +112,7 @@
assertNull(r.getInterface());
}
+ @Test
public void testMatches() {
class PatchedRouteInfo {
private final RouteInfo mRouteInfo;
@@ -113,6 +152,7 @@
assertFalse(ipv4Default.matches(Address("2001:db8::f00")));
}
+ @Test
public void testEquals() {
// IPv4
RouteInfo r1 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0");
@@ -146,6 +186,7 @@
assertNotEqualEitherWay(r1, r3);
}
+ @Test
public void testHostAndDefaultRoutes() {
RouteInfo r;
@@ -228,6 +269,7 @@
assertFalse(r.isIPv6Default());
}
+ @Test
public void testTruncation() {
LinkAddress l;
RouteInfo r;
@@ -244,6 +286,7 @@
// Make sure that creating routes to multicast addresses doesn't throw an exception. Even though
// there's nothing we can do with them, we don't want to crash if, e.g., someone calls
// requestRouteToHostAddress("230.0.0.0", MOBILE_HIPRI);
+ @Test
public void testMulticastRoute() {
RouteInfo r;
r = new RouteInfo(Prefix("230.0.0.0/32"), Address("192.0.2.1"), "wlan0");
@@ -251,16 +294,36 @@
// No exceptions? Good.
}
+ @Test
public void testParceling() {
RouteInfo r;
-
- r = new RouteInfo(Prefix("::/0"), Address("2001:db8::"), null);
+ r = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), null);
assertParcelingIsLossless(r);
-
r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0");
- assertParcelSane(r, 7);
+ assertParcelingIsLossless(r);
+ r = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", RTN_UNREACHABLE);
+ assertParcelingIsLossless(r);
}
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testMtuParceling() {
+ final RouteInfo r = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::"), "testiface",
+ RTN_UNREACHABLE, 1450 /* mtu */);
+ assertParcelingIsLossless(r);
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.Q)
+ public void testFieldCount_Q() {
+ assertFieldCountEquals(6, RouteInfo.class);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testFieldCount() {
+ // Make sure any new field is covered by the above parceling tests when changing this number
+ assertFieldCountEquals(7, RouteInfo.class);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testMtu() {
RouteInfo r;
r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0",
diff --git a/tests/net/common/java/android/net/util/SocketUtilsTest.kt b/tests/net/common/java/android/net/util/SocketUtilsTest.kt
index 9c7cfb0..aaf97f3 100644
--- a/tests/net/common/java/android/net/util/SocketUtilsTest.kt
+++ b/tests/net/common/java/android/net/util/SocketUtilsTest.kt
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package android.net.util;
+package android.net.util
+import android.os.Build
import android.system.NetlinkSocketAddress
import android.system.Os
import android.system.OsConstants.AF_INET
@@ -26,18 +27,26 @@
import android.system.PacketSocketAddress
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
private const val TEST_INDEX = 123
private const val TEST_PORT = 555
+private const val FF_BYTE = 0xff.toByte()
+
@RunWith(AndroidJUnit4::class)
@SmallTest
class SocketUtilsTest {
+ @Rule @JvmField
+ val ignoreRule = DevSdkIgnoreRule()
+
@Test
fun testMakeNetlinkSocketAddress() {
val nlAddress = SocketUtils.makeNetlinkSocketAddress(TEST_PORT, RTMGRP_NEIGH)
@@ -50,16 +59,21 @@
}
@Test
- fun testMakePacketSocketAddress() {
+ fun testMakePacketSocketAddress_Q() {
val pkAddress = SocketUtils.makePacketSocketAddress(ETH_P_ALL, TEST_INDEX)
assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress)
- val ff = 0xff.toByte()
- val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX,
- byteArrayOf(ff, ff, ff, ff, ff, ff))
+ val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX, ByteArray(6) { FF_BYTE })
assertTrue("Not PacketSocketAddress object", pkAddress2 is PacketSocketAddress)
}
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testMakePacketSocketAddress() {
+ val pkAddress = SocketUtils.makePacketSocketAddress(
+ ETH_P_ALL, TEST_INDEX, ByteArray(6) { FF_BYTE })
+ assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress)
+ }
+
@Test
fun testCloseSocket() {
// Expect no exception happening with null object.
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index 490c467..23caf49 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
@@ -26,6 +26,7 @@
import android.os.IBinder
import com.android.networkstack.metrics.DataStallStatsUtils
import com.android.networkstack.netlink.TcpSocketTracker
+import com.android.server.NetworkStackService
import com.android.server.NetworkStackService.NetworkMonitorConnector
import com.android.server.NetworkStackService.NetworkStackConnector
import com.android.server.connectivity.NetworkMonitor
@@ -88,6 +89,7 @@
val nm = NetworkMonitor(this@TestNetworkStackService, cb,
this.network,
mock(IpConnectivityLog::class.java), mock(SharedLog::class.java),
+ mock(NetworkStackService.NetworkStackServiceManager::class.java),
NetworkMonitorDeps(privateDnsBypassNetwork),
mock(DataStallStatsUtils::class.java),
mock(TcpSocketTracker::class.java))
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 1c69209..a35fb40 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -222,7 +222,7 @@
@Override
public Network getNetwork() {
- return mNetworkAgent.network;
+ return mNetworkAgent.getNetwork();
}
public void expectPreventReconnectReceived(long timeoutMs) {
diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java
index d6a2176..2273bc6 100644
--- a/tests/net/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java
@@ -22,7 +22,6 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
import android.test.mock.MockContext;
@@ -232,10 +231,12 @@
builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
final VpnProfile profile = builder.build().toVpnProfile();
+ final String expectedSecret = Ikev2VpnProfile.PREFIX_INLINE
+ + Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded());
verifyVpnProfileCommon(profile);
assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert);
assertEquals(
- Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded()),
+ expectedSecret,
profile.ipsecSecret);
assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index daf187d..91c9a2a 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -22,6 +22,8 @@
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;
@@ -122,11 +124,11 @@
for (MacAddress mac : multicastAddresses) {
String msg = mac.toString() + " expected to be a multicast address";
- assertTrue(msg, mac.isMulticastAddress());
+ assertTrue(msg, MacAddressUtils.isMulticastAddress(mac));
}
for (MacAddress mac : unicastAddresses) {
String msg = mac.toString() + " expected not to be a multicast address";
- assertFalse(msg, mac.isMulticastAddress());
+ assertFalse(msg, MacAddressUtils.isMulticastAddress(mac));
}
}
@@ -156,7 +158,7 @@
public void testMacAddressConversions() {
final int iterations = 10000;
for (int i = 0; i < iterations; i++) {
- MacAddress mac = MacAddress.createRandomUnicastAddress();
+ MacAddress mac = MacAddressUtils.createRandomUnicastAddress();
String stringRepr = mac.toString();
byte[] bytesRepr = mac.toByteArray();
@@ -188,7 +190,7 @@
final String expectedLocalOui = "26:5f:78";
final MacAddress base = MacAddress.fromString(anotherOui + ":0:0:0");
for (int i = 0; i < iterations; i++) {
- MacAddress mac = MacAddress.createRandomUnicastAddress(base, r);
+ MacAddress mac = MacAddressUtils.createRandomUnicastAddress(base, r);
String stringRepr = mac.toString();
assertTrue(stringRepr + " expected to be a locally assigned address",
@@ -199,7 +201,7 @@
}
for (int i = 0; i < iterations; i++) {
- MacAddress mac = MacAddress.createRandomUnicastAddress();
+ MacAddress mac = MacAddressUtils.createRandomUnicastAddress();
String stringRepr = mac.toString();
assertTrue(stringRepr + " expected to be a locally assigned address",
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 47b3461..6985415 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,8 +23,6 @@
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
-import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
@@ -78,6 +76,7 @@
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.RouteInfo.RTN_UNREACHABLE;
+import static android.system.OsConstants.IPPROTO_TCP;
import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType;
import static com.android.testutils.ConcurrentUtilsKt.await;
@@ -99,6 +98,7 @@
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.startsWith;
import static org.mockito.Matchers.anyInt;
@@ -138,6 +138,7 @@
import android.content.res.Resources;
import android.location.LocationManager;
import android.net.CaptivePortalData;
+import android.net.ConnectionInfo;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.ConnectivityManager.PacketKeepalive;
@@ -153,6 +154,7 @@
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
+import android.net.InetAddresses;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.IpSecManager;
@@ -176,6 +178,7 @@
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.net.Uri;
+import android.net.VpnManager;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
@@ -200,6 +203,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.security.KeyStore;
import android.system.Os;
import android.test.mock.MockContentResolver;
import android.text.TextUtils;
@@ -272,6 +276,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
+import java.util.function.Supplier;
import kotlin.reflect.KClass;
@@ -445,15 +450,21 @@
return mPackageManager;
}
+ private int checkMockedPermission(String permission, Supplier<Integer> ifAbsent) {
+ final Integer granted = mMockedPermissions.get(permission);
+ return granted != null ? granted : ifAbsent.get();
+ }
+
@Override
public int checkPermission(String permission, int pid, int uid) {
- final Integer granted = mMockedPermissions.get(permission);
- if (granted == null) {
- // All non-mocked permissions should be held by the test or unnecessary: check as
- // normal to make sure the code does not rely on unexpected permissions.
- return super.checkPermission(permission, pid, uid);
- }
- return granted;
+ return checkMockedPermission(
+ permission, () -> super.checkPermission(permission, pid, uid));
+ }
+
+ @Override
+ public int checkCallingOrSelfPermission(String permission) {
+ return checkMockedPermission(
+ permission, () -> super.checkCallingOrSelfPermission(permission));
}
@Override
@@ -635,7 +646,7 @@
}
};
- assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId);
+ assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId);
mNmCallbacks = nmCbCaptor.getValue();
mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
@@ -1002,12 +1013,13 @@
// Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
// not inherit from NetworkAgent.
private TestNetworkAgentWrapper mMockNetworkAgent;
+ private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
private VpnInfo mVpnInfo;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
- userId);
+ userId, mock(KeyStore.class));
}
public void setNetworkAgent(TestNetworkAgentWrapper agent) {
@@ -1022,6 +1034,10 @@
updateCapabilities(null /* defaultNetwork */);
}
+ public void setVpnType(int vpnType) {
+ mVpnType = vpnType;
+ }
+
@Override
public int getNetId() {
if (mMockNetworkAgent == null) {
@@ -1040,6 +1056,11 @@
return mConnected; // Similar trickery
}
+ @Override
+ public int getActiveAppVpnType() {
+ return mVpnType;
+ }
+
private void connect(boolean isAlwaysMetered) {
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mConnected = true;
@@ -1158,6 +1179,10 @@
Arrays.asList(new UserInfo[] {
new UserInfo(VPN_USER, "", 0),
}));
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+ when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
+ .thenReturn(applicationInfo);
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
@@ -3014,7 +3039,7 @@
networkCapabilities.addTransportType(TRANSPORT_WIFI)
.setNetworkSpecifier(new MatchAllNetworkSpecifier());
mService.requestNetwork(networkCapabilities, null, 0, null,
- ConnectivityManager.TYPE_WIFI, TEST_PACKAGE_NAME);
+ ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
});
class NonParcelableSpecifier extends NetworkSpecifier {
@@ -5896,6 +5921,12 @@
final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
final String kNat64PrefixString = "2001:db8:64:64:64:64::";
final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96);
+ final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(),
+ MOBILE_IFNAME);
+ final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME);
+ final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME);
+ final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(),
+ CLAT_PREFIX + MOBILE_IFNAME);
final NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(TRANSPORT_CELLULAR)
@@ -5908,15 +5939,13 @@
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
cellLp.addLinkAddress(myIpv6);
- cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
- cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
+ cellLp.addRoute(defaultRoute);
+ cellLp.addRoute(ipv6Subnet);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
reset(mNetworkManagementService);
reset(mMockDnsResolver);
reset(mMockNetd);
reset(mBatteryStatsService);
- when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
- .thenReturn(getClatInterfaceConfig(myIpv4));
// Connect with ipv6 link properties. Expect prefix discovery to be started.
mCellNetworkAgent.connect(true);
@@ -5924,6 +5953,7 @@
waitForIdle();
verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt());
+ assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute);
verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(),
TYPE_MOBILE);
@@ -5939,6 +5969,7 @@
cellLp.addLinkAddress(myIpv4);
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+ assertRoutesAdded(cellNetId, ipv4Subnet);
verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
@@ -5949,15 +5980,18 @@
verifyNoMoreInteractions(mMockNetd);
verifyNoMoreInteractions(mMockDnsResolver);
+ reset(mNetworkManagementService);
reset(mMockNetd);
reset(mMockDnsResolver);
+ when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
+ .thenReturn(getClatInterfaceConfig(myIpv4));
// Remove IPv4 address. Expect prefix discovery to be started again.
cellLp.removeLinkAddress(myIpv4);
- cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
+ assertRoutesRemoved(cellNetId, ipv4Subnet);
// When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent);
@@ -5976,6 +6010,7 @@
List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
.getStackedLinks();
assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
+ assertRoutesAdded(cellNetId, stackedDefault);
// Change trivial linkproperties and see if stacked link is preserved.
cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
@@ -6001,9 +6036,10 @@
// Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
// linkproperties are cleaned up.
cellLp.addLinkAddress(myIpv4);
- cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
+ cellLp.addRoute(ipv4Subnet);
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+ assertRoutesAdded(cellNetId, ipv4Subnet);
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
@@ -6014,6 +6050,7 @@
expected.setNat64Prefix(kNat64Prefix);
assertEquals(expected, actualLpAfterIpv4);
assertEquals(0, actualLpAfterIpv4.getStackedLinks().size());
+ assertRoutesRemoved(cellNetId, stackedDefault);
// The interface removed callback happens but has no effect after stop is called.
clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
@@ -6021,8 +6058,11 @@
verifyNoMoreInteractions(mMockNetd);
verifyNoMoreInteractions(mMockDnsResolver);
+ reset(mNetworkManagementService);
reset(mMockNetd);
reset(mMockDnsResolver);
+ when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
+ .thenReturn(getClatInterfaceConfig(myIpv4));
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
@@ -6036,6 +6076,7 @@
cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+ assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added.
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kNat64PrefixString, 96);
@@ -6047,15 +6088,20 @@
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
+ assertRoutesAdded(cellNetId, stackedDefault);
// NAT64 prefix is removed. Expect that clat is stopped.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
kNat64PrefixString, 96);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
+ assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault);
+
+ // Stop has no effect because clat is already stopped.
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
(lp) -> lp.getStackedLinks().size() == 0);
+ verifyNoMoreInteractions(mMockNetd);
// Clean up.
mCellNetworkAgent.disconnect();
@@ -6411,17 +6457,173 @@
assertEquals(wifiLp, mService.getActiveLinkProperties());
}
+ private void setupLocationPermissions(
+ int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = targetSdk;
+ when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
+ .thenReturn(applicationInfo);
+
+ when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
+
+ if (op != null) {
+ when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
+ .thenReturn(AppOpsManager.MODE_ALLOWED);
+ }
+
+ if (perm != null) {
+ mServiceContext.setPermission(perm, PERMISSION_GRANTED);
+ }
+ }
+
+ private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
+ final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
+
+ return mService
+ .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
+ .getOwnerUid();
+ }
+
@Test
- public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
- int callerUid = Process.myUid();
- final NetworkCapabilities originalNc = new NetworkCapabilities();
- originalNc.setOwnerUid(callerUid);
+ public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
- final NetworkCapabilities newNc =
- mService.networkCapabilitiesRestrictedForCallerPermissions(
- originalNc, Process.myPid(), callerUid);
+ final int myUid = Process.myUid();
+ assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+ }
- assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
+ @Test
+ public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
+ setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION);
+
+ final int myUid = Process.myUid();
+ assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+ }
+
+ @Test
+ public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
+ // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
+ setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
+
+ final int myUid = Process.myUid();
+ assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+ }
+
+ @Test
+ public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
+ // Test that even with fine location permission, not being the owner leads to sanitization.
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
+
+ final int myUid = Process.myUid();
+ assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
+ }
+
+ @Test
+ public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
+ // Test that not having fine location permission leads to sanitization.
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION);
+
+ // Test that without the location permission, the owner field is sanitized.
+ final int myUid = Process.myUid();
+ assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+ }
+
+ @Test
+ public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
+
+ // Test that without the location permission, the owner field is sanitized.
+ final int myUid = Process.myUid();
+ assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+ }
+
+ private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
+ throws Exception {
+ final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
+ establishVpn(new LinkProperties(), vpnOwnerUid, vpnRange);
+ mMockVpn.setVpnType(vpnType);
+
+ final VpnInfo vpnInfo = new VpnInfo();
+ vpnInfo.ownerUid = vpnOwnerUid;
+ mMockVpn.setVpnInfo(vpnInfo);
+ }
+
+ private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
+ throws Exception {
+ setupConnectionOwnerUid(vpnOwnerUid, vpnType);
+
+ // Test as VPN app
+ mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
+ }
+
+ private ConnectionInfo getTestConnectionInfo() throws Exception {
+ return new ConnectionInfo(
+ IPPROTO_TCP,
+ new InetSocketAddress(InetAddresses.parseNumericAddress("1.2.3.4"), 1234),
+ new InetSocketAddress(InetAddresses.parseNumericAddress("2.3.4.5"), 2345));
+ }
+
+ @Test
+ public void testGetConnectionOwnerUidPlatformVpn() throws Exception {
+ final int myUid = Process.myUid();
+ setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_PLATFORM);
+
+ try {
+ mService.getConnectionOwnerUid(getTestConnectionInfo());
+ fail("Expected SecurityException for non-VpnService app");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testGetConnectionOwnerUidVpnServiceWrongUser() throws Exception {
+ final int myUid = Process.myUid();
+ setupConnectionOwnerUidAsVpnApp(myUid + 1, VpnManager.TYPE_VPN_SERVICE);
+
+ try {
+ mService.getConnectionOwnerUid(getTestConnectionInfo());
+ fail("Expected SecurityException for non-VpnService app");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testGetConnectionOwnerUidVpnServiceDoesNotThrow() throws Exception {
+ final int myUid = Process.myUid();
+ setupConnectionOwnerUidAsVpnApp(myUid, VpnManager.TYPE_VPN_SERVICE);
+
+ // TODO: Test the returned UID
+ mService.getConnectionOwnerUid(getTestConnectionInfo());
+ }
+
+ @Test
+ public void testGetConnectionOwnerUidVpnServiceNetworkStackDoesNotThrow() throws Exception {
+ final int myUid = Process.myUid();
+ setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
+ mServiceContext.setPermission(
+ android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
+
+ // TODO: Test the returned UID
+ mService.getConnectionOwnerUid(getTestConnectionInfo());
+ }
+
+ @Test
+ public void testGetConnectionOwnerUidVpnServiceMainlineNetworkStackDoesNotThrow()
+ throws Exception {
+ final int myUid = Process.myUid();
+ setupConnectionOwnerUid(myUid, VpnManager.TYPE_VPN_SERVICE);
+ mServiceContext.setPermission(
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
+
+ // TODO: Test the returned UID
+ mService.getConnectionOwnerUid(getTestConnectionInfo());
}
private TestNetworkAgentWrapper establishVpn(
@@ -6467,6 +6669,20 @@
}
}
+ private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
+ InOrder inOrder = inOrder(mNetworkManagementService);
+ for (int i = 0; i < routes.length; i++) {
+ inOrder.verify(mNetworkManagementService).addRoute(eq(netId), eq(routes[i]));
+ }
+ }
+
+ private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
+ InOrder inOrder = inOrder(mNetworkManagementService);
+ for (int i = 0; i < routes.length; i++) {
+ inOrder.verify(mNetworkManagementService).removeRoute(eq(netId), eq(routes[i]));
+ }
+ }
+
@Test
public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest wifiRequest =
@@ -6528,7 +6744,7 @@
public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
- null, null, null, null, null, new NetworkCapabilities(), null,
+ null, null, null, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0);
mServiceContext.setPermission(
@@ -6544,7 +6760,7 @@
public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
- null, null, null, null, null, new NetworkCapabilities(), null,
+ null, null, null, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0);
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
@@ -6560,7 +6776,7 @@
public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
- null, null, null, null, null, new NetworkCapabilities(), null,
+ null, null, null, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -6586,7 +6802,7 @@
nc.setAdministratorUids(Arrays.asList(Process.myUid()));
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
- null, null, null, null, null, nc, null, mServiceContext, null, null,
+ null, null, null, null, null, nc, 0, mServiceContext, null, null,
mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -6608,7 +6824,7 @@
nc.setAdministratorUids(Arrays.asList(Process.myUid()));
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
- null, null, null, null, null, nc, null, mServiceContext, null, null,
+ null, null, null, null, null, nc, 0, mServiceContext, null, null,
mService, null, null, null, 0);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
@@ -6623,21 +6839,6 @@
mContext.getOpPackageName()));
}
- private void setupLocationPermissions(
- int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
- final ApplicationInfo applicationInfo = new ApplicationInfo();
- applicationInfo.targetSdkVersion = targetSdk;
- when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
- .thenReturn(applicationInfo);
-
- when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
-
- when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
- .thenReturn(AppOpsManager.MODE_ALLOWED);
-
- mServiceContext.setPermission(perm, PERMISSION_GRANTED);
- }
-
private void setUpConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
@@ -6668,8 +6869,13 @@
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
// Verify onConnectivityReport fired
- verify(mConnectivityDiagnosticsCallback)
- .onConnectivityReport(any(ConnectivityReport.class));
+ verify(mConnectivityDiagnosticsCallback).onConnectivityReport(
+ argThat(report -> {
+ final NetworkCapabilities nc = report.getNetworkCapabilities();
+ return nc.getUids() == null
+ && nc.getAdministratorUids().isEmpty()
+ && nc.getOwnerUid() == Process.INVALID_UID;
+ }));
}
@Test
@@ -6684,7 +6890,13 @@
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
// Verify onDataStallSuspected fired
- verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(any(DataStallReport.class));
+ verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(
+ argThat(report -> {
+ final NetworkCapabilities nc = report.getNetworkCapabilities();
+ return nc.getUids() == null
+ && nc.getAdministratorUids().isEmpty()
+ && nc.getOwnerUid() == Process.INVALID_UID;
+ }));
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index e863266..24a8717 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -38,7 +38,6 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkProvider;
-import android.net.NetworkScore;
import android.os.INetworkManagementService;
import android.text.format.DateUtils;
@@ -353,10 +352,8 @@
NetworkCapabilities caps = new NetworkCapabilities();
caps.addCapability(0);
caps.addTransportType(transport);
- NetworkScore ns = new NetworkScore();
- ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
- caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
+ caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
NetworkProvider.ID_NONE);
nai.everValidated = true;
return nai;
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index eb78529..1994d1f 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -59,9 +59,15 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.net.Ikev2VpnProfile;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.IpSecManager;
+import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
import android.net.UidRange;
import android.net.VpnManager;
import android.net.VpnService;
@@ -72,6 +78,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
import android.util.ArrayMap;
@@ -83,6 +90,7 @@
import com.android.internal.R;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
+import com.android.server.IpSecService;
import org.junit.Before;
import org.junit.Test;
@@ -92,6 +100,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -124,6 +133,9 @@
}
static final String TEST_VPN_PKG = "com.dummy.vpn";
+ private static final String TEST_VPN_SERVER = "1.2.3.4";
+ private static final String TEST_VPN_IDENTITY = "identity";
+ private static final byte[] TEST_VPN_PSK = "psk".getBytes();
/**
* Names and UIDs for some fake packages. Important points:
@@ -150,23 +162,39 @@
@Mock private Vpn.SystemServices mSystemServices;
@Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator;
@Mock private ConnectivityManager mConnectivityManager;
+ @Mock private IpSecService mIpSecService;
@Mock private KeyStore mKeyStore;
- private final VpnProfile mVpnProfile = new VpnProfile("key");
+ private final VpnProfile mVpnProfile;
+
+ private IpSecManager mIpSecManager;
+
+ public VpnTest() throws Exception {
+ // Build an actual VPN profile that is capable of being converted to and from an
+ // Ikev2VpnProfile
+ final Ikev2VpnProfile.Builder builder =
+ new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY);
+ builder.setAuthPsk(TEST_VPN_PSK);
+ mVpnProfile = builder.build().toVpnProfile();
+ }
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mIpSecManager = new IpSecManager(mContext, mIpSecService);
+
when(mContext.getPackageManager()).thenReturn(mPackageManager);
setMockedPackages(mPackages);
- when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName());
+ when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG);
+ when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
.thenReturn(mConnectivityManager);
+ when(mContext.getSystemService(eq(Context.IPSEC_SERVICE))).thenReturn(mIpSecManager);
when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
.thenReturn(Resources.getSystem().getString(
R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
@@ -260,17 +288,17 @@
assertFalse(vpn.getLockdown());
// Set always-on without lockdown.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList()));
+ assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList(), mKeyStore));
assertTrue(vpn.getAlwaysOn());
assertFalse(vpn.getLockdown());
// Set always-on with lockdown.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList()));
+ assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList(), mKeyStore));
assertTrue(vpn.getAlwaysOn());
assertTrue(vpn.getLockdown());
// Remove always-on configuration.
- assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList()));
+ assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList(), mKeyStore));
assertFalse(vpn.getAlwaysOn());
assertFalse(vpn.getLockdown());
}
@@ -284,11 +312,11 @@
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));
+ 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]);
// Set always-on with lockdown.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
+ 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)
@@ -297,7 +325,7 @@
assertUnblocked(vpn, user.start + PKG_UIDS[1]);
// Switch to another app.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
+ 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)
@@ -316,7 +344,8 @@
final UidRange user = UidRange.createForUser(primaryUser.id);
// Set always-on with lockdown and whitelist app PKGS[2] from lockdown.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[2])));
+ 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)
@@ -325,7 +354,8 @@
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
// Change whitelisted app to PKGS[3].
- assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(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)
}));
@@ -337,7 +367,8 @@
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
// Change the VPN app.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[3])));
+ 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)
@@ -350,7 +381,7 @@
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
// Remove the whitelist.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
+ 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)
@@ -363,7 +394,8 @@
assertUnblocked(vpn, user.start + PKG_UIDS[0]);
// Add the whitelist.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[1])));
+ 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)
}));
@@ -375,12 +407,13 @@
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
// Try whitelisting a package with a comma, should be rejected.
- assertFalse(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList("a.b,c.d")));
+ assertFalse(vpn.setAlwaysOnPackage(
+ PKGS[0], true, Collections.singletonList("a.b,c.d"), mKeyStore));
// Pass a non-existent packages in the whitelist, they (and only they) should be ignored.
// Whitelisted 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")));
+ 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)
@@ -405,7 +438,7 @@
final UidRange profile = UidRange.createForUser(tempProfile.id);
// Set lockdown.
- assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
+ 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)
@@ -499,22 +532,22 @@
.thenReturn(Collections.singletonList(resInfo));
// null package name should return false
- assertFalse(vpn.isAlwaysOnPackageSupported(null));
+ assertFalse(vpn.isAlwaysOnPackageSupported(null, mKeyStore));
// Pre-N apps are not supported
appInfo.targetSdkVersion = VERSION_CODES.M;
- assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
+ assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore));
// N+ apps are supported by default
appInfo.targetSdkVersion = VERSION_CODES.N;
- assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0]));
+ assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore));
// Apps that opt out explicitly are not supported
appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT;
Bundle metaData = new Bundle();
metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false);
svcInfo.metaData = metaData;
- assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
+ assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore));
}
@Test
@@ -531,7 +564,7 @@
.cancelAsUser(anyString(), anyInt(), eq(userHandle));
// Start showing a notification for disconnected once always-on.
- vpn.setAlwaysOnPackage(PKGS[0], false, null);
+ vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore);
order.verify(mNotificationManager)
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
@@ -545,7 +578,7 @@
.notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
// Notification should be cleared after unsetting always-on package.
- vpn.setAlwaysOnPackage(null, false, null);
+ vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
}
@@ -656,8 +689,12 @@
}
private Vpn createVpnAndSetupUidChecks(int... grantedOps) throws Exception {
- final Vpn vpn = createVpn(primaryUser.id);
- setMockedUsers(primaryUser);
+ return createVpnAndSetupUidChecks(primaryUser, grantedOps);
+ }
+
+ private Vpn createVpnAndSetupUidChecks(UserInfo user, int... grantedOps) throws Exception {
+ final Vpn vpn = createVpn(user.id);
+ setMockedUsers(user);
when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt()))
.thenReturn(Process.myUid());
@@ -726,6 +763,19 @@
}
@Test
+ public void testProvisionVpnProfileRestrictedUser() throws Exception {
+ final Vpn vpn =
+ createVpnAndSetupUidChecks(
+ restrictedProfileA, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);
+
+ try {
+ vpn.provisionVpnProfile(TEST_VPN_PKG, mVpnProfile, mKeyStore);
+ fail("Expected SecurityException due to restricted user");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
public void testDeleteVpnProfile() throws Exception {
final Vpn vpn = createVpnAndSetupUidChecks();
@@ -736,6 +786,19 @@
}
@Test
+ public void testDeleteVpnProfileRestrictedUser() throws Exception {
+ final Vpn vpn =
+ createVpnAndSetupUidChecks(
+ restrictedProfileA, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);
+
+ try {
+ vpn.deleteVpnProfile(TEST_VPN_PKG, mKeyStore);
+ fail("Expected SecurityException due to restricted user");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
public void testGetVpnProfilePrivileged() throws Exception {
final Vpn vpn = createVpnAndSetupUidChecks();
@@ -820,6 +883,32 @@
}
@Test
+ public void testStartVpnProfileRestrictedUser() throws Exception {
+ final Vpn vpn =
+ createVpnAndSetupUidChecks(
+ restrictedProfileA, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);
+
+ try {
+ vpn.startVpnProfile(TEST_VPN_PKG, mKeyStore);
+ fail("Expected SecurityException due to restricted user");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testStopVpnProfileRestrictedUser() throws Exception {
+ final Vpn vpn =
+ createVpnAndSetupUidChecks(
+ restrictedProfileA, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN);
+
+ try {
+ vpn.stopVpnProfile(TEST_VPN_PKG);
+ fail("Expected SecurityException due to restricted user");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
public void testSetPackageAuthorizationVpnService() throws Exception {
final Vpn vpn = createVpnAndSetupUidChecks();
@@ -864,12 +953,68 @@
eq(AppOpsManager.MODE_IGNORED));
}
+ private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) {
+ assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null, mKeyStore));
+
+ verify(mKeyStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
+ verify(mAppOps).setMode(
+ eq(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG),
+ eq(AppOpsManager.MODE_ALLOWED));
+
+ verify(mSystemServices).settingsSecurePutStringForUser(
+ eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(primaryUser.id));
+ verify(mSystemServices).settingsSecurePutIntForUser(
+ eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0),
+ eq(primaryUser.id));
+ verify(mSystemServices).settingsSecurePutStringForUser(
+ eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(primaryUser.id));
+ }
+
+ @Test
+ public void testSetAndStartAlwaysOnVpn() throws Exception {
+ final Vpn vpn = createVpn(primaryUser.id);
+ setMockedUsers(primaryUser);
+
+ // UID checks must return a different UID; otherwise it'll be treated as already prepared.
+ final int uid = Process.myUid() + 1;
+ when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt()))
+ .thenReturn(uid);
+ when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
+ .thenReturn(mVpnProfile.encode());
+
+ setAndVerifyAlwaysOnPackage(vpn, uid, false);
+ assertTrue(vpn.startAlwaysOnVpn(mKeyStore));
+
+ // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
+ // a subsequent CL.
+ }
+
+ @Test
+ public void testStartLegacyVpn() throws Exception {
+ final Vpn vpn = createVpn(primaryUser.id);
+ setMockedUsers(primaryUser);
+
+ // Dummy egress interface
+ final String egressIface = "DUMMY0";
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(egressIface);
+
+ final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
+ InetAddresses.parseNumericAddress("192.0.2.0"), egressIface);
+ lp.addRoute(defaultRoute);
+
+ vpn.startLegacyVpn(mVpnProfile, mKeyStore, lp);
+
+ // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
+ // a subsequent CL.
+ }
+
/**
* Mock some methods of vpn object.
*/
private Vpn createVpn(@UserIdInt int userId) {
return new Vpn(Looper.myLooper(), mContext, mNetService,
- userId, mSystemServices, mIkev2SessionCreator);
+ userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
}
private static void assertBlocked(Vpn vpn, int... uids) {
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index a9e0b9a..36deca3 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -64,6 +64,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
@@ -163,7 +164,6 @@
private @Mock IBinder mBinder;
private @Mock AlarmManager mAlarmManager;
private HandlerThread mHandlerThread;
- private Handler mHandler;
private NetworkStatsService mService;
private INetworkStatsSession mSession;
@@ -192,15 +192,11 @@
PowerManager.WakeLock wakeLock =
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mService = new NetworkStatsService(
- mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock,
- mServiceContext.getSystemService(TelephonyManager.class), mSettings,
- mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir));
mHandlerThread = new HandlerThread("HandlerThread");
- mHandlerThread.start();
- Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService);
- mHandler = new Handler(mHandlerThread.getLooper(), callback);
- mService.setHandler(mHandler, callback);
+ final NetworkStatsService.Dependencies deps = makeDependencies();
+ mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock,
+ mClock, mServiceContext.getSystemService(TelephonyManager.class), mSettings,
+ mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps);
mElapsedRealtime = 0L;
@@ -217,11 +213,21 @@
// catch INetworkManagementEventObserver during systemReady()
ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
- ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
}
+ @NonNull
+ private NetworkStatsService.Dependencies makeDependencies() {
+ return new NetworkStatsService.Dependencies() {
+ @Override
+ public HandlerThread makeHandlerThread() {
+ return mHandlerThread;
+ }
+ };
+ }
+
@After
public void tearDown() throws Exception {
IoUtils.deleteContents(mStatsDir);
@@ -234,6 +240,8 @@
mSession.close();
mService = null;
+
+ mHandlerThread.quitSafely();
}
@Test
@@ -939,9 +947,7 @@
long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB
assertEquals(minThresholdInBytes, request.thresholdInBytes);
- // Send dummy message to make sure that any previous message has been handled
- mHandler.sendMessage(mHandler.obtainMessage(-1));
- HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT);
+ HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
// Make sure that the caller binder gets connected
verify(mBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
@@ -1077,7 +1083,7 @@
// Simulates alert quota of the provider has been reached.
cb.onAlertReached();
- HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT);
+ HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
// Verifies that polling is triggered by alert reached.
provider.expectStatsUpdate(0 /* unused */);
@@ -1294,9 +1300,7 @@
private void forcePollAndWaitForIdle() {
mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
- // Send dummy message to make sure that any previous message has been handled
- mHandler.sendMessage(mHandler.obtainMessage(-1));
- HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT);
+ HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
}
static class LatchedHandler extends Handler {