Update multiple validation result to ConnectivityService
Once a network is determined to have partial connectivity, it cannot go back to full connectivity without a disconnect. This is because NetworkMonitor can only communicate either PARTIAL_CONNECTIVITY or VALID, but not both. Thus, multiple validation results allow ConnectivityService to know the real network status. Bug: 129662877 Bug: 130683832 Test: atest FrameworksNetTests Test: atest NetworkStackTests Test: atest --generate-new-metrics 50 NetworkStackTests:com.android.server.connectivity.NetworkMonitorTest Test: Simulate partial connectvitiy Change-Id: I406c9368617c03a2dd3ab15fb1f6dbf539d7c714
This commit is contained in:
@@ -25,8 +25,8 @@ import static android.net.ConnectivityManager.TYPE_NONE;
|
|||||||
import static android.net.ConnectivityManager.TYPE_VPN;
|
import static android.net.ConnectivityManager.TYPE_VPN;
|
||||||
import static android.net.ConnectivityManager.getNetworkTypeName;
|
import static android.net.ConnectivityManager.getNetworkTypeName;
|
||||||
import static android.net.ConnectivityManager.isNetworkTypeValid;
|
import static android.net.ConnectivityManager.isNetworkTypeValid;
|
||||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
|
||||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||||
@@ -2603,21 +2603,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
|
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
|
||||||
if (nai == null) break;
|
if (nai == null) break;
|
||||||
|
|
||||||
final boolean partialConnectivity =
|
final boolean wasPartial = nai.partialConnectivity;
|
||||||
(msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
|
nai.partialConnectivity = ((msg.arg1 & NETWORK_VALIDATION_RESULT_PARTIAL) != 0);
|
||||||
|| (nai.networkMisc.acceptPartialConnectivity
|
|
||||||
&& nai.partialConnectivity);
|
|
||||||
// Once a network is determined to have partial connectivity, it cannot
|
|
||||||
// go back to full connectivity without a disconnect. This is because
|
|
||||||
// NetworkMonitor can only communicate either PARTIAL_CONNECTIVITY or VALID,
|
|
||||||
// but not both.
|
|
||||||
// TODO: Provide multi-testResult to improve the communication between
|
|
||||||
// ConnectivityService and NetworkMonitor, so that ConnectivityService could
|
|
||||||
// know the real status of network.
|
|
||||||
final boolean partialConnectivityChanged =
|
final boolean partialConnectivityChanged =
|
||||||
(partialConnectivity && !nai.partialConnectivity);
|
(wasPartial != nai.partialConnectivity);
|
||||||
|
|
||||||
final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
|
final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0);
|
||||||
final boolean wasValidated = nai.lastValidated;
|
final boolean wasValidated = nai.lastValidated;
|
||||||
final boolean wasDefault = isDefaultNetwork(nai);
|
final boolean wasDefault = isDefaultNetwork(nai);
|
||||||
if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified
|
if (nai.everCaptivePortalDetected && !nai.captivePortalLoginNotified
|
||||||
@@ -2647,21 +2638,23 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
|
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
handleFreshlyValidatedNetwork(nai);
|
handleFreshlyValidatedNetwork(nai);
|
||||||
// Clear NO_INTERNET and LOST_INTERNET notifications if network becomes
|
// Clear NO_INTERNET, PARTIAL_CONNECTIVITY and LOST_INTERNET
|
||||||
// valid.
|
// notifications if network becomes valid.
|
||||||
mNotifier.clearNotification(nai.network.netId,
|
mNotifier.clearNotification(nai.network.netId,
|
||||||
NotificationType.NO_INTERNET);
|
NotificationType.NO_INTERNET);
|
||||||
mNotifier.clearNotification(nai.network.netId,
|
mNotifier.clearNotification(nai.network.netId,
|
||||||
NotificationType.LOST_INTERNET);
|
NotificationType.LOST_INTERNET);
|
||||||
|
mNotifier.clearNotification(nai.network.netId,
|
||||||
|
NotificationType.PARTIAL_CONNECTIVITY);
|
||||||
}
|
}
|
||||||
} else if (partialConnectivityChanged) {
|
} else if (partialConnectivityChanged) {
|
||||||
nai.partialConnectivity = partialConnectivity;
|
|
||||||
updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
|
updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
|
||||||
}
|
}
|
||||||
updateInetCondition(nai);
|
updateInetCondition(nai);
|
||||||
// Let the NetworkAgent know the state of its network
|
// Let the NetworkAgent know the state of its network
|
||||||
Bundle redirectUrlBundle = new Bundle();
|
Bundle redirectUrlBundle = new Bundle();
|
||||||
redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
|
redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl);
|
||||||
|
// TODO: Evaluate to update partial connectivity to status to NetworkAgent.
|
||||||
nai.asyncChannel.sendMessage(
|
nai.asyncChannel.sendMessage(
|
||||||
NetworkAgent.CMD_REPORT_NETWORK_STATUS,
|
NetworkAgent.CMD_REPORT_NETWORK_STATUS,
|
||||||
(valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
|
(valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
|
||||||
@@ -3441,6 +3434,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
// Inform NetworkMonitor that partial connectivity is acceptable. This will likely
|
// Inform NetworkMonitor that partial connectivity is acceptable. This will likely
|
||||||
// result in a partial connectivity result which will be processed by
|
// result in a partial connectivity result which will be processed by
|
||||||
// maybeHandleNetworkMonitorMessage.
|
// maybeHandleNetworkMonitorMessage.
|
||||||
|
//
|
||||||
|
// TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
|
||||||
|
// per network. Therefore, NetworkMonitor may still do https probe.
|
||||||
try {
|
try {
|
||||||
nai.networkMonitor().setAcceptPartialConnectivity();
|
nai.networkMonitor().setAcceptPartialConnectivity();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
|
|||||||
@@ -30,9 +30,12 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
|
|||||||
import static android.net.ConnectivityManager.TYPE_NONE;
|
import static android.net.ConnectivityManager.TYPE_NONE;
|
||||||
import static android.net.ConnectivityManager.TYPE_VPN;
|
import static android.net.ConnectivityManager.TYPE_VPN;
|
||||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
|
||||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
|
||||||
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
|
||||||
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
|
||||||
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
|
||||||
|
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
||||||
@@ -443,6 +446,16 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class MockNetworkAgent {
|
private class MockNetworkAgent {
|
||||||
|
private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
|
||||||
|
| NETWORK_VALIDATION_PROBE_HTTP
|
||||||
|
| NETWORK_VALIDATION_PROBE_HTTPS;
|
||||||
|
private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE
|
||||||
|
| NETWORK_VALIDATION_RESULT_VALID;
|
||||||
|
private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE
|
||||||
|
| NETWORK_VALIDATION_PROBE_FALLBACK
|
||||||
|
| NETWORK_VALIDATION_RESULT_PARTIAL;
|
||||||
|
private static final int VALIDATION_RESULT_INVALID = 0;
|
||||||
|
|
||||||
private final INetworkMonitor mNetworkMonitor;
|
private final INetworkMonitor mNetworkMonitor;
|
||||||
private final NetworkInfo mNetworkInfo;
|
private final NetworkInfo mNetworkInfo;
|
||||||
private final NetworkCapabilities mNetworkCapabilities;
|
private final NetworkCapabilities mNetworkCapabilities;
|
||||||
@@ -460,17 +473,17 @@ public class ConnectivityServiceTest {
|
|||||||
private String mRedirectUrl;
|
private String mRedirectUrl;
|
||||||
|
|
||||||
private INetworkMonitorCallbacks mNmCallbacks;
|
private INetworkMonitorCallbacks mNmCallbacks;
|
||||||
private int mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
|
private int mNmValidationResult = VALIDATION_RESULT_BASE;
|
||||||
private String mNmValidationRedirectUrl = null;
|
private String mNmValidationRedirectUrl = null;
|
||||||
private boolean mNmProvNotificationRequested = false;
|
private boolean mNmProvNotificationRequested = false;
|
||||||
|
|
||||||
void setNetworkValid() {
|
void setNetworkValid() {
|
||||||
mNmValidationResult = NETWORK_TEST_RESULT_VALID;
|
mNmValidationResult = VALIDATION_RESULT_VALID;
|
||||||
mNmValidationRedirectUrl = null;
|
mNmValidationRedirectUrl = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNetworkInvalid() {
|
void setNetworkInvalid() {
|
||||||
mNmValidationResult = NETWORK_TEST_RESULT_INVALID;
|
mNmValidationResult = VALIDATION_RESULT_INVALID;
|
||||||
mNmValidationRedirectUrl = null;
|
mNmValidationRedirectUrl = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +493,12 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setNetworkPartial() {
|
void setNetworkPartial() {
|
||||||
mNmValidationResult = NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
|
mNmValidationResult = VALIDATION_RESULT_PARTIAL;
|
||||||
|
mNmValidationRedirectUrl = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNetworkPartialValid() {
|
||||||
|
mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
|
||||||
mNmValidationRedirectUrl = null;
|
mNmValidationRedirectUrl = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,7 +615,7 @@ public class ConnectivityServiceTest {
|
|||||||
private void onValidationRequested() {
|
private void onValidationRequested() {
|
||||||
try {
|
try {
|
||||||
if (mNmProvNotificationRequested
|
if (mNmProvNotificationRequested
|
||||||
&& mNmValidationResult == NETWORK_TEST_RESULT_VALID) {
|
&& mNmValidationResult == VALIDATION_RESULT_VALID) {
|
||||||
mNmCallbacks.hideProvisioningNotification();
|
mNmCallbacks.hideProvisioningNotification();
|
||||||
mNmProvNotificationRequested = false;
|
mNmProvNotificationRequested = false;
|
||||||
}
|
}
|
||||||
@@ -2651,7 +2669,7 @@ public class ConnectivityServiceTest {
|
|||||||
|
|
||||||
// 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.setNetworkValid();
|
mWiFiNetworkAgent.setNetworkPartialValid();
|
||||||
// If the user chooses yes to use this partial connectivity wifi, switch the default
|
// If the user chooses yes to use this partial connectivity wifi, switch the default
|
||||||
// network to wifi and check if wifi becomes valid or not.
|
// network to wifi and check if wifi becomes valid or not.
|
||||||
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
|
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
|
||||||
@@ -2748,6 +2766,54 @@ public class ConnectivityServiceTest {
|
|||||||
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
|
||||||
|
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
|
||||||
|
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
|
||||||
|
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
|
||||||
|
mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
|
||||||
|
|
||||||
|
final TestNetworkCallback validatedCallback = new TestNetworkCallback();
|
||||||
|
final NetworkRequest validatedRequest = new NetworkRequest.Builder()
|
||||||
|
.addCapability(NET_CAPABILITY_VALIDATED).build();
|
||||||
|
mCm.registerNetworkCallback(validatedRequest, validatedCallback);
|
||||||
|
|
||||||
|
// Bring up a network with a captive portal.
|
||||||
|
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
|
||||||
|
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
|
||||||
|
String firstRedirectUrl = "http://example.com/firstPath";
|
||||||
|
mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
|
||||||
|
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
|
||||||
|
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
|
||||||
|
|
||||||
|
// Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
|
||||||
|
mCm.startCaptivePortalApp(mWiFiNetworkAgent.getNetwork());
|
||||||
|
verify(mWiFiNetworkAgent.mNetworkMonitor, timeout(TIMEOUT_MS).times(1))
|
||||||
|
.launchCaptivePortalApp();
|
||||||
|
|
||||||
|
// Report that the captive portal is dismissed with partial connectivity, and check that
|
||||||
|
// callbacks are fired.
|
||||||
|
mWiFiNetworkAgent.setNetworkPartial();
|
||||||
|
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
|
||||||
|
waitForIdle();
|
||||||
|
captivePortalCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
|
||||||
|
mWiFiNetworkAgent);
|
||||||
|
|
||||||
|
// Report partial connectivity is accepted.
|
||||||
|
mWiFiNetworkAgent.setNetworkPartialValid();
|
||||||
|
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
|
||||||
|
false /* always */);
|
||||||
|
waitForIdle();
|
||||||
|
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
|
||||||
|
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
|
||||||
|
NetworkCapabilities nc =
|
||||||
|
validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
|
||||||
|
mWiFiNetworkAgent);
|
||||||
|
|
||||||
|
mCm.unregisterNetworkCallback(captivePortalCallback);
|
||||||
|
mCm.unregisterNetworkCallback(validatedCallback);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCaptivePortal() {
|
public void testCaptivePortal() {
|
||||||
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
|
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
|
||||||
|
|||||||
Reference in New Issue
Block a user