Merge "Fix a crash when changing preferences"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 6031646..60c1f2b 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -33,13 +33,13 @@
"NetworkStackApiStableShims",
"androidx.annotation_annotation",
"modules-utils-build",
- "netlink-client",
"networkstack-client",
"android.hardware.tetheroffload.config-V1.0-java",
"android.hardware.tetheroffload.control-V1.0-java",
"android.hardware.tetheroffload.control-V1.1-java",
"net-utils-framework-common",
"net-utils-device-common",
+ "net-utils-device-common-netlink",
"netd-client",
],
libs: [
diff --git a/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp b/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp
index 7970a23..260dbc1 100644
--- a/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp
+++ b/Tethering/jni/com_android_networkstack_tethering_BpfMap.cpp
@@ -42,6 +42,8 @@
jint fd = bpf::bpfFdGet(pathname.c_str(), static_cast<unsigned>(mode));
+ if (fd < 0) jniThrowErrnoException(env, "bpfFdGet", errno);
+
return fd;
}
diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
index 01be97a..5b39a23 100644
--- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java
@@ -42,9 +42,6 @@
import android.net.ip.ConntrackMonitor;
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
-import android.net.netlink.ConntrackMessage;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkSocket;
import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
@@ -66,6 +63,9 @@
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.Struct;
+import com.android.net.module.util.netlink.ConntrackMessage;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkSocket;
import com.android.networkstack.tethering.apishim.common.BpfCoordinatorShim;
import java.net.Inet4Address;
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/Tethering/src/com/android/networkstack/tethering/OffloadController.java
index beb1821..d60c21d 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadController.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadController.java
@@ -42,9 +42,6 @@
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
import android.net.RouteInfo;
-import android.net.netlink.ConntrackMessage;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkSocket;
import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.SharedLog;
import android.os.Handler;
@@ -56,6 +53,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.netlink.ConntrackMessage;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkSocket;
import com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats;
import java.net.Inet4Address;
diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
index e3ac660..f336d9b 100644
--- a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
+++ b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java
@@ -16,10 +16,11 @@
package com.android.networkstack.tethering;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static android.net.util.TetheringUtils.uint16;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.hardware.tetheroffload.config.V1_0.IOffloadConfig;
@@ -28,9 +29,6 @@
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback;
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.StructNfGenMsg;
-import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.net.util.SocketUtils;
import android.os.Handler;
@@ -43,6 +41,9 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.netlink.NetlinkSocket;
+import com.android.net.module.util.netlink.StructNfGenMsg;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/Tethering/tests/integration/Android.bp b/Tethering/tests/integration/Android.bp
index b93a969..2593b1b 100644
--- a/Tethering/tests/integration/Android.bp
+++ b/Tethering/tests/integration/Android.bp
@@ -41,9 +41,10 @@
"libdexmakerjvmtiagent",
"libstaticjvmtiagent",
],
- jarjar_rules: ":NetworkStackJarJarRules",
}
+// Library including tethering integration tests targeting the latest stable SDK.
+// Use with NetworkStackJarJarRules.
android_library {
name: "TetheringIntegrationTestsLatestSdkLib",
target_sdk_version: "30",
@@ -56,6 +57,8 @@
]
}
+// Library including tethering integration tests targeting current development SDK.
+// Use with NetworkStackJarJarRules.
android_library {
name: "TetheringIntegrationTestsLib",
target_sdk_version: "current",
@@ -76,6 +79,7 @@
"mts",
],
compile_multilib: "both",
+ jarjar_rules: ":NetworkStackJarJarRules",
}
android_library {
@@ -88,13 +92,33 @@
"TetheringTestsLatestSdkLib",
"TetheringIntegrationTestsLatestSdkLib",
],
- jarjar_rules: ":TetheringTestsJarJarRules",
+ // Jarjar rules should normally be applied on final artifacts and not intermediate libraries as
+ // applying different rules on intermediate libraries can cause conflicts when combining them
+ // (the resulting artifact can end up with multiple incompatible implementations of the same
+ // classes). But this library is used to combine tethering coverage tests with connectivity
+ // coverage tests into a single coverage target. The tests need to use the same jarjar rules as
+ // covered production code for coverage to be calculated properly, so jarjar is applied
+ // separately on each set of tests.
+ jarjar_rules: ":TetheringCoverageJarJarRules",
manifest: "AndroidManifest_coverage.xml",
visibility: [
"//packages/modules/Connectivity/tests:__subpackages__"
],
}
+// Combine NetworkStack and Tethering jarjar rules for coverage target. The jarjar files are
+// simply concatenated in the order specified in srcs.
+genrule {
+ name: "TetheringCoverageJarJarRules",
+ srcs: [
+ ":TetheringTestsJarJarRules",
+ ":NetworkStackJarJarRules",
+ ],
+ out: ["jarjar-rules-tethering-coverage.txt"],
+ cmd: "cat $(in) > $(out)",
+ visibility: ["//visibility:private"],
+}
+
// 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.
diff --git a/Tethering/tests/jarjar-rules.txt b/Tethering/tests/jarjar-rules.txt
index 9cb143e..23d3f56 100644
--- a/Tethering/tests/jarjar-rules.txt
+++ b/Tethering/tests/jarjar-rules.txt
@@ -17,3 +17,8 @@
# TestableLooper from "testables" can be used instead of TestLooper from frameworks-base-testutils.
zap android.os.test.TestLooperTest*
zap com.android.test.filters.SelectTestTests*
+
+# When used in combined test suites like ConnectivityCoverageTests, these test jarjar rules are
+# combined with the jarjar-rules.txt of other included modules (like NetworkStack jarjar rules).
+# They will effectively be added after the following line break. Note that jarjar stops at the first
+# matching rule, so any rule in this file takes precedence over rules in the following ones.
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
index 0deb177..f97270c 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
@@ -388,4 +388,15 @@
assertEquals(OsConstants.E2BIG, expected.errno);
}
}
+
+ @Test
+ public void testOpenNonexistentMap() throws Exception {
+ try {
+ final BpfMap<TetherDownstream6Key, Tether6Value> nonexistentMap = new BpfMap<>(
+ "/sys/fs/bpf/tethering/nonexistent", BpfMap.BPF_F_RDWR,
+ TetherDownstream6Key.class, Tether6Value.class);
+ } catch (ErrnoException expected) {
+ assertEquals(OsConstants.ENOENT, expected.errno);
+ }
+ }
}
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
index 57c28fc..7ee69b2 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
@@ -16,10 +16,9 @@
package com.android.networkstack.tethering;
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
+import static com.android.net.module.util.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_GET;
import static com.android.networkstack.tethering.OffloadHardwareInterface.IPCTNL_MSG_CT_NEW;
import static com.android.networkstack.tethering.OffloadHardwareInterface.NFNL_SUBSYS_CTNETLINK;
@@ -29,7 +28,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.HandlerThread;
@@ -40,6 +38,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 6bf6a9f..ef4330a 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -31,14 +31,14 @@
import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
import static android.net.ip.IpServer.STATE_TETHERED;
import static android.net.ip.IpServer.STATE_UNAVAILABLE;
-import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
-import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH;
-import static android.net.netlink.StructNdMsg.NUD_FAILED;
-import static android.net.netlink.StructNdMsg.NUD_REACHABLE;
-import static android.net.netlink.StructNdMsg.NUD_STALE;
import static android.system.OsConstants.ETH_P_IPV6;
import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH;
+import static com.android.net.module.util.netlink.NetlinkConstants.RTM_DELNEIGH;
+import static com.android.net.module.util.netlink.NetlinkConstants.RTM_NEWNEIGH;
+import static com.android.net.module.util.netlink.StructNdMsg.NUD_FAILED;
+import static com.android.net.module.util.netlink.StructNdMsg.NUD_REACHABLE;
+import static com.android.net.module.util.netlink.StructNdMsg.NUD_STALE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
index 7e9e34f..6e96085 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java
@@ -24,13 +24,6 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStats.UID_TETHERING;
import static android.net.ip.ConntrackMonitor.ConntrackEvent;
-import static android.net.netlink.ConntrackMessage.DYING_MASK;
-import static android.net.netlink.ConntrackMessage.ESTABLISHED_MASK;
-import static android.net.netlink.ConntrackMessage.Tuple;
-import static android.net.netlink.ConntrackMessage.TupleIpv4;
-import static android.net.netlink.ConntrackMessage.TupleProto;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
import static android.system.OsConstants.ETH_P_IP;
import static android.system.OsConstants.ETH_P_IPV6;
@@ -40,6 +33,13 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.staticMockMarker;
+import static com.android.net.module.util.netlink.ConntrackMessage.DYING_MASK;
+import static com.android.net.module.util.netlink.ConntrackMessage.ESTABLISHED_MASK;
+import static com.android.net.module.util.netlink.ConntrackMessage.Tuple;
+import static com.android.net.module.util.netlink.ConntrackMessage.TupleIpv4;
+import static com.android.net.module.util.netlink.ConntrackMessage.TupleProto;
+import static com.android.net.module.util.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE;
+import static com.android.net.module.util.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
import static com.android.networkstack.tethering.BpfCoordinator.CONNTRACK_TIMEOUT_UPDATE_INTERVAL_MS;
import static com.android.networkstack.tethering.BpfCoordinator.NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED;
import static com.android.networkstack.tethering.BpfCoordinator.NF_CONNTRACK_UDP_TIMEOUT_STREAM;
@@ -82,9 +82,6 @@
import android.net.ip.ConntrackMonitor;
import android.net.ip.ConntrackMonitor.ConntrackEventConsumer;
import android.net.ip.IpServer;
-import android.net.netlink.ConntrackMessage;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkSocket;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Build;
@@ -100,6 +97,9 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.Struct;
+import com.android.net.module.util.netlink.ConntrackMessage;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkSocket;
import com.android.networkstack.tethering.BpfCoordinator.BpfConntrackEventConsumer;
import com.android.networkstack.tethering.BpfCoordinator.ClientInfo;
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
index a8b3b92..24716b2 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java
@@ -43,8 +43,6 @@
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_1.OffloadCallbackEvent;
-import android.net.netlink.StructNfGenMsg;
-import android.net.netlink.StructNlMsgHdr;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.NativeHandle;
@@ -57,6 +55,9 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.netlink.StructNfGenMsg;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index f999dfa..f45768f 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -178,10 +178,10 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.StateMachine;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.net.module.util.CollectionUtils;
import com.android.networkstack.tethering.TestConnectivityManager.TestNetworkAgent;
import com.android.testutils.MiscAsserts;
@@ -365,7 +365,8 @@
final String[] ifaces = new String[] {
TEST_RNDIS_IFNAME, TEST_WLAN_IFNAME, TEST_WIFI_IFNAME, TEST_MOBILE_IFNAME,
TEST_DUN_IFNAME, TEST_P2P_IFNAME, TEST_NCM_IFNAME, TEST_ETH_IFNAME};
- return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
+ return new InterfaceParams(ifName,
+ CollectionUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
MacAddress.ALL_ZEROS_ADDRESS);
}
diff --git a/service/Android.bp b/service/Android.bp
index abaeeb3..e58a998 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -69,9 +69,9 @@
"modules-utils-build",
"modules-utils-os",
"net-utils-device-common",
+ "net-utils-device-common-netlink",
"net-utils-framework-common",
"netd-client",
- "netlink-client",
"networkstack-client",
"PlatformProperties",
"service-connectivity-protos",
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index bf32ad5..b22457a 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -114,4 +114,15 @@
<!-- Whether to cancel network notifications automatically when tapped -->
<bool name="config_autoCancelNetworkNotifications">true</bool>
+ <!-- When no internet or partial connectivity is detected on a network, and a high priority
+ (heads up) notification would be shown due to the network being explicitly selected,
+ directly show the dialog that would normally be shown when tapping the notification
+ instead of showing the notification. -->
+ <bool name="config_notifyNoInternetAsDialogWhenHighPriority">false</bool>
+
+ <!-- When showing notifications indicating partial connectivity, display the same notifications
+ as no connectivity instead. This may be easier to understand for users but offers less
+ details on what is happening. -->
+ <bool name="config_partialConnectivityNotifiedAsNoInternet">false</bool>
+
</resources>
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index 6ac6a0e..5af13d7 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -32,6 +32,8 @@
<item type="array" name="config_networkNotifySwitches"/>
<item type="bool" name="config_ongoingSignInNotification"/>
<item type="bool" name="config_autoCancelNetworkNotifications"/>
+ <item type="bool" name="config_notifyNoInternetAsDialogWhenHighPriority"/>
+ <item type="bool" name="config_partialConnectivityNotifiedAsNoInternet"/>
<item type="drawable" name="stat_notify_wifi_in_range"/>
<item type="drawable" name="stat_notify_rssi_in_range"/>
</policy>
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 3450d27..34e15ca 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -179,7 +179,6 @@
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.netd.aidl.NativeUidRangeConfig;
-import android.net.netlink.InetDiagMessage;
import android.net.networkstack.ModuleNetworkStackClient;
import android.net.networkstack.NetworkStackClientBase;
import android.net.resolv.aidl.DnsHealthEventParcel;
@@ -235,6 +234,7 @@
import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.PermissionUtils;
+import com.android.net.module.util.netlink.InetDiagMessage;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
diff --git a/service/src/com/android/server/connectivity/NetworkNotificationManager.java b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
index ae98d92..155f6c4 100644
--- a/service/src/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
@@ -198,11 +198,22 @@
}
final Resources r = mResources.get();
+ if (highPriority && maybeNotifyViaDialog(r, notifyType, intent)) {
+ Log.d(TAG, "Notified via dialog for event " + nameOf(eventId));
+ return;
+ }
+
final CharSequence title;
final CharSequence details;
Icon icon = Icon.createWithResource(
mResources.getResourcesContext(), getIcon(transportType));
- if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
+ final boolean showAsNoInternet = notifyType == NotificationType.PARTIAL_CONNECTIVITY
+ && r.getBoolean(R.bool.config_partialConnectivityNotifiedAsNoInternet);
+ if (showAsNoInternet) {
+ Log.d(TAG, "Showing partial connectivity as NO_INTERNET");
+ }
+ if ((notifyType == NotificationType.NO_INTERNET || showAsNoInternet)
+ && transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.wifi_no_internet, name);
details = r.getString(R.string.wifi_no_internet_detailed);
} else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) {
@@ -306,6 +317,24 @@
}
}
+ private boolean maybeNotifyViaDialog(Resources res, NotificationType notifyType,
+ PendingIntent intent) {
+ if (notifyType != NotificationType.NO_INTERNET
+ && notifyType != NotificationType.PARTIAL_CONNECTIVITY) {
+ return false;
+ }
+ if (!res.getBoolean(R.bool.config_notifyNoInternetAsDialogWhenHighPriority)) {
+ return false;
+ }
+
+ try {
+ intent.send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Error sending dialog PendingIntent", e);
+ }
+ return true;
+ }
+
/**
* Clear the notification with the given id, only if it matches the given type.
*/
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index a49c0a6..7c0fb91 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -25,6 +25,12 @@
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.net.ConnectivitySettingsManager.UIDS_ALLOWED_ON_RESTRICTED_NETWORKS;
+import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_NETWORK;
+import static android.net.INetd.PERMISSION_NONE;
+import static android.net.INetd.PERMISSION_SYSTEM;
+import static android.net.INetd.PERMISSION_UNINSTALLED;
+import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
@@ -261,8 +267,8 @@
mUsers.addAll(mUserManager.getUserHandles(true /* excludeDying */));
final SparseArray<String> netdPermToSystemPerm = new SparseArray<>();
- netdPermToSystemPerm.put(INetd.PERMISSION_INTERNET, INTERNET);
- netdPermToSystemPerm.put(INetd.PERMISSION_UPDATE_DEVICE_STATS, UPDATE_DEVICE_STATS);
+ netdPermToSystemPerm.put(PERMISSION_INTERNET, INTERNET);
+ netdPermToSystemPerm.put(PERMISSION_UPDATE_DEVICE_STATS, UPDATE_DEVICE_STATS);
for (int i = 0; i < netdPermToSystemPerm.size(); i++) {
final int netdPermission = netdPermToSystemPerm.keyAt(i);
final String systemPermission = netdPermToSystemPerm.valueAt(i);
@@ -369,8 +375,8 @@
}
try {
if (add) {
- mNetd.networkSetPermissionForUser(INetd.PERMISSION_NETWORK, toIntArray(network));
- mNetd.networkSetPermissionForUser(INetd.PERMISSION_SYSTEM, toIntArray(system));
+ mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, toIntArray(network));
+ mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, toIntArray(system));
} else {
mNetd.networkClearPermissionForUser(toIntArray(network));
mNetd.networkClearPermissionForUser(toIntArray(system));
@@ -439,7 +445,7 @@
}
private int getPermissionForUid(final int uid) {
- int permission = INetd.PERMISSION_NONE;
+ int permission = PERMISSION_NONE;
// Check all the packages for this UID. The UID has the permission if any of the
// packages in it has the permission.
final String[] packages = mPackageManager.getPackagesForUid(uid);
@@ -453,7 +459,7 @@
}
} else {
// The last package of this uid is removed from device. Clean the package up.
- permission = INetd.PERMISSION_UNINSTALLED;
+ permission = PERMISSION_UNINSTALLED;
}
return permission;
}
@@ -573,11 +579,11 @@
for (int i = 0; i < requestedPermissions.length; i++) {
if (requestedPermissions[i].equals(INTERNET)
&& ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
- permissions |= INetd.PERMISSION_INTERNET;
+ permissions |= PERMISSION_INTERNET;
}
if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS)
&& ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
- permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS;
+ permissions |= PERMISSION_UPDATE_DEVICE_STATS;
}
}
return permissions;
@@ -750,19 +756,19 @@
for (int i = 0; i < netdPermissionsAppIds.size(); i++) {
int permissions = netdPermissionsAppIds.valueAt(i);
switch(permissions) {
- case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS):
+ case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS):
allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_INTERNET:
+ case PERMISSION_INTERNET:
internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_UPDATE_DEVICE_STATS:
+ case PERMISSION_UPDATE_DEVICE_STATS:
updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_NONE:
+ case PERMISSION_NONE:
noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_UNINSTALLED:
+ case PERMISSION_UNINSTALLED:
uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
default:
@@ -774,23 +780,22 @@
// TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids()
if (allPermissionAppIds.size() != 0) {
mNetd.trafficSetNetPermForUids(
- INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
+ PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS,
toIntArray(allPermissionAppIds));
}
if (internetPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET,
+ mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET,
toIntArray(internetPermissionAppIds));
}
if (updateStatsPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS,
+ mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS,
toIntArray(updateStatsPermissionAppIds));
}
if (noPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE,
- toIntArray(noPermissionAppIds));
+ mNetd.trafficSetNetPermForUids(PERMISSION_NONE, toIntArray(noPermissionAppIds));
}
if (uninstalledAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED,
+ mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED,
toIntArray(uninstalledAppIds));
}
} catch (RemoteException e) {
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 5a71319..ee13619 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -1825,8 +1825,15 @@
// Verify that networks are available as expected if wifi or cell is supported. Continue the
// test if none of them are supported since test should still able to verify the permission
// mechanism.
- if (supportWifi) requestAndWaitForAvailable(makeWifiNetworkRequest(), wifiCb);
- if (supportTelephony) requestAndWaitForAvailable(makeCellNetworkRequest(), telephonyCb);
+ if (supportWifi) {
+ mCtsNetUtils.ensureWifiConnected();
+ registerCallbackAndWaitForAvailable(makeWifiNetworkRequest(), wifiCb);
+ }
+ if (supportTelephony) {
+ // connectToCell needs to be followed by disconnectFromCell, which is called in tearDown
+ mCtsNetUtils.connectToCell();
+ registerCallbackAndWaitForAvailable(makeCellNetworkRequest(), telephonyCb);
+ }
try {
// Verify we cannot set Airplane Mode without correct permission:
@@ -1863,6 +1870,8 @@
+ "called whilst holding the NETWORK_AIRPLANE_MODE permission.");
}
// Verify that turning airplane mode off takes effect as expected.
+ // connectToCell only registers a request, it cannot / does not need to be called twice
+ mCtsNetUtils.ensureWifiConnected();
if (supportWifi) waitForAvailable(wifiCb);
if (supportTelephony) waitForAvailable(telephonyCb);
} finally {
@@ -1875,7 +1884,7 @@
}
}
- private void requestAndWaitForAvailable(@NonNull final NetworkRequest request,
+ private void registerCallbackAndWaitForAvailable(@NonNull final NetworkRequest request,
@NonNull final TestableNetworkCallback cb) {
mCm.registerNetworkCallback(request, cb);
waitForAvailable(cb);
diff --git a/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java b/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
index a20f1cc..f0c87673 100644
--- a/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
@@ -16,6 +16,7 @@
package android.net.cts;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static com.android.testutils.TestPermissionUtil.runAsShell;
@@ -168,7 +169,9 @@
mContext.registerReceiver(receiver, new IntentFilter(Proxy.PROXY_CHANGE_ACTION));
// Call setCurrentProxyScriptUrl with the URL of the pac file.
- runAsShell(NETWORK_SETTINGS, () -> {
+ // Note that the proxy script is global to device, and setting it from a different user
+ // should require INTERACT_ACROSS_USERS_FULL permission which the Settings app has.
+ runAsShell(NETWORK_SETTINGS, INTERACT_ACROSS_USERS_FULL, () -> {
mPacProxyManager.setCurrentProxyScriptUrl(proxy);
});
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index 52ce83a..e9c4e5a 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -71,6 +71,7 @@
// Include both the 32 and 64 bit versions
compile_multilib: "both",
+ jarjar_rules: ":NetworkStackJarJarRules",
}
// Tethering CTS tests for development and release. These tests always target the platform SDK
@@ -95,4 +96,5 @@
// Include both the 32 and 64 bit versions
compile_multilib: "both",
+ jarjar_rules: ":NetworkStackJarJarRules",
}
diff --git a/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index eff6658..c7cf040 100644
--- a/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
+++ b/tests/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
@@ -36,7 +36,6 @@
import java.io.ByteArrayInputStream
import java.net.HttpURLConnection
import java.net.URL
-import java.net.URLConnection
import java.nio.charset.StandardCharsets
private const val TEST_NETID = 42
@@ -63,6 +62,28 @@
override fun getPrivateDnsBypassNetwork(network: Network?) = privateDnsBypassNetwork
}
+ /**
+ * Mock [HttpURLConnection] to simulate reply from a server.
+ */
+ private class MockConnection(
+ url: URL,
+ private val response: HttpResponse
+ ) : HttpURLConnection(url) {
+ private val responseBytes = response.content.toByteArray(StandardCharsets.UTF_8)
+ override fun getResponseCode() = response.responseCode
+ override fun getContentLengthLong() = responseBytes.size.toLong()
+ override fun getHeaderField(field: String): String? {
+ return when (field) {
+ "location" -> response.redirectUrl
+ else -> null
+ }
+ }
+ override fun getInputStream() = ByteArrayInputStream(responseBytes)
+ override fun connect() = Unit
+ override fun disconnect() = Unit
+ override fun usingProxy() = false
+ }
+
private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector(
context, TestPermissionChecker(), NetworkStackService.Dependencies()) {
@@ -70,17 +91,8 @@
private val privateDnsBypassNetwork = TestNetwork(TEST_NETID)
private inner class TestNetwork(netId: Int) : Network(netId) {
- override fun openConnection(url: URL): URLConnection {
- val response = InstrumentationConnector.processRequest(url)
- val responseBytes = response.content.toByteArray(StandardCharsets.UTF_8)
-
- val connection = mock(HttpURLConnection::class.java)
- doReturn(response.responseCode).`when`(connection).responseCode
- doReturn(responseBytes.size.toLong()).`when`(connection).contentLengthLong
- doReturn(response.redirectUrl).`when`(connection).getHeaderField("location")
- doReturn(ByteArrayInputStream(responseBytes)).`when`(connection).inputStream
- return connection
- }
+ override fun openConnection(url: URL) = MockConnection(
+ url, InstrumentationConnector.processRequest(url))
}
override fun makeNetworkMonitor(
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index a7f57e8..96ea761 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -58,6 +58,7 @@
jarjar_rules: "jarjar-rules.txt",
static_libs: [
"androidx.test.rules",
+ "androidx.test.uiautomator",
"bouncycastle-repackaged-unbundled",
"core-tests-support",
"FrameworksNetCommonTests",
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
index 4c60ccf..887f171 100644
--- a/tests/unit/AndroidManifest.xml
+++ b/tests/unit/AndroidManifest.xml
@@ -53,6 +53,8 @@
<application>
<uses-library android:name="android.test.runner" />
<uses-library android:name="android.net.ipsec.ike" />
+ <activity
+ android:name="com.android.server.connectivity.NetworkNotificationManagerTest$TestDialogActivity"/>
</application>
<instrumentation
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 70b9f74..fb80248 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -2243,6 +2243,7 @@
deathRecipient.get().binderDied();
// Wait for the release message to be processed.
waitForIdle();
+ // After waitForIdle(), the message was processed and the service didn't crash.
}
@Test
diff --git a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 07deeef..2cf5d8e 100644
--- a/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -27,6 +27,7 @@
import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.SIGN_IN;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.clearInvocations;
@@ -39,9 +40,14 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -49,10 +55,19 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.Build;
+import android.os.Bundle;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
+import android.util.DisplayMetrics;
+import android.widget.TextView;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
import com.android.connectivity.resources.R;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
@@ -83,6 +98,7 @@
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);
+ private static final long TEST_TIMEOUT_MS = 10_000L;
static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
static final NetworkCapabilities VPN_CAPABILITIES = new NetworkCapabilities();
@@ -101,8 +117,28 @@
VPN_CAPABILITIES.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
}
+ /**
+ * Test activity that shows the action it was started with on screen, and dismisses when the
+ * text is tapped.
+ */
+ public static class TestDialogActivity extends Activity {
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setTurnScreenOn(true);
+ getSystemService(KeyguardManager.class).requestDismissKeyguard(
+ this, null /* callback */);
+
+ final TextView txt = new TextView(this);
+ txt.setText(getIntent().getAction());
+ txt.setOnClickListener(e -> finish());
+ setContentView(txt);
+ }
+ }
+
@Mock Context mCtx;
@Mock Resources mResources;
+ @Mock DisplayMetrics mDisplayMetrics;
@Mock PackageManager mPm;
@Mock TelephonyManager mTelephonyManager;
@Mock NotificationManager mNotificationManager;
@@ -124,6 +160,7 @@
mCellNai.networkInfo = mNetworkInfo;
mVpnNai.networkCapabilities = VPN_CAPABILITIES;
mVpnNai.networkInfo = mNetworkInfo;
+ mDisplayMetrics.density = 2.275f;
doReturn(true).when(mVpnNai).isVPN();
when(mCtx.getResources()).thenReturn(mResources);
when(mCtx.getPackageManager()).thenReturn(mPm);
@@ -136,6 +173,7 @@
when(mNetworkInfo.getExtraInfo()).thenReturn(TEST_EXTRA_INFO);
ConnectivityResources.setResourcesContextForTest(mCtx);
when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
+ when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
// Come up with some credible-looking transport names. The actual values do not matter.
String[] transportNames = new String[NetworkCapabilities.MAX_TRANSPORT + 1];
@@ -341,4 +379,82 @@
mManager.clearNotification(id, PARTIAL_CONNECTIVITY);
verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId));
}
+
+ @Test
+ public void testNotifyNoInternetAsDialogWhenHighPriority() throws Exception {
+ doReturn(true).when(mResources).getBoolean(
+ R.bool.config_notifyNoInternetAsDialogWhenHighPriority);
+
+ mManager.showNotification(TEST_NOTIF_ID, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
+ // Non-"no internet" notifications are not affected
+ verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(NETWORK_SWITCH.eventId), any());
+
+ final Instrumentation instr = InstrumentationRegistry.getInstrumentation();
+ final Context ctx = instr.getContext();
+ final String testAction = "com.android.connectivity.coverage.TEST_DIALOG";
+ final Intent intent = new Intent(testAction)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .setClassName(ctx.getPackageName(), TestDialogActivity.class.getName());
+ final PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0 /* requestCode */,
+ intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+
+ mManager.showNotification(TEST_NOTIF_ID, NO_INTERNET, mWifiNai, null /* switchToNai */,
+ pendingIntent, true /* highPriority */);
+
+ // Previous notifications are still dismissed
+ verify(mNotificationManager).cancel(TEST_NOTIF_TAG, NETWORK_SWITCH.eventId);
+
+ // Verify that the activity is shown (the activity shows the action on screen)
+ final UiObject actionText = UiDevice.getInstance(instr).findObject(
+ new UiSelector().text(testAction));
+ assertTrue("Activity not shown", actionText.waitForExists(TEST_TIMEOUT_MS));
+
+ // Tapping the text should dismiss the dialog
+ actionText.click();
+ assertTrue("Activity not dismissed", actionText.waitUntilGone(TEST_TIMEOUT_MS));
+
+ // Verify no NO_INTERNET notification was posted
+ verify(mNotificationManager, never()).notify(any(), eq(NO_INTERNET.eventId), any());
+ }
+
+ private void doNotificationTextTest(NotificationType type, @StringRes int expectedTitleRes,
+ String expectedTitleArg, @StringRes int expectedContentRes) {
+ final String expectedTitle = "title " + expectedTitleArg;
+ final String expectedContent = "expected content";
+ doReturn(expectedTitle).when(mResources).getString(expectedTitleRes, expectedTitleArg);
+ doReturn(expectedContent).when(mResources).getString(expectedContentRes);
+
+ mManager.showNotification(TEST_NOTIF_ID, type, mWifiNai, mCellNai, null, false);
+ final ArgumentCaptor<Notification> notifCap = ArgumentCaptor.forClass(Notification.class);
+
+ verify(mNotificationManager).notify(eq(TEST_NOTIF_TAG), eq(type.eventId),
+ notifCap.capture());
+ final Notification notif = notifCap.getValue();
+
+ assertEquals(expectedTitle, notif.extras.getString(Notification.EXTRA_TITLE));
+ assertEquals(expectedContent, notif.extras.getString(Notification.EXTRA_TEXT));
+ }
+
+ @Test
+ public void testNotificationText_NoInternet() {
+ doNotificationTextTest(NO_INTERNET,
+ R.string.wifi_no_internet, TEST_EXTRA_INFO,
+ R.string.wifi_no_internet_detailed);
+ }
+
+ @Test
+ public void testNotificationText_Partial() {
+ doNotificationTextTest(PARTIAL_CONNECTIVITY,
+ R.string.network_partial_connectivity, TEST_EXTRA_INFO,
+ R.string.network_partial_connectivity_detailed);
+ }
+
+ @Test
+ public void testNotificationText_PartialAsNoInternet() {
+ doReturn(true).when(mResources).getBoolean(
+ R.bool.config_partialConnectivityNotifiedAsNoInternet);
+ doNotificationTextTest(PARTIAL_CONNECTIVITY,
+ R.string.wifi_no_internet, TEST_EXTRA_INFO,
+ R.string.wifi_no_internet_detailed);
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 8f46508..a9749c4 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -31,6 +31,11 @@
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.net.ConnectivitySettingsManager.UIDS_ALLOWED_ON_RESTRICTED_NETWORKS;
+import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_NONE;
+import static android.net.INetd.PERMISSION_SYSTEM;
+import static android.net.INetd.PERMISSION_UNINSTALLED;
+import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.SYSTEM_UID;
@@ -123,6 +128,8 @@
private static final String PARTITION_VENDOR = "vendor";
private static final int VERSION_P = Build.VERSION_CODES.P;
private static final int VERSION_Q = Build.VERSION_CODES.Q;
+ private static final int PERMISSION_TRAFFIC_ALL =
+ PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS;
@Mock private Context mContext;
@Mock private PackageManager mPackageManager;
@@ -132,6 +139,7 @@
@Mock private SystemConfigManager mSystemConfigManager;
private PermissionMonitor mPermissionMonitor;
+ private NetdMonitor mNetdMonitor;
@Before
public void setUp() throws Exception {
@@ -155,6 +163,7 @@
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
+ mNetdMonitor = new NetdMonitor(mNetdService);
when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(/* empty app list */ null);
mPermissionMonitor.startMonitoring();
@@ -460,25 +469,26 @@
}
private class NetdMonitor {
- private final HashMap<Integer, Boolean> mApps = new HashMap<>();
+ private final HashMap<Integer, Boolean> mUidsNetworkPermission = new HashMap<>();
+ private final HashMap<Integer, Integer> mAppIdsTrafficPermission = new HashMap<>();
NetdMonitor(INetd mockNetd) throws Exception {
- // Add hook to verify and track result of setPermission.
+ // Add hook to verify and track result of networkSetPermission.
doAnswer((InvocationOnMock invocation) -> {
final Object[] args = invocation.getArguments();
- final Boolean isSystem = args[0].equals(INetd.PERMISSION_SYSTEM);
+ final Boolean isSystem = args[0].equals(PERMISSION_SYSTEM);
for (final int uid : (int[]) args[1]) {
// TODO: Currently, permission monitor will send duplicate commands for each uid
// corresponding to each user. Need to fix that and uncomment below test.
// if (mApps.containsKey(uid) && mApps.get(uid) == isSystem) {
// fail("uid " + uid + " is already set to " + isSystem);
// }
- mApps.put(uid, isSystem);
+ mUidsNetworkPermission.put(uid, isSystem);
}
return null;
}).when(mockNetd).networkSetPermissionForUser(anyInt(), any(int[].class));
- // Add hook to verify and track result of clearPermission.
+ // Add hook to verify and track result of networkClearPermission.
doAnswer((InvocationOnMock invocation) -> {
final Object[] args = invocation.getArguments();
for (final int uid : (int[]) args[0]) {
@@ -487,42 +497,62 @@
// if (!mApps.containsKey(uid)) {
// fail("uid " + uid + " does not exist.");
// }
- mApps.remove(uid);
+ mUidsNetworkPermission.remove(uid);
}
return null;
}).when(mockNetd).networkClearPermissionForUser(any(int[].class));
+
+ // Add hook to verify and track result of trafficSetNetPerm.
+ doAnswer((InvocationOnMock invocation) -> {
+ final Object[] args = invocation.getArguments();
+ final int permission = (int) args[0];
+ for (final int appId : (int[]) args[1]) {
+ mAppIdsTrafficPermission.put(appId, permission);
+ }
+ return null;
+ }).when(mockNetd).trafficSetNetPermForUids(anyInt(), any(int[].class));
}
- public void expectPermission(Boolean permission, UserHandle[] users, int[] apps) {
+ public void expectNetworkPerm(Boolean permission, UserHandle[] users, int... appIds) {
for (final UserHandle user : users) {
- for (final int app : apps) {
- final int uid = user.getUid(app);
- if (!mApps.containsKey(uid)) {
+ for (final int appId : appIds) {
+ final int uid = user.getUid(appId);
+ if (!mUidsNetworkPermission.containsKey(uid)) {
fail("uid " + uid + " does not exist.");
}
- if (mApps.get(uid) != permission) {
+ if (mUidsNetworkPermission.get(uid) != permission) {
fail("uid " + uid + " has wrong permission: " + permission);
}
}
}
}
- public void expectNoPermission(UserHandle[] users, int[] apps) {
+ public void expectNoNetworkPerm(UserHandle[] users, int... appIds) {
for (final UserHandle user : users) {
- for (final int app : apps) {
- final int uid = user.getUid(app);
- if (mApps.containsKey(uid)) {
+ for (final int appId : appIds) {
+ final int uid = user.getUid(appId);
+ if (mUidsNetworkPermission.containsKey(uid)) {
fail("uid " + uid + " has listed permissions, expected none.");
}
}
}
}
+
+ public void expectTrafficPerm(int permission, int... appIds) {
+ for (final int appId : appIds) {
+ if (!mAppIdsTrafficPermission.containsKey(appId)) {
+ fail("appId " + appId + " does not exist.");
+ }
+ if (mAppIdsTrafficPermission.get(appId) != permission) {
+ fail("appId " + appId + " has wrong permission: "
+ + mAppIdsTrafficPermission.get(appId));
+ }
+ }
+ }
}
@Test
public void testUserAndPackageAddRemove() throws Exception {
- final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
-
// MOCK_UID1: MOCK_PACKAGE1 only has network permission.
// SYSTEM_UID: SYSTEM_PACKAGE1 has system permission.
// SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission.
@@ -537,15 +567,15 @@
// Add SYSTEM_PACKAGE2, expect only have network permission.
mPermissionMonitor.onUserAdded(MOCK_USER1);
addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID);
- netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, SYSTEM_UID);
// Add SYSTEM_PACKAGE1, expect permission escalate.
addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, SYSTEM_UID);
mPermissionMonitor.onUserAdded(MOCK_USER2);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_UID);
// Remove SYSTEM_PACKAGE2, expect keep system permission.
when(mPackageManager.getPackagesForUid(MOCK_USER1.getUid(SYSTEM_UID)))
@@ -554,19 +584,19 @@
.thenReturn(new String[]{SYSTEM_PACKAGE1});
removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2},
SYSTEM_PACKAGE2, SYSTEM_UID);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_UID);
// Add SYSTEM_PACKAGE2, expect keep system permission.
addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_UID);
addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID});
- netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_UID);
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ MOCK_UID1);
// Remove MOCK_UID1, expect no permission left for all user.
when(mPackageManager.getPackagesForUid(MOCK_USER1.getUid(MOCK_UID1)))
@@ -575,29 +605,28 @@
.thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{MOCK_UID1});
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID1);
// Remove SYSTEM_PACKAGE1, expect permission downgrade.
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{SYSTEM_PACKAGE2});
removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2},
SYSTEM_PACKAGE1, SYSTEM_UID);
- netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
+ SYSTEM_UID);
mPermissionMonitor.onUserRemoved(MOCK_USER1);
- netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER2}, new int[]{SYSTEM_UID});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER2}, SYSTEM_UID);
// Remove all packages, expect no permission left.
when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{});
removePackageForUsers(new UserHandle[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID, MOCK_UID1});
+ mNetdMonitor.expectNoNetworkPerm(
+ new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_UID, MOCK_UID1);
// Remove last user, expect no redundant clearPermission is invoked.
mPermissionMonitor.onUserRemoved(MOCK_USER2);
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
- new int[]{SYSTEM_UID, MOCK_UID1});
+ mNetdMonitor.expectNoNetworkPerm(
+ new UserHandle[]{MOCK_USER1, MOCK_USER2}, SYSTEM_UID, MOCK_UID1);
}
@Test
@@ -688,74 +717,38 @@
}
}
- private class NetdServiceMonitor {
- private final HashMap<Integer, Integer> mPermissions = new HashMap<>();
-
- NetdServiceMonitor(INetd mockNetdService) throws Exception {
- // Add hook to verify and track result of setPermission.
- doAnswer((InvocationOnMock invocation) -> {
- final Object[] args = invocation.getArguments();
- final int permission = (int) args[0];
- for (final int uid : (int[]) args[1]) {
- mPermissions.put(uid, permission);
- }
- return null;
- }).when(mockNetdService).trafficSetNetPermForUids(anyInt(), any(int[].class));
- }
-
- public void expectPermission(int permission, int[] apps) {
- for (final int app : apps) {
- if (!mPermissions.containsKey(app)) {
- fail("uid " + app + " does not exist.");
- }
- if (mPermissions.get(app) != permission) {
- fail("uid " + app + " has wrong permission: " + mPermissions.get(app));
- }
- }
- }
- }
-
@Test
public void testPackagePermissionUpdate() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
// MOCK_UID1: MOCK_PACKAGE1 only has internet permission.
// MOCK_UID2: MOCK_PACKAGE2 does not have any permission.
// SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission.
// SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission.
-
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
- netdPermissionsAppIds.put(MOCK_UID1, INetd.PERMISSION_INTERNET);
- netdPermissionsAppIds.put(MOCK_UID2, INetd.PERMISSION_NONE);
- netdPermissionsAppIds.put(SYSTEM_UID1, INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS);
- netdPermissionsAppIds.put(SYSTEM_UID2, INetd.PERMISSION_UPDATE_DEVICE_STATS);
+ netdPermissionsAppIds.put(MOCK_UID1, PERMISSION_INTERNET);
+ netdPermissionsAppIds.put(MOCK_UID2, PERMISSION_NONE);
+ netdPermissionsAppIds.put(SYSTEM_UID1, PERMISSION_TRAFFIC_ALL);
+ netdPermissionsAppIds.put(SYSTEM_UID2, PERMISSION_UPDATE_DEVICE_STATS);
// Send the permission information to netd, expect permission updated.
mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET,
- new int[]{MOCK_UID1});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID2});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_UPDATE_DEVICE_STATS,
- new int[]{SYSTEM_UID2});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, SYSTEM_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, SYSTEM_UID2);
// Update permission of MOCK_UID1, expect new permission show up.
- mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1,
- INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, PERMISSION_TRAFFIC_ALL);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
// Change permissions of SYSTEM_UID2, expect new permission show up and old permission
// revoked.
- mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2,
- INetd.PERMISSION_INTERNET);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{SYSTEM_UID2});
+ mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, PERMISSION_INTERNET);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, SYSTEM_UID2);
// Revoke permission from SYSTEM_UID1, expect no permission stored.
- mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, INetd.PERMISSION_NONE);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{SYSTEM_UID1});
+ mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, PERMISSION_NONE);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, SYSTEM_UID1);
}
private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions)
@@ -776,24 +769,18 @@
@Test
public void testPackageInstall() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
-
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID2});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID2);
}
@Test
public void testPackageInstallSharedUid() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
-
PackageInfo packageInfo1 = addPackage(MOCK_PACKAGE1, MOCK_UID1,
new String[] {INTERNET, UPDATE_DEVICE_STATS});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
// Install another package with the same uid and no permissions should not cause the UID to
// lose permissions.
@@ -802,57 +789,45 @@
when(mPackageManager.getPackagesForUid(MOCK_UID1))
.thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
}
@Test
public void testPackageUninstallBasic() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
-
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_UID1);
}
@Test
public void testPackageRemoveThenAdd() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
-
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_UID1);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
}
@Test
public void testPackageUpdate() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
-
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID1);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
}
@Test
public void testPackageUninstallWithMultiplePackages() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
-
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
// Mock another package with the same uid but different permissions.
PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET);
@@ -861,7 +836,7 @@
MOCK_PACKAGE2});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
}
@Test
@@ -878,7 +853,6 @@
@Test
public void testUpdateUidPermissionsFromSystemConfig() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
when(mPackageManager.getInstalledPackages(anyInt())).thenReturn(new ArrayList<>());
when(mSystemConfigManager.getSystemPermissionUids(eq(INTERNET)))
.thenReturn(new int[]{ MOCK_UID1, MOCK_UID2 });
@@ -886,10 +860,8 @@
.thenReturn(new int[]{ MOCK_UID2 });
mPermissionMonitor.startMonitoring();
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{ MOCK_UID1 });
- netdServiceMonitor.expectPermission(
- INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
- new int[]{ MOCK_UID2 });
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID2);
}
private BroadcastReceiver expectBroadcastReceiver(String... actions) {
@@ -909,7 +881,6 @@
@Test
public void testIntentReceiver() throws Exception {
- final NetdServiceMonitor netdServiceMonitor = new NetdServiceMonitor(mNetdService);
final BroadcastReceiver receiver = expectBroadcastReceiver(
Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_REMOVED);
@@ -920,8 +891,7 @@
setPackagePermissions(MOCK_PACKAGE1, MOCK_UID1,
new String[] { INTERNET, UPDATE_DEVICE_STATS });
receiver.onReceive(mContext, addedIntent);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[] { MOCK_UID1 });
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
// Verify receiving PACKAGE_REMOVED intent.
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(null);
@@ -929,7 +899,7 @@
Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */));
removedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID1);
receiver.onReceive(mContext, removedIntent);
- netdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[] { MOCK_UID1 });
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_UID1);
}
private ContentObserver expectRegisterContentObserver(Uri expectedUri) {
@@ -949,7 +919,6 @@
@Test
public void testUidsAllowedOnRestrictedNetworksChanged() throws Exception {
- final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
final ContentObserver contentObserver = expectRegisterContentObserver(
Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS));
@@ -963,27 +932,25 @@
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
new ArraySet<>(new Integer[] { MOCK_UID1 }));
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID2);
// MOCK_UID2 is listed in setting that allow to use restricted networks, MOCK_UID2
// should have SYSTEM permission but MOCK_UID1 should revoke permission.
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
new ArraySet<>(new Integer[] { MOCK_UID2 }));
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1);
// No uid lists in setting, should revoke permission from all uids.
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectNoPermission(
- new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1, MOCK_UID2});
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1, MOCK_UID2);
}
@Test
public void testUidsAllowedOnRestrictedNetworksChangedWithSharedUid() throws Exception {
- final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
final ContentObserver contentObserver = expectRegisterContentObserver(
Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS));
@@ -995,29 +962,28 @@
// MOCK_PACKAGE1 have CHANGE_NETWORK_STATE, MOCK_UID1 should have NETWORK permission.
addPackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
- netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
// MOCK_UID1 is listed in setting that allow to use restricted networks, MOCK_UID1
// should upgrade to SYSTEM permission.
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
new ArraySet<>(new Integer[] { MOCK_UID1 }));
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
// No app lists in setting, MOCK_UID1 should downgrade to NETWORK permission.
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
// MOCK_PACKAGE1 removed, should revoke permission from MOCK_UID1.
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{MOCK_PACKAGE2});
removePackageForUsers(new UserHandle[]{MOCK_USER1}, MOCK_PACKAGE1, MOCK_UID1);
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1);
}
@Test
public void testUidsAllowedOnRestrictedNetworksChangedWithMultipleUsers() throws Exception {
- final NetdMonitor netdMonitor = new NetdMonitor(mNetdService);
final ContentObserver contentObserver = expectRegisterContentObserver(
Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS));
@@ -1032,44 +998,37 @@
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
new ArraySet<>(new Integer[] { MOCK_UID1 }));
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID1});
- netdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1}, new int[]{MOCK_UID2});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID2);
// Add user MOCK_USER2.
mPermissionMonitor.onUserAdded(MOCK_USER2);
// MOCK_UID1 in both users should all have SYSTEM permission and MOCK_UID2 has no
// permissions in either user.
- netdMonitor.expectPermission(
- SYSTEM, new UserHandle[] { MOCK_USER1, MOCK_USER2 }, new int[]{MOCK_UID1});
- netdMonitor.expectNoPermission(
- new UserHandle[] { MOCK_USER1, MOCK_USER2 }, new int[]{MOCK_UID2});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID1);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID2);
// MOCK_UID2 is listed in setting that allow to use restricted networks, MOCK_UID2
// in both users should have SYSTEM permission and MOCK_UID1 has no permissions.
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(
new ArraySet<>(new Integer[] { MOCK_UID2 }));
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectPermission(
- SYSTEM, new UserHandle[] { MOCK_USER1, MOCK_USER2 }, new int[]{MOCK_UID2});
- netdMonitor.expectNoPermission(
- new UserHandle[] { MOCK_USER1, MOCK_USER2 }, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_UID1);
// Remove user MOCK_USER1
mPermissionMonitor.onUserRemoved(MOCK_USER1);
- netdMonitor.expectPermission(SYSTEM, new UserHandle[] {MOCK_USER2}, new int[]{MOCK_UID2});
- netdMonitor.expectNoPermission(new UserHandle[] {MOCK_USER2}, new int[]{MOCK_UID1});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER2}, MOCK_UID2);
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER2}, MOCK_UID1);
// No uid lists in setting, should revoke permission from all uids.
when(mDeps.getUidsAllowedOnRestrictedNetworks(any())).thenReturn(new ArraySet<>());
contentObserver.onChange(true /* selfChange */);
- netdMonitor.expectNoPermission(
- new UserHandle[]{MOCK_USER2}, new int[]{ MOCK_UID1, MOCK_UID2 });
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER2}, 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);
@@ -1080,10 +1039,8 @@
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});
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1, MOCK_UID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, 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);
@@ -1094,18 +1051,15 @@
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});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, 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);
@@ -1124,18 +1078,15 @@
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});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID2);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, 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);
@@ -1146,8 +1097,8 @@
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});
+ mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_UID1);
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
@@ -1157,16 +1108,13 @@
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});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, 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);
@@ -1179,8 +1127,8 @@
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});
+ mNetdMonitor.expectNetworkPerm(NETWORK, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_UID1);
// Verify receiving EXTERNAL_APPLICATIONS_AVAILABLE intent and update permission to netd.
final Intent externalIntent = new Intent(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
@@ -1192,9 +1140,7 @@
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});
+ mNetdMonitor.expectNetworkPerm(SYSTEM, new UserHandle[]{MOCK_USER1}, MOCK_UID1);
+ mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID1);
}
}