Test no Internet and partial connectivity notifications.
Test: new unit tests pass
Change-Id: I363fa3ef15476a30e7b8708a80867dd456e5e520
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 7e63761..8ec979a 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -4949,11 +4949,16 @@
}
}
- private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) {
- if (VDBG) log("scheduleUnvalidatedPrompt " + nai.network);
+ private void scheduleUnvalidatedPrompt(@NonNull final Network network) {
+ scheduleUnvalidatedPrompt(network, PROMPT_UNVALIDATED_DELAY_MS);
+ }
+
+ /** Schedule unvalidated prompt for testing */
+ @VisibleForTesting
+ public void scheduleUnvalidatedPrompt(@NonNull final Network network, final long delayMs) {
+ if (VDBG) log("scheduleUnvalidatedPrompt " + network);
mHandler.sendMessageDelayed(
- mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network),
- PROMPT_UNVALIDATED_DELAY_MS);
+ mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, network), delayMs);
}
@Override
@@ -9208,7 +9213,7 @@
networkAgent.networkMonitor().notifyNetworkConnected(params.linkProperties,
params.networkCapabilities);
}
- scheduleUnvalidatedPrompt(networkAgent);
+ scheduleUnvalidatedPrompt(networkAgent.network);
// Whether a particular NetworkRequest listen should cause signal strength thresholds to
// be communicated to a particular NetworkAgent depends only on the network's immutable,
diff --git a/service/src/com/android/server/connectivity/NetworkNotificationManager.java b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
index 155f6c4..45da0ea 100644
--- a/service/src/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/service/src/com/android/server/connectivity/NetworkNotificationManager.java
@@ -394,8 +394,9 @@
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
}
- @VisibleForTesting
- static String tagFor(int id) {
+ /** Get the logging tag for a notification ID */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public static String tagFor(int id) {
return String.format("ConnectivityNotification:%d", id);
}
diff --git a/tests/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/integration/util/com/android/server/NetworkAgentWrapper.java
index 97688d5..28edcb2 100644
--- a/tests/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -269,6 +269,7 @@
mNetworkAgent.sendNetworkScore(score);
}
+ // TODO : remove adjustScore and replace with the appropriate exiting flags.
public void adjustScore(int change) {
final int newLegacyScore = mScore.getLegacyInt() + change;
final NetworkScore.Builder builder = new NetworkScore.Builder()
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 85aec56..9ba466a 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -368,6 +368,7 @@
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo;
+import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.QosCallbackTracker;
@@ -3533,6 +3534,54 @@
mCm.unregisterNetworkCallback(callback);
}
+ /** Expects the specified notification and returns the notification ID. */
+ private int expectNotification(TestNetworkAgentWrapper agent, NotificationType type) {
+ verify(mNotificationManager).notify(
+ eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)),
+ eq(type.eventId), any());
+ return type.eventId;
+ }
+
+ /**
+ * Expects the specified notification happens when the unvalidated prompt message arrives
+ *
+ * @return the notification ID.
+ **/
+ private int expectUnvalidationCheckWillNotify(TestNetworkAgentWrapper agent,
+ NotificationType type) {
+ mService.scheduleUnvalidatedPrompt(agent.getNetwork(), 0 /* delayMs */);
+ waitForIdle();
+ return expectNotification(agent, type);
+ }
+
+ /**
+ * Expects that the notification for the specified network is cleared.
+ *
+ * This generally happens when the network disconnects or when the newtwork validates. During
+ * normal usage the notification is also cleared by the system when the notification is tapped.
+ */
+ private void expectClearNotification(TestNetworkAgentWrapper agent, int expectedId) {
+ verify(mNotificationManager).cancel(
+ eq(NetworkNotificationManager.tagFor(agent.getNetwork().netId)), eq(expectedId));
+ }
+
+ /**
+ * Expects that no notification happens when the unvalidated prompt message arrives
+ *
+ * @return the notification ID.
+ **/
+ private void expectUnvalidationCheckWillNotNotify(TestNetworkAgentWrapper agent) {
+ mService.scheduleUnvalidatedPrompt(agent.getNetwork(), 0 /*delayMs */);
+ waitForIdle();
+ verify(mNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any());
+ }
+
+ private void expectDisconnectAndClearNotifications(TestNetworkCallback callback,
+ TestNetworkAgentWrapper agent, int id) {
+ callback.expectCallback(CallbackEntry.LOST, agent);
+ expectClearNotification(agent, id);
+ }
+
private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
/*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false);
@@ -3653,10 +3702,13 @@
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- // Cell Remains the default.
+ // Cell remains the default.
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- // Lower wifi's score to below than cell, and check that it doesn't disconnect because
+ // Expect a high-priority NO_INTERNET notification.
+ expectUnvalidationCheckWillNotify(mWiFiNetworkAgent, NotificationType.NO_INTERNET);
+
+ // Lower WiFi's score to lower than cell, and check that it doesn't disconnect because
// it's explicitly selected.
mWiFiNetworkAgent.adjustScore(-40);
mWiFiNetworkAgent.adjustScore(40);
@@ -3670,18 +3722,26 @@
// Disconnect wifi, and then reconnect, again with explicitlySelected=true.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ expectDisconnectAndClearNotifications(callback, mWiFiNetworkAgent,
+ NotificationType.NO_INTERNET.eventId);
+
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ // Expect a high-priority NO_INTERNET notification.
+ expectUnvalidationCheckWillNotify(mWiFiNetworkAgent, NotificationType.NO_INTERNET);
+
// If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
// network to disconnect.
mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
- callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ expectDisconnectAndClearNotifications(callback, mWiFiNetworkAgent,
+ NotificationType.NO_INTERNET.eventId);
+ reset(mNotificationManager);
// Reconnect, again with explicitlySelected=true, but this time validate.
+ // Expect no notifications.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(true);
@@ -3689,6 +3749,7 @@
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
@@ -3711,16 +3772,19 @@
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
+ expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
// Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
// Check that the network is not scored specially and that the device prefers cell data.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false, true);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
// Clean up.
mWiFiNetworkAgent.disconnect();
@@ -4088,6 +4152,12 @@
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
+ // Expect a PARTIAL_CONNECTIVITY notification. The notification appears as soon as partial
+ // connectivity is detected, and is low priority because the network was not explicitly
+ // selected by the user. This happens if we reconnect to a network where the user previously
+ // accepted partial connectivity without checking "always".
+ expectNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY);
+
// With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
// probe.
mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
@@ -4100,7 +4170,7 @@
waitForIdle();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
- // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
+ // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
@@ -4109,9 +4179,13 @@
assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ // Once the network validates, the notification disappears.
+ expectClearNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY.eventId);
+
// Disconnect and reconnect wifi with partial connectivity again.
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -4119,20 +4193,28 @@
// Mobile data should be the default network.
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ waitForIdle();
+
+ // Expect a low-priority PARTIAL_CONNECTIVITY notification as soon as partial connectivity
+ // is detected.
+ expectNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY);
// If the user chooses no, disconnect wifi immediately.
- mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
+ mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false /* accept */,
false /* always */);
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ expectClearNotification(mWiFiNetworkAgent, NotificationType.PARTIAL_CONNECTIVITY.eventId);
+ reset(mNotificationManager);
- // If user accepted partial connectivity before, and device reconnects to that network
- // again, but now the network has full connectivity. The network shouldn't contain
+ // If the user accepted partial connectivity before, and the device connects to that network
+ // again, but now the network has full connectivity, then the network shouldn't contain
// NET_CAPABILITY_PARTIAL_CONNECTIVITY.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
// acceptUnvalidated is also used as setting for accepting partial networks.
mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
true /* acceptUnvalidated */);
mWiFiNetworkAgent.connect(true);
+ expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
@@ -4163,9 +4245,11 @@
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
+ expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
+
mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
- // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
+ // Need a trigger point to let NetworkMonitor tell ConnectivityService that the network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
@@ -4187,8 +4271,10 @@
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(
NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ verifyNoMoreInteractions(mNotificationManager);
}
@Test