Loading res/values/config.xml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -39,6 +39,10 @@ </string-array> </string-array> <string-array name="config_captive_portal_fallback_probe_specs" translatable="false"> <string-array name="config_captive_portal_fallback_probe_specs" translatable="false"> </string-array> </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. --> <!-- Customized default DNS Servers address. --> <string-array name="config_default_dns_servers" translatable="false"> <string-array name="config_default_dns_servers" translatable="false"> Loading res/values/overlayable.xml +2 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ <item type="integer" name="config_captive_portal_dns_probe_timeout"/> <item type="integer" name="config_captive_portal_dns_probe_timeout"/> <item type="string" name="config_captive_portal_http_url"/> <item type="string" name="config_captive_portal_http_url"/> <item type="string" name="config_captive_portal_https_url"/> <item type="string" name="config_captive_portal_https_url"/> <item type="array" name="config_captive_portal_http_urls"/> <item type="array" name="config_captive_portal_https_urls"/> <item type="array" name="config_captive_portal_fallback_urls"/> <item type="array" name="config_captive_portal_fallback_urls"/> <item type="bool" name="config_no_sim_card_uses_neighbor_mcc"/> <item type="bool" name="config_no_sim_card_uses_neighbor_mcc"/> <!-- Configuration value for DhcpResults --> <!-- Configuration value for DhcpResults --> Loading src/android/net/util/NetworkStackUtils.java +23 −0 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,18 @@ public class NetworkStackUtils { public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls"; "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. * 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). * The User-Agent field is unset when this setting has no value (HttpUrlConnection default). Loading Loading @@ -111,6 +123,17 @@ public class NetworkStackUtils { */ */ public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; 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 * @deprecated Considering boolean experiment flag is likely to cause misconfiguration * particularly when NetworkStack module rolls back to previous version. It's * particularly when NetworkStack module rolls back to previous version. It's Loading src/com/android/server/connectivity/NetworkMonitor.java +80 −23 Original line number Original line Diff line number Diff line Loading @@ -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_IGNORE; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT; 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_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_USER_AGENT; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; 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.DISMISS_PORTAL_IN_VALIDATED_NETWORK; import static android.net.util.NetworkStackUtils.isEmpty; import static android.net.util.NetworkStackUtils.isEmpty; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; Loading Loading @@ -358,9 +362,11 @@ public class NetworkMonitor extends StateMachine { private final TcpSocketTracker mTcpTracker; private final TcpSocketTracker mTcpTracker; // Configuration values for captive portal detection probes. // Configuration values for captive portal detection probes. private final String mCaptivePortalUserAgent; private final String mCaptivePortalUserAgent; private final URL mCaptivePortalHttpsUrl; private final URL mCaptivePortalHttpUrl; private final URL[] mCaptivePortalFallbackUrls; private final URL[] mCaptivePortalFallbackUrls; @NonNull private final URL[] mCaptivePortalHttpUrls; @NonNull private final URL[] mCaptivePortalHttpsUrls; @Nullable @Nullable private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs; private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs; Loading Loading @@ -480,8 +486,8 @@ public class NetworkMonitor extends StateMachine { mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); mUseHttps = getUseHttpsValidation(); mUseHttps = getUseHttpsValidation(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl()); mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls(); mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl()); mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls(); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs(); mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs(); mRandom = deps.getRandom(); mRandom = deps.getRandom(); Loading Loading @@ -1594,19 +1600,8 @@ public class NetworkMonitor extends StateMachine { try { try { final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL, final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL, null); null); final URL[] settingProviderUrls = final URL[] settingProviderUrls; combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS); 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]; } return getProbeUrlArrayConfig(settingProviderUrls, return getProbeUrlArrayConfig(settingProviderUrls, R.array.config_captive_portal_fallback_urls, R.array.config_captive_portal_fallback_urls, R.array.default_captive_portal_fallback_urls, this::makeURL); R.array.default_captive_portal_fallback_urls, this::makeURL); Loading Loading @@ -1638,6 +1633,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. * Read a setting from a resource or the settings provider. * * Loading Loading @@ -1678,6 +1716,24 @@ public class NetworkMonitor extends StateMachine { private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) { @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) { final Resources res = getContextByMccIfNoSimCardOrDefault().getResources(); 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); String[] configValue = res.getStringArray(configResId); if (configValue.length == 0) { if (configValue.length == 0) { Loading @@ -1685,7 +1741,7 @@ public class NetworkMonitor extends StateMachine { return providerValue; return providerValue; } } configValue = res.getStringArray(defaultResId); configValue = defaultConfig; } } return convertStrings(configValue, resourceConverter, Arrays.copyOf(providerValue, 0)); return convertStrings(configValue, resourceConverter, Arrays.copyOf(providerValue, 0)); Loading Loading @@ -1746,8 +1802,8 @@ public class NetworkMonitor extends StateMachine { } } URL pacUrl = null; URL pacUrl = null; URL httpsUrl = mCaptivePortalHttpsUrl; final URL[] httpsUrls = mCaptivePortalHttpsUrls; URL httpUrl = mCaptivePortalHttpUrl; final URL[] httpUrls = mCaptivePortalHttpUrls; // On networks with a PAC instead of fetching a URL that should result in a 204 // 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: // response, we instead simply fetch the PAC script. This is done for a few reasons: Loading @@ -1774,7 +1830,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; return CaptivePortalProbeResult.FAILED; } } Loading @@ -1786,9 +1843,9 @@ public class NetworkMonitor extends StateMachine { reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } else if (mUseHttps) { } else if (mUseHttps) { // Probe results are reported inside sendParallelHttpProbes. // Probe results are reported inside sendParallelHttpProbes. result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl); result = sendParallelHttpProbes(proxyInfo, httpsUrls[0], httpUrls[0]); } else { } else { result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); result = sendDnsAndHttpProbes(proxyInfo, httpUrls[0], ValidationProbeEvent.PROBE_HTTP); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } } Loading tests/lib/src/com/android/testutils/NetworkStatsUtils.kt +22 −6 Original line number Original line Diff line number Diff line Loading @@ -29,16 +29,24 @@ fun orderInsensitiveEquals( if (compareTime && leftStats.getElapsedRealtime() != rightStats.getElapsedRealtime()) { if (compareTime && leftStats.getElapsedRealtime() != rightStats.getElapsedRealtime()) { return false return false } } if (leftStats.size() != rightStats.size()) return false // While operations such as add/subtract will preserve empty entries. This will make // the result be hard to verify during test. Remove them before comparing since they // are not really affect correctness. // TODO (b/152827872): Remove empty entries after addition/subtraction. val leftTrimmedEmpty = leftStats.removeEmptyEntries() val rightTrimmedEmpty = rightStats.removeEmptyEntries() if (leftTrimmedEmpty.size() != rightTrimmedEmpty.size()) return false val left = NetworkStats.Entry() val left = NetworkStats.Entry() val right = NetworkStats.Entry() val right = NetworkStats.Entry() // Order insensitive compare. // Order insensitive compare. for (i in 0 until leftStats.size()) { for (i in 0 until leftTrimmedEmpty.size()) { leftStats.getValues(i, left) leftTrimmedEmpty.getValues(i, left) val j: Int = rightStats.findIndexHinted(left.iface, left.uid, left.set, left.tag, val j: Int = rightTrimmedEmpty.findIndexHinted(left.iface, left.uid, left.set, left.tag, left.metered, left.roaming, left.defaultNetwork, i) left.metered, left.roaming, left.defaultNetwork, i) if (j == -1) return false if (j == -1) return false rightStats.getValues(j, right) rightTrimmedEmpty.getValues(j, right) if (left != right) return false if (left != right) return false } } return true return true Loading @@ -60,3 +68,11 @@ fun assertNetworkStatsEquals( assertTrue(orderInsensitiveEquals(expected, actual, compareTime), assertTrue(orderInsensitiveEquals(expected, actual, compareTime), "expected: " + expected + " but was: " + actual) "expected: " + expected + " but was: " + actual) } } /** * Assert that after being parceled then unparceled, {@link NetworkStats} is equal to the original * object. */ fun assertParcelingIsLossless(stats: NetworkStats) { assertParcelingIsLossless(stats, { a, b -> orderInsensitiveEquals(a, b) }) } Loading
res/values/config.xml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -39,6 +39,10 @@ </string-array> </string-array> <string-array name="config_captive_portal_fallback_probe_specs" translatable="false"> <string-array name="config_captive_portal_fallback_probe_specs" translatable="false"> </string-array> </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. --> <!-- Customized default DNS Servers address. --> <string-array name="config_default_dns_servers" translatable="false"> <string-array name="config_default_dns_servers" translatable="false"> Loading
res/values/overlayable.xml +2 −0 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ <item type="integer" name="config_captive_portal_dns_probe_timeout"/> <item type="integer" name="config_captive_portal_dns_probe_timeout"/> <item type="string" name="config_captive_portal_http_url"/> <item type="string" name="config_captive_portal_http_url"/> <item type="string" name="config_captive_portal_https_url"/> <item type="string" name="config_captive_portal_https_url"/> <item type="array" name="config_captive_portal_http_urls"/> <item type="array" name="config_captive_portal_https_urls"/> <item type="array" name="config_captive_portal_fallback_urls"/> <item type="array" name="config_captive_portal_fallback_urls"/> <item type="bool" name="config_no_sim_card_uses_neighbor_mcc"/> <item type="bool" name="config_no_sim_card_uses_neighbor_mcc"/> <!-- Configuration value for DhcpResults --> <!-- Configuration value for DhcpResults --> Loading
src/android/net/util/NetworkStackUtils.java +23 −0 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,18 @@ public class NetworkStackUtils { public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls"; "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. * 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). * The User-Agent field is unset when this setting has no value (HttpUrlConnection default). Loading Loading @@ -111,6 +123,17 @@ public class NetworkStackUtils { */ */ public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; 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 * @deprecated Considering boolean experiment flag is likely to cause misconfiguration * particularly when NetworkStack module rolls back to previous version. It's * particularly when NetworkStack module rolls back to previous version. It's Loading
src/com/android/server/connectivity/NetworkMonitor.java +80 −23 Original line number Original line Diff line number Diff line Loading @@ -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_IGNORE; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT; 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_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_USER_AGENT; import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS; 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.DISMISS_PORTAL_IN_VALIDATED_NETWORK; import static android.net.util.NetworkStackUtils.isEmpty; import static android.net.util.NetworkStackUtils.isEmpty; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; Loading Loading @@ -358,9 +362,11 @@ public class NetworkMonitor extends StateMachine { private final TcpSocketTracker mTcpTracker; private final TcpSocketTracker mTcpTracker; // Configuration values for captive portal detection probes. // Configuration values for captive portal detection probes. private final String mCaptivePortalUserAgent; private final String mCaptivePortalUserAgent; private final URL mCaptivePortalHttpsUrl; private final URL mCaptivePortalHttpUrl; private final URL[] mCaptivePortalFallbackUrls; private final URL[] mCaptivePortalFallbackUrls; @NonNull private final URL[] mCaptivePortalHttpUrls; @NonNull private final URL[] mCaptivePortalHttpsUrls; @Nullable @Nullable private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs; private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs; Loading Loading @@ -480,8 +486,8 @@ public class NetworkMonitor extends StateMachine { mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled(); mUseHttps = getUseHttpsValidation(); mUseHttps = getUseHttpsValidation(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); mCaptivePortalUserAgent = getCaptivePortalUserAgent(); mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl()); mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls(); mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl()); mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls(); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(); mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs(); mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs(); mRandom = deps.getRandom(); mRandom = deps.getRandom(); Loading Loading @@ -1594,19 +1600,8 @@ public class NetworkMonitor extends StateMachine { try { try { final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL, final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL, null); null); final URL[] settingProviderUrls = final URL[] settingProviderUrls; combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS); 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]; } return getProbeUrlArrayConfig(settingProviderUrls, return getProbeUrlArrayConfig(settingProviderUrls, R.array.config_captive_portal_fallback_urls, R.array.config_captive_portal_fallback_urls, R.array.default_captive_portal_fallback_urls, this::makeURL); R.array.default_captive_portal_fallback_urls, this::makeURL); Loading Loading @@ -1638,6 +1633,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. * Read a setting from a resource or the settings provider. * * Loading Loading @@ -1678,6 +1716,24 @@ public class NetworkMonitor extends StateMachine { private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId, @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) { @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) { final Resources res = getContextByMccIfNoSimCardOrDefault().getResources(); 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); String[] configValue = res.getStringArray(configResId); if (configValue.length == 0) { if (configValue.length == 0) { Loading @@ -1685,7 +1741,7 @@ public class NetworkMonitor extends StateMachine { return providerValue; return providerValue; } } configValue = res.getStringArray(defaultResId); configValue = defaultConfig; } } return convertStrings(configValue, resourceConverter, Arrays.copyOf(providerValue, 0)); return convertStrings(configValue, resourceConverter, Arrays.copyOf(providerValue, 0)); Loading Loading @@ -1746,8 +1802,8 @@ public class NetworkMonitor extends StateMachine { } } URL pacUrl = null; URL pacUrl = null; URL httpsUrl = mCaptivePortalHttpsUrl; final URL[] httpsUrls = mCaptivePortalHttpsUrls; URL httpUrl = mCaptivePortalHttpUrl; final URL[] httpUrls = mCaptivePortalHttpUrls; // On networks with a PAC instead of fetching a URL that should result in a 204 // 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: // response, we instead simply fetch the PAC script. This is done for a few reasons: Loading @@ -1774,7 +1830,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; return CaptivePortalProbeResult.FAILED; } } Loading @@ -1786,9 +1843,9 @@ public class NetworkMonitor extends StateMachine { reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } else if (mUseHttps) { } else if (mUseHttps) { // Probe results are reported inside sendParallelHttpProbes. // Probe results are reported inside sendParallelHttpProbes. result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl); result = sendParallelHttpProbes(proxyInfo, httpsUrls[0], httpUrls[0]); } else { } else { result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP); result = sendDnsAndHttpProbes(proxyInfo, httpUrls[0], ValidationProbeEvent.PROBE_HTTP); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, result); } } Loading
tests/lib/src/com/android/testutils/NetworkStatsUtils.kt +22 −6 Original line number Original line Diff line number Diff line Loading @@ -29,16 +29,24 @@ fun orderInsensitiveEquals( if (compareTime && leftStats.getElapsedRealtime() != rightStats.getElapsedRealtime()) { if (compareTime && leftStats.getElapsedRealtime() != rightStats.getElapsedRealtime()) { return false return false } } if (leftStats.size() != rightStats.size()) return false // While operations such as add/subtract will preserve empty entries. This will make // the result be hard to verify during test. Remove them before comparing since they // are not really affect correctness. // TODO (b/152827872): Remove empty entries after addition/subtraction. val leftTrimmedEmpty = leftStats.removeEmptyEntries() val rightTrimmedEmpty = rightStats.removeEmptyEntries() if (leftTrimmedEmpty.size() != rightTrimmedEmpty.size()) return false val left = NetworkStats.Entry() val left = NetworkStats.Entry() val right = NetworkStats.Entry() val right = NetworkStats.Entry() // Order insensitive compare. // Order insensitive compare. for (i in 0 until leftStats.size()) { for (i in 0 until leftTrimmedEmpty.size()) { leftStats.getValues(i, left) leftTrimmedEmpty.getValues(i, left) val j: Int = rightStats.findIndexHinted(left.iface, left.uid, left.set, left.tag, val j: Int = rightTrimmedEmpty.findIndexHinted(left.iface, left.uid, left.set, left.tag, left.metered, left.roaming, left.defaultNetwork, i) left.metered, left.roaming, left.defaultNetwork, i) if (j == -1) return false if (j == -1) return false rightStats.getValues(j, right) rightTrimmedEmpty.getValues(j, right) if (left != right) return false if (left != right) return false } } return true return true Loading @@ -60,3 +68,11 @@ fun assertNetworkStatsEquals( assertTrue(orderInsensitiveEquals(expected, actual, compareTime), assertTrue(orderInsensitiveEquals(expected, actual, compareTime), "expected: " + expected + " but was: " + actual) "expected: " + expected + " but was: " + actual) } } /** * Assert that after being parceled then unparceled, {@link NetworkStats} is equal to the original * object. */ fun assertParcelingIsLossless(stats: NetworkStats) { assertParcelingIsLossless(stats, { a, b -> orderInsensitiveEquals(a, b) }) }