Merge "Add ServiceExpiredCallback" into main
diff --git a/Tethering/common/TetheringLib/api/current.txt b/Tethering/common/TetheringLib/api/current.txt
index 14191eb..d802177 100644
--- a/Tethering/common/TetheringLib/api/current.txt
+++ b/Tethering/common/TetheringLib/api/current.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/Tethering/common/TetheringLib/api/module-lib-current.txt b/Tethering/common/TetheringLib/api/module-lib-current.txt
index f09b26d..460c216 100644
--- a/Tethering/common/TetheringLib/api/module-lib-current.txt
+++ b/Tethering/common/TetheringLib/api/module-lib-current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public final class TetheringConstants {
diff --git a/Tethering/common/TetheringLib/api/module-lib-removed.txt b/Tethering/common/TetheringLib/api/module-lib-removed.txt
index 14191eb..d802177 100644
--- a/Tethering/common/TetheringLib/api/module-lib-removed.txt
+++ b/Tethering/common/TetheringLib/api/module-lib-removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/Tethering/common/TetheringLib/api/removed.txt b/Tethering/common/TetheringLib/api/removed.txt
index 14191eb..d802177 100644
--- a/Tethering/common/TetheringLib/api/removed.txt
+++ b/Tethering/common/TetheringLib/api/removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/Tethering/common/TetheringLib/api/system-current.txt b/Tethering/common/TetheringLib/api/system-current.txt
index 83cee25..844ff64 100644
--- a/Tethering/common/TetheringLib/api/system-current.txt
+++ b/Tethering/common/TetheringLib/api/system-current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public final class TetheredClient implements android.os.Parcelable {
diff --git a/Tethering/common/TetheringLib/api/system-removed.txt b/Tethering/common/TetheringLib/api/system-removed.txt
index 14191eb..d802177 100644
--- a/Tethering/common/TetheringLib/api/system-removed.txt
+++ b/Tethering/common/TetheringLib/api/system-removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
index 81d4fbe..60f2d17 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
@@ -44,6 +44,7 @@
import com.android.net.module.util.netlink.NetlinkUtils;
import com.android.net.module.util.netlink.StructNlMsgHdr;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -84,6 +85,14 @@
mOffloadHw = new OffloadHardwareInterface(mHandler, mLog, mDeps);
}
+ @After
+ public void tearDown() throws Exception {
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ mHandlerThread.join();
+ }
+ }
+
void findConnectionOrThrow(FileDescriptor fd, InetSocketAddress local, InetSocketAddress remote)
throws Exception {
Log.d(TAG, "Looking for socket " + local + " -> " + remote);
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index e4b211f..86745d4 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.app.usage {
public final class NetworkStats implements java.lang.AutoCloseable {
diff --git a/framework-t/api/module-lib-current.txt b/framework-t/api/module-lib-current.txt
index fd42a37..5a8d47b 100644
--- a/framework-t/api/module-lib-current.txt
+++ b/framework-t/api/module-lib-current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.app.usage {
public class NetworkStatsManager {
diff --git a/framework-t/api/module-lib-removed.txt b/framework-t/api/module-lib-removed.txt
index 14191eb..d802177 100644
--- a/framework-t/api/module-lib-removed.txt
+++ b/framework-t/api/module-lib-removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/framework-t/api/removed.txt b/framework-t/api/removed.txt
index d9d243d..1ba87d8 100644
--- a/framework-t/api/removed.txt
+++ b/framework-t/api/removed.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public class TrafficStats {
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index 9bdb595..f6b5657 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.app.usage {
public class NetworkStatsManager {
@@ -307,6 +305,7 @@
ctor public NetworkStats(long, int);
method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
+ method public android.net.NetworkStats clone();
method public int describeContents();
method @NonNull public java.util.Iterator<android.net.NetworkStats.Entry> iterator();
method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
diff --git a/framework-t/api/system-removed.txt b/framework-t/api/system-removed.txt
index 14191eb..d802177 100644
--- a/framework-t/api/system-removed.txt
+++ b/framework-t/api/system-removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/framework-t/src/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java
index e4d6e24..90c0361 100644
--- a/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ b/framework-t/src/android/net/EthernetNetworkSpecifier.java
@@ -26,8 +26,6 @@
/**
* A {@link NetworkSpecifier} used to identify ethernet interfaces.
- *
- * @see EthernetManager
*/
public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable {
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 4f00977..6860c3c 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public class CaptivePortal implements android.os.Parcelable {
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index ac57c10..193bd92 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public final class ConnectivityFrameworkInitializer {
diff --git a/framework/api/module-lib-removed.txt b/framework/api/module-lib-removed.txt
index 14191eb..d802177 100644
--- a/framework/api/module-lib-removed.txt
+++ b/framework/api/module-lib-removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/framework/api/removed.txt b/framework/api/removed.txt
index f5da46a..303a1e6 100644
--- a/framework/api/removed.txt
+++ b/framework/api/removed.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public class ConnectivityManager {
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index cd120e9..e812024 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -1,6 +1,4 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
package android.net {
public class CaptivePortal implements android.os.Parcelable {
@@ -96,6 +94,7 @@
}
public final class DscpPolicy implements android.os.Parcelable {
+ method public int describeContents();
method @Nullable public java.net.InetAddress getDestinationAddress();
method @Nullable public android.util.Range<java.lang.Integer> getDestinationPortRange();
method public int getDscpValue();
@@ -103,6 +102,7 @@
method public int getProtocol();
method @Nullable public java.net.InetAddress getSourceAddress();
method public int getSourcePort();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.DscpPolicy> CREATOR;
field public static final int PROTOCOL_ANY = -1; // 0xffffffff
field public static final int SOURCE_PORT_ANY = -1; // 0xffffffff
diff --git a/framework/api/system-removed.txt b/framework/api/system-removed.txt
index 14191eb..d802177 100644
--- a/framework/api/system-removed.txt
+++ b/framework/api/system-removed.txt
@@ -1,3 +1 @@
// Signature format: 2.0
-// - add-additional-overrides=no
-// - migrating=Migration in progress see b/299366704
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 74d50f8..f959114 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -453,6 +453,7 @@
NET_CAPABILITY_MMTEL,
NET_CAPABILITY_PRIORITIZE_LATENCY,
NET_CAPABILITY_PRIORITIZE_BANDWIDTH,
+ NET_CAPABILITY_LOCAL_NETWORK,
})
public @interface NetCapability { }
@@ -714,7 +715,21 @@
*/
public static final int NET_CAPABILITY_PRIORITIZE_BANDWIDTH = 35;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PRIORITIZE_BANDWIDTH;
+ /**
+ * This is a local network, e.g. a tethering downstream or a P2P direct network.
+ *
+ * <p>
+ * Note that local networks are not sent to callbacks by default. To receive callbacks about
+ * them, the {@link NetworkRequest} instance must be prepared to see them, either by
+ * adding the capability with {@link NetworkRequest.Builder#addCapability}, by removing
+ * this forbidden capability with {@link NetworkRequest.Builder#removeForbiddenCapability},
+ * or by clearing all capabilites with {@link NetworkRequest.Builder#clearCapabilities()}.
+ * </p>
+ * @hide
+ */
+ public static final int NET_CAPABILITY_LOCAL_NETWORK = 36;
+
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_LOCAL_NETWORK;
// Set all bits up to the MAX_NET_CAPABILITY-th bit
private static final long ALL_VALID_CAPABILITIES = (2L << MAX_NET_CAPABILITY) - 1;
@@ -859,7 +874,7 @@
}
/**
- * Removes (if found) the given forbidden capability from this {@code NetworkCapability}
+ * Removes (if found) the given forbidden capability from this {@link NetworkCapabilities}
* instance that were added via addForbiddenCapability(int) or setCapabilities(int[], int[]).
*
* @param capability the capability to be removed.
@@ -873,6 +888,16 @@
}
/**
+ * Removes all forbidden capabilities from this {@link NetworkCapabilities} instance.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
+ * @hide
+ */
+ public @NonNull NetworkCapabilities removeAllForbiddenCapabilities() {
+ mForbiddenNetworkCapabilities = 0;
+ return this;
+ }
+
+ /**
* Sets (or clears) the given capability on this {@link NetworkCapabilities}
* instance.
* @hide
@@ -1039,11 +1064,12 @@
}
/**
- * Check if this NetworkCapabilities has system managed capabilities or not.
+ * Check if this NetworkCapabilities has connectivity-managed capabilities or not.
* @hide
*/
public boolean hasConnectivityManagedCapability() {
- return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0);
+ return (mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0
+ || mForbiddenNetworkCapabilities != 0;
}
/**
@@ -2523,6 +2549,7 @@
case NET_CAPABILITY_MMTEL: return "MMTEL";
case NET_CAPABILITY_PRIORITIZE_LATENCY: return "PRIORITIZE_LATENCY";
case NET_CAPABILITY_PRIORITIZE_BANDWIDTH: return "PRIORITIZE_BANDWIDTH";
+ case NET_CAPABILITY_LOCAL_NETWORK: return "LOCAL_NETWORK";
default: return Integer.toString(capability);
}
}
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index 5cc9f1b..9824faa 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -20,6 +20,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
@@ -283,6 +284,15 @@
NET_CAPABILITY_TRUSTED,
NET_CAPABILITY_VALIDATED);
+ /**
+ * Capabilities that are forbidden by default.
+ * Forbidden capabilities only make sense in NetworkRequest, not for network agents.
+ * Therefore these capabilities are only in NetworkRequest.
+ */
+ private static final int[] DEFAULT_FORBIDDEN_CAPABILITIES = new int[] {
+ NET_CAPABILITY_LOCAL_NETWORK
+ };
+
private final NetworkCapabilities mNetworkCapabilities;
// A boolean that represents whether the NOT_VCN_MANAGED capability should be deduced when
@@ -298,6 +308,16 @@
// it for apps that do not have the NETWORK_SETTINGS permission.
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.setSingleUid(Process.myUid());
+ // Default forbidden capabilities are foremost meant to help with backward
+ // compatibility. When adding new types of network identified by a capability that
+ // might confuse older apps, a default forbidden capability will have apps not see
+ // these networks unless they explicitly ask for it.
+ // If the app called clearCapabilities() it will see everything, but then it
+ // can be argued that it's fair to send them too, since it asked for everything
+ // explicitly.
+ for (final int forbiddenCap : DEFAULT_FORBIDDEN_CAPABILITIES) {
+ mNetworkCapabilities.addForbiddenCapability(forbiddenCap);
+ }
}
/**
diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java
index 2522958..00382f6 100644
--- a/framework/src/android/net/NetworkScore.java
+++ b/framework/src/android/net/NetworkScore.java
@@ -45,7 +45,8 @@
@IntDef(value = {
KEEP_CONNECTED_NONE,
KEEP_CONNECTED_FOR_HANDOVER,
- KEEP_CONNECTED_FOR_TEST
+ KEEP_CONNECTED_FOR_TEST,
+ KEEP_CONNECTED_DOWNSTREAM_NETWORK
})
public @interface KeepConnectedReason { }
@@ -64,6 +65,12 @@
* @hide
*/
public static final int KEEP_CONNECTED_FOR_TEST = 2;
+ /**
+ * Keep this network connected even if there is no outstanding request for it, because
+ * it is a downstream network.
+ * @hide
+ */
+ public static final int KEEP_CONNECTED_DOWNSTREAM_NETWORK = 3;
// Agent-managed policies
// This network should lose to a wifi that has ever been validated
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 48e86d8..01b8de7 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -48,6 +48,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.PermissionUtils;
import com.android.net.module.util.SharedLog;
@@ -237,7 +238,18 @@
mDeps = deps;
// Interface match regex.
- mIfaceMatch = mDeps.getInterfaceRegexFromResource(mContext);
+ String ifaceMatchRegex = mDeps.getInterfaceRegexFromResource(mContext);
+ // "*" is a magic string to indicate "pick the default".
+ if (ifaceMatchRegex.equals("*")) {
+ if (SdkLevel.isAtLeastU()) {
+ // On U+, include both usb%d and eth%d interfaces.
+ ifaceMatchRegex = "(usb|eth)\\d+";
+ } else {
+ // On T, include only eth%d interfaces.
+ ifaceMatchRegex = "eth\\d+";
+ }
+ }
+ mIfaceMatch = ifaceMatchRegex;
// Read default Ethernet interface configuration from resources
final String[] interfaceConfigs = mDeps.getInterfaceConfigFromResource(context);
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index f30abc6..045d707f 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -194,8 +194,11 @@
-->
</string-array>
- <!-- Regex of wired ethernet ifaces -->
- <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
+ <!-- Regex of wired ethernet ifaces. Network interfaces that match this regex will be tracked
+ by ethernet service.
+ If set to "*", ethernet service uses "(eth|usb)\\d+" on Android U+ and eth\\d+ on
+ Android T. -->
+ <string translatable="false" name="config_ethernet_iface_regex">*</string>
<!-- Ignores Wi-Fi validation failures after roam.
If validation fails on a Wi-Fi network after a roam to a new BSSID,
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index ea4d82a..8475110 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -8034,6 +8034,7 @@
}
}
}
+ if (!highestPriorityNri.isBeingSatisfied()) return null;
return highestPriorityNri.getSatisfier();
}
@@ -11468,7 +11469,8 @@
// If there is no default network, default network is considered active to keep the existing
// behavior. Initial value is used until first connect to the default network.
private volatile boolean mIsDefaultNetworkActive = true;
- private final ArrayMap<String, IdleTimerParams> mActiveIdleTimers = new ArrayMap<>();
+ // Key is netId. Value is configured idle timer information.
+ private final SparseArray<IdleTimerParams> mActiveIdleTimers = new SparseArray<>();
private static class IdleTimerParams {
public final int timeout;
@@ -11496,7 +11498,7 @@
public void handleReportNetworkActivity(NetworkActivityParams activityParams) {
ensureRunningOnConnectivityServiceThread();
- if (mActiveIdleTimers.isEmpty()) {
+ if (mActiveIdleTimers.size() == 0) {
// This activity change is not for the current default network.
// This can happen if netd callback post activity change event message but
// the default network is lost before processing this message.
@@ -11572,6 +11574,7 @@
*/
private boolean setupDataActivityTracking(NetworkAgentInfo networkAgent) {
final String iface = networkAgent.linkProperties.getInterfaceName();
+ final int netId = networkAgent.network().netId;
final int timeout;
final int type;
@@ -11596,7 +11599,7 @@
if (timeout > 0 && iface != null) {
try {
- mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
+ mActiveIdleTimers.put(netId, new IdleTimerParams(timeout, type));
mNetd.idletimerAddInterface(iface, timeout, Integer.toString(type));
return true;
} catch (Exception e) {
@@ -11612,6 +11615,7 @@
*/
private void removeDataActivityTracking(NetworkAgentInfo networkAgent) {
final String iface = networkAgent.linkProperties.getInterfaceName();
+ final int netId = networkAgent.network().netId;
final NetworkCapabilities caps = networkAgent.networkCapabilities;
if (iface == null) return;
@@ -11627,11 +11631,12 @@
try {
updateRadioPowerState(false /* isActive */, type);
- final IdleTimerParams params = mActiveIdleTimers.remove(iface);
+ final IdleTimerParams params = mActiveIdleTimers.get(netId);
if (params == null) {
// IdleTimer is not added if the configured timeout is 0 or negative value
return;
}
+ mActiveIdleTimers.remove(netId);
// The call fails silently if no idle timer setup for this interface
mNetd.idletimerRemoveInterface(iface, params.timeout,
Integer.toString(params.transportType));
@@ -11702,9 +11707,9 @@
pw.print("mIsDefaultNetworkActive="); pw.println(mIsDefaultNetworkActive);
pw.println("Idle timers:");
try {
- for (Map.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
- pw.print(" "); pw.print(ent.getKey()); pw.println(":");
- final IdleTimerParams params = ent.getValue();
+ for (int i = 0; i < mActiveIdleTimers.size(); i++) {
+ pw.print(" "); pw.print(mActiveIdleTimers.keyAt(i)); pw.println(":");
+ final IdleTimerParams params = mActiveIdleTimers.valueAt(i);
pw.print(" timeout="); pw.print(params.timeout);
pw.print(" type="); pw.println(params.transportType);
}
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index bdd841f..0f72cd4 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -453,6 +453,8 @@
* apply to the allowedUids field.
* They also should not mutate immutable capabilities, although for backward-compatibility
* this is not enforced and limited to just a log.
+ * Forbidden capabilities also make no sense for networks, so they are disallowed and
+ * will be ignored with a warning.
*
* @param carrierPrivilegeAuthenticator the authenticator, to check access UIDs.
*/
@@ -461,6 +463,7 @@
final NetworkCapabilities nc = new NetworkCapabilities(mDeclaredCapabilitiesUnsanitized);
if (nc.hasConnectivityManagedCapability()) {
Log.wtf(TAG, "BUG: " + this + " has CS-managed capability.");
+ nc.removeAllForbiddenCapabilities();
}
if (networkCapabilities.getOwnerUid() != nc.getOwnerUid()) {
Log.e(TAG, toShortString() + ": ignoring attempt to change owner from "
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
index 35f22b9..46229b0 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/DevSdkIgnoreRule.kt
@@ -27,6 +27,9 @@
@Deprecated("Use Build.VERSION_CODES", ReplaceWith("Build.VERSION_CODES.S_V2"))
const val SC_V2 = Build.VERSION_CODES.S_V2
+// TODO: Remove this when Build.VERSION_CODES.VANILLA_ICE_CREAM is available in all branches
+// where this code builds
+const val VANILLA_ICE_CREAM = 35 // Bui1ld.VERSION_CODES.VANILLA_ICE_CREAM
private val MAX_TARGET_SDK_ANNOTATION_RE = Pattern.compile("MaxTargetSdk([0-9]+)$")
private val targetSdk = InstrumentationRegistry.getContext().applicationInfo.targetSdkVersion
diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java
index aae3425..bec9a4a 100644
--- a/tests/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java
@@ -26,6 +26,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
@@ -63,6 +64,7 @@
import static com.android.modules.utils.build.SdkLevel.isAtLeastR;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static com.android.testutils.MiscAsserts.assertEmpty;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -369,6 +371,9 @@
.addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
+ if (isAtLeastV()) {
+ netCap.addCapability(NET_CAPABILITY_LOCAL_NETWORK);
+ }
if (isAtLeastS()) {
final ArraySet<Integer> allowedUids = new ArraySet<>();
allowedUids.add(4);
diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
index 718ca6d..594f3fb 100644
--- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
@@ -19,8 +19,10 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
@@ -28,6 +30,8 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static com.android.testutils.DevSdkIgnoreRuleKt.VANILLA_ICE_CREAM;
+
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertArrayEquals;
@@ -489,6 +493,32 @@
assertArrayEquals(netCapabilities, nr.getCapabilities());
}
+ @Test @IgnoreUpTo(VANILLA_ICE_CREAM)
+ public void testDefaultCapabilities() {
+ final NetworkRequest defaultNR = new NetworkRequest.Builder().build();
+ assertTrue(defaultNR.hasForbiddenCapability(NET_CAPABILITY_LOCAL_NETWORK));
+ assertFalse(defaultNR.hasCapability(NET_CAPABILITY_LOCAL_NETWORK));
+ assertTrue(defaultNR.hasCapability(NET_CAPABILITY_NOT_VPN));
+
+ final NetworkCapabilities emptyNC =
+ NetworkCapabilities.Builder.withoutDefaultCapabilities().build();
+ assertFalse(defaultNR.canBeSatisfiedBy(emptyNC));
+
+ // defaultNC represent the capabilities of a network agent, so they must not contain
+ // forbidden capabilities by default.
+ final NetworkCapabilities defaultNC = new NetworkCapabilities.Builder().build();
+ assertArrayEquals(new int[0], defaultNC.getForbiddenCapabilities());
+ // A default NR can be satisfied by default NC.
+ assertTrue(defaultNR.canBeSatisfiedBy(defaultNC));
+
+ // Conversely, network requests have forbidden capabilities by default to manage
+ // backward compatibility, so test that these forbidden capabilities are in place.
+ // Starting in V, NET_CAPABILITY_LOCAL_NETWORK is introduced but is not seen by
+ // default, thanks to a default forbidden capability in NetworkRequest.
+ defaultNC.addCapability(NET_CAPABILITY_LOCAL_NETWORK);
+ assertFalse(defaultNR.canBeSatisfiedBy(defaultNC));
+ }
+
@Test
public void testBuildRequestFromExistingRequestWithBuilder() {
assumeTrue(TestUtils.shouldTestSApis());
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 16f0c44..ee11f7c 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -77,6 +77,7 @@
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
@@ -469,6 +470,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -1498,14 +1500,7 @@
private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
private UnderlyingNetworkInfo mUnderlyingNetworkInfo;
-
- // This ConditionVariable allow tests to wait for LegacyVpnRunner to be started.
- // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
- // test expects two starts in a row, or even if the production code calls start twice in a
- // row. find a better solution. Simply putting a method to create a LegacyVpnRunner into
- // Vpn.Dependencies doesn't work because LegacyVpnRunner is not a static class and has
- // extensive access into the internals of Vpn.
- private ConditionVariable mStartLegacyVpnCv = new ConditionVariable();
+ private String mSessionKey;
public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext,
@@ -1666,24 +1661,52 @@
mInterface = null;
}
- @Override
- public void startLegacyVpnRunner() {
- mStartLegacyVpnCv.open();
+ private synchronized void startLegacyVpn() {
+ updateState(DetailedState.CONNECTING, "startLegacyVpn");
}
- public void expectStartLegacyVpnRunner() {
- assertTrue("startLegacyVpnRunner not called after " + TIMEOUT_MS + " ms",
- mStartLegacyVpnCv.block(TIMEOUT_MS));
+ // Mock the interaction of IkeV2VpnRunner start. In the context of ConnectivityService,
+ // setVpnDefaultForUids() is the main interaction and a sessionKey is stored.
+ private synchronized void startPlatformVpn() {
+ updateState(DetailedState.CONNECTING, "startPlatformVpn");
+ mSessionKey = UUID.randomUUID().toString();
+ // Assuming no disallowed applications
+ final Set<Range<Integer>> ranges = UidRange.toIntRanges(Set.of(PRIMARY_UIDRANGE));
+ mCm.setVpnDefaultForUids(mSessionKey, ranges);
+ // Wait for vpn network preference updates.
+ waitForIdle();
}
@Override
- public void stopVpnRunnerPrivileged() {
- if (mVpnRunner != null) {
- super.stopVpnRunnerPrivileged();
- disconnect();
- mStartLegacyVpnCv = new ConditionVariable();
+ public void startLegacyVpnPrivileged(VpnProfile profile,
+ @Nullable Network underlying, @NonNull LinkProperties egress) {
+ switch (profile.type) {
+ case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
+ case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
+ case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
+ case VpnProfile.TYPE_IKEV2_FROM_IKE_TUN_CONN_PARAMS:
+ startPlatformVpn();
+ break;
+ case VpnProfile.TYPE_L2TP_IPSEC_PSK:
+ case VpnProfile.TYPE_L2TP_IPSEC_RSA:
+ case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
+ case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
+ case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
+ startLegacyVpn();
+ break;
+ default:
+ fail("Unknown VPN profile type");
}
- mVpnRunner = null;
+ }
+
+ @Override
+ public synchronized void stopVpnRunnerPrivileged() {
+ if (mSessionKey != null) {
+ // Clear vpn network preference.
+ mCm.setVpnDefaultForUids(mSessionKey, Collections.EMPTY_LIST);
+ mSessionKey = null;
+ }
+ disconnect();
}
@Override
@@ -10178,7 +10201,7 @@
doAsUid(Process.SYSTEM_UID, () -> mCm.unregisterNetworkCallback(perUidCb));
}
- private VpnProfile setupLegacyLockdownVpn() {
+ private VpnProfile setupLockdownVpn(int profileType) {
final String profileName = "testVpnProfile";
final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8);
doReturn(profileTag).when(mVpnProfileStore).get(Credentials.LOCKDOWN_VPN);
@@ -10187,7 +10210,9 @@
profile.name = "My VPN";
profile.server = "192.0.2.1";
profile.dnsServers = "8.8.8.8";
- profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK;
+ profile.ipsecIdentifier = "My ipsecIdentifier";
+ profile.ipsecSecret = "My PSK";
+ profile.type = profileType;
final byte[] encodedProfile = profile.encode();
doReturn(encodedProfile).when(mVpnProfileStore).get(Credentials.VPN + profileName);
@@ -10205,8 +10230,8 @@
mMockVpn.connect(true);
}
- @Test
- public void testLegacyLockdownVpn() throws Exception {
+ private void doTestLockdownVpn(VpnProfile profile, boolean expectSetVpnDefaultForUids)
+ throws Exception {
mServiceContext.setPermission(
Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
@@ -10221,9 +10246,6 @@
mCm.registerSystemDefaultNetworkCallback(systemDefaultCallback,
new Handler(ConnectivityThread.getInstanceLooper()));
- // Pretend lockdown VPN was configured.
- final VpnProfile profile = setupLegacyLockdownVpn();
-
// Init lockdown state to simulate LockdownVpnTracker behavior.
mCm.setLegacyLockdownVpnEnabled(true);
mMockVpn.setEnableTeardown(false);
@@ -10236,46 +10258,50 @@
cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
// When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
// with the state of the VPN network. So expect a CONNECTING broadcast.
- ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
+ final ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
mCellAgent.connect(false /* validated */);
callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
systemDefaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellAgent);
- b1.expectBroadcast();
+ b.expectBroadcast();
// Simulate LockdownVpnTracker attempting to start the VPN since it received the
// systemDefault callback.
mMockVpn.startLegacyVpnPrivileged(profile, mCellAgent.getNetwork(), cellLp);
- assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ if (expectSetVpnDefaultForUids) {
+ // setVpnDefaultForUids() releases the original network request and creates a VPN
+ // request so LOST callback is received.
+ defaultCallback.expect(LOST, mCellAgent);
+ // Due to the VPN default request, getActiveNetworkInfo() gets the mNoServiceNetwork
+ // as the network satisfier.
+ assertNull(mCm.getActiveNetworkInfo());
+ } else {
+ assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ }
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
assertExtraInfoFromCmBlocked(mCellAgent);
- // TODO: it would be nice if we could simply rely on the production code here, and have
- // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with
- // ConnectivityService, etc. That would require duplicating a fair bit of code from the
- // Vpn tests around how to mock out LegacyVpnRunner. But even if we did that, this does not
- // work for at least two reasons:
- // 1. In this test, calling registerNetworkAgent does not actually result in an agent being
- // registered. This is because nothing calls onNetworkMonitorCreated, which is what
- // actually ends up causing handleRegisterNetworkAgent to be called. Code in this test
- // that wants to register an agent must use TestNetworkAgentWrapper.
- // 2. Even if we exposed Vpn#agentConnect to the test, and made MockVpn#agentConnect call
- // the TestNetworkAgentWrapper code, this would deadlock because the
- // TestNetworkAgentWrapper code cannot be called on the handler thread since it calls
- // waitForIdle().
- mMockVpn.expectStartLegacyVpnRunner();
- b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
- ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
+ final ExpectedBroadcast b2 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
+ final ExpectedBroadcast b3 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
establishLegacyLockdownVpn(mCellAgent.getNetwork());
callback.expectAvailableThenValidatedCallbacks(mMockVpn);
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
systemDefaultCallback.assertNoCallback();
- NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
- b1.expectBroadcast();
+ final NetworkCapabilities vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
b2.expectBroadcast();
- assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
+ b3.expectBroadcast();
+ if (expectSetVpnDefaultForUids) {
+ // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
+ // network satisfier which has TYPE_VPN.
+ assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+ } else {
+ // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
+ // getActiveNetworkInfo() can only return the info for the system-wide default instead.
+ // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
+ assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
+ }
assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
@@ -10296,55 +10322,78 @@
wifiNc.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc);
- b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ final ExpectedBroadcast b4 =
+ expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
// Wifi is CONNECTING because the VPN isn't up yet.
- b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
+ final ExpectedBroadcast b5 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
mWiFiAgent.connect(false /* validated */);
// Wifi is not blocked since VPN network is still connected.
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
defaultCallback.assertNoCallback();
systemDefaultCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
- b1.expectBroadcast();
- b2.expectBroadcast();
+ b4.expectBroadcast();
+ b5.expectBroadcast();
// Simulate LockdownVpnTracker restarting the VPN since it received the systemDefault
// callback with different network.
- final ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
+ final ExpectedBroadcast b6 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
mMockVpn.stopVpnRunnerPrivileged();
mMockVpn.startLegacyVpnPrivileged(profile, mWiFiAgent.getNetwork(), wifiLp);
- mMockVpn.expectStartLegacyVpnRunner();
+ // VPN network is disconnected (to restart)
callback.expect(LOST, mMockVpn);
defaultCallback.expect(LOST, mMockVpn);
+ // The network preference is cleared when VPN is disconnected so it receives callbacks for
+ // the system-wide default.
defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiAgent);
+ if (expectSetVpnDefaultForUids) {
+ // setVpnDefaultForUids() releases the original network request and creates a VPN
+ // request so LOST callback is received.
+ defaultCallback.expect(LOST, mWiFiAgent);
+ }
systemDefaultCallback.assertNoCallback();
- b3.expectBroadcast();
+ b6.expectBroadcast();
// While the VPN is reconnecting on the new network, everything is blocked.
- assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ if (expectSetVpnDefaultForUids) {
+ // Due to the VPN default request, getActiveNetworkInfo() gets the mNoServiceNetwork
+ // as the network satisfier.
+ assertNull(mCm.getActiveNetworkInfo());
+ } else {
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ }
assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
assertExtraInfoFromCmBlocked(mWiFiAgent);
// The VPN comes up again on wifi.
- b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
- b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
+ final ExpectedBroadcast b7 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
+ final ExpectedBroadcast b8 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
establishLegacyLockdownVpn(mWiFiAgent.getNetwork());
callback.expectAvailableThenValidatedCallbacks(mMockVpn);
defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
systemDefaultCallback.assertNoCallback();
- b1.expectBroadcast();
- b2.expectBroadcast();
- assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ b7.expectBroadcast();
+ b8.expectBroadcast();
+ if (expectSetVpnDefaultForUids) {
+ // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
+ // network satisfier which has TYPE_VPN.
+ assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+ } else {
+ // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
+ // getActiveNetworkInfo() can only return the info for the system-wide default instead.
+ // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ }
assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
assertExtraInfoFromCmPresent(mWiFiAgent);
- vpnNc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
- assertTrue(vpnNc.hasTransport(TRANSPORT_VPN));
- assertTrue(vpnNc.hasTransport(TRANSPORT_WIFI));
- assertFalse(vpnNc.hasTransport(TRANSPORT_CELLULAR));
- assertTrue(vpnNc.hasCapability(NET_CAPABILITY_NOT_METERED));
+ final NetworkCapabilities vpnNc2 = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
+ assertTrue(vpnNc2.hasTransport(TRANSPORT_VPN));
+ assertTrue(vpnNc2.hasTransport(TRANSPORT_WIFI));
+ assertFalse(vpnNc2.hasTransport(TRANSPORT_CELLULAR));
+ assertTrue(vpnNc2.hasCapability(NET_CAPABILITY_NOT_METERED));
// Disconnect cell. Nothing much happens since it's not the default network.
mCellAgent.disconnect();
@@ -10352,14 +10401,25 @@
defaultCallback.assertNoCallback();
systemDefaultCallback.assertNoCallback();
- assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ if (expectSetVpnDefaultForUids) {
+ // Due to the VPN default request, getActiveNetworkInfo() gets the VPN network as the
+ // network satisfier which has TYPE_VPN.
+ assertActiveNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+ } else {
+ // LegacyVpnRunner does not call setVpnDefaultsForUids(), which means
+ // getActiveNetworkInfo() can only return the info for the system-wide default instead.
+ // This should be fixed, but LegacyVpnRunner will be removed soon anyway.
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ }
assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
assertExtraInfoFromCmPresent(mWiFiAgent);
- b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
- b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
+ final ExpectedBroadcast b9 =
+ expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
+ final ExpectedBroadcast b10 =
+ expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
mWiFiAgent.disconnect();
callback.expect(LOST, mWiFiAgent);
callback.expectCaps(mMockVpn, c -> !c.hasTransport(TRANSPORT_WIFI));
@@ -10371,15 +10431,27 @@
// null. Since the satisfiers are set to null in the rematch, an extra LOST callback is
// called.
systemDefaultCallback.expect(LOST, mWiFiAgent);
- b1.expectBroadcast();
+ b9.expectBroadcast();
mMockVpn.stopVpnRunnerPrivileged();
callback.expect(LOST, mMockVpn);
defaultCallback.expect(LOST, mMockVpn);
- b2.expectBroadcast();
+ b10.expectBroadcast();
assertNoCallbacks(callback, defaultCallback, systemDefaultCallback);
}
+ @Test
+ public void testLockdownVpn_LegacyVpnRunner() throws Exception {
+ final VpnProfile profile = setupLockdownVpn(VpnProfile.TYPE_IPSEC_XAUTH_PSK);
+ doTestLockdownVpn(profile, false /* expectSetVpnDefaultForUids */);
+ }
+
+ @Test
+ public void testLockdownVpn_Ikev2VpnRunner() throws Exception {
+ final VpnProfile profile = setupLockdownVpn(VpnProfile.TYPE_IKEV2_IPSEC_PSK);
+ doTestLockdownVpn(profile, true /* expectSetVpnDefaultForUids */);
+ }
+
@Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
public void testLockdownSetFirewallUidRule() throws Exception {
final Set<Range<Integer>> lockdownRange = UidRange.toIntRanges(Set.of(PRIMARY_UIDRANGE));
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
index 3701b0c..8917ed3 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsMultinetworkSocketClientTest.java
@@ -42,6 +42,7 @@
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -69,6 +70,7 @@
@Mock private SocketCreationCallback mSocketCreationCallback;
@Mock private SharedLog mSharedLog;
private MdnsMultinetworkSocketClient mSocketClient;
+ private HandlerThread mHandlerThread;
private Handler mHandler;
private SocketKey mSocketKey;
@@ -76,14 +78,23 @@
public void setUp() throws SocketException {
MockitoAnnotations.initMocks(this);
- final HandlerThread thread = new HandlerThread("MdnsMultinetworkSocketClientTest");
- thread.start();
- mHandler = new Handler(thread.getLooper());
+ mHandlerThread = new HandlerThread("MdnsMultinetworkSocketClientTest");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
mSocketKey = new SocketKey(1000 /* interfaceIndex */);
- mSocketClient = new MdnsMultinetworkSocketClient(thread.getLooper(), mProvider, mSharedLog);
+ mSocketClient = new MdnsMultinetworkSocketClient(
+ mHandlerThread.getLooper(), mProvider, mSharedLog);
mHandler.post(() -> mSocketClient.setCallback(mCallback));
}
+ @After
+ public void tearDown() throws Exception {
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ mHandlerThread.join();
+ }
+ }
+
private SocketCallback expectSocketCallback() {
return expectSocketCallback(mListener, mNetwork);
}
diff --git a/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt b/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt
index a9b9896..86426c2 100644
--- a/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/CSKeepConnectedTest.kt
@@ -16,8 +16,12 @@
package com.android.server
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkRequest
import android.net.NetworkScore
+import android.net.NetworkScore.KEEP_CONNECTED_DOWNSTREAM_NETWORK
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
import android.os.Build
import androidx.test.filters.SmallTest
@@ -33,6 +37,20 @@
@IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
class CSKeepConnectedTest : CSTest() {
@Test
+ fun testKeepConnectedLocalAgent() {
+ deps.setBuildSdk(VERSION_V)
+ val nc = NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_LOCAL_NETWORK)
+ .build()
+ val keepConnectedAgent = Agent(nc = nc, score = FromS(NetworkScore.Builder()
+ .setKeepConnectedReason(KEEP_CONNECTED_DOWNSTREAM_NETWORK)
+ .build()))
+ val dontKeepConnectedAgent = Agent(nc = nc)
+ doTestKeepConnected(keepConnectedAgent, dontKeepConnectedAgent)
+ }
+
+ @Test
fun testKeepConnectedForTest() {
val keepAgent = Agent(score = FromS(NetworkScore.Builder()
.setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST)
diff --git a/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt b/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
index afaf79f..1d0d5df 100644
--- a/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
+++ b/tests/unit/java/com/android/server/connectivityservice/base/CSAgentWrapper.kt
@@ -98,7 +98,7 @@
nmCbCaptor.capture())
// Create the actual agent. NetworkAgent is abstract, so make an anonymous subclass.
- if (SdkLevel.isAtLeastS()) {
+ if (deps.isAtLeastS()) {
agent = object : NetworkAgent(context, csHandlerThread.looper, TAG,
nc, lp, score.value, nac, provider) {}
} else {
@@ -112,7 +112,7 @@
}
private fun onValidationRequested() {
- if (SdkLevel.isAtLeastT()) {
+ if (deps.isAtLeastT()) {
verify(networkMonitor).notifyNetworkConnectedParcel(any())
} else {
verify(networkMonitor).notifyNetworkConnected(any(), any())
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
index 292f77e..c477b2c 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -59,6 +59,7 @@
import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -139,6 +140,14 @@
mUsageCallback = new TestableUsageCallback(mUsageCallbackBinder);
}
+ @After
+ public void tearDown() throws Exception {
+ if (mObserverHandlerThread != null) {
+ mObserverHandlerThread.quitSafely();
+ mObserverHandlerThread.join();
+ }
+ }
+
@Test
public void testRegister_thresholdTooLow_setsDefaultThreshold() throws Exception {
final long thresholdTooLowBytes = 1L;