Merge "Test no Internet and partial connectivity notifications."

This commit is contained in:
Jean Chalard
2022-09-15 03:56:13 +00:00
committed by Gerrit Code Review
4 changed files with 109 additions and 16 deletions

View File

@@ -4949,11 +4949,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
} }
private void scheduleUnvalidatedPrompt(NetworkAgentInfo nai) { private void scheduleUnvalidatedPrompt(@NonNull final Network network) {
if (VDBG) log("scheduleUnvalidatedPrompt " + nai.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.sendMessageDelayed(
mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, nai.network), mHandler.obtainMessage(EVENT_PROMPT_UNVALIDATED, network), delayMs);
PROMPT_UNVALIDATED_DELAY_MS);
} }
@Override @Override
@@ -9208,7 +9213,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
networkAgent.networkMonitor().notifyNetworkConnected(params.linkProperties, networkAgent.networkMonitor().notifyNetworkConnected(params.linkProperties,
params.networkCapabilities); params.networkCapabilities);
} }
scheduleUnvalidatedPrompt(networkAgent); scheduleUnvalidatedPrompt(networkAgent.network);
// Whether a particular NetworkRequest listen should cause signal strength thresholds to // Whether a particular NetworkRequest listen should cause signal strength thresholds to
// be communicated to a particular NetworkAgent depends only on the network's immutable, // be communicated to a particular NetworkAgent depends only on the network's immutable,

View File

@@ -394,8 +394,9 @@ public class NetworkNotificationManager {
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show(); Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
} }
@VisibleForTesting /** Get the logging tag for a notification ID */
static String tagFor(int id) { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public static String tagFor(int id) {
return String.format("ConnectivityNotification:%d", id); return String.format("ConnectivityNotification:%d", id);
} }

View File

@@ -269,6 +269,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
mNetworkAgent.sendNetworkScore(score); mNetworkAgent.sendNetworkScore(score);
} }
// TODO : remove adjustScore and replace with the appropriate exiting flags.
public void adjustScore(int change) { public void adjustScore(int change) {
final int newLegacyScore = mScore.getLegacyInt() + change; final int newLegacyScore = mScore.getLegacyInt() + change;
final NetworkScore.Builder builder = new NetworkScore.Builder() final NetworkScore.Builder builder = new NetworkScore.Builder()

View File

@@ -368,6 +368,7 @@ import com.android.server.connectivity.ConnectivityFlags;
import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat; import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.QosCallbackTracker; import com.android.server.connectivity.QosCallbackTracker;
@@ -3533,6 +3534,54 @@ public class ConnectivityServiceTest {
mCm.unregisterNetworkCallback(callback); 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) { private NativeNetworkConfig nativeNetworkConfigPhysical(int netId, int permission) {
return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission, return new NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL, permission,
/*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false); /*secure=*/ false, VpnManager.TYPE_VPN_NONE, /*excludeLocalRoutes=*/ false);
@@ -3653,10 +3702,13 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// Cell Remains the default. // Cell remains the default.
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 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. // it's explicitly selected.
mWiFiNetworkAgent.adjustScore(-40); mWiFiNetworkAgent.adjustScore(-40);
mWiFiNetworkAgent.adjustScore(40); mWiFiNetworkAgent.adjustScore(40);
@@ -3670,18 +3722,26 @@ public class ConnectivityServiceTest {
// Disconnect wifi, and then reconnect, again with explicitlySelected=true. // Disconnect wifi, and then reconnect, again with explicitlySelected=true.
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); expectDisconnectAndClearNotifications(callback, mWiFiNetworkAgent,
NotificationType.NO_INTERNET.eventId);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false); mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); 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 // If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
// network to disconnect. // network to disconnect.
mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false); 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. // Reconnect, again with explicitlySelected=true, but this time validate.
// Expect no notifications.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false); mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(true); mWiFiNetworkAgent.connect(true);
@@ -3689,6 +3749,7 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET); mEthernetNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true); mEthernetNetworkAgent.connect(true);
@@ -3711,16 +3772,19 @@ public class ConnectivityServiceTest {
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect(); mEthernetNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent); callback.expectCallback(CallbackEntry.LOST, mEthernetNetworkAgent);
expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
// Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true. // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
// Check that the network is not scored specially and that the device prefers cell data. // Check that the network is not scored specially and that the device prefers cell data.
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false, true); mWiFiNetworkAgent.explicitlySelected(false, true);
mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
// Clean up. // Clean up.
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
@@ -4088,6 +4152,12 @@ public class ConnectivityServiceTest {
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback(); 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 // With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
// probe. // probe.
mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */); mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
@@ -4100,7 +4170,7 @@ public class ConnectivityServiceTest {
waitForIdle(); waitForIdle();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity(); 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. // validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
@@ -4109,9 +4179,13 @@ public class ConnectivityServiceTest {
assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY)); assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 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. // Disconnect and reconnect wifi with partial connectivity again.
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connectWithPartialConnectivity(); mWiFiNetworkAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -4119,20 +4193,28 @@ public class ConnectivityServiceTest {
// Mobile data should be the default network. // Mobile data should be the default network.
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); 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. // If the user chooses no, disconnect wifi immediately.
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */, mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false /* accept */,
false /* always */); false /* always */);
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); 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 // If the user accepted partial connectivity before, and the device connects to that network
// again, but now the network has full connectivity. The network shouldn't contain // again, but now the network has full connectivity, then the network shouldn't contain
// NET_CAPABILITY_PARTIAL_CONNECTIVITY. // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
// acceptUnvalidated is also used as setting for accepting partial networks. // acceptUnvalidated is also used as setting for accepting partial networks.
mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */, mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
true /* acceptUnvalidated */); true /* acceptUnvalidated */);
mWiFiNetworkAgent.connect(true); mWiFiNetworkAgent.connect(true);
expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
// If user accepted partial connectivity network before, // If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in // NetworkMonitor#setAcceptPartialConnectivity() will be called in
@@ -4163,9 +4245,11 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */); 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. // validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true); mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
@@ -4187,8 +4271,10 @@ public class ConnectivityServiceTest {
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith( callback.expectCapabilitiesWith(
NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
expectUnvalidationCheckWillNotNotify(mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect(); mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
verifyNoMoreInteractions(mNotificationManager);
} }
@Test @Test