Merge "Load ncm regexs config to tetherableUsbRegexs if isUsingNcm=true"
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index bd7ebda..88c885a 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -67,6 +67,20 @@
name: "com.android.tethering-bootclasspath-fragment",
contents: ["framework-tethering"],
apex_available: ["com.android.tethering"],
+
+ // The bootclasspath_fragments that provide APIs on which this depends.
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+
+ // Additional stubs libraries that this fragment's contents use which are
+ // not provided by another bootclasspath_fragment.
+ additional_stubs: [
+ "android-non-updatable",
+ ],
}
override_apex {
diff --git a/Tethering/bpf_progs/offload.c b/Tethering/bpf_progs/offload.c
index 6ff370c..336d27a 100644
--- a/Tethering/bpf_progs/offload.c
+++ b/Tethering/bpf_progs/offload.c
@@ -569,6 +569,16 @@
// For a rawip tx interface it will simply be a bunch of zeroes and later stripped.
*eth = v->macHeader;
+ // Decrement the IPv4 TTL, we already know it's greater than 1.
+ // u8 TTL field is followed by u8 protocol to make a u16 for ipv4 header checksum update.
+ // Since we're keeping the ipv4 checksum valid (which means the checksum of the entire
+ // ipv4 header remains 0), the overall checksum of the entire packet does not change.
+ const int sz2 = sizeof(__be16);
+ const __be16 old_ttl_proto = *(__be16 *)&ip->ttl;
+ const __be16 new_ttl_proto = old_ttl_proto - htons(0x0100);
+ bpf_l3_csum_replace(skb, ETH_IP4_OFFSET(check), old_ttl_proto, new_ttl_proto, sz2);
+ bpf_skb_store_bytes(skb, ETH_IP4_OFFSET(ttl), &new_ttl_proto, sz2, 0);
+
const int l4_offs_csum = is_tcp ? ETH_IP4_TCP_OFFSET(check) : ETH_IP4_UDP_OFFSET(check);
const int sz4 = sizeof(__be32);
// UDP 0 is special and stored as FFFF (this flag also causes a csum of 0 to be unmodified)
@@ -586,7 +596,6 @@
bpf_l3_csum_replace(skb, ETH_IP4_OFFSET(check), old_saddr, new_saddr, sz4);
bpf_skb_store_bytes(skb, ETH_IP4_OFFSET(saddr), &new_saddr, sz4, 0);
- const int sz2 = sizeof(__be16);
// The offsets for TCP and UDP ports: source (u16 @ L4 offset 0) & dest (u16 @ L4 offset 2) are
// actually the same, so the compiler should just optimize them both down to a constant.
bpf_l4_csum_replace(skb, l4_offs_csum, k.srcPort, v->srcPort, sz2 | l4_flags);
@@ -597,8 +606,6 @@
bpf_skb_store_bytes(skb, is_tcp ? ETH_IP4_TCP_OFFSET(dest) : ETH_IP4_UDP_OFFSET(dest),
&v->dstPort, sz2, 0);
- // TEMP HACK: lack of TTL decrement
-
// This requires the bpf_ktime_get_boot_ns() helper which was added in 5.8,
// and backported to all Android Common Kernel 4.14+ trees.
if (updatetime) v->last_used = bpf_ktime_get_boot_ns();
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 9b95dac..2c1fd29 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -1069,11 +1069,13 @@
throw new AssertionError("IP address array not valid IPv4 address!");
}
- final long ageMs = (now - value.lastUsed) / 1_000_000;
- return String.format("[%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %dms",
- key.dstMac, key.iif, getIfName(key.iif), src4, key.srcPort,
+ final String protoStr = (key.l4proto == OsConstants.IPPROTO_TCP) ? "tcp" : "udp";
+ final String ageStr = (value.lastUsed == 0) ? "-"
+ : String.format("%dms", (now - value.lastUsed) / 1_000_000);
+ return String.format("%s [%s] %d(%s) %s:%d -> %d(%s) %s:%d -> %s:%d [%s] %s",
+ protoStr, key.dstMac, key.iif, getIfName(key.iif), src4, key.srcPort,
value.oif, getIfName(value.oif),
- public4, publicPort, dst4, value.dstPort, value.ethDstMac, ageMs);
+ public4, publicPort, dst4, value.dstPort, value.ethDstMac, ageStr);
}
private void dumpIpv4ForwardingRuleMap(long now, boolean downstream,
@@ -1094,12 +1096,14 @@
try (BpfMap<Tether4Key, Tether4Value> upstreamMap = mDeps.getBpfUpstream4Map();
BpfMap<Tether4Key, Tether4Value> downstreamMap = mDeps.getBpfDownstream4Map()) {
- pw.println("IPv4 Upstream: [inDstMac] iif(iface) src -> nat -> dst [outDstMac] age");
+ pw.println("IPv4 Upstream: proto [inDstMac] iif(iface) src -> nat -> "
+ + "dst [outDstMac] age");
pw.increaseIndent();
dumpIpv4ForwardingRuleMap(now, UPSTREAM, upstreamMap, pw);
pw.decreaseIndent();
- pw.println("IPv4 Downstream: [inDstMac] iif(iface) src -> nat -> dst [outDstMac] age");
+ pw.println("IPv4 Downstream: proto [inDstMac] iif(iface) src -> nat -> "
+ + "dst [outDstMac] age");
pw.increaseIndent();
dumpIpv4ForwardingRuleMap(now, DOWNSTREAM, downstreamMap, pw);
pw.decreaseIndent();
diff --git a/Tethering/tests/Android.bp b/Tethering/tests/Android.bp
index 8f31c57..72ca666 100644
--- a/Tethering/tests/Android.bp
+++ b/Tethering/tests/Android.bp
@@ -22,7 +22,7 @@
name: "TetheringTestsJarJarRules",
srcs: ["jarjar-rules.txt"],
visibility: [
- "//frameworks/base/packages/Tethering/tests:__subpackages__",
+ "//packages/modules/Connectivity/tests:__subpackages__",
"//packages/modules/Connectivity/Tethering/tests:__subpackages__",
]
}
diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp
index e807613..b93a969 100644
--- a/Tethering/tests/integration/Android.bp
+++ b/Tethering/tests/integration/Android.bp
@@ -78,9 +78,27 @@
compile_multilib: "both",
}
+android_library {
+ name: "TetheringCoverageTestsLib",
+ min_sdk_version: "30",
+ static_libs: [
+ "NetdStaticLibTestsLib",
+ "NetworkStaticLibTestsLib",
+ "NetworkStackTestsLib",
+ "TetheringTestsLatestSdkLib",
+ "TetheringIntegrationTestsLatestSdkLib",
+ ],
+ jarjar_rules: ":TetheringTestsJarJarRules",
+ manifest: "AndroidManifest_coverage.xml",
+ visibility: [
+ "//packages/modules/Connectivity/tests:__subpackages__"
+ ],
+}
+
// Special version of the tethering tests that includes all tests necessary for code coverage
// purposes. This is currently the union of TetheringTests, TetheringIntegrationTests and
// NetworkStackTests.
+// TODO: remove in favor of ConnectivityCoverageTests, which includes below tests and more
android_test {
name: "TetheringCoverageTests",
platform_apis: true,
@@ -91,11 +109,7 @@
defaults: ["libnetworkstackutilsjni_deps"],
static_libs: [
"modules-utils-native-coverage-listener",
- "NetdStaticLibTestsLib",
- "NetworkStaticLibTestsLib",
- "NetworkStackTestsLib",
- "TetheringTestsLatestSdkLib",
- "TetheringIntegrationTestsLatestSdkLib",
+ "TetheringCoverageTestsLib",
],
jni_libs: [
// For mockito extended
diff --git a/Tethering/tests/unit/Android.bp b/Tethering/tests/unit/Android.bp
index 192a540..f6e29cd 100644
--- a/Tethering/tests/unit/Android.bp
+++ b/Tethering/tests/unit/Android.bp
@@ -75,7 +75,6 @@
"libstaticjvmtiagent",
"libtetherutilsjni",
],
- jarjar_rules: ":TetheringTestsJarJarRules",
}
// Library containing the unit tests. This is used by the coverage test target to pull in the
@@ -100,4 +99,5 @@
],
defaults: ["TetheringTestsDefaults"],
compile_multilib: "both",
+ jarjar_rules: ":TetheringTestsJarJarRules",
}
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
index d800816..fc34585 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
@@ -26,6 +26,7 @@
import static android.net.RouteInfo.RTN_UNICAST;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE;
import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID;
import static com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
@@ -66,6 +67,7 @@
import android.net.RouteInfo;
import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.SharedLog;
+import android.os.Build;
import android.os.Handler;
import android.os.test.TestLooper;
import android.provider.Settings;
@@ -76,10 +78,13 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.TestableNetworkStatsProviderCbBinder;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -95,6 +100,9 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class OffloadControllerTest {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
private static final String RNDIS0 = "test_rndis0";
private static final String RMNET0 = "test_rmnet_data0";
private static final String WLAN0 = "test_wlan0";
@@ -511,8 +519,8 @@
public void testSetDataWarningAndLimit() throws Exception {
// Verify the OffloadController is called by R framework, where the framework doesn't send
// warning.
+ // R only uses HAL 1.0.
checkSetDataWarningAndLimit(false, OFFLOAD_HAL_VERSION_1_0);
- checkSetDataWarningAndLimit(false, OFFLOAD_HAL_VERSION_1_1);
// Verify the OffloadController is called by S+ framework, where the framework sends
// warning along with limit.
checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_1_0);
@@ -650,17 +658,26 @@
}
@Test
- public void testDataWarningAndLimitCallback() throws Exception {
+ public void testDataWarningAndLimitCallback_LimitReached() throws Exception {
enableOffload();
startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
- OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ final OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
callback.onStoppedLimitReached();
mTetherStatsProviderCb.expectNotifyStatsUpdated();
- mTetherStatsProviderCb.expectNotifyWarningOrLimitReached();
+ if (isAtLeastS()) {
+ mTetherStatsProviderCb.expectNotifyWarningOrLimitReached();
+ } else {
+ mTetherStatsProviderCb.expectLegacyNotifyLimitReached();
+ }
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.R) // HAL 1.1 is only supported from S
+ public void testDataWarningAndLimitCallback_WarningReached() throws Exception {
startOffloadController(OFFLOAD_HAL_VERSION_1_1, true /*expectStart*/);
- callback = mControlCallbackCaptor.getValue();
+ final OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
callback.onWarningReached();
mTetherStatsProviderCb.expectNotifyStatsUpdated();
mTetherStatsProviderCb.expectNotifyWarningOrLimitReached();
diff --git a/framework/Android.bp b/framework/Android.bp
index 93ef3bf..ee3a5d5 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -97,8 +97,6 @@
],
},
impl_only_libs: [
- // TODO (b/183097033) remove once module_current includes core_platform
- "stable.core.platform.api.stubs",
"framework-tethering.stubs.module_lib",
"framework-wifi.stubs.module_lib",
"net-utils-device-common",
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 7e2f688..14ec608 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -4939,7 +4939,7 @@
Log.e(TAG, "Can't set proxy properties", e);
}
// Must flush DNS cache as new network may have different DNS resolutions.
- InetAddressCompat.clearDnsCache();
+ InetAddress.clearDnsCache();
// Must flush socket pool as idle sockets will be bound to previous network and may
// cause subsequent fetches to be performed on old network.
NetworkEventDispatcher.getInstance().dispatchNetworkConfigurationChange();
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index 085de6b..8fc0065 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -29,6 +29,8 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.net.ConnectivityManager.MultipathPreference;
+import android.os.Binder;
+import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
@@ -1039,6 +1041,15 @@
return getUidSetFromString(uidList);
}
+ private static boolean isCallingFromSystem() {
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+ if (uid == Process.SYSTEM_UID && pid == Process.myPid()) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Set the list of uids(from {@link Settings}) that is allowed to use restricted networks.
*
@@ -1047,6 +1058,15 @@
*/
public static void setUidsAllowedOnRestrictedNetworks(@NonNull Context context,
@NonNull Set<Integer> uidList) {
+ final boolean calledFromSystem = isCallingFromSystem();
+ if (!calledFromSystem) {
+ // Enforce NETWORK_SETTINGS check if it's debug build. This is for MTS test only.
+ if (!Build.isDebuggable()) {
+ throw new SecurityException("Only system can set this setting.");
+ }
+ context.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS,
+ "Requires NETWORK_SETTINGS permission");
+ }
final String uids = getUidStringFromSet(uidList);
Settings.Global.putString(context.getContentResolver(), UIDS_ALLOWED_ON_RESTRICTED_NETWORKS,
uids);
diff --git a/framework/src/android/net/InetAddressCompat.java b/framework/src/android/net/InetAddressCompat.java
deleted file mode 100644
index 6b7e75c..0000000
--- a/framework/src/android/net/InetAddressCompat.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.util.Log;
-
-import java.lang.reflect.InvocationTargetException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-/**
- * Compatibility utility for InetAddress core platform APIs.
- *
- * Connectivity has access to such APIs, but they are not part of the module_current stubs yet
- * (only core_current). Most stable core platform APIs are included manually in the connectivity
- * build rules, but because InetAddress is also part of the base java SDK that is earlier on the
- * classpath, the extra core platform APIs are not seen.
- *
- * TODO (b/183097033): remove this utility as soon as core_current is part of module_current
- * @hide
- */
-public class InetAddressCompat {
-
- /**
- * @see InetAddress#clearDnsCache()
- */
- public static void clearDnsCache() {
- try {
- InetAddress.class.getMethod("clearDnsCache").invoke(null);
- } catch (InvocationTargetException e) {
- if (e.getCause() instanceof RuntimeException) {
- throw (RuntimeException) e.getCause();
- }
- throw new IllegalStateException("Unknown InvocationTargetException", e.getCause());
- } catch (IllegalAccessException | NoSuchMethodException e) {
- Log.wtf(InetAddressCompat.class.getSimpleName(), "Error clearing DNS cache", e);
- }
- }
-
- /**
- * @see InetAddress#getAllByNameOnNet(String, int)
- */
- public static InetAddress[] getAllByNameOnNet(String host, int netId) throws
- UnknownHostException {
- return (InetAddress[]) callGetByNameMethod("getAllByNameOnNet", host, netId);
- }
-
- /**
- * @see InetAddress#getByNameOnNet(String, int)
- */
- public static InetAddress getByNameOnNet(String host, int netId) throws
- UnknownHostException {
- return (InetAddress) callGetByNameMethod("getByNameOnNet", host, netId);
- }
-
- private static Object callGetByNameMethod(String method, String host, int netId)
- throws UnknownHostException {
- try {
- return InetAddress.class.getMethod(method, String.class, int.class)
- .invoke(null, host, netId);
- } catch (InvocationTargetException e) {
- if (e.getCause() instanceof UnknownHostException) {
- throw (UnknownHostException) e.getCause();
- }
- if (e.getCause() instanceof RuntimeException) {
- throw (RuntimeException) e.getCause();
- }
- throw new IllegalStateException("Unknown InvocationTargetException", e.getCause());
- } catch (IllegalAccessException | NoSuchMethodException e) {
- Log.wtf(InetAddressCompat.class.getSimpleName(), "Error calling " + method, e);
- throw new IllegalStateException("Error querying via " + method, e);
- }
- }
-}
diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java
index 1f49033..b3770ea 100644
--- a/framework/src/android/net/Network.java
+++ b/framework/src/android/net/Network.java
@@ -142,7 +142,7 @@
* @throws UnknownHostException if the address lookup fails.
*/
public InetAddress[] getAllByName(String host) throws UnknownHostException {
- return InetAddressCompat.getAllByNameOnNet(host, getNetIdForResolv());
+ return InetAddress.getAllByNameOnNet(host, getNetIdForResolv());
}
/**
@@ -155,7 +155,7 @@
* if the address lookup fails.
*/
public InetAddress getByName(String host) throws UnknownHostException {
- return InetAddressCompat.getByNameOnNet(host, getNetIdForResolv());
+ return InetAddress.getByNameOnNet(host, getNetIdForResolv());
}
/**
diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java
index 7e62d28..9791cbf 100644
--- a/framework/src/android/net/util/MultinetworkPolicyTracker.java
+++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java
@@ -182,7 +182,7 @@
public void setTestAllowBadWifiUntil(long timeMs) {
Log.d(TAG, "setTestAllowBadWifiUntil: " + mTestAllowBadWifiUntilMs);
mTestAllowBadWifiUntilMs = timeMs;
- updateAvoidBadWifi();
+ reevaluateInternal();
}
@VisibleForTesting
diff --git a/service/Android.bp b/service/Android.bp
index 841e189..848de12 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -57,9 +57,6 @@
":net-module-utils-srcs",
],
libs: [
- // TODO (b/183097033) remove once system_server_current includes core_current
- "stable.core.platform.api.stubs",
- "android_system_server_stubs_current",
"framework-annotations-lib",
"framework-connectivity.impl",
"framework-tethering.stubs.module_lib",
@@ -112,3 +109,9 @@
"com.android.tethering",
],
}
+
+filegroup {
+ name: "connectivity-jarjar-rules",
+ srcs: ["jarjar-rules.txt"],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
+}
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index 078a9eb..bf32ad5 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -107,4 +107,11 @@
<string-array translatable="false" name="config_networkNotifySwitches">
</string-array>
+ <!-- Whether to use an ongoing notification for signing in to captive portals, instead of a
+ notification that can be dismissed. -->
+ <bool name="config_ongoingSignInNotification">false</bool>
+
+ <!-- Whether to cancel network notifications automatically when tapped -->
+ <bool name="config_autoCancelNetworkNotifications">true</bool>
+
</resources>
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index f0f4ae8..6ac6a0e 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -30,7 +30,10 @@
<item type="integer" name="config_networkWakeupPacketMask"/>
<item type="integer" name="config_networkNotifySwitchType"/>
<item type="array" name="config_networkNotifySwitches"/>
-
+ <item type="bool" name="config_ongoingSignInNotification"/>
+ <item type="bool" name="config_autoCancelNetworkNotifications"/>
+ <item type="drawable" name="stat_notify_wifi_in_range"/>
+ <item type="drawable" name="stat_notify_rssi_in_range"/>
</policy>
</overlayable>
</resources>
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 352d266..dfaa6b1 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -55,6 +55,7 @@
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_SKIPPED;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
@@ -541,9 +542,9 @@
private static final int EVENT_SET_AVOID_UNVALIDATED = 35;
/**
- * used to trigger revalidation of a network.
+ * used to handle reported network connectivity. May trigger revalidation of a network.
*/
- private static final int EVENT_REVALIDATE_NETWORK = 36;
+ private static final int EVENT_REPORT_NETWORK_CONNECTIVITY = 36;
// Handle changes in Private DNS settings.
private static final int EVENT_PRIVATE_DNS_SETTINGS_CHANGED = 37;
@@ -3260,11 +3261,6 @@
}
case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
// TODO: prevent loops, e.g., if a network declares itself as underlying.
- if (!nai.supportsUnderlyingNetworks()) {
- Log.wtf(TAG, "Non-virtual networks cannot have underlying networks");
- break;
- }
-
final List<Network> underlying = (List<Network>) arg.second;
if (isLegacyLockdownNai(nai)
@@ -3541,8 +3537,14 @@
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(mNetId);
if (nai == null) return;
+ // NetworkMonitor reports the network validation result as a bitmask while
+ // ConnectivityDiagnostics treats this value as an int. Convert the result to a single
+ // logical value for ConnectivityDiagnostics.
+ final int validationResult = networkMonitorValidationResultToConnDiagsValidationResult(
+ p.result);
+
final PersistableBundle extras = new PersistableBundle();
- extras.putInt(KEY_NETWORK_VALIDATION_RESULT, p.result);
+ extras.putInt(KEY_NETWORK_VALIDATION_RESULT, validationResult);
extras.putInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, p.probesSucceeded);
extras.putInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK, p.probesAttempted);
@@ -3618,6 +3620,22 @@
}
}
+ /**
+ * Converts the given NetworkMonitor-specific validation result bitmask to a
+ * ConnectivityDiagnostics-specific validation result int.
+ */
+ private int networkMonitorValidationResultToConnDiagsValidationResult(int validationResult) {
+ if ((validationResult & NETWORK_VALIDATION_RESULT_SKIPPED) != 0) {
+ return ConnectivityReport.NETWORK_VALIDATION_RESULT_SKIPPED;
+ }
+ if ((validationResult & NETWORK_VALIDATION_RESULT_VALID) == 0) {
+ return ConnectivityReport.NETWORK_VALIDATION_RESULT_INVALID;
+ }
+ return (validationResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0
+ ? ConnectivityReport.NETWORK_VALIDATION_RESULT_PARTIALLY_VALID
+ : ConnectivityReport.NETWORK_VALIDATION_RESULT_VALID;
+ }
+
private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) {
log("Data stall detected with methods: " + p.detectionMethod);
@@ -4867,8 +4885,9 @@
mKeepaliveTracker.handleStopKeepalive(nai, slot, reason);
break;
}
- case EVENT_REVALIDATE_NETWORK: {
- handleReportNetworkConnectivity((Network) msg.obj, msg.arg1, toBool(msg.arg2));
+ case EVENT_REPORT_NETWORK_CONNECTIVITY: {
+ handleReportNetworkConnectivity((NetworkAgentInfo) msg.obj, msg.arg1,
+ toBool(msg.arg2));
break;
}
case EVENT_PRIVATE_DNS_SETTINGS_CHANGED:
@@ -5031,41 +5050,34 @@
final int uid = mDeps.getCallingUid();
final int connectivityInfo = encodeBool(hasConnectivity);
- // Handle ConnectivityDiagnostics event before attempting to revalidate the network. This
- // forces an ordering of ConnectivityDiagnostics events in the case where hasConnectivity
- // does not match the known connectivity of the network - this causes NetworkMonitor to
- // revalidate the network and generate a ConnectivityDiagnostics ConnectivityReport event.
final NetworkAgentInfo nai;
if (network == null) {
nai = getDefaultNetwork();
} else {
nai = getNetworkAgentInfoForNetwork(network);
}
- if (nai != null) {
- mConnectivityDiagnosticsHandler.sendMessage(
- mConnectivityDiagnosticsHandler.obtainMessage(
- ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED,
- connectivityInfo, 0, nai));
- }
mHandler.sendMessage(
- mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network));
+ mHandler.obtainMessage(
+ EVENT_REPORT_NETWORK_CONNECTIVITY, uid, connectivityInfo, nai));
}
private void handleReportNetworkConnectivity(
- Network network, int uid, boolean hasConnectivity) {
- final NetworkAgentInfo nai;
- if (network == null) {
- nai = getDefaultNetwork();
- } else {
- nai = getNetworkAgentInfoForNetwork(network);
- }
- if (nai == null || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING ||
- nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
+ @Nullable NetworkAgentInfo nai, int uid, boolean hasConnectivity) {
+ // TODO(b/192611346): remove NetworkInfo.State.DISCONNECTING as it's not used
+ if (nai == null
+ || nai != getNetworkAgentInfoForNetwork(nai.network)
+ || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTING
+ || nai.networkInfo.getState() == NetworkInfo.State.DISCONNECTED) {
return;
}
// Revalidate if the app report does not match our current validated state.
if (hasConnectivity == nai.lastValidated) {
+ mConnectivityDiagnosticsHandler.sendMessage(
+ mConnectivityDiagnosticsHandler.obtainMessage(
+ ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED,
+ new ReportedNetworkConnectivityInfo(
+ hasConnectivity, false /* isNetworkRevalidating */, uid, nai)));
return;
}
if (DBG) {
@@ -5081,6 +5093,16 @@
if (isNetworkWithCapabilitiesBlocked(nc, uid, false)) {
return;
}
+
+ // Send CONNECTIVITY_REPORTED event before re-validating the Network to force an ordering of
+ // ConnDiags events. This ensures that #onNetworkConnectivityReported() will be called
+ // before #onConnectivityReportAvailable(), which is called once Network evaluation is
+ // completed.
+ mConnectivityDiagnosticsHandler.sendMessage(
+ mConnectivityDiagnosticsHandler.obtainMessage(
+ ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED,
+ new ReportedNetworkConnectivityInfo(
+ hasConnectivity, true /* isNetworkRevalidating */, uid, nai)));
nai.networkMonitor().forceReevaluation(uid);
}
@@ -5277,12 +5299,12 @@
* information, e.g underlying ifaces.
*/
private UnderlyingNetworkInfo createVpnInfo(NetworkAgentInfo nai) {
- if (!nai.isVPN()) return null;
-
Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list.
- if (underlyingNetworks == null) {
+ // TODO: stop using propagateUnderlyingCapabilities here, for example, by always
+ // initializing NetworkAgentInfo#declaredUnderlyingNetworks to an empty array.
+ if (underlyingNetworks == null && nai.propagateUnderlyingCapabilities()) {
final NetworkAgentInfo defaultNai = getDefaultNetworkForUid(
nai.networkCapabilities.getOwnerUid());
if (defaultNai != null) {
@@ -5331,7 +5353,7 @@
private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) {
// TODO: support more than one level of underlying networks, either via a fixed-depth search
// (e.g., 2 levels of underlying networks), or via loop detection, or....
- if (!nai.supportsUnderlyingNetworks()) return false;
+ if (!nai.propagateUnderlyingCapabilities()) return false;
final Network[] underlying = underlyingNetworksOrDefault(
nai.networkCapabilities.getOwnerUid(), nai.declaredUnderlyingNetworks);
return CollectionUtils.contains(underlying, network);
@@ -6280,7 +6302,8 @@
callingAttributionTag);
if (VDBG) log("pendingListenForNetwork for " + nri);
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT, nri));
}
/** Returns the next Network provider ID. */
@@ -7303,7 +7326,7 @@
newNc.addCapability(NET_CAPABILITY_NOT_ROAMING);
}
- if (nai.supportsUnderlyingNetworks()) {
+ if (nai.propagateUnderlyingCapabilities()) {
applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, nai.declaredCapabilities,
newNc);
}
@@ -8329,13 +8352,13 @@
// Second phase : deal with the active request (if any)
if (null != activeRequest && activeRequest.isRequest()) {
final boolean oldNeeded = offer.neededFor(activeRequest);
- // An offer is needed if it is currently served by this provider or if this offer
- // can beat the current satisfier.
+ // If an offer can satisfy the request, it is considered needed if it is currently
+ // served by this provider or if this offer can beat the current satisfier.
final boolean currentlyServing = satisfier != null
- && satisfier.factorySerialNumber == offer.providerId;
- final boolean newNeeded = (currentlyServing
- || (activeRequest.canBeSatisfiedBy(offer.caps)
- && networkRanker.mightBeat(activeRequest, satisfier, offer)));
+ && satisfier.factorySerialNumber == offer.providerId
+ && activeRequest.canBeSatisfiedBy(offer.caps);
+ final boolean newNeeded = currentlyServing
+ || networkRanker.mightBeat(activeRequest, satisfier, offer);
if (newNeeded != oldNeeded) {
if (newNeeded) {
offer.onNetworkNeeded(activeRequest);
@@ -8445,7 +8468,7 @@
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
if (!createNativeNetwork(networkAgent)) return;
- if (networkAgent.supportsUnderlyingNetworks()) {
+ if (networkAgent.propagateUnderlyingCapabilities()) {
// Initialize the network's capabilities to their starting values according to the
// underlying networks. This ensures that the capabilities are correct before
// anything happens to the network.
@@ -9039,8 +9062,7 @@
* the platform. This event will invoke {@link
* IConnectivityDiagnosticsCallback#onNetworkConnectivityReported} for permissioned
* callbacks.
- * obj = Network that was reported on
- * arg1 = boolint for the quality reported
+ * obj = ReportedNetworkConnectivityInfo with info on reported Network connectivity.
*/
private static final int EVENT_NETWORK_CONNECTIVITY_REPORTED = 5;
@@ -9078,7 +9100,7 @@
break;
}
case EVENT_NETWORK_CONNECTIVITY_REPORTED: {
- handleNetworkConnectivityReported((NetworkAgentInfo) msg.obj, toBool(msg.arg1));
+ handleNetworkConnectivityReported((ReportedNetworkConnectivityInfo) msg.obj);
break;
}
default: {
@@ -9148,6 +9170,28 @@
}
}
+ /**
+ * Class used for sending info for a call to {@link #reportNetworkConnectivity()} to {@link
+ * ConnectivityDiagnosticsHandler}.
+ */
+ private static class ReportedNetworkConnectivityInfo {
+ public final boolean hasConnectivity;
+ public final boolean isNetworkRevalidating;
+ public final int reporterUid;
+ @NonNull public final NetworkAgentInfo nai;
+
+ private ReportedNetworkConnectivityInfo(
+ boolean hasConnectivity,
+ boolean isNetworkRevalidating,
+ int reporterUid,
+ @NonNull NetworkAgentInfo nai) {
+ this.hasConnectivity = hasConnectivity;
+ this.isNetworkRevalidating = isNetworkRevalidating;
+ this.reporterUid = reporterUid;
+ this.nai = nai;
+ }
+ }
+
private void handleRegisterConnectivityDiagnosticsCallback(
@NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) {
ensureRunningOnConnectivityServiceThread();
@@ -9255,13 +9299,14 @@
networkCapabilities,
extras);
nai.setConnectivityReport(report);
+
final List<IConnectivityDiagnosticsCallback> results =
- getMatchingPermissionedCallbacks(nai);
+ getMatchingPermissionedCallbacks(nai, Process.INVALID_UID);
for (final IConnectivityDiagnosticsCallback cb : results) {
try {
cb.onConnectivityReportAvailable(report);
} catch (RemoteException ex) {
- loge("Error invoking onConnectivityReport", ex);
+ loge("Error invoking onConnectivityReportAvailable", ex);
}
}
}
@@ -9280,7 +9325,7 @@
networkCapabilities,
extras);
final List<IConnectivityDiagnosticsCallback> results =
- getMatchingPermissionedCallbacks(nai);
+ getMatchingPermissionedCallbacks(nai, Process.INVALID_UID);
for (final IConnectivityDiagnosticsCallback cb : results) {
try {
cb.onDataStallSuspected(report);
@@ -9291,15 +9336,39 @@
}
private void handleNetworkConnectivityReported(
- @NonNull NetworkAgentInfo nai, boolean connectivity) {
+ @NonNull ReportedNetworkConnectivityInfo reportedNetworkConnectivityInfo) {
+ final NetworkAgentInfo nai = reportedNetworkConnectivityInfo.nai;
+ final ConnectivityReport cachedReport = nai.getConnectivityReport();
+
+ // If the Network is being re-validated as a result of this call to
+ // reportNetworkConnectivity(), notify all permissioned callbacks. Otherwise, only notify
+ // permissioned callbacks registered by the reporter.
final List<IConnectivityDiagnosticsCallback> results =
- getMatchingPermissionedCallbacks(nai);
+ getMatchingPermissionedCallbacks(
+ nai,
+ reportedNetworkConnectivityInfo.isNetworkRevalidating
+ ? Process.INVALID_UID
+ : reportedNetworkConnectivityInfo.reporterUid);
+
for (final IConnectivityDiagnosticsCallback cb : results) {
try {
- cb.onNetworkConnectivityReported(nai.network, connectivity);
+ cb.onNetworkConnectivityReported(
+ nai.network, reportedNetworkConnectivityInfo.hasConnectivity);
} catch (RemoteException ex) {
loge("Error invoking onNetworkConnectivityReported", ex);
}
+
+ // If the Network isn't re-validating, also provide the cached report. If there is no
+ // cached report, the Network is still being validated and a report will be sent once
+ // validation is complete. Note that networks which never undergo validation will still
+ // have a cached ConnectivityReport with RESULT_SKIPPED.
+ if (!reportedNetworkConnectivityInfo.isNetworkRevalidating && cachedReport != null) {
+ try {
+ cb.onConnectivityReportAvailable(cachedReport);
+ } catch (RemoteException ex) {
+ loge("Error invoking onConnectivityReportAvailable", ex);
+ }
+ }
}
}
@@ -9312,20 +9381,38 @@
return sanitized;
}
+ /**
+ * Gets a list of ConnectivityDiagnostics callbacks that match the specified Network and uid.
+ *
+ * <p>If Process.INVALID_UID is specified, all matching callbacks will be returned.
+ */
private List<IConnectivityDiagnosticsCallback> getMatchingPermissionedCallbacks(
- @NonNull NetworkAgentInfo nai) {
+ @NonNull NetworkAgentInfo nai, int uid) {
final List<IConnectivityDiagnosticsCallback> results = new ArrayList<>();
for (Entry<IBinder, ConnectivityDiagnosticsCallbackInfo> entry :
mConnectivityDiagnosticsCallbacks.entrySet()) {
final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue();
final NetworkRequestInfo nri = cbInfo.mRequestInfo;
+
// Connectivity Diagnostics rejects multilayer requests at registration hence get(0).
- if (nai.satisfies(nri.mRequests.get(0))) {
- if (checkConnectivityDiagnosticsPermissions(
- nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
- results.add(entry.getValue().mCb);
- }
+ if (!nai.satisfies(nri.mRequests.get(0))) {
+ continue;
}
+
+ // UID for this callback must either be:
+ // - INVALID_UID (which sends callbacks to all UIDs), or
+ // - The callback's owner (the owner called reportNetworkConnectivity() and is being
+ // notified as a result)
+ if (uid != Process.INVALID_UID && uid != nri.mUid) {
+ continue;
+ }
+
+ if (!checkConnectivityDiagnosticsPermissions(
+ nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) {
+ continue;
+ }
+
+ results.add(entry.getValue().mCb);
}
return results;
}
@@ -9354,7 +9441,7 @@
private boolean ownsVpnRunningOverNetwork(int uid, Network network) {
for (NetworkAgentInfo virtual : mNetworkAgentInfos) {
- if (virtual.supportsUnderlyingNetworks()
+ if (virtual.propagateUnderlyingCapabilities()
&& virtual.networkCapabilities.getOwnerUid() == uid
&& CollectionUtils.contains(virtual.declaredUnderlyingNetworks, network)) {
return true;
@@ -9953,7 +10040,7 @@
// - The request for the mobile network preferred.
// - The request for the default network, for fallback.
requests.add(createDefaultInternetRequestForTransport(
- TRANSPORT_CELLULAR, NetworkRequest.Type.LISTEN));
+ TRANSPORT_CELLULAR, NetworkRequest.Type.REQUEST));
requests.add(createDefaultInternetRequestForTransport(
TYPE_NONE, NetworkRequest.Type.TRACK_DEFAULT));
final Set<UidRange> ranges = new ArraySet<>();
diff --git a/service/src/com/android/server/connectivity/KeepaliveTracker.java b/service/src/com/android/server/connectivity/KeepaliveTracker.java
index acf39f0..ee1538a 100644
--- a/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -373,12 +373,10 @@
Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
}
}
- // Ignore the case when the network disconnects immediately after stop() has been
- // called and the keepalive code is waiting for the response from the modem. This
- // might happen when the caller listens for a lower-layer network disconnect
- // callback and stop the keepalive at that time. But the stop() races with the
- // stop() generated in ConnectivityService network disconnection code path.
- if (mStartedState == STOPPING && reason == ERROR_INVALID_NETWORK) return;
+ // To prevent races from re-entrance of stop(), return if the state is already stopping.
+ // This might happen if multiple event sources stop keepalive in a short time. Such as
+ // network disconnect after user calls stop(), or tear down socket after binder died.
+ if (mStartedState == STOPPING) return;
// Store the reason of stopping, and report it after the keepalive is fully stopped.
if (mStopReason != ERROR_STOP_REASON_UNINITIALIZED) {
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 18becd4..bbf523a 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -157,8 +157,8 @@
@NonNull public NetworkCapabilities networkCapabilities;
@NonNull public final NetworkAgentConfig networkAgentConfig;
- // Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true.
- // The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are
+ // Underlying networks declared by the agent.
+ // The networks in this list might be declared by a VPN using setUnderlyingNetworks and are
// not guaranteed to be current or correct, or even to exist.
//
// This array is read and iterated on multiple threads with no locking so its contents must
@@ -168,7 +168,7 @@
// The capabilities originally announced by the NetworkAgent, regardless of any capabilities
// that were added or removed due to this network's underlying networks.
- // Only set if #supportsUnderlyingNetworks is true.
+ // Only set if #propagateUnderlyingCapabilities is true.
public @Nullable NetworkCapabilities declaredCapabilities;
// Indicates if netd has been told to create this Network. From this point on the appropriate
@@ -898,8 +898,11 @@
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
}
- /** Whether this network might have underlying networks. Currently only true for VPNs. */
- public boolean supportsUnderlyingNetworks() {
+ /**
+ * Whether this network should propagate the capabilities from its underlying networks.
+ * Currently only true for VPNs.
+ */
+ public boolean propagateUnderlyingCapabilities() {
return isVPN();
}
diff --git a/service/src/com/android/server/connectivity/NetworkNotificationManager.java b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
index b57ad5d..ae98d92 100644
--- a/service/src/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
@@ -274,13 +274,17 @@
.setWhen(System.currentTimeMillis())
.setShowWhen(notifyType == NotificationType.NETWORK_SWITCH)
.setSmallIcon(icon)
- .setAutoCancel(true)
+ .setAutoCancel(r.getBoolean(R.bool.config_autoCancelNetworkNotifications))
.setTicker(title)
.setColor(mContext.getColor(android.R.color.system_notification_accent_color))
.setContentTitle(title)
.setContentIntent(intent)
.setLocalOnly(true)
- .setOnlyAlertOnce(true);
+ .setOnlyAlertOnce(true)
+ // TODO: consider having action buttons to disconnect on the sign-in notification
+ // especially if it is ongoing
+ .setOngoing(notifyType == NotificationType.SIGN_IN
+ && r.getBoolean(R.bool.config_ongoingSignInNotification));
if (notifyType == NotificationType.NETWORK_SWITCH) {
builder.setStyle(new Notification.BigTextStyle().bigText(details));
diff --git a/service/src/com/android/server/connectivity/NetworkOffer.java b/service/src/com/android/server/connectivity/NetworkOffer.java
index 8285e7a..1e975dd 100644
--- a/service/src/com/android/server/connectivity/NetworkOffer.java
+++ b/service/src/com/android/server/connectivity/NetworkOffer.java
@@ -143,6 +143,6 @@
@Override
public String toString() {
- return "NetworkOffer [ Score " + score + " ]";
+ return "NetworkOffer [ Score " + score + " Caps " + caps + "]";
}
}
diff --git a/service/src/com/android/server/connectivity/OsCompat.java b/service/src/com/android/server/connectivity/OsCompat.java
deleted file mode 100644
index 57e3dcd..0000000
--- a/service/src/com/android/server/connectivity/OsCompat.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.connectivity;
-
-import android.system.ErrnoException;
-import android.system.Os;
-
-import java.io.FileDescriptor;
-
-/**
- * Compatibility utility for android.system.Os core platform APIs.
- *
- * Connectivity has access to such APIs, but they are not part of the module_current stubs yet
- * (only core_current). Most stable core platform APIs are included manually in the connectivity
- * build rules, but because Os is also part of the base java SDK that is earlier on the
- * classpath, the extra core platform APIs are not seen.
- *
- * TODO (b/157639992, b/183097033): remove as soon as core_current is part of system_server_current
- * @hide
- */
-public class OsCompat {
- // This value should be correct on all architectures supported by Android, but hardcoding ioctl
- // numbers should be avoided.
- /**
- * @see android.system.OsConstants#TIOCOUTQ
- */
- public static final int TIOCOUTQ = 0x5411;
-
- /**
- * @see android.system.Os#getsockoptInt(FileDescriptor, int, int)
- */
- public static int getsockoptInt(FileDescriptor fd, int level, int option) throws
- ErrnoException {
- try {
- return (int) Os.class.getMethod(
- "getsockoptInt", FileDescriptor.class, int.class, int.class)
- .invoke(null, fd, level, option);
- } catch (ReflectiveOperationException e) {
- if (e.getCause() instanceof ErrnoException) {
- throw (ErrnoException) e.getCause();
- }
- throw new IllegalStateException("Error calling getsockoptInt", e);
- }
- }
-
- /**
- * @see android.system.Os#ioctlInt(FileDescriptor, int)
- */
- public static int ioctlInt(FileDescriptor fd, int cmd) throws
- ErrnoException {
- try {
- return (int) Os.class.getMethod(
- "ioctlInt", FileDescriptor.class, int.class).invoke(null, fd, cmd);
- } catch (ReflectiveOperationException e) {
- if (e.getCause() instanceof ErrnoException) {
- throw (ErrnoException) e.getCause();
- }
- throw new IllegalStateException("Error calling ioctlInt", e);
- }
- }
-}
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index 99118ac..512d767 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -121,15 +121,23 @@
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- final Uri packageData = intent.getData();
- final String packageName =
- packageData != null ? packageData.getSchemeSpecificPart() : null;
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ final Uri packageData = intent.getData();
+ final String packageName =
+ packageData != null ? packageData.getSchemeSpecificPart() : null;
onPackageAdded(packageName, uid);
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ final Uri packageData = intent.getData();
+ final String packageName =
+ packageData != null ? packageData.getSchemeSpecificPart() : null;
onPackageRemoved(packageName, uid);
+ } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+ final String[] pkgList =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ onExternalApplicationsAvailable(pkgList);
} else {
Log.wtf(TAG, "received unexpected intent: " + action);
}
@@ -194,6 +202,12 @@
mIntentReceiver, intentFilter, null /* broadcastPermission */,
null /* scheduler */);
+ final IntentFilter externalIntentFilter =
+ new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ userAllContext.registerReceiver(
+ mIntentReceiver, externalIntentFilter, null /* broadcastPermission */,
+ null /* scheduler */);
+
// Register UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
mDeps.registerContentObserver(
userAllContext,
@@ -812,6 +826,21 @@
update(mUsers, removedUids, false /* add */);
}
+ private synchronized void onExternalApplicationsAvailable(String[] pkgList) {
+ if (CollectionUtils.isEmpty(pkgList)) {
+ Log.e(TAG, "No available external application.");
+ return;
+ }
+
+ for (String app : pkgList) {
+ final PackageInfo info = getPackageInfo(app);
+ if (info == null || info.applicationInfo == null) continue;
+
+ final int appId = info.applicationInfo.uid;
+ onPackageAdded(app, appId); // Use onPackageAdded to add package one by one.
+ }
+ }
+
/** Dump info to dumpsys */
public void dump(IndentingPrintWriter pw) {
pw.println("Interface filtering rules:");
diff --git a/service/src/com/android/server/connectivity/TcpKeepaliveController.java b/service/src/com/android/server/connectivity/TcpKeepaliveController.java
index 73f3475..c480594 100644
--- a/service/src/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/service/src/com/android/server/connectivity/TcpKeepaliveController.java
@@ -27,8 +27,7 @@
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IP_TOS;
import static android.system.OsConstants.IP_TTL;
-
-import static com.android.server.connectivity.OsCompat.TIOCOUTQ;
+import static android.system.OsConstants.TIOCOUTQ;
import android.annotation.NonNull;
import android.net.InvalidPacketException;
@@ -176,10 +175,10 @@
}
// Query write sequence number from SEND_QUEUE.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE);
- tcpDetails.seq = OsCompat.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+ tcpDetails.seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
// Query read sequence number from RECV_QUEUE.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE);
- tcpDetails.ack = OsCompat.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+ tcpDetails.ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
// Switch to NO_QUEUE to prevent illegal socket read/write in repair mode.
Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE);
// Finally, check if socket is still idle. TODO : this check needs to move to
@@ -199,9 +198,9 @@
tcpDetails.rcvWndScale = trw.rcvWndScale;
if (tcpDetails.srcAddress.length == 4 /* V4 address length */) {
// Query TOS.
- tcpDetails.tos = OsCompat.getsockoptInt(fd, IPPROTO_IP, IP_TOS);
+ tcpDetails.tos = Os.getsockoptInt(fd, IPPROTO_IP, IP_TOS);
// Query TTL.
- tcpDetails.ttl = OsCompat.getsockoptInt(fd, IPPROTO_IP, IP_TTL);
+ tcpDetails.ttl = Os.getsockoptInt(fd, IPPROTO_IP, IP_TTL);
}
} catch (ErrnoException e) {
Log.e(TAG, "Exception reading TCP state from socket", e);
@@ -306,7 +305,7 @@
private static boolean isReceiveQueueEmpty(FileDescriptor fd)
throws ErrnoException {
- final int result = OsCompat.ioctlInt(fd, SIOCINQ);
+ final int result = Os.ioctlInt(fd, SIOCINQ);
if (result != 0) {
Log.e(TAG, "Read queue has data");
return false;
@@ -316,7 +315,7 @@
private static boolean isSendQueueEmpty(FileDescriptor fd)
throws ErrnoException {
- final int result = OsCompat.ioctlInt(fd, SIOCOUTQ);
+ final int result = Os.ioctlInt(fd, SIOCOUTQ);
if (result != 0) {
Log.e(TAG, "Write queue has data");
return false;
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index 28339f1..e1fab09 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -43,13 +43,30 @@
],
}
+// Connectivity coverage tests combines Tethering and Connectivity tests, each with their
+// respective jarjar rules applied.
+// Some tests may be duplicated (in particular static lib tests), as they need to be run under both
+// jarjared packages to cover both usages.
+android_library {
+ name: "ConnectivityCoverageTestsLib",
+ min_sdk_version: "30",
+ static_libs: [
+ "FrameworksNetTestsLib",
+ "NetdStaticLibTestsLib",
+ "NetworkStaticLibTestsLib",
+ ],
+ jarjar_rules: ":connectivity-jarjar-rules",
+ manifest: "AndroidManifest_coverage.xml",
+ visibility: ["//visibility:private"],
+}
+
android_test {
name: "ConnectivityCoverageTests",
// Tethering started on SDK 30
min_sdk_version: "30",
// TODO: change to 31 as soon as it is available
target_sdk_version: "30",
- test_suites: ["device-tests", "mts"],
+ test_suites: ["general-tests", "mts"],
defaults: [
"framework-connectivity-test-defaults",
"FrameworksNetTests-jni-defaults",
@@ -62,13 +79,9 @@
// (some tests would fail).
// TODO: consider removing extended mockito usage in tests that use it, for performance
"mockito-target-extended-minus-junit4",
- "FrameworksNetTestsLib",
"modules-utils-native-coverage-listener",
- "NetdStaticLibTestsLib",
- "NetworkStaticLibTestsLib",
- "NetworkStackTestsLib",
- "TetheringTestsLatestSdkLib",
- "TetheringIntegrationTestsLatestSdkLib",
+ "ConnectivityCoverageTestsLib",
+ "TetheringCoverageTestsLib",
],
jni_libs: [
// For mockito extended
diff --git a/tests/common/java/android/net/NetworkProviderTest.kt b/tests/common/java/android/net/NetworkProviderTest.kt
index 8cea12e..ff5de1d 100644
--- a/tests/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/common/java/android/net/NetworkProviderTest.kt
@@ -315,9 +315,7 @@
LinkProperties(), scoreWeaker, config, provider) {}
agent.register()
agent.markConnected()
- // TODO: The request is satisying by offer 2 instead of offer 1, thus it should not be
- // considered as needed.
- offerCallback1.expectOnNetworkNeeded(ncFilter2)
+ offerCallback1.assertNoCallback() // Still unneeded.
offerCallback2.assertNoCallback() // Still needed.
offerCallback3.assertNoCallback() // Still needed.
offerCallback4.expectOnNetworkUnneeded(ncFilter4)
@@ -326,7 +324,7 @@
// if a request is currently satisfied by the network provided by the same provider.
// TODO: Consider offers with weaker score are unneeded.
agent.sendNetworkScore(scoreStronger)
- offerCallback1.assertNoCallback()
+ offerCallback1.assertNoCallback() // Still unneeded.
offerCallback2.assertNoCallback() // Still needed.
offerCallback3.assertNoCallback() // Still needed.
offerCallback4.assertNoCallback() // Still unneeded.
@@ -334,7 +332,7 @@
// Verify that offer callbacks cannot receive any event if offer is unregistered.
provider2.unregisterNetworkOffer(offerCallback4)
agent.unregister()
- offerCallback1.assertNoCallback() // Still needed.
+ offerCallback1.assertNoCallback() // Still unneeded.
offerCallback2.assertNoCallback() // Still needed.
offerCallback3.assertNoCallback() // Still needed.
// Since the agent is unregistered, and the offer has chance to satisfy the request,
@@ -344,7 +342,7 @@
// Verify that offer callbacks cannot receive any event if provider is unregistered.
mCm.unregisterNetworkProvider(provider)
mCm.unregisterNetworkCallback(cb2)
- offerCallback1.assertNoCallback() // Should be unneeded if not unregistered.
+ offerCallback1.assertNoCallback() // No callback since it is still unneeded.
offerCallback2.assertNoCallback() // Should be unneeded if not unregistered.
offerCallback3.assertNoCallback() // Should be unneeded if not unregistered.
offerCallback4.assertNoCallback() // Already unregistered.
diff --git a/tests/common/java/android/net/metrics/IpConnectivityLogTest.java b/tests/common/java/android/net/metrics/IpConnectivityLogTest.java
index d4780d3..ab97f2d 100644
--- a/tests/common/java/android/net/metrics/IpConnectivityLogTest.java
+++ b/tests/common/java/android/net/metrics/IpConnectivityLogTest.java
@@ -19,6 +19,8 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static com.android.net.module.util.NetworkCapabilitiesUtils.unpackBits;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.timeout;
@@ -31,8 +33,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.util.BitUtils;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,7 +49,7 @@
@SmallTest
public class IpConnectivityLogTest {
private static final int FAKE_NET_ID = 100;
- private static final int[] FAKE_TRANSPORT_TYPES = BitUtils.unpackBits(TRANSPORT_WIFI);
+ private static final int[] FAKE_TRANSPORT_TYPES = unpackBits(TRANSPORT_WIFI);
private static final long FAKE_TIME_STAMP = System.currentTimeMillis();
private static final String FAKE_INTERFACE_NAME = "test";
private static final IpReachabilityEvent FAKE_EV =
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyManagerTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyManagerTest.java
index ddc5fd4..ad7ec9e 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyManagerTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/NetworkPolicyManagerTest.java
@@ -23,6 +23,8 @@
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isUidNetworkingBlocked;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isUidRestrictedOnMeteredNetworks;
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
+import static com.android.cts.net.hostside.Property.BATTERY_SAVER_MODE;
+import static com.android.cts.net.hostside.Property.DATA_SAVER_MODE;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -79,6 +81,7 @@
assertFalse(isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_ALLOWED_NON_METERED
}
+ @RequiredProperties({DATA_SAVER_MODE, BATTERY_SAVER_MODE})
@Test
public void testIsUidNetworkingBlocked_withSystemUid() throws Exception {
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
@@ -103,6 +106,7 @@
}
}
+ @RequiredProperties({DATA_SAVER_MODE})
@Test
public void testIsUidNetworkingBlocked_withDataSaverMode() throws Exception {
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
@@ -182,6 +186,7 @@
}
}
+ @RequiredProperties({BATTERY_SAVER_MODE})
@Test
public void testIsUidNetworkingBlocked_withPowerSaverMode() throws Exception {
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
@@ -209,6 +214,7 @@
}
}
+ @RequiredProperties({DATA_SAVER_MODE})
@Test
public void testIsUidRestrictedOnMeteredNetworks() throws Exception {
try {
diff --git a/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java b/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java
index a54fd64..86642ea 100644
--- a/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/BatteryStatsManagerTest.java
@@ -35,6 +35,7 @@
import android.os.Build;
import android.os.connectivity.CellularBatteryStats;
import android.os.connectivity.WifiBatteryStats;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import androidx.test.runner.AndroidJUnit4;
@@ -80,6 +81,7 @@
}
@Test
+ @AppModeFull(reason = "Cannot get CHANGE_NETWORK_STATE to request wifi/cell in instant mode")
@SkipPresubmit(reason = "Virtual hardware does not support wifi battery stats")
public void testReportNetworkInterfaceForTransports() throws Exception {
try {
@@ -132,6 +134,7 @@
}
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+ @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testReportNetworkInterfaceForTransports_throwsSecurityException()
throws Exception {
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
index ccbdbd3..a40c92d 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
@@ -22,6 +22,7 @@
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.NETWORK_VALIDATION_RESULT_SKIPPED;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
@@ -78,6 +79,7 @@
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.ArrayUtils;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -292,7 +294,7 @@
final String interfaceName =
mConnectivityManager.getLinkProperties(network).getInterfaceName();
connDiagsCallback.expectOnConnectivityReportAvailable(
- network, interfaceName, TRANSPORT_CELLULAR);
+ network, interfaceName, TRANSPORT_CELLULAR, NETWORK_VALIDATION_RESULT_VALID);
connDiagsCallback.assertNoCallback();
}
@@ -423,9 +425,10 @@
cb.expectOnNetworkConnectivityReported(mTestNetwork, hasConnectivity);
- // if hasConnectivity does not match the network's known connectivity, it will be
- // revalidated which will trigger another onConnectivityReportAvailable callback.
- if (!hasConnectivity) {
+ // All calls to #onNetworkConnectivityReported are expected to be accompanied by a call to
+ // #onConnectivityReportAvailable for S+ (for R, ConnectivityReports were only sent when the
+ // Network was re-validated - when reported connectivity != known connectivity).
+ if (SdkLevel.isAtLeastS() || !hasConnectivity) {
cb.expectOnConnectivityReportAvailable(mTestNetwork, interfaceName);
}
@@ -479,11 +482,19 @@
public void expectOnConnectivityReportAvailable(
@NonNull Network network, @NonNull String interfaceName) {
- expectOnConnectivityReportAvailable(network, interfaceName, TRANSPORT_TEST);
+ // Test Networks both do not require validation and are not tested for validation. This
+ // results in the validation result being reported as SKIPPED for S+ (for R, the
+ // platform marked these Networks as VALID).
+ final int expectedNetworkValidationResult =
+ SdkLevel.isAtLeastS()
+ ? NETWORK_VALIDATION_RESULT_SKIPPED
+ : NETWORK_VALIDATION_RESULT_VALID;
+ expectOnConnectivityReportAvailable(
+ network, interfaceName, TRANSPORT_TEST, expectedNetworkValidationResult);
}
- public void expectOnConnectivityReportAvailable(
- @NonNull Network network, @NonNull String interfaceName, int transportType) {
+ public void expectOnConnectivityReportAvailable(@NonNull Network network,
+ @NonNull String interfaceName, int transportType, int expectedValidationResult) {
final ConnectivityReport result =
(ConnectivityReport) mHistory.poll(CALLBACK_TIMEOUT_MILLIS, x -> true);
assertEquals(network, result.getNetwork());
@@ -496,9 +507,9 @@
final PersistableBundle extras = result.getAdditionalInfo();
assertTrue(extras.containsKey(KEY_NETWORK_VALIDATION_RESULT));
- final int validationResult = extras.getInt(KEY_NETWORK_VALIDATION_RESULT);
- assertEquals("Network validation result is not 'valid'",
- NETWORK_VALIDATION_RESULT_VALID, validationResult);
+ final int actualValidationResult = extras.getInt(KEY_NETWORK_VALIDATION_RESULT);
+ assertEquals("Network validation result is incorrect",
+ expectedValidationResult, actualValidationResult);
assertTrue(extras.containsKey(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK));
final int probesSucceeded = extras.getInt(KEY_NETWORK_VALIDATION_RESULT);
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index a19c7a6..527897e 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -72,6 +72,7 @@
import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.MiscAsserts.assertThrows;
@@ -499,6 +500,7 @@
@Test
public void testGetAllNetworkStateSnapshots()
throws InterruptedException {
+ assumeTrue(mPackageManager.hasSystemFeature(FEATURE_TELEPHONY));
// Make sure cell is active to retrieve IMSI for verification in later step.
final Network cellNetwork = mCtsNetUtils.connectToCell();
final String subscriberId = getSubscriberIdForCellNetwork(cellNetwork);
@@ -936,8 +938,8 @@
// noticeably flaky.
Thread.sleep(NO_CALLBACK_TIMEOUT_MS);
- // TODO: BUG (b/189868426): this should also apply to listens
- if (!useListen) {
+ // For R- frameworks, listens will receive duplicated callbacks. See b/189868426.
+ if (isAtLeastS() || !useListen) {
assertEquals("PendingIntent should only be received once", 1, receivedCount.get());
}
} finally {
@@ -952,8 +954,8 @@
boolean useListen) {
assertArrayEquals(filed.networkCapabilities.getCapabilities(),
broadcasted.networkCapabilities.getCapabilities());
- // TODO: BUG (b/189868426): this should also apply to listens
- if (useListen) return;
+ // For R- frameworks, listens will receive duplicated callbacks. See b/189868426.
+ if (!isAtLeastS() && useListen) return;
assertArrayEquals(filed.networkCapabilities.getTransportTypes(),
broadcasted.networkCapabilities.getTransportTypes());
}
@@ -1077,7 +1079,7 @@
final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
if (!m.find()) {
- fail("Unexpected format from cmd netpolicy");
+ fail("Unexpected format from cmd netpolicy, policyString = " + policyString);
}
return m.group(1);
}
@@ -2874,6 +2876,10 @@
public void testUidsAllowedOnRestrictedNetworks() throws Exception {
assumeTrue(TestUtils.shouldTestSApis());
+ // TODO (b/175199465): figure out a reasonable permission check for
+ // setUidsAllowedOnRestrictedNetworks that allows tests but not system-external callers.
+ assumeTrue(Build.isDebuggable());
+
final int uid = mPackageManager.getPackageUid(mContext.getPackageName(), 0 /* flag */);
final Set<Integer> originalUidsAllowedOnRestrictedNetworks =
ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(mContext);
@@ -2881,8 +2887,9 @@
// because it has been just installed to device. In case the uid is existed in setting
// mistakenly, try to remove the uid and set correct uids to setting.
originalUidsAllowedOnRestrictedNetworks.remove(uid);
- ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(mContext,
- originalUidsAllowedOnRestrictedNetworks);
+ runWithShellPermissionIdentity(() ->
+ ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
+ mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
final Handler h = new Handler(Looper.getMainLooper());
final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback();
@@ -2929,8 +2936,9 @@
final Set<Integer> newUidsAllowedOnRestrictedNetworks =
new ArraySet<>(originalUidsAllowedOnRestrictedNetworks);
newUidsAllowedOnRestrictedNetworks.add(uid);
- ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(mContext,
- newUidsAllowedOnRestrictedNetworks);
+ runWithShellPermissionIdentity(() ->
+ ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
+ mContext, newUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
// Wait a while for sending allowed uids on the restricted network to netd.
// TODD: Have a significant signal to know the uids has been send to netd.
assertBindSocketToNetworkSuccess(network);
@@ -2939,8 +2947,9 @@
agent.unregister();
// Restore setting.
- ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(mContext,
- originalUidsAllowedOnRestrictedNetworks);
+ runWithShellPermissionIdentity(() ->
+ ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
+ mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
}
}
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index ccc9416..7c380e3 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -101,6 +101,7 @@
import com.android.testutils.TestableNetworkCallback
import org.junit.After
import org.junit.Assert.assertArrayEquals
+import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -1034,6 +1035,9 @@
@Test
fun testQosCallbackRegisterWithUnregister() {
+ // Instant apps can't bind sockets to localhost
+ // TODO: use @AppModeFull when supported by DevSdkIgnoreRunner
+ assumeFalse(realContext.packageManager.isInstantApp())
val (agent, socket) = setupForQosCallbackTesting()
val qosCallback = TestableQosCallback()
@@ -1060,6 +1064,9 @@
@Test
fun testQosCallbackOnQosSession() {
+ // Instant apps can't bind sockets to localhost
+ // TODO: use @AppModeFull when supported by DevSdkIgnoreRunner
+ assumeFalse(realContext.packageManager.isInstantApp())
val (agent, socket) = setupForQosCallbackTesting()
val qosCallback = TestableQosCallback()
Executors.newSingleThreadExecutor().let { executor ->
@@ -1104,6 +1111,9 @@
@Test
fun testQosCallbackOnError() {
+ // Instant apps can't bind sockets to localhost
+ // TODO: use @AppModeFull when supported by DevSdkIgnoreRunner
+ assumeFalse(realContext.packageManager.isInstantApp())
val (agent, socket) = setupForQosCallbackTesting()
val qosCallback = TestableQosCallback()
Executors.newSingleThreadExecutor().let { executor ->
@@ -1142,6 +1152,9 @@
@Test
fun testQosCallbackIdsAreMappedCorrectly() {
+ // Instant apps can't bind sockets to localhost
+ // TODO: use @AppModeFull when supported by DevSdkIgnoreRunner
+ assumeFalse(realContext.packageManager.isInstantApp())
val (agent, socket) = setupForQosCallbackTesting()
val qosCallback1 = TestableQosCallback()
val qosCallback2 = TestableQosCallback()
@@ -1182,6 +1195,9 @@
@Test
fun testQosCallbackWhenNetworkReleased() {
+ // Instant apps can't bind sockets to localhost
+ // TODO: use @AppModeFull when supported by DevSdkIgnoreRunner
+ assumeFalse(realContext.packageManager.isInstantApp())
val (agent, socket) = setupForQosCallbackTesting()
Executors.newSingleThreadExecutor().let { executor ->
try {
diff --git a/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java b/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
index 7d5e9ff..a20f1cc 100644
--- a/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
@@ -35,6 +35,7 @@
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
@@ -145,6 +146,7 @@
}
}
+ @AppModeFull(reason = "Instant apps can't bind sockets to localhost for a test proxy server")
@Test
public void testSetCurrentProxyScriptUrl() throws Exception {
// Register a PacProxyInstalledListener
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 0a5e506..bd1b74a 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -361,6 +361,7 @@
@Test
public void testRequestLatestEntitlementResult() throws Exception {
assumeTrue(mTM.isTetheringSupported());
+ assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY));
// Verify that requestLatestTetheringEntitlementResult() can get entitlement
// result(TETHER_ERROR_ENTITLEMENT_UNKNOWN due to invalid downstream type) via listener.
assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult(
diff --git a/tests/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/integration/util/com/android/server/NetworkAgentWrapper.java
index 17db179..95ea401 100644
--- a/tests/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -55,6 +55,7 @@
import com.android.testutils.HandlerUtils;
import com.android.testutils.TestableNetworkCallback;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -255,6 +256,15 @@
}
}
+ public void setUnderlyingNetworks(List<Network> underlyingNetworks) {
+ mNetworkAgent.setUnderlyingNetworks(underlyingNetworks);
+ }
+
+ public void setOwnerUid(int uid) {
+ mNetworkCapabilities.setOwnerUid(uid);
+ mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+ }
+
public void connect() {
if (!mConnected.compareAndSet(false /* expect */, true /* update */)) {
// compareAndSet returns false when the value couldn't be updated because it did not
diff --git a/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java b/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
index be95b6c..08a3007 100644
--- a/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
+++ b/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
@@ -40,9 +40,10 @@
import android.os.RemoteException;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -51,9 +52,9 @@
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsManagerTest {
private static final String TEST_SUBSCRIBER_ID = "subid";
diff --git a/tests/unit/java/android/net/ConnectivityManagerTest.java b/tests/unit/java/android/net/ConnectivityManagerTest.java
index b36e379..e7873af 100644
--- a/tests/unit/java/android/net/ConnectivityManagerTest.java
+++ b/tests/unit/java/android/net/ConnectivityManagerTest.java
@@ -59,7 +59,6 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.net.ConnectivityManager.NetworkCallback;
-import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
@@ -68,9 +67,10 @@
import android.os.Messenger;
import android.os.Process;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -79,9 +79,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
public class ConnectivityManagerTest {
@Mock Context mCtx;
diff --git a/tests/unit/java/android/net/Ikev2VpnProfileTest.java b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
index afd85e8..56e5c62 100644
--- a/tests/unit/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/unit/java/android/net/Ikev2VpnProfileTest.java
@@ -26,13 +26,13 @@
import android.os.Build;
import android.test.mock.MockContext;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.net.VpnProfile;
import com.android.internal.org.bouncycastle.x509.X509V1CertificateGenerator;
import com.android.net.module.util.ProxyUtils;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -53,8 +53,8 @@
/** Unit tests for {@link Ikev2VpnProfile.Builder}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class Ikev2VpnProfileTest {
private static final String SERVER_ADDR_STRING = "1.2.3.4";
private static final String IDENTITY_STRING = "Identity";
diff --git a/tests/unit/java/android/net/IpMemoryStoreTest.java b/tests/unit/java/android/net/IpMemoryStoreTest.java
index 6be5396..0b82759 100644
--- a/tests/unit/java/android/net/IpMemoryStoreTest.java
+++ b/tests/unit/java/android/net/IpMemoryStoreTest.java
@@ -39,9 +39,10 @@
import android.os.Build;
import android.os.RemoteException;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -55,9 +56,9 @@
import java.net.UnknownHostException;
import java.util.Arrays;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpMemoryStoreTest {
private static final String TAG = IpMemoryStoreTest.class.getSimpleName();
private static final String TEST_CLIENT_ID = "testClientId";
diff --git a/tests/unit/java/android/net/IpSecAlgorithmTest.java b/tests/unit/java/android/net/IpSecAlgorithmTest.java
index fc08408..cac8c2d 100644
--- a/tests/unit/java/android/net/IpSecAlgorithmTest.java
+++ b/tests/unit/java/android/net/IpSecAlgorithmTest.java
@@ -28,11 +28,11 @@
import android.os.Build;
import android.os.Parcel;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.CollectionUtils;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,8 +46,8 @@
/** Unit tests for {@link IpSecAlgorithm}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpSecAlgorithmTest {
private static final byte[] KEY_MATERIAL;
diff --git a/tests/unit/java/android/net/IpSecConfigTest.java b/tests/unit/java/android/net/IpSecConfigTest.java
index 457c923..b87cb48 100644
--- a/tests/unit/java/android/net/IpSecConfigTest.java
+++ b/tests/unit/java/android/net/IpSecConfigTest.java
@@ -25,17 +25,18 @@
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
/** Unit tests for {@link IpSecConfig}. */
@SmallTest
-@RunWith(JUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpSecConfigTest {
@Test
diff --git a/tests/unit/java/android/net/IpSecManagerTest.java b/tests/unit/java/android/net/IpSecManagerTest.java
index 3fd0064..cda8eb7 100644
--- a/tests/unit/java/android/net/IpSecManagerTest.java
+++ b/tests/unit/java/android/net/IpSecManagerTest.java
@@ -35,11 +35,11 @@
import android.system.Os;
import android.test.mock.MockContext;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.IpSecService;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -51,8 +51,8 @@
/** Unit tests for {@link IpSecManager}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpSecManagerTest {
private static final int TEST_UDP_ENCAP_PORT = 34567;
diff --git a/tests/unit/java/android/net/IpSecTransformTest.java b/tests/unit/java/android/net/IpSecTransformTest.java
index 96b09c3..81375f1 100644
--- a/tests/unit/java/android/net/IpSecTransformTest.java
+++ b/tests/unit/java/android/net/IpSecTransformTest.java
@@ -21,17 +21,18 @@
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
/** Unit tests for {@link IpSecTransform}. */
@SmallTest
-@RunWith(JUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpSecTransformTest {
@Test
diff --git a/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java b/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java
index 3fcb515..ed4f61d 100644
--- a/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java
+++ b/tests/unit/java/android/net/KeepalivePacketDataUtilTest.java
@@ -27,19 +27,19 @@
import android.os.Build;
import android.util.Log;
-import androidx.test.filters.SdkSuppress;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import java.net.InetAddress;
import java.nio.ByteBuffer;
-@RunWith(JUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public final class KeepalivePacketDataUtilTest {
private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
diff --git a/tests/unit/java/android/net/MacAddressTest.java b/tests/unit/java/android/net/MacAddressTest.java
index 0039e44..ae7deaa 100644
--- a/tests/unit/java/android/net/MacAddressTest.java
+++ b/tests/unit/java/android/net/MacAddressTest.java
@@ -24,11 +24,11 @@
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.net.module.util.MacAddressUtils;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,8 +38,8 @@
import java.util.Random;
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class MacAddressTest {
static class AddrTypeTestCase {
diff --git a/tests/unit/java/android/net/NetworkIdentityTest.kt b/tests/unit/java/android/net/NetworkIdentityTest.kt
index 4d04b19..f963593 100644
--- a/tests/unit/java/android/net/NetworkIdentityTest.kt
+++ b/tests/unit/java/android/net/NetworkIdentityTest.kt
@@ -21,14 +21,14 @@
import android.net.NetworkIdentity.OEM_PRIVATE
import android.net.NetworkIdentity.getOemBitfield
import android.os.Build
-import androidx.test.filters.SdkSuppress
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import kotlin.test.assertEquals
-@RunWith(JUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class NetworkIdentityTest {
@Test
fun testGetOemBitfield() {
diff --git a/tests/unit/java/android/net/NetworkStatsHistoryTest.java b/tests/unit/java/android/net/NetworkStatsHistoryTest.java
index 3ecce50..c5f8c00 100644
--- a/tests/unit/java/android/net/NetworkStatsHistoryTest.java
+++ b/tests/unit/java/android/net/NetworkStatsHistoryTest.java
@@ -42,11 +42,11 @@
import android.util.Log;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.tests.net.R;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Test;
@@ -58,9 +58,9 @@
import java.io.DataOutputStream;
import java.util.Random;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsHistoryTest {
private static final String TAG = "NetworkStatsHistoryTest";
diff --git a/tests/unit/java/android/net/NetworkStatsTest.java b/tests/unit/java/android/net/NetworkStatsTest.java
index 9a3f4c2..c971da1 100644
--- a/tests/unit/java/android/net/NetworkStatsTest.java
+++ b/tests/unit/java/android/net/NetworkStatsTest.java
@@ -43,9 +43,10 @@
import android.os.Process;
import android.util.ArrayMap;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.google.android.collect.Sets;
@@ -55,9 +56,9 @@
import java.util.Arrays;
import java.util.HashSet;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsTest {
private static final String TEST_IFACE = "test0";
@@ -733,6 +734,56 @@
ROAMING_ALL, DEFAULT_NETWORK_ALL, 50500L, 27L, 100200L, 55, 0);
}
+ // Tests a case where an PlatformVpn is used, where the entire datapath is in the kernel,
+ // including all encapsulation/decapsulation.
+ @Test
+ public void testMigrateTun_platformVpn() {
+ final int ownerUid = Process.SYSTEM_UID;
+ final String tunIface = "ipsec1";
+ final String underlyingIface = "wlan0";
+ NetworkStats delta = new NetworkStats(TEST_START, 9)
+ // 2 different apps sent/receive data via ipsec1.
+ .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
+ .insertEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
+ // Owner (system) sends data through the tunnel
+ .insertEntry(tunIface, ownerUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 2000L, 20L, 3000L, 30L, 0L)
+ // 1 app already has some traffic on the underlying interface, the other doesn't yet
+ .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L);
+
+ delta.migrateTun(ownerUid, tunIface, Arrays.asList(underlyingIface));
+ assertEquals(9, delta.size()); // 3 DBG entries + 1 entry per app per interface
+
+ // tunIface entries should not be changed.
+ assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+ assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L);
+ assertValues(delta, 2, tunIface, ownerUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 2000L, 20L, 3000L, 30L, 0L);
+
+ // Existing underlying Iface entries are updated to include usage over ipsec1
+ assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 51000L, 35L, 102000L, 70L, 0L);
+
+ // New entries are added on underlying Iface traffic
+ assertContains(delta, underlyingIface, ownerUid, SET_DEFAULT, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 2000L, 20L, 3000L, 30L, 0L);
+ assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L);
+
+ // New entries are added for debug purpose
+ assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+ assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 500, 2L, 200L, 5L, 0L);
+ assertContains(delta, underlyingIface, ownerUid, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 2000L, 20L, 3000L, 30L, 0L);
+ }
+
@Test
public void testFilter_NoFilter() {
NetworkStats.Entry entry1 = new NetworkStats.Entry(
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index 437f961..49c7271 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -19,10 +19,10 @@
import android.content.Context
import android.net.ConnectivityManager.TYPE_MOBILE
import android.net.ConnectivityManager.TYPE_WIFI
-import android.net.NetworkIdentity.SUBTYPE_COMBINED
import android.net.NetworkIdentity.OEM_NONE
import android.net.NetworkIdentity.OEM_PAID
import android.net.NetworkIdentity.OEM_PRIVATE
+import android.net.NetworkIdentity.SUBTYPE_COMBINED
import android.net.NetworkIdentity.buildNetworkIdentity
import android.net.NetworkStats.DEFAULT_NETWORK_ALL
import android.net.NetworkStats.METERED_ALL
@@ -31,25 +31,25 @@
import android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD
import android.net.NetworkTemplate.MATCH_WIFI
import android.net.NetworkTemplate.MATCH_WIFI_WILDCARD
-import android.net.NetworkTemplate.WIFI_NETWORKID_ALL
import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA
import android.net.NetworkTemplate.NETWORK_TYPE_ALL
import android.net.NetworkTemplate.OEM_MANAGED_ALL
import android.net.NetworkTemplate.OEM_MANAGED_NO
import android.net.NetworkTemplate.OEM_MANAGED_YES
import android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT
-import android.net.NetworkTemplate.buildTemplateWifi
-import android.net.NetworkTemplate.buildTemplateWifiWildcard
+import android.net.NetworkTemplate.WIFI_NETWORKID_ALL
import android.net.NetworkTemplate.buildTemplateCarrierMetered
import android.net.NetworkTemplate.buildTemplateMobileWithRatType
+import android.net.NetworkTemplate.buildTemplateWifi
+import android.net.NetworkTemplate.buildTemplateWifiWildcard
import android.os.Build
import android.telephony.TelephonyManager
-import androidx.test.filters.SdkSuppress
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.assertParcelSane
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import kotlin.test.assertEquals
@@ -62,8 +62,8 @@
private const val TEST_SSID1 = "ssid1"
private const val TEST_SSID2 = "ssid2"
-@RunWith(JUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class NetworkTemplateTest {
private val mockContext = mock(Context::class.java)
diff --git a/tests/unit/java/android/net/NetworkUtilsTest.java b/tests/unit/java/android/net/NetworkUtilsTest.java
index b292998..a28245d 100644
--- a/tests/unit/java/android/net/NetworkUtilsTest.java
+++ b/tests/unit/java/android/net/NetworkUtilsTest.java
@@ -20,8 +20,10 @@
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,9 +31,9 @@
import java.math.BigInteger;
import java.util.TreeSet;
-@RunWith(AndroidJUnit4.class)
-@androidx.test.filters.SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkUtilsTest {
@Test
public void testRoutedIPv4AddressCount() {
diff --git a/tests/unit/java/android/net/QosSocketFilterTest.java b/tests/unit/java/android/net/QosSocketFilterTest.java
index 1635c34..91f2cdd 100644
--- a/tests/unit/java/android/net/QosSocketFilterTest.java
+++ b/tests/unit/java/android/net/QosSocketFilterTest.java
@@ -21,8 +21,10 @@
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,9 +32,9 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
-@RunWith(AndroidJUnit4.class)
-@androidx.test.filters.SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class QosSocketFilterTest {
@Test
diff --git a/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java b/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java
index e198c8b..ead964e 100644
--- a/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java
+++ b/tests/unit/java/android/net/TelephonyNetworkSpecifierTest.java
@@ -26,16 +26,17 @@
import android.os.Build;
import android.telephony.SubscriptionManager;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.testutils.DevSdkIgnoreRule;
+
import org.junit.Test;
/**
* Unit test for {@link android.net.TelephonyNetworkSpecifier}.
*/
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class TelephonyNetworkSpecifierTest {
private static final int TEST_SUBID = 5;
private static final String TEST_SSID = "Test123";
diff --git a/tests/unit/java/android/net/VpnManagerTest.java b/tests/unit/java/android/net/VpnManagerTest.java
index b4d850a..532081a 100644
--- a/tests/unit/java/android/net/VpnManagerTest.java
+++ b/tests/unit/java/android/net/VpnManagerTest.java
@@ -31,12 +31,12 @@
import android.test.mock.MockContext;
import android.util.SparseArray;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.MessageUtils;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -44,8 +44,8 @@
/** Unit tests for {@link VpnManager}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class VpnManagerTest {
private static final String PKG_NAME = "fooPackage";
diff --git a/tests/unit/java/android/net/VpnTransportInfoTest.java b/tests/unit/java/android/net/VpnTransportInfoTest.java
index ae2ac04..b4c7ac4 100644
--- a/tests/unit/java/android/net/VpnTransportInfoTest.java
+++ b/tests/unit/java/android/net/VpnTransportInfoTest.java
@@ -26,16 +26,17 @@
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class VpnTransportInfoTest {
@Test
diff --git a/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java b/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java
index 219cfff..5d0b783 100644
--- a/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java
+++ b/tests/unit/java/android/net/ipmemorystore/ParcelableTests.java
@@ -25,9 +25,10 @@
import android.os.Parcel;
import android.os.Parcelable;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,9 +39,9 @@
import java.util.Arrays;
import java.util.Collections;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class ParcelableTests {
@Test
public void testNetworkAttributesParceling() throws Exception {
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 59a9316..31c8927 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -35,11 +35,11 @@
import android.os.Message;
import android.os.Messenger;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.AsyncChannel;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import org.junit.After;
@@ -49,9 +49,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NsdManagerTest {
static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD;
diff --git a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
index afe54d1..ca8cf07 100644
--- a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
+++ b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
@@ -26,9 +26,10 @@
import android.os.Parcel;
import android.os.StrictMode;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,9 +39,9 @@
import java.util.Arrays;
import java.util.Map;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NsdServiceInfoTest {
public final static InetAddress LOCALHOST;
diff --git a/tests/unit/java/android/net/util/DnsUtilsTest.java b/tests/unit/java/android/net/util/DnsUtilsTest.java
index 0bac75e..660d516 100644
--- a/tests/unit/java/android/net/util/DnsUtilsTest.java
+++ b/tests/unit/java/android/net/util/DnsUtilsTest.java
@@ -27,9 +27,10 @@
import android.net.InetAddresses;
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -39,9 +40,9 @@
import java.util.Collections;
import java.util.List;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class DnsUtilsTest {
private InetAddress stringToAddress(@NonNull String addr) {
return InetAddresses.parseNumericAddress(addr);
diff --git a/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt b/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt
index 65fb4ed..40f39a4 100644
--- a/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt
+++ b/tests/unit/java/android/net/util/KeepaliveUtilsTest.kt
@@ -26,16 +26,16 @@
import android.net.NetworkCapabilities.TRANSPORT_VPN
import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.os.Build
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import com.android.internal.R
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.any
import org.mockito.Mockito.doReturn
@@ -47,9 +47,9 @@
* Build, install and run with:
* atest android.net.util.KeepaliveUtilsTest
*/
-@RunWith(JUnit4::class)
+@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class KeepaliveUtilsTest {
// Prepare mocked context with given resource strings.
diff --git a/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt
index 7d602ab..576b8d3 100644
--- a/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt
+++ b/tests/unit/java/android/net/util/MultinetworkPolicyTrackerTest.kt
@@ -31,11 +31,11 @@
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.test.mock.MockContentResolver
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
import com.android.connectivity.resources.R
import com.android.internal.util.test.FakeSettingsProvider
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@@ -59,9 +59,9 @@
* Build, install and run with:
* atest android.net.util.MultinetworkPolicyTrackerTest
*/
-@RunWith(AndroidJUnit4::class)
+@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class MultinetworkPolicyTrackerTest {
private val resources = mock(Resources::class.java).also {
doReturn(R.integer.config_networkAvoidBadWifi).`when`(it).getIdentifier(
diff --git a/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java b/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java
index a4d8ea9..51388d4 100644
--- a/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java
+++ b/tests/unit/java/com/android/internal/net/NetworkUtilsInternalTest.java
@@ -31,17 +31,19 @@
import android.system.ErrnoException;
import android.system.Os;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import libcore.io.IoUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
-@RunWith(AndroidJUnit4.class)
-@androidx.test.filters.SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkUtilsInternalTest {
private static void expectSocketSuccess(String msg, int domain, int type) {
diff --git a/tests/unit/java/com/android/internal/net/VpnProfileTest.java b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
index 64cbc4e..a945a1f 100644
--- a/tests/unit/java/com/android/internal/net/VpnProfileTest.java
+++ b/tests/unit/java/com/android/internal/net/VpnProfileTest.java
@@ -27,12 +27,13 @@
import android.net.IpSecAlgorithm;
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import java.util.ArrayList;
import java.util.Arrays;
@@ -40,8 +41,8 @@
/** Unit tests for {@link VpnProfile}. */
@SmallTest
-@RunWith(JUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class VpnProfileTest {
private static final String DUMMY_PROFILE_KEY = "Test";
diff --git a/tests/unit/java/com/android/internal/util/BitUtilsTest.java b/tests/unit/java/com/android/internal/util/BitUtilsTest.java
deleted file mode 100644
index 9c6ac9b..0000000
--- a/tests/unit/java/com/android/internal/util/BitUtilsTest.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import static com.android.internal.util.BitUtils.bytesToBEInt;
-import static com.android.internal.util.BitUtils.bytesToLEInt;
-import static com.android.internal.util.BitUtils.getUint16;
-import static com.android.internal.util.BitUtils.getUint32;
-import static com.android.internal.util.BitUtils.getUint8;
-import static com.android.internal.util.BitUtils.packBits;
-import static com.android.internal.util.BitUtils.uint16;
-import static com.android.internal.util.BitUtils.uint32;
-import static com.android.internal.util.BitUtils.uint8;
-import static com.android.internal.util.BitUtils.unpackBits;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import android.os.Build;
-
-import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.Random;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
-public class BitUtilsTest {
-
- @Test
- public void testUnsignedByteWideningConversions() {
- byte b0 = 0;
- byte b1 = 1;
- byte bm1 = -1;
- assertEquals(0, uint8(b0));
- assertEquals(1, uint8(b1));
- assertEquals(127, uint8(Byte.MAX_VALUE));
- assertEquals(128, uint8(Byte.MIN_VALUE));
- assertEquals(255, uint8(bm1));
- assertEquals(255, uint8((byte)255));
- }
-
- @Test
- public void testUnsignedShortWideningConversions() {
- short s0 = 0;
- short s1 = 1;
- short sm1 = -1;
- assertEquals(0, uint16(s0));
- assertEquals(1, uint16(s1));
- assertEquals(32767, uint16(Short.MAX_VALUE));
- assertEquals(32768, uint16(Short.MIN_VALUE));
- assertEquals(65535, uint16(sm1));
- assertEquals(65535, uint16((short)65535));
- }
-
- @Test
- public void testUnsignedShortComposition() {
- byte b0 = 0;
- byte b1 = 1;
- byte b2 = 2;
- byte b10 = 10;
- byte b16 = 16;
- byte b128 = -128;
- byte b224 = -32;
- byte b255 = -1;
- assertEquals(0x0000, uint16(b0, b0));
- assertEquals(0xffff, uint16(b255, b255));
- assertEquals(0x0a01, uint16(b10, b1));
- assertEquals(0x8002, uint16(b128, b2));
- assertEquals(0x01ff, uint16(b1, b255));
- assertEquals(0x80ff, uint16(b128, b255));
- assertEquals(0xe010, uint16(b224, b16));
- }
-
- @Test
- public void testUnsignedIntWideningConversions() {
- assertEquals(0, uint32(0));
- assertEquals(1, uint32(1));
- assertEquals(2147483647L, uint32(Integer.MAX_VALUE));
- assertEquals(2147483648L, uint32(Integer.MIN_VALUE));
- assertEquals(4294967295L, uint32(-1));
- assertEquals(4294967295L, uint32((int)4294967295L));
- }
-
- @Test
- public void testBytesToInt() {
- assertEquals(0x00000000, bytesToBEInt(bytes(0, 0, 0, 0)));
- assertEquals(0xffffffff, bytesToBEInt(bytes(255, 255, 255, 255)));
- assertEquals(0x0a000001, bytesToBEInt(bytes(10, 0, 0, 1)));
- assertEquals(0x0a000002, bytesToBEInt(bytes(10, 0, 0, 2)));
- assertEquals(0x0a001fff, bytesToBEInt(bytes(10, 0, 31, 255)));
- assertEquals(0xe0000001, bytesToBEInt(bytes(224, 0, 0, 1)));
-
- assertEquals(0x00000000, bytesToLEInt(bytes(0, 0, 0, 0)));
- assertEquals(0x01020304, bytesToLEInt(bytes(4, 3, 2, 1)));
- assertEquals(0xffff0000, bytesToLEInt(bytes(0, 0, 255, 255)));
- }
-
- @Test
- public void testUnsignedGetters() {
- ByteBuffer b = ByteBuffer.allocate(4);
- b.putInt(0xffff);
-
- assertEquals(0x0, getUint8(b, 0));
- assertEquals(0x0, getUint8(b, 1));
- assertEquals(0xff, getUint8(b, 2));
- assertEquals(0xff, getUint8(b, 3));
-
- assertEquals(0x0, getUint16(b, 0));
- assertEquals(0xffff, getUint16(b, 2));
-
- b.rewind();
- b.putInt(0xffffffff);
- assertEquals(0xffffffffL, getUint32(b, 0));
- }
-
- @Test
- public void testBitsPacking() {
- BitPackingTestCase[] testCases = {
- new BitPackingTestCase(0, ints()),
- new BitPackingTestCase(1, ints(0)),
- new BitPackingTestCase(2, ints(1)),
- new BitPackingTestCase(3, ints(0, 1)),
- new BitPackingTestCase(4, ints(2)),
- new BitPackingTestCase(6, ints(1, 2)),
- new BitPackingTestCase(9, ints(0, 3)),
- new BitPackingTestCase(~Long.MAX_VALUE, ints(63)),
- new BitPackingTestCase(~Long.MAX_VALUE + 1, ints(0, 63)),
- new BitPackingTestCase(~Long.MAX_VALUE + 2, ints(1, 63)),
- };
- for (BitPackingTestCase tc : testCases) {
- int[] got = unpackBits(tc.packedBits);
- assertTrue(
- "unpackBits("
- + tc.packedBits
- + "): expected "
- + Arrays.toString(tc.bits)
- + " but got "
- + Arrays.toString(got),
- Arrays.equals(tc.bits, got));
- }
- for (BitPackingTestCase tc : testCases) {
- long got = packBits(tc.bits);
- assertEquals(
- "packBits("
- + Arrays.toString(tc.bits)
- + "): expected "
- + tc.packedBits
- + " but got "
- + got,
- tc.packedBits,
- got);
- }
-
- long[] moreTestCases = {
- 0, 1, -1, 23895, -908235, Long.MAX_VALUE, Long.MIN_VALUE, new Random().nextLong(),
- };
- for (long l : moreTestCases) {
- assertEquals(l, packBits(unpackBits(l)));
- }
- }
-
- static byte[] bytes(int b1, int b2, int b3, int b4) {
- return new byte[] {b(b1), b(b2), b(b3), b(b4)};
- }
-
- static byte b(int i) {
- return (byte) i;
- }
-
- static int[] ints(int... array) {
- return array;
- }
-
- static class BitPackingTestCase {
- final int[] bits;
- final long packedBits;
-
- BitPackingTestCase(long packedBits, int[] bits) {
- this.bits = bits;
- this.packedBits = packedBits;
- }
- }
-}
diff --git a/tests/unit/java/com/android/internal/util/RingBufferTest.java b/tests/unit/java/com/android/internal/util/RingBufferTest.java
deleted file mode 100644
index 81a6513..0000000
--- a/tests/unit/java/com/android/internal/util/RingBufferTest.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import android.os.Build;
-
-import androidx.test.filters.SdkSuppress;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
-public class RingBufferTest {
-
- @Test
- public void testEmptyRingBuffer() {
- RingBuffer<String> buffer = new RingBuffer<>(String.class, 100);
-
- assertArrayEquals(new String[0], buffer.toArray());
- }
-
- @Test
- public void testIncorrectConstructorArguments() {
- try {
- RingBuffer<String> buffer = new RingBuffer<>(String.class, -10);
- fail("Should not be able to create a negative capacity RingBuffer");
- } catch (IllegalArgumentException expected) {
- }
-
- try {
- RingBuffer<String> buffer = new RingBuffer<>(String.class, 0);
- fail("Should not be able to create a 0 capacity RingBuffer");
- } catch (IllegalArgumentException expected) {
- }
- }
-
- @Test
- public void testRingBufferWithNoWrapping() {
- RingBuffer<String> buffer = new RingBuffer<>(String.class, 100);
-
- buffer.append("a");
- buffer.append("b");
- buffer.append("c");
- buffer.append("d");
- buffer.append("e");
-
- String[] expected = {"a", "b", "c", "d", "e"};
- assertArrayEquals(expected, buffer.toArray());
- }
-
- @Test
- public void testRingBufferWithCapacity1() {
- RingBuffer<String> buffer = new RingBuffer<>(String.class, 1);
-
- buffer.append("a");
- assertArrayEquals(new String[]{"a"}, buffer.toArray());
-
- buffer.append("b");
- assertArrayEquals(new String[]{"b"}, buffer.toArray());
-
- buffer.append("c");
- assertArrayEquals(new String[]{"c"}, buffer.toArray());
-
- buffer.append("d");
- assertArrayEquals(new String[]{"d"}, buffer.toArray());
-
- buffer.append("e");
- assertArrayEquals(new String[]{"e"}, buffer.toArray());
- }
-
- @Test
- public void testRingBufferWithWrapping() {
- int capacity = 100;
- RingBuffer<String> buffer = new RingBuffer<>(String.class, capacity);
-
- buffer.append("a");
- buffer.append("b");
- buffer.append("c");
- buffer.append("d");
- buffer.append("e");
-
- String[] expected1 = {"a", "b", "c", "d", "e"};
- assertArrayEquals(expected1, buffer.toArray());
-
- String[] expected2 = new String[capacity];
- int firstIndex = 0;
- int lastIndex = capacity - 1;
-
- expected2[firstIndex] = "e";
- for (int i = 1; i < capacity; i++) {
- buffer.append("x");
- expected2[i] = "x";
- }
- assertArrayEquals(expected2, buffer.toArray());
-
- buffer.append("x");
- expected2[firstIndex] = "x";
- assertArrayEquals(expected2, buffer.toArray());
-
- for (int i = 0; i < 10; i++) {
- for (String s : expected2) {
- buffer.append(s);
- }
- }
- assertArrayEquals(expected2, buffer.toArray());
-
- buffer.append("a");
- expected2[lastIndex] = "a";
- assertArrayEquals(expected2, buffer.toArray());
- }
-
- @Test
- public void testGetNextSlot() {
- int capacity = 100;
- RingBuffer<DummyClass1> buffer = new RingBuffer<>(DummyClass1.class, capacity);
-
- final DummyClass1[] actual = new DummyClass1[capacity];
- final DummyClass1[] expected = new DummyClass1[capacity];
- for (int i = 0; i < capacity; ++i) {
- final DummyClass1 obj = buffer.getNextSlot();
- obj.x = capacity * i;
- actual[i] = obj;
- expected[i] = new DummyClass1();
- expected[i].x = capacity * i;
- }
- assertArrayEquals(expected, buffer.toArray());
-
- for (int i = 0; i < capacity; ++i) {
- if (actual[i] != buffer.getNextSlot()) {
- fail("getNextSlot() should re-use objects if available");
- }
- }
-
- RingBuffer<DummyClass2> buffer2 = new RingBuffer<>(DummyClass2.class, capacity);
- assertNull("getNextSlot() should return null if the object can't be initiated "
- + "(No nullary constructor)", buffer2.getNextSlot());
-
- RingBuffer<DummyClass3> buffer3 = new RingBuffer<>(DummyClass3.class, capacity);
- assertNull("getNextSlot() should return null if the object can't be initiated "
- + "(Inaccessible class)", buffer3.getNextSlot());
- }
-
- public static final class DummyClass1 {
- int x;
-
- public boolean equals(Object o) {
- if (o instanceof DummyClass1) {
- final DummyClass1 other = (DummyClass1) o;
- return other.x == this.x;
- }
- return false;
- }
- }
-
- public static final class DummyClass2 {
- public DummyClass2(int x) {}
- }
-
- private static final class DummyClass3 {}
-}
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 0e67583..cec3882 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -300,9 +300,7 @@
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.connectivity.resources.R;
import com.android.internal.app.IBatteryStats;
@@ -326,6 +324,8 @@
import com.android.server.connectivity.Vpn;
import com.android.server.connectivity.VpnProfileStore;
import com.android.server.net.NetworkPinner;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.ExceptionUtils;
import com.android.testutils.HandlerUtils;
import com.android.testutils.RecorderCallback.CallbackEntry;
@@ -389,9 +389,9 @@
* Build, install and run with:
* runtest frameworks-net -c com.android.server.ConnectivityServiceTest
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class ConnectivityServiceTest {
private static final String TAG = "ConnectivityServiceTest";
@@ -5450,6 +5450,8 @@
// the follow-up network disconnection will be processed first.
mWiFiNetworkAgent.setKeepaliveResponseDelay(3 * TIMEOUT_MS);
ka.stop();
+ // Call stop() twice shouldn't result in crash, b/182586681.
+ ka.stop();
// Make sure the stop has been processed. Wait for executor idle is needed to prevent
// flaky since the actual stop call to the service is delegated to executor thread.
@@ -5747,37 +5749,59 @@
@Test
public void testNetworkCallbackMaximum() throws Exception {
final int MAX_REQUESTS = 100;
- final int CALLBACKS = 89;
- final int INTENTS = 11;
+ final int CALLBACKS = 87;
+ final int DIFF_INTENTS = 10;
+ final int SAME_INTENTS = 10;
final int SYSTEM_ONLY_MAX_REQUESTS = 250;
- assertEquals(MAX_REQUESTS, CALLBACKS + INTENTS);
+ // Assert 1 (Default request filed before testing) + CALLBACKS + DIFF_INTENTS +
+ // 1 (same intent) = MAX_REQUESTS - 1, since the capacity is MAX_REQUEST - 1.
+ assertEquals(MAX_REQUESTS - 1, 1 + CALLBACKS + DIFF_INTENTS + 1);
NetworkRequest networkRequest = new NetworkRequest.Builder().build();
ArrayList<Object> registered = new ArrayList<>();
- int j = 0;
- while (j++ < CALLBACKS / 2) {
- NetworkCallback cb = new NetworkCallback();
- mCm.requestNetwork(networkRequest, cb);
+ for (int j = 0; j < CALLBACKS; j++) {
+ final NetworkCallback cb = new NetworkCallback();
+ if (j < CALLBACKS / 2) {
+ mCm.requestNetwork(networkRequest, cb);
+ } else {
+ mCm.registerNetworkCallback(networkRequest, cb);
+ }
registered.add(cb);
}
- while (j++ < CALLBACKS) {
- NetworkCallback cb = new NetworkCallback();
- mCm.registerNetworkCallback(networkRequest, cb);
- registered.add(cb);
+
+ // Since ConnectivityService will de-duplicate the request with the same intent,
+ // register multiple times does not really increase multiple requests.
+ final PendingIntent same_pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("same"), FLAG_IMMUTABLE);
+ for (int j = 0; j < SAME_INTENTS; j++) {
+ mCm.registerNetworkCallback(networkRequest, same_pi);
+ // Wait for the requests with the same intent to be de-duplicated. Because
+ // ConnectivityService side incrementCountOrThrow in binder, decrementCount in handler
+ // thread, waitForIdle is needed to ensure decrementCount being invoked for same intent
+ // requests before doing further tests.
+ waitForIdle();
}
- j = 0;
- while (j++ < INTENTS / 2) {
- final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
- new Intent("a" + j), FLAG_IMMUTABLE);
- mCm.requestNetwork(networkRequest, pi);
- registered.add(pi);
+ for (int j = 0; j < SAME_INTENTS; j++) {
+ mCm.requestNetwork(networkRequest, same_pi);
+ // Wait for the requests with the same intent to be de-duplicated.
+ // Refer to the reason above.
+ waitForIdle();
}
- while (j++ < INTENTS) {
- final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
- new Intent("b" + j), FLAG_IMMUTABLE);
- mCm.registerNetworkCallback(networkRequest, pi);
- registered.add(pi);
+ registered.add(same_pi);
+
+ for (int j = 0; j < DIFF_INTENTS; j++) {
+ if (j < DIFF_INTENTS / 2) {
+ final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("a" + j), FLAG_IMMUTABLE);
+ mCm.requestNetwork(networkRequest, pi);
+ registered.add(pi);
+ } else {
+ final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */,
+ new Intent("b" + j), FLAG_IMMUTABLE);
+ mCm.registerNetworkCallback(networkRequest, pi);
+ registered.add(pi);
+ }
}
// Test that the limit is enforced when MAX_REQUESTS simultaneous requests are added.
@@ -5827,10 +5851,10 @@
for (Object o : registered) {
if (o instanceof NetworkCallback) {
- mCm.unregisterNetworkCallback((NetworkCallback)o);
+ mCm.unregisterNetworkCallback((NetworkCallback) o);
}
if (o instanceof PendingIntent) {
- mCm.unregisterNetworkCallback((PendingIntent)o);
+ mCm.unregisterNetworkCallback((PendingIntent) o);
}
}
waitForIdle();
@@ -6005,7 +6029,7 @@
verify(mStatsManager, atLeastOnce()).notifyNetworkStatus(networksCaptor.capture(),
any(List.class), eq(defaultIface), vpnInfosCaptor.capture());
- assertSameElements(networksCaptor.getValue(), networks);
+ assertSameElements(networks, networksCaptor.getValue());
List<UnderlyingNetworkInfo> infos = vpnInfosCaptor.getValue();
if (vpnUid != null) {
@@ -6210,6 +6234,77 @@
}
@Test
+ public void testNonVpnUnderlyingNetworks() throws Exception {
+ // Ensure wifi and cellular are not torn down.
+ for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .addTransportType(transport)
+ .removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+ .build();
+ mCm.requestNetwork(request, new NetworkCallback());
+ }
+
+ // Connect a VCN-managed wifi network.
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+ mWiFiNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+ mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+ mWiFiNetworkAgent.connect(true /* validated */);
+
+ final List<Network> none = List.of();
+ expectNotifyNetworkStatus(none, null); // Wifi is not the default network
+
+ // Create a virtual network based on the wifi network.
+ final int ownerUid = 10042;
+ NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .setOwnerUid(ownerUid)
+ .setAdministratorUids(new int[]{ownerUid})
+ .build();
+ final String vcnIface = "ipsec42";
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(vcnIface);
+ final TestNetworkAgentWrapper vcn = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, lp, nc);
+ vcn.setUnderlyingNetworks(List.of(mWiFiNetworkAgent.getNetwork()));
+ vcn.connect(false /* validated */);
+
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(callback);
+ callback.expectAvailableCallbacksUnvalidated(vcn);
+
+ // The underlying wifi network's capabilities are not propagated to the virtual network,
+ // but NetworkStatsService is informed of the underlying interface.
+ nc = mCm.getNetworkCapabilities(vcn.getNetwork());
+ assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+ assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+ final List<Network> onlyVcn = List.of(vcn.getNetwork());
+ expectNotifyNetworkStatus(onlyVcn, vcnIface, ownerUid, vcnIface, List.of(WIFI_IFNAME));
+
+ // Add NOT_METERED to the underlying network, check that it is not propagated.
+ mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+ callback.assertNoCallback();
+ nc = mCm.getNetworkCapabilities(vcn.getNetwork());
+ assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+
+ // Switch underlying networks.
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+ mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+ mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_ROAMING);
+ mCellNetworkAgent.connect(false /* validated */);
+ vcn.setUnderlyingNetworks(List.of(mCellNetworkAgent.getNetwork()));
+
+ // The underlying capability changes do not propagate to the virtual network, but
+ // NetworkStatsService is informed of the new underlying interface.
+ callback.assertNoCallback();
+ nc = mCm.getNetworkCapabilities(vcn.getNetwork());
+ assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+ assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+ expectNotifyNetworkStatus(onlyVcn, vcnIface, ownerUid, vcnIface, List.of(MOBILE_IFNAME));
+ }
+
+ @Test
public void testBasicDnsConfigurationPushed() throws Exception {
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
@@ -10197,6 +10292,9 @@
public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception {
setUpConnectivityDiagnosticsCallback();
+ // reset to ignore callbacks from setup
+ reset(mConnectivityDiagnosticsCallback);
+
final Network n = mCellNetworkAgent.getNetwork();
final boolean hasConnectivity = true;
mService.reportNetworkConnectivity(n, hasConnectivity);
@@ -10207,6 +10305,8 @@
// Verify onNetworkConnectivityReported fired
verify(mConnectivityDiagnosticsCallback)
.onNetworkConnectivityReported(eq(n), eq(hasConnectivity));
+ verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
+ argThat(report -> areConnDiagCapsRedacted(report.getNetworkCapabilities())));
final boolean noConnectivity = false;
mService.reportNetworkConnectivity(n, noConnectivity);
@@ -10217,6 +10317,54 @@
// Wait for onNetworkConnectivityReported to fire
verify(mConnectivityDiagnosticsCallback)
.onNetworkConnectivityReported(eq(n), eq(noConnectivity));
+
+ // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
+ verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS).times(2))
+ .onConnectivityReportAvailable(
+ argThat(report ->
+ areConnDiagCapsRedacted(report.getNetworkCapabilities())));
+ }
+
+ @Test
+ public void testConnectivityDiagnosticsCallbackOnConnectivityReportedSeparateUid()
+ throws Exception {
+ setUpConnectivityDiagnosticsCallback();
+
+ // reset to ignore callbacks from setup
+ reset(mConnectivityDiagnosticsCallback);
+
+ // report known Connectivity from a different uid. Verify that network is not re-validated
+ // and this callback is not notified.
+ final Network n = mCellNetworkAgent.getNetwork();
+ final boolean hasConnectivity = true;
+ doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, hasConnectivity));
+
+ // Block until all other events are done processing.
+ HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ // Verify onNetworkConnectivityReported did not fire
+ verify(mConnectivityDiagnosticsCallback, never())
+ .onNetworkConnectivityReported(any(), anyBoolean());
+ verify(mConnectivityDiagnosticsCallback, never())
+ .onConnectivityReportAvailable(any());
+
+ // report different Connectivity from a different uid. Verify that network is re-validated
+ // and that this callback is notified.
+ final boolean noConnectivity = false;
+ doAsUid(Process.myUid() + 1, () -> mService.reportNetworkConnectivity(n, noConnectivity));
+
+ // Block until all other events are done processing.
+ HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+ // Wait for onNetworkConnectivityReported to fire
+ verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
+ .onNetworkConnectivityReported(eq(n), eq(noConnectivity));
+
+ // Also expect a ConnectivityReport after NetworkMonitor asynchronously re-validates
+ verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS))
+ .onConnectivityReportAvailable(
+ argThat(report ->
+ areConnDiagCapsRedacted(report.getNetworkCapabilities())));
}
@Test
@@ -13361,43 +13509,43 @@
}
@Test
- public void testSetMobileDataPreferredUids_noIssueToFactory() throws Exception {
- // First set mobile data preferred uid to create a multi-layer requests: 1. listen for
+ public void testMultilayerRequestsOfSetMobileDataPreferredUids() throws Exception {
+ // First set mobile data preferred uid to create a multi-layer requests: 1. request for
// cellular, 2. track the default network for fallback.
setAndUpdateMobileDataPreferredUids(
Set.of(PRIMARY_USER_HANDLE.getUid(TEST_PACKAGE_UID)));
final HandlerThread handlerThread = new HandlerThread("MockFactory");
handlerThread.start();
- NetworkCapabilities internetFilter = new NetworkCapabilities()
+ final NetworkCapabilities cellFilter = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
- final MockNetworkFactory internetFactory = new MockNetworkFactory(handlerThread.getLooper(),
- mServiceContext, "internetFactory", internetFilter, mCsHandlerThread);
- internetFactory.setScoreFilter(40);
+ final MockNetworkFactory cellFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ mServiceContext, "cellFactory", cellFilter, mCsHandlerThread);
+ cellFactory.setScoreFilter(40);
try {
- internetFactory.register();
- // Default internet request only. The first request is listen for cellular network,
- // which is never sent to factories (it's a LISTEN, not requestable). The second
- // fallback request is TRACK_DEFAULT which is also not sent to factories.
- internetFactory.expectRequestAdds(1);
- internetFactory.assertRequestCountEquals(1);
+ cellFactory.register();
+ // Default internet request and the mobile data preferred request.
+ cellFactory.expectRequestAdds(2);
+ cellFactory.assertRequestCountEquals(2);
- mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- mCellNetworkAgent.connect(true);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
- // The internet factory however is outscored, and should lose its requests.
- internetFactory.expectRequestRemove();
- internetFactory.assertRequestCountEquals(0);
+ // The cellFactory however is outscored, and should lose default internet request.
+ // But it should still see mobile data preferred request.
+ cellFactory.expectRequestRemove();
+ cellFactory.assertRequestCountEquals(1);
- mCellNetworkAgent.disconnect();
+ mWiFiNetworkAgent.disconnect();
// The network satisfying the default internet request has disconnected, so the
- // internetFactory sees the default request again.
- internetFactory.expectRequestAdds(1);
- internetFactory.assertRequestCountEquals(1);
+ // cellFactory sees the default internet requests again.
+ cellFactory.expectRequestAdd();
+ cellFactory.assertRequestCountEquals(2);
} finally {
- internetFactory.terminate();
+ cellFactory.terminate();
handlerThread.quitSafely();
}
}
diff --git a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
index 2b5bfac..5bbbe40 100644
--- a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -64,13 +64,14 @@
import android.test.mock.MockContext;
import android.util.ArraySet;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
import com.android.server.IpSecService.TunnelInterfaceRecord;
+import com.android.testutils.DevSdkIgnoreRule;
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -84,8 +85,10 @@
/** Unit tests for {@link IpSecService}. */
@SmallTest
@RunWith(Parameterized.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
public class IpSecServiceParameterizedTest {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(
+ Build.VERSION_CODES.R /* ignoreClassUpTo */);
private static final int TEST_SPI = 0xD1201D;
diff --git a/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java
index 0e3b03c..6957d51 100644
--- a/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java
@@ -34,12 +34,12 @@
import android.os.IBinder;
import android.os.RemoteException;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.IpSecService.IResource;
import com.android.server.IpSecService.RefcountedResource;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -53,8 +53,8 @@
/** Unit tests for {@link IpSecService.RefcountedResource}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpSecServiceRefcountedResourceTest {
Context mMockContext;
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
diff --git a/tests/unit/java/com/android/server/IpSecServiceTest.java b/tests/unit/java/com/android/server/IpSecServiceTest.java
index 2dc21c0..fabd6f1 100644
--- a/tests/unit/java/com/android/server/IpSecServiceTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceTest.java
@@ -51,9 +51,10 @@
import android.system.StructStat;
import android.util.Range;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import dalvik.system.SocketTagger;
@@ -72,8 +73,8 @@
/** Unit tests for {@link IpSecService}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpSecServiceTest {
private static final int DROID_SPI = 0xD1201D;
diff --git a/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt
index 750703c..64736f2 100644
--- a/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt
+++ b/tests/unit/java/com/android/server/LegacyTypeTrackerTest.kt
@@ -45,11 +45,11 @@
import android.net.NetworkInfo.DetailedState.DISCONNECTED
import android.os.Build
import android.telephony.TelephonyManager
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
import com.android.server.ConnectivityService.LegacyTypeTracker
import com.android.server.connectivity.NetworkAgentInfo
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
@@ -66,9 +66,9 @@
const val UNSUPPORTED_TYPE = TYPE_WIMAX
-@RunWith(AndroidJUnit4::class)
+@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class LegacyTypeTrackerTest {
private val supportedTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_MOBILE,
TYPE_MOBILE_SUPL, TYPE_MOBILE_MMS, TYPE_MOBILE_SUPL, TYPE_MOBILE_DUN, TYPE_MOBILE_HIPRI,
diff --git a/tests/unit/java/com/android/server/NetIdManagerTest.kt b/tests/unit/java/com/android/server/NetIdManagerTest.kt
index 5c43197..811134e 100644
--- a/tests/unit/java/com/android/server/NetIdManagerTest.kt
+++ b/tests/unit/java/com/android/server/NetIdManagerTest.kt
@@ -17,19 +17,19 @@
package com.android.server
import android.os.Build
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
import com.android.server.NetIdManager.MIN_NET_ID
-import com.android.testutils.assertThrows
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.ExceptionUtils.ThrowingRunnable
+import com.android.testutils.assertThrows
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
-@RunWith(AndroidJUnit4::class)
+@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class NetIdManagerTest {
@Test
fun testReserveReleaseNetId() {
diff --git a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
index 32a8f3b..ea29da0 100644
--- a/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/unit/java/com/android/server/NetworkManagementServiceTest.java
@@ -45,12 +45,11 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.internal.app.IBatteryStats;
import com.android.server.NetworkManagementService.Dependencies;
import com.android.server.net.BaseNetworkObserver;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
@@ -66,9 +65,9 @@
/**
* Tests for {@link NetworkManagementService}.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkManagementServiceTest {
private NetworkManagementService mNMService;
@Mock private Context mContext;
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 5ea0e8e..e80a938 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -37,13 +37,13 @@
import android.os.Looper;
import android.os.Message;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.NsdService.DaemonConnection;
import com.android.server.NsdService.DaemonConnectionSupplier;
import com.android.server.NsdService.NativeCallbackReceiver;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import org.junit.After;
@@ -58,9 +58,9 @@
// TODOs:
// - test client can send requests and receive replies
// - test NSD_ON ENABLE/DISABLED listening
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NsdServiceTest {
static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD;
diff --git a/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java b/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
index 9f0c9d6..9ef558f 100644
--- a/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/DnsManagerTest.java
@@ -60,12 +60,12 @@
import android.test.mock.MockContentResolver;
import android.util.SparseArray;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.MessageUtils;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import libcore.net.InetAddressUtils;
@@ -85,9 +85,9 @@
* Build, install and run with:
* runtest frameworks-net -c com.android.server.connectivity.DnsManagerTest
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class DnsManagerTest {
static final String TEST_IFACENAME = "test_wlan0";
static final int TEST_NETID = 100;
diff --git a/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt b/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
index 02f3da7..785153a 100644
--- a/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/FullScoreTest.kt
@@ -22,27 +22,25 @@
import android.os.Build
import android.text.TextUtils
import android.util.ArraySet
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
import com.android.server.connectivity.FullScore.MAX_CS_MANAGED_POLICY
import com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED
import com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED
import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED
import com.android.server.connectivity.FullScore.POLICY_IS_VPN
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Test
import org.junit.runner.RunWith
-import kotlin.collections.minOfOrNull
-import kotlin.collections.maxOfOrNull
import kotlin.reflect.full.staticProperties
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
import kotlin.test.assertTrue
-@RunWith(AndroidJUnit4::class)
+@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class FullScoreTest {
// Convenience methods
fun FullScore.withPolicies(
diff --git a/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index d6acea1..52b05aa 100644
--- a/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/unit/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -45,10 +45,9 @@
import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,9 +56,9 @@
import java.util.List;
// TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpConnectivityEventBuilderTest {
@Test
diff --git a/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index d0038a4..063ccd3 100644
--- a/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/unit/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -51,11 +51,10 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.internal.util.BitUtils;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -67,9 +66,9 @@
import java.io.PrintWriter;
import java.io.StringWriter;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class IpConnectivityMetricsTest {
static final IpReachabilityEvent FAKE_EV =
new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
diff --git a/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java
index 3f3bfdd..58a7c89 100644
--- a/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -46,13 +46,13 @@
import android.os.Build;
import android.text.format.DateUtils;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.connectivity.resources.R;
import com.android.server.ConnectivityService;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
@@ -61,9 +61,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class LingerMonitorTest {
static final String CELLULAR = "CELLULAR";
static final String WIFI = "WIFI";
diff --git a/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
index f8ef31c..e2ad00d 100644
--- a/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java
@@ -28,8 +28,7 @@
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
-import static junit.framework.TestCase.assertNotNull;
-
+import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
@@ -63,15 +62,15 @@
import android.util.DataUnit;
import android.util.RecurrenceRule;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkStatsManagerInternal;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
@@ -89,9 +88,9 @@
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class MultipathPolicyTrackerTest {
private static final Network TEST_NETWORK = new Network(123);
private static final int POLICY_SNOOZED = -100;
diff --git a/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java
index 9204d14..f358726 100644
--- a/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/unit/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -44,11 +44,11 @@
import android.os.Handler;
import android.os.test.TestLooper;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.ConnectivityService;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -58,9 +58,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class Nat464XlatTest {
static final String BASE_IFACE = "test0";
diff --git a/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 8aad1a2..7d6c3ae 100644
--- a/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -36,11 +36,10 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Base64;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.runner.AndroidJUnit4;
-
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -54,9 +53,9 @@
import java.util.Comparator;
import java.util.List;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetdEventListenerServiceTest {
private static final String EXAMPLE_IPV4 = "192.0.2.1";
private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 160068f..07deeef 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -16,8 +16,17 @@
package com.android.server.connectivity;
-import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
+import static android.app.Notification.FLAG_AUTO_CANCEL;
+import static android.app.Notification.FLAG_ONGOING_EVENT;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.LOST_INTERNET;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.NETWORK_SWITCH;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.NO_INTERNET;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.PARTIAL_CONNECTIVITY;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.PRIVATE_DNS_BROKEN;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.SIGN_IN;
+
+import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.clearInvocations;
@@ -43,12 +52,12 @@
import android.os.UserHandle;
import android.telephony.TelephonyManager;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.connectivity.resources.R;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
@@ -65,13 +74,15 @@
import java.util.Collections;
import java.util.List;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkNotificationManagerTest {
private static final String TEST_SSID = "Test SSID";
private static final String TEST_EXTRA_INFO = "extra";
+ private static final int TEST_NOTIF_ID = 101;
+ private static final String TEST_NOTIF_TAG = NetworkNotificationManager.tagFor(TEST_NOTIF_ID);
static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
static final NetworkCapabilities VPN_CAPABILITIES = new NetworkCapabilities();
@@ -133,6 +144,7 @@
}
when(mResources.getStringArray(R.array.network_switch_type_name))
.thenReturn(transportNames);
+ when(mResources.getBoolean(R.bool.config_autoCancelNetworkNotifications)).thenReturn(true);
mManager = new NetworkNotificationManager(mCtx, mTelephonyManager);
}
@@ -229,29 +241,65 @@
verify(mNotificationManager, never()).notify(any(), anyInt(), any());
}
+ private void assertNotification(NotificationType type, boolean ongoing, boolean autoCancel) {
+ final ArgumentCaptor<Notification> noteCaptor = ArgumentCaptor.forClass(Notification.class);
+ mManager.showNotification(TEST_NOTIF_ID, type, mWifiNai, mCellNai, null, false);
+ verify(mNotificationManager, times(1)).notify(eq(TEST_NOTIF_TAG), eq(type.eventId),
+ noteCaptor.capture());
+
+ assertEquals("Notification ongoing flag should be " + (ongoing ? "set" : "unset"),
+ ongoing, (noteCaptor.getValue().flags & FLAG_ONGOING_EVENT) != 0);
+ assertEquals("Notification autocancel flag should be " + (autoCancel ? "set" : "unset"),
+ autoCancel, (noteCaptor.getValue().flags & FLAG_AUTO_CANCEL) != 0);
+ }
+
@Test
public void testDuplicatedNotificationsNoInternetThenSignIn() {
- final int id = 101;
- final String tag = NetworkNotificationManager.tagFor(id);
-
// Show first NO_INTERNET
- mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
+ assertNotification(NO_INTERNET, false /* ongoing */, true /* autoCancel */);
// Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
- mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
- verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
+ assertNotification(SIGN_IN, false /* ongoing */, true /* autoCancel */);
+ verify(mNotificationManager, times(1)).cancel(eq(TEST_NOTIF_TAG), eq(NO_INTERNET.eventId));
// Network disconnects
- mManager.clearNotification(id);
- verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
+ mManager.clearNotification(TEST_NOTIF_ID);
+ verify(mNotificationManager, times(1)).cancel(eq(TEST_NOTIF_TAG), eq(SIGN_IN.eventId));
+ }
+
+ @Test
+ public void testOngoingSignInNotification() {
+ doReturn(true).when(mResources).getBoolean(R.bool.config_ongoingSignInNotification);
+
+ // Show first NO_INTERNET
+ assertNotification(NO_INTERNET, false /* ongoing */, true /* autoCancel */);
+
+ // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
+ assertNotification(SIGN_IN, true /* ongoing */, true /* autoCancel */);
+ verify(mNotificationManager, times(1)).cancel(eq(TEST_NOTIF_TAG), eq(NO_INTERNET.eventId));
+
+ // Network disconnects
+ mManager.clearNotification(TEST_NOTIF_ID);
+ verify(mNotificationManager, times(1)).cancel(eq(TEST_NOTIF_TAG), eq(SIGN_IN.eventId));
+ }
+
+ @Test
+ public void testNoAutoCancelNotification() {
+ doReturn(false).when(mResources).getBoolean(R.bool.config_autoCancelNetworkNotifications);
+
+ // Show NO_INTERNET, then SIGN_IN
+ assertNotification(NO_INTERNET, false /* ongoing */, false /* autoCancel */);
+ assertNotification(SIGN_IN, false /* ongoing */, false /* autoCancel */);
+ verify(mNotificationManager, times(1)).cancel(eq(TEST_NOTIF_TAG), eq(NO_INTERNET.eventId));
+
+ mManager.clearNotification(TEST_NOTIF_ID);
+ verify(mNotificationManager, times(1)).cancel(eq(TEST_NOTIF_TAG), eq(SIGN_IN.eventId));
}
@Test
public void testDuplicatedNotificationsSignInThenNoInternet() {
- final int id = 101;
- final String tag = NetworkNotificationManager.tagFor(id);
+ final int id = TEST_NOTIF_ID;
+ final String tag = TEST_NOTIF_TAG;
// Show first SIGN_IN
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
@@ -270,8 +318,8 @@
@Test
public void testClearNotificationByType() {
- final int id = 101;
- final String tag = NetworkNotificationManager.tagFor(id);
+ final int id = TEST_NOTIF_ID;
+ final String tag = TEST_NOTIF_TAG;
// clearNotification(int id, NotificationType notifyType) will check if given type is equal
// to previous type or not. If they are equal then clear the notification; if they are not
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt b/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt
index d12f1c0..d03c567 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/NetworkOfferTest.kt
@@ -21,9 +21,9 @@
import android.net.NetworkRequest
import android.net.NetworkScore.KEEP_CONNECTED_NONE
import android.os.Build
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.eq
@@ -34,9 +34,9 @@
const val POLICY_NONE = 0L
-@RunWith(AndroidJUnit4::class)
+@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class NetworkOfferTest {
val mockCallback = mock(INetworkOfferCallback::class.java)
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
index c35b60e..4408958 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/NetworkRankerTest.kt
@@ -24,11 +24,11 @@
import android.net.NetworkScore.POLICY_TRANSPORT_PRIMARY
import android.net.NetworkScore.POLICY_YIELD_TO_BAD_WIFI
import android.os.Build
-import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
-import androidx.test.runner.AndroidJUnit4
import com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD
import com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@@ -38,8 +38,8 @@
private fun caps(transport: Int) = NetworkCapabilities.Builder().addTransportType(transport).build()
@SmallTest
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
class NetworkRankerTest {
private val mRanker = NetworkRanker()
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 9c7d9c0..8f46508 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -79,9 +79,10 @@
import android.util.SparseIntArray;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -97,11 +98,12 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class PermissionMonitorTest {
private static final UserHandle MOCK_USER1 = UserHandle.of(0);
private static final UserHandle MOCK_USER2 = UserHandle.of(1);
@@ -210,16 +212,12 @@
return packageInfo;
}
- private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid,
- UserHandle user) {
+ private static PackageInfo buildPackageInfo(String packageName, int uid,
+ String... permissions) {
final PackageInfo pkgInfo;
- if (hasSystemPermission) {
- pkgInfo = systemPackageInfoWithPermissions(
- CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
- } else {
- pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, "");
- }
- pkgInfo.applicationInfo.uid = user.getUid(UserHandle.getAppId(uid));
+ pkgInfo = systemPackageInfoWithPermissions(permissions);
+ pkgInfo.packageName = packageName;
+ pkgInfo.applicationInfo.uid = uid;
return pkgInfo;
}
@@ -605,15 +603,12 @@
@Test
public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- Arrays.asList(new PackageInfo[] {
- buildPackageInfo(true /* hasSystemPermission */, SYSTEM_UID1, MOCK_USER1),
- buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1),
- buildPackageInfo(false /* hasSystemPermission */, MOCK_UID2, MOCK_USER1),
- buildPackageInfo(false /* hasSystemPermission */, VPN_UID, MOCK_USER1)
- }));
- when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1),
- eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1));
+ List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_UID1, CHANGE_NETWORK_STATE,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS),
+ buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
+ buildPackageInfo(MOCK_PACKAGE2, MOCK_UID2),
+ buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)));
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1);
mPermissionMonitor.startMonitoring();
// Every app on user 0 except MOCK_UID2 are under VPN.
final Set<UidRange> vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] {
@@ -657,13 +652,10 @@
@Test
public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- Arrays.asList(new PackageInfo[] {
- buildPackageInfo(true /* hasSystemPermission */, SYSTEM_UID1, MOCK_USER1),
- buildPackageInfo(false /* hasSystemPermission */, VPN_UID, MOCK_USER1)
- }));
- when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1),
- eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
- buildPackageInfo(false /* hasSystemPermission */, MOCK_UID1, MOCK_USER1));
+ List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_UID1, CHANGE_NETWORK_STATE,
+ NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS),
+ buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)));
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1);
mPermissionMonitor.startMonitoring();
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1));
@@ -900,13 +892,26 @@
new int[]{ MOCK_UID2 });
}
+ private BroadcastReceiver expectBroadcastReceiver(String... actions) {
+ final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(),
+ argThat(filter -> {
+ for (String action : actions) {
+ if (!filter.hasAction(action)) {
+ return false;
+ }
+ }
+ return true;
+ }), any(), any());
+ return receiverCaptor.getValue();
+ }
+
@Test
public void testIntentReceiver() throws Exception {
final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
- final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(), any(), any(), any());
- final BroadcastReceiver receiver = receiverCaptor.getValue();
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED);
// Verify receiving PACKAGE_ADDED intent.
final Intent addedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED,
@@ -1060,4 +1065,136 @@
netdMonitor.expectNoPermission(
new UserHandle[]{MOCK_USER2}, new int[]{ MOCK_UID1, MOCK_UID2 });
}
+
+ @Test
+ public void testOnExternalApplicationsAvailable() throws Exception {
+ final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
+ final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+
+ // Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
+ // and have different uids. There has no permission for both uids.
+ when(mUserManager.getUserHandles(eq(true))).thenReturn(List.of(MOCK_USER1));
+ when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
+ buildPackageInfo(MOCK_PACKAGE2, MOCK_UID2)));
+ mPermissionMonitor.startMonitoring();
+ netdMonitor.expectNoPermission(
+ new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2});
+ netdServiceMonitor.expectPermission(
+ INetd.PERMISSION_NONE, new int[]{MOCK_UID1, MOCK_UID2});
+
+ // Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
+ final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST,
+ new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, INTERNET);
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID2, CHANGE_NETWORK_STATE,
+ UPDATE_DEVICE_STATS);
+ receiver.onReceive(mContext, externalIntent);
+ netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+ netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[] { MOCK_UID1 });
+ netdServiceMonitor.expectPermission(
+ INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID2});
+ }
+
+ @Test
+ public void testOnExternalApplicationsAvailable_AppsNotRegisteredOnStartMonitoring()
+ throws Exception {
+ final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
+ final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+
+ // One user MOCK_USER1
+ mPermissionMonitor.onUserAdded(MOCK_USER1);
+
+ // Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
+ // and have different uids. There has no permission for both uids.
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, INTERNET);
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID2, CHANGE_NETWORK_STATE,
+ UPDATE_DEVICE_STATS);
+
+ // Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
+ final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST,
+ new String[] { MOCK_PACKAGE1 , MOCK_PACKAGE2});
+ receiver.onReceive(mContext, externalIntent);
+ netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+ netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[] { MOCK_UID1 });
+ netdServiceMonitor.expectPermission(
+ INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID2});
+ }
+
+ @Test
+ public void testOnExternalApplicationsAvailableWithSharedUid()
+ throws Exception {
+ final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
+ final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+
+ // Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
+ // storage and shared on MOCK_UID1. There has no permission for MOCK_UID1.
+ when(mUserManager.getUserHandles(eq(true))).thenReturn(List.of(MOCK_USER1));
+ when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
+ buildPackageInfo(MOCK_PACKAGE2, MOCK_UID1)));
+ mPermissionMonitor.startMonitoring();
+ netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ netdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[] {MOCK_UID1});
+
+ // Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
+ final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[] {MOCK_PACKAGE1});
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1, CHANGE_NETWORK_STATE);
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID1, UPDATE_DEVICE_STATS);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1))
+ .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
+ receiver.onReceive(mContext, externalIntent);
+ netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ netdServiceMonitor.expectPermission(
+ INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[] {MOCK_UID1});
+ }
+
+ @Test
+ public void testOnExternalApplicationsAvailableWithSharedUid_DifferentStorage()
+ throws Exception {
+ final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
+ final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
+ final BroadcastReceiver receiver = expectBroadcastReceiver(
+ Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+
+ // Initial the permission state. MOCK_PACKAGE1 is installed on external storage and
+ // MOCK_PACKAGE2 is installed on device. These two packages are shared on MOCK_UID1.
+ // MOCK_UID1 has NETWORK and INTERNET permissions.
+ when(mUserManager.getUserHandles(eq(true))).thenReturn(List.of(MOCK_USER1));
+ when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
+ List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID1),
+ buildPackageInfo(MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE,
+ INTERNET)));
+ mPermissionMonitor.startMonitoring();
+ netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[] {MOCK_UID1});
+
+ // Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
+ final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ externalIntent.putExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST, new String[] {MOCK_PACKAGE1});
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID1,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, UPDATE_DEVICE_STATS);
+ buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE2, MOCK_UID1, CHANGE_NETWORK_STATE,
+ INTERNET);
+ when(mPackageManager.getPackagesForUid(MOCK_UID1))
+ .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
+ receiver.onReceive(mContext, externalIntent);
+ netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ netdServiceMonitor.expectPermission(
+ INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
+ new int[] {MOCK_UID1});
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 6971b3ca..b706090 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -82,7 +82,6 @@
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
-import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.ConditionVariable;
@@ -97,15 +96,15 @@
import android.util.ArraySet;
import android.util.Range;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.server.IpSecService;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -140,9 +139,9 @@
* Build, install and run with:
* runtest frameworks-net -c com.android.server.connectivity.VpnTest
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
public class VpnTest {
private static final String TAG = "VpnTest";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java b/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java
index 84a1a8f..03d9404 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsAccessTest.java
@@ -28,11 +28,11 @@
import android.os.Build;
import android.telephony.TelephonyManager;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.LocalServices;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
@@ -41,9 +41,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsAccessTest {
private static final String TEST_PKG = "com.example.test";
private static final int TEST_UID = 12345;
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java
index 57f48f5..e771558 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -51,11 +51,11 @@
import android.util.RecurrenceRule;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.tests.net.R;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -81,9 +81,9 @@
/**
* Tests for {@link NetworkStatsCollection}.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsCollectionTest {
private static final String TEST_FILE = "test.bin";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
index 4c80678..8d7aa4e 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -40,11 +40,11 @@
import android.os.Build;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.tests.net.R;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -62,9 +62,9 @@
import java.io.OutputStream;
/** Tests for {@link NetworkStatsFactory}. */
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
private static final String CLAT_PREFIX = "v4-";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
index 7e8081b..e35104e 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -51,11 +51,11 @@
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import org.junit.Before;
@@ -70,9 +70,9 @@
/**
* Tests for {@link NetworkStatsObservers}.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsObserversTest {
private static final String TEST_IFACE = "test0";
private static final String TEST_IFACE2 = "test1";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 9b2c278..ab76460 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -114,14 +114,14 @@
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import com.android.testutils.TestableNetworkStatsProviderBinder;
@@ -148,9 +148,9 @@
* TODO: This test used to be really brittle because it used Easymock - it uses Mockito now, but
* still uses the Easymock structure, which could be simplified.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkStatsServiceTest extends NetworkStatsBaseTest {
private static final String TAG = "NetworkStatsServiceTest";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
index f30a9c5..2bc385c 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
@@ -42,15 +42,14 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import androidx.test.filters.SdkSuppress;
-
import com.android.internal.util.CollectionUtils;
import com.android.server.net.NetworkStatsSubscriptionsMonitor.RatTypeListener;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -60,8 +59,8 @@
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
-@RunWith(JUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public final class NetworkStatsSubscriptionsMonitorTest {
private static final int TEST_SUBID1 = 3;
private static final int TEST_SUBID2 = 5;
diff --git a/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java b/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
index 406fdd8..5f3efed 100644
--- a/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
+++ b/tests/unit/java/com/android/server/net/ipmemorystore/NetworkAttributesTest.java
@@ -22,9 +22,10 @@
import android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk;
import android.os.Build;
-import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,8 +37,8 @@
/** Unit tests for {@link NetworkAttributes}. */
@SmallTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class NetworkAttributesTest {
private static final String WEIGHT_FIELD_NAME_PREFIX = "WEIGHT_";
private static final float EPSILON = 0.0001f;