diff options
| -rw-r--r-- | services/core/java/com/android/server/connectivity/NetworkMonitor.java | 50 |
1 files 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 0c86ad8e8551..56859e68e34f 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<InetAddress> addrs = Arrays.asList(super.getAllByName(host)); + + // Ensure the address family of the first address is tried first. + LinkedHashMap<Class, InetAddress> 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); |