From d8a06089e7a94af53eb53ea12c5108954a53d381 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 28 Jun 2017 23:39:40 +0900 Subject: [PATCH 1/2] Update our user agent to something newer. Bug: 36532213 Test: aosp_bullhead-eng builds Change-Id: I4e3d832248a746c9fef5302a1eafbe66ade8ed25 --- .../java/com/android/server/connectivity/NetworkMonitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 66347e66314b4..0c86ad8e85512 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -95,7 +95,7 @@ public class NetworkMonitor extends StateMachine { "http://play.googleapis.com/generate_204"; private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " - + "Chrome/52.0.2743.82 Safari/537.36"; + + "Chrome/60.0.3112.32 Safari/537.36"; private static final int SOCKET_TIMEOUT_MS = 10000; private static final int PROBE_TIMEOUT_MS = 3000; From d8978acdd76ea262c1596df7501bae5706ae79b5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 28 Jun 2017 23:42:41 +0900 Subject: [PATCH 2/2] Only connect to one address per address family. This ensures probes don't take too long when a host has multiple addresses. So for example: $ adb shell settings put global captive_portal_http_url http://play.googleapis.com/generate_204 $ host play.googleapis.com play.googleapis.com is an alias for googleapis.l.google.com. googleapis.l.google.com has address 216.58.196.234 googleapis.l.google.com has address 216.58.197.10 googleapis.l.google.com has address 172.217.26.106 googleapis.l.google.com has address 172.217.27.170 googleapis.l.google.com has address 216.58.199.234 googleapis.l.google.com has address 216.58.221.170 googleapis.l.google.com has IPv6 address 2404:6800:400a:807::200a results in: 06-29 21:38:09.695 - PROBE_DNS play.googleapis.com 270ms OK 2404:6800:400a:806::200a,172.217.26.106 Bug: 36532213 Test: as described in commit description Change-Id: I6779a8356bac8d4a3912b0822379d45dfc662541 --- .../server/connectivity/NetworkMonitor.java | 50 +++++++++++++++---- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 0c86ad8e85512..56859e68e34fc 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -29,6 +29,7 @@ import android.content.IntentFilter; import android.net.CaptivePortal; import android.net.ConnectivityManager; import android.net.ICaptivePortal; +import android.net.Network; import android.net.NetworkRequest; import android.net.ProxyInfo; import android.net.TrafficStats; @@ -71,6 +72,9 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; @@ -228,6 +232,7 @@ public class NetworkMonitor extends StateMachine { private final Context mContext; private final Handler mConnectivityServiceHandler; private final NetworkAgentInfo mNetworkAgentInfo; + private final Network mNetwork; private final int mNetId; private final TelephonyManager mTelephonyManager; private final WifiManager mWifiManager; @@ -286,7 +291,8 @@ public class NetworkMonitor extends StateMachine { mMetricsLog = logger; mConnectivityServiceHandler = handler; mNetworkAgentInfo = networkAgentInfo; - mNetId = mNetworkAgentInfo.network.netId; + mNetwork = new OneAddressPerFamilyNetwork(networkAgentInfo.network); + mNetId = mNetwork.netId; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); @@ -415,7 +421,7 @@ public class NetworkMonitor extends StateMachine { maybeLogEvaluationResult( networkEventType(validationStage(), EvaluationResult.VALIDATED)); mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED, - NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null)); + NETWORK_TEST_RESULT_VALID, mNetId, null)); mValidations++; } @@ -440,7 +446,8 @@ public class NetworkMonitor extends StateMachine { case CMD_LAUNCH_CAPTIVE_PORTAL_APP: final Intent intent = new Intent( ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN); - intent.putExtra(ConnectivityManager.EXTRA_NETWORK, mNetworkAgentInfo.network); + // OneAddressPerFamilyNetwork is not parcelable across processes. + intent.putExtra(ConnectivityManager.EXTRA_NETWORK, new Network(mNetwork)); intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL, new CaptivePortal(new ICaptivePortal.Stub() { @Override @@ -468,8 +475,7 @@ public class NetworkMonitor extends StateMachine { @Override public void exit() { - Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0, - mNetworkAgentInfo.network.netId, null); + Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0, mNetId, null); mConnectivityServiceHandler.sendMessage(message); } } @@ -623,7 +629,7 @@ public class NetworkMonitor extends StateMachine { CustomIntentReceiver(String action, int token, int what) { mToken = token; mWhat = what; - mAction = action + "_" + mNetworkAgentInfo.network.netId + "_" + token; + mAction = action + "_" + mNetId + "_" + token; mContext.registerReceiver(this, new IntentFilter(mAction)); } public PendingIntent getPendingIntent() { @@ -659,8 +665,7 @@ public class NetworkMonitor extends StateMachine { CMD_LAUNCH_CAPTIVE_PORTAL_APP); } // Display the sign in notification. - Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1, - mNetworkAgentInfo.network.netId, + Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1, mNetId, mLaunchCaptivePortalAppBroadcastReceiver.getPendingIntent()); mConnectivityServiceHandler.sendMessage(message); // Retest for captive portal occasionally. @@ -675,6 +680,31 @@ public class NetworkMonitor extends StateMachine { } } + // Limits the list of IP addresses returned by getAllByName or tried by openConnection to at + // most one per address family. This ensures we only wait up to 20 seconds for TCP connections + // to complete, regardless of how many IP addresses a host has. + private static class OneAddressPerFamilyNetwork extends Network { + public OneAddressPerFamilyNetwork(Network network) { + super(network); + } + + @Override + public InetAddress[] getAllByName(String host) throws UnknownHostException { + List addrs = Arrays.asList(super.getAllByName(host)); + + // Ensure the address family of the first address is tried first. + LinkedHashMap addressByFamily = new LinkedHashMap<>(); + addressByFamily.put(addrs.get(0).getClass(), addrs.get(0)); + Collections.shuffle(addrs); + + for (InetAddress addr : addrs) { + addressByFamily.put(addr.getClass(), addr); + } + + return addressByFamily.values().toArray(new InetAddress[addressByFamily.size()]); + } + } + private static String getCaptivePortalServerHttpsUrl(Context context) { return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTPS_URL, DEFAULT_HTTPS_URL); } @@ -805,7 +835,7 @@ public class NetworkMonitor extends StateMachine { int result; String connectInfo; try { - InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host); + InetAddress[] addresses = mNetwork.getAllByName(host); StringBuffer buffer = new StringBuffer(); for (InetAddress address : addresses) { buffer.append(',').append(address.getHostAddress()); @@ -833,7 +863,7 @@ public class NetworkMonitor extends StateMachine { String redirectUrl = null; final Stopwatch probeTimer = new Stopwatch().start(); try { - urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url); + urlConnection = (HttpURLConnection) mNetwork.openConnection(url); urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC); urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS); urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);