diff options
author | Chiachang Wang <chiachangwang@google.com> | 2020-03-31 07:50:59 +0000 |
---|---|---|
committer | Chiachang Wang <chiachangwang@google.com> | 2020-04-01 02:37:56 +0000 |
commit | a64bb70602f3aed9921244affeec256858c1a763 (patch) | |
tree | 42fb6737299a7a3bc2a965625b32fef267b38831 | |
parent | 014f79a870a29dab1c963bd9df940e0b011fafab (diff) |
[MP01] Add configuration to support multiple probes
Add configuration to allow configuring multiple probe.
Bug: 139034276
Test: atest NetworkStackTests NetworkStackNextTests
Merged-In: Ib2c1d16d2088ef043cdc6f9cb323a9df552beefb
Change-Id: Ib2c1d16d2088ef043cdc6f9cb323a9df552beefb
-rw-r--r-- | res/values/config.xml | 4 | ||||
-rw-r--r-- | src/android/net/util/NetworkStackUtils.java | 23 | ||||
-rw-r--r-- | src/com/android/server/connectivity/NetworkMonitor.java | 103 |
3 files changed, 107 insertions, 23 deletions
diff --git a/res/values/config.xml b/res/values/config.xml index 13c9326..a2f3959 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -39,6 +39,10 @@ </string-array> <string-array name="config_captive_portal_fallback_probe_specs" translatable="false"> </string-array> + <string-array name="config_captive_portal_http_urls" translatable="false"> + </string-array> + <string-array name="config_captive_portal_https_urls" translatable="false"> + </string-array> <!-- Customized default DNS Servers address. --> <string-array name="config_default_dns_servers" translatable="false"> diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java index 9d913fc..bc41549 100644 --- a/src/android/net/util/NetworkStackUtils.java +++ b/src/android/net/util/NetworkStackUtils.java @@ -56,6 +56,18 @@ public class NetworkStackUtils { "captive_portal_other_fallback_urls"; /** + * A comma separated list of URLs used for captive portal detection in addition to the HTTP url + * associated with the CAPTIVE_PORTAL_HTTP_URL settings. + */ + public static final String CAPTIVE_PORTAL_OTHER_HTTP_URLS = "captive_portal_other_http_urls"; + + /** + * A comma separated list of URLs used for network validation. in addition to the HTTPS url + * associated with the CAPTIVE_PORTAL_HTTPS_URL settings. + */ + public static final String CAPTIVE_PORTAL_OTHER_HTTPS_URLS = "captive_portal_other_https_urls"; + + /** * Which User-Agent string to use in the header of the captive portal detection probes. * The User-Agent field is unset when this setting has no value (HttpUrlConnection default). */ @@ -112,6 +124,17 @@ public class NetworkStackUtils { public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; /** + * The default list of HTTP URLs to use for detecting captive portals. + */ + public static final String[] DEFAULT_CAPTIVE_PORTAL_HTTP_URLS = + new String [] {"http://connectivitycheck.gstatic.com/generate_204"}; + /** + * The default list of HTTPS URLs for network validation, to use for confirming internet + * connectivity. + */ + public static final String[] DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS = + new String [] {"https://www.google.com/generate_204"}; + /** * @deprecated Considering boolean experiment flag is likely to cause misconfiguration * particularly when NetworkStack module rolls back to previous version. It's * much safer to determine whether or not to enable one specific experimental diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java index fcdd507..6d5ab6e 100644 --- a/src/com/android/server/connectivity/NetworkMonitor.java +++ b/src/com/android/server/connectivity/NetworkMonitor.java @@ -63,8 +63,12 @@ import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_IGNORE; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS; +import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_HTTPS_URLS; +import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_HTTP_URLS; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USER_AGENT; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; +import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS; +import static android.net.util.NetworkStackUtils.DEFAULT_CAPTIVE_PORTAL_HTTP_URLS; import static android.net.util.NetworkStackUtils.DISMISS_PORTAL_IN_VALIDATED_NETWORK; import static android.net.util.NetworkStackUtils.isEmpty; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; @@ -359,9 +363,11 @@ public class NetworkMonitor extends StateMachine { private final TcpSocketTracker mTcpTracker; // Configuration values for captive portal detection probes. private final String mCaptivePortalUserAgent; - private final URL mCaptivePortalHttpsUrl; - private final URL mCaptivePortalHttpUrl; private final URL[] mCaptivePortalFallbackUrls; + @NonNull + private final URL[] mCaptivePortalHttpUrls; + @NonNull + private final URL[] mCaptivePortalHttpsUrls; @Nullable private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs; @@ -483,8 +489,8 @@ public class NetworkMonitor extends StateMachine { mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); mUseHttps = getUseHttpsValidation(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); - mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl()); - mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl()); + mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls(); + mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls(); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs(); mRandom = deps.getRandom(); @@ -1596,19 +1602,8 @@ public class NetworkMonitor extends StateMachine { try { final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL, null); - - final URL[] settingProviderUrls; - if (!TextUtils.isEmpty(firstUrl)) { - final String otherUrls = mDependencies.getDeviceConfigProperty( - NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, ""); - // otherUrls may be empty, but .split() ignores trailing empty strings - final String separator = ","; - final String[] urls = (firstUrl + separator + otherUrls).split(separator); - settingProviderUrls = convertStrings(urls, this::makeURL, new URL[0]); - } else { - settingProviderUrls = new URL[0]; - } - + final URL[] settingProviderUrls = + combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS); return getProbeUrlArrayConfig(settingProviderUrls, R.array.config_captive_portal_fallback_urls, R.array.default_captive_portal_fallback_urls, this::makeURL); @@ -1640,6 +1635,49 @@ public class NetworkMonitor extends StateMachine { } } + private URL[] makeCaptivePortalHttpsUrls() { + final String firstUrl = getCaptivePortalServerHttpsUrl(); + try { + final URL[] settingProviderUrls = + combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTPS_URLS); + return getProbeUrlArrayConfig(settingProviderUrls, + R.array.config_captive_portal_https_urls, + DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS, this::makeURL); + } catch (Exception e) { + // Don't let a misconfiguration bootloop the system. + Log.e(TAG, "Error parsing configured https URLs", e); + // Ensure URL aligned with legacy configuration. + return new URL[]{makeURL(firstUrl)}; + } + } + + private URL[] makeCaptivePortalHttpUrls() { + final String firstUrl = getCaptivePortalServerHttpUrl(); + try { + final URL[] settingProviderUrls = + combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTP_URLS); + return getProbeUrlArrayConfig(settingProviderUrls, + R.array.config_captive_portal_http_urls, + DEFAULT_CAPTIVE_PORTAL_HTTP_URLS, this::makeURL); + } catch (Exception e) { + // Don't let a misconfiguration bootloop the system. + Log.e(TAG, "Error parsing configured http URLs", e); + // Ensure URL aligned with legacy configuration. + return new URL[]{makeURL(firstUrl)}; + } + } + + private URL[] combineCaptivePortalUrls(final String firstUrl, final String name) { + if (TextUtils.isEmpty(firstUrl)) return new URL[0]; + + final String otherUrls = mDependencies.getDeviceConfigProperty( + NAMESPACE_CONNECTIVITY, name, ""); + // otherUrls may be empty, but .split() ignores trailing empty strings + final String separator = ","; + final String[] urls = (firstUrl + separator + otherUrls).split(separator); + return convertStrings(urls, this::makeURL, new URL[0]); + } + /** * Read a setting from a resource or the settings provider. * @@ -1680,6 +1718,24 @@ public class NetworkMonitor extends StateMachine { private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) { final Resources res = getContextByMccIfNoSimCardOrDefault().getResources(); + return getProbeUrlArrayConfig(providerValue, configResId, res.getStringArray(defaultResId), + resourceConverter); + } + + /** + * Get an array configuration from resources or the settings provider. + * + * <p>The configuration resource is prioritized, then the provider values, then the default + * resource values. + * @param providerValue Values obtained from the setting provider. + * @param configResId ID of the configuration resource. + * @param defaultConfig Values of default configuration. + * @param resourceConverter Converter from the resource strings to stored setting class. Null + * return values are ignored. + */ + private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, + String[] defaultConfig, @NonNull Function<String, T> resourceConverter) { + final Resources res = getContextByMccIfNoSimCardOrDefault().getResources(); String[] configValue = res.getStringArray(configResId); if (configValue.length == 0) { @@ -1687,7 +1743,7 @@ public class NetworkMonitor extends StateMachine { return providerValue; } - configValue = res.getStringArray(defaultResId); + configValue = defaultConfig; } return convertStrings(configValue, resourceConverter, Arrays.copyOf(providerValue, 0)); @@ -1748,8 +1804,8 @@ public class NetworkMonitor extends StateMachine { } URL pacUrl = null; - URL httpsUrl = mCaptivePortalHttpsUrl; - URL httpUrl = mCaptivePortalHttpUrl; + final URL[] httpsUrls = mCaptivePortalHttpsUrls; + final URL[] httpUrls = mCaptivePortalHttpUrls; // On networks with a PAC instead of fetching a URL that should result in a 204 // response, we instead simply fetch the PAC script. This is done for a few reasons: @@ -1776,7 +1832,8 @@ public class NetworkMonitor extends StateMachine { } } - if ((pacUrl == null) && (httpUrl == null || httpsUrl == null)) { + if ((pacUrl == null) && (httpUrls.length == 0 || httpsUrls.length == 0 + || httpUrls[0] == null || httpsUrls[0] == null)) { return CaptivePortalProbeResult.FAILED; } @@ -1788,9 +1845,9 @@ public class NetworkMonitor extends StateMachine { reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } else if (mUseHttps) { // Probe results are reported inside sendParallelHttpProbes. - result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl); + result = sendParallelHttpProbes(proxyInfo, httpsUrls[0], httpUrls[0]); } else { - result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); + result = sendDnsAndHttpProbes(proxyInfo, httpUrls[0], ValidationProbeEvent.PROBE_HTTP); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } |