Merge commit 'bac61807d3bcfff957b358cb9ad77850bd373689' into HEAD
Change-Id: I29374270c8e0c2f2859efaf1d55af9f73da0f8d7
This commit is contained in:
@@ -140,6 +140,7 @@ public class ProxyProperties implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
|
if (!TextUtils.isEmpty(mPacFileUrl)) return true;
|
||||||
try {
|
try {
|
||||||
Proxy.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort),
|
Proxy.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort),
|
||||||
mExclusionList == null ? "" : mExclusionList);
|
mExclusionList == null ? "" : mExclusionList);
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ import android.net.wifi.WifiStateTracker;
|
|||||||
import android.net.wimax.WimaxManagerConstants;
|
import android.net.wimax.WimaxManagerConstants;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.FileUtils;
|
import android.os.FileUtils;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
@@ -141,6 +142,7 @@ import java.net.Inet4Address;
|
|||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -154,6 +156,10 @@ import java.util.Random;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -3454,7 +3460,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
synchronized (mProxyLock) {
|
synchronized (mProxyLock) {
|
||||||
if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
|
if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
|
||||||
if (mDefaultProxy == proxy) return; // catches repeated nulls
|
if (mDefaultProxy == proxy) return; // catches repeated nulls
|
||||||
if (!proxy.isValid()) {
|
if (proxy != null && !proxy.isValid()) {
|
||||||
if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
|
if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4083,8 +4089,28 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
static class CheckMp extends
|
static class CheckMp extends
|
||||||
AsyncTask<CheckMp.Params, Void, Integer> {
|
AsyncTask<CheckMp.Params, Void, Integer> {
|
||||||
private static final String CHECKMP_TAG = "CheckMp";
|
private static final String CHECKMP_TAG = "CheckMp";
|
||||||
|
|
||||||
|
// adb shell setprop persist.checkmp.testfailures 1 to enable testing failures
|
||||||
|
private static boolean mTestingFailures;
|
||||||
|
|
||||||
|
// Choosing 4 loops as half of them will use HTTPS and the other half HTTP
|
||||||
|
private static final int MAX_LOOPS = 4;
|
||||||
|
|
||||||
|
// Number of milli-seconds to complete all of the retires
|
||||||
public static final int MAX_TIMEOUT_MS = 60000;
|
public static final int MAX_TIMEOUT_MS = 60000;
|
||||||
|
|
||||||
|
// The socket should retry only 5 seconds, the default is longer
|
||||||
private static final int SOCKET_TIMEOUT_MS = 5000;
|
private static final int SOCKET_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
|
// Sleep time for network errors
|
||||||
|
private static final int NET_ERROR_SLEEP_SEC = 3;
|
||||||
|
|
||||||
|
// Sleep time for network route establishment
|
||||||
|
private static final int NET_ROUTE_ESTABLISHMENT_SLEEP_SEC = 3;
|
||||||
|
|
||||||
|
// Short sleep time for polling :(
|
||||||
|
private static final int POLLING_SLEEP_SEC = 1;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ConnectivityService mCs;
|
private ConnectivityService mCs;
|
||||||
private TelephonyManager mTm;
|
private TelephonyManager mTm;
|
||||||
@@ -4110,6 +4136,31 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As explained to me by Brian Carlstrom and Kenny Root, Certificates can be
|
||||||
|
// issued by name or ip address, for Google its by name so when we construct
|
||||||
|
// this HostnameVerifier we'll pass the original Uri and use it to verify
|
||||||
|
// the host. If the host name in the original uril fails we'll test the
|
||||||
|
// hostname parameter just incase things change.
|
||||||
|
static class CheckMpHostnameVerifier implements HostnameVerifier {
|
||||||
|
Uri mOrgUri;
|
||||||
|
|
||||||
|
CheckMpHostnameVerifier(Uri orgUri) {
|
||||||
|
mOrgUri = orgUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(String hostname, SSLSession session) {
|
||||||
|
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
|
||||||
|
String orgUriHost = mOrgUri.getHost();
|
||||||
|
boolean retVal = hv.verify(orgUriHost, session) || hv.verify(hostname, session);
|
||||||
|
if (DBG) {
|
||||||
|
log("isMobileOk: hostnameVerify retVal=" + retVal + " hostname=" + hostname
|
||||||
|
+ " orgUriHost=" + orgUriHost);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The call back object passed in Params. onComplete will be called
|
* The call back object passed in Params. onComplete will be called
|
||||||
* on the main thread.
|
* on the main thread.
|
||||||
@@ -4120,6 +4171,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CheckMp(Context context, ConnectivityService cs) {
|
public CheckMp(Context context, ConnectivityService cs) {
|
||||||
|
if (Build.IS_DEBUGGABLE) {
|
||||||
|
mTestingFailures =
|
||||||
|
SystemProperties.getInt("persist.checkmp.testfailures", 0) == 1;
|
||||||
|
} else {
|
||||||
|
mTestingFailures = false;
|
||||||
|
}
|
||||||
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mCs = cs;
|
mCs = cs;
|
||||||
|
|
||||||
@@ -4191,7 +4249,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
|
mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sleep(1);
|
sleep(POLLING_SLEEP_SEC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4209,7 +4267,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
if (VDBG) log("isMobileOk: hipri not started yet");
|
if (VDBG) log("isMobileOk: hipri not started yet");
|
||||||
result = CMP_RESULT_CODE_NO_CONNECTION;
|
result = CMP_RESULT_CODE_NO_CONNECTION;
|
||||||
sleep(1);
|
sleep(POLLING_SLEEP_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue trying to connect until time has run out
|
// Continue trying to connect until time has run out
|
||||||
@@ -4225,7 +4283,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
log("isMobileOk: not connected ni=" +
|
log("isMobileOk: not connected ni=" +
|
||||||
mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
|
mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
|
||||||
}
|
}
|
||||||
sleep(1);
|
sleep(POLLING_SLEEP_SEC);
|
||||||
result = CMP_RESULT_CODE_NO_CONNECTION;
|
result = CMP_RESULT_CODE_NO_CONNECTION;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -4243,7 +4301,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
|
|
||||||
// Get of the addresses associated with the url host. We need to use the
|
// Get of the addresses associated with the url host. We need to use the
|
||||||
// address otherwise HttpURLConnection object will use the name to get
|
// address otherwise HttpURLConnection object will use the name to get
|
||||||
// the addresses and is will try every address but that will bypass the
|
// the addresses and will try every address but that will bypass the
|
||||||
// route to host we setup and the connection could succeed as the default
|
// route to host we setup and the connection could succeed as the default
|
||||||
// interface might be connected to the internet via wifi or other interface.
|
// interface might be connected to the internet via wifi or other interface.
|
||||||
InetAddress[] addresses;
|
InetAddress[] addresses;
|
||||||
@@ -4280,14 +4338,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
|
|
||||||
int addrTried = 0;
|
int addrTried = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
// Loop through at most 3 valid addresses or until
|
// Loop through at most MAX_LOOPS valid addresses or until
|
||||||
// we run out of time
|
// we run out of time
|
||||||
if (addrTried++ >= 3) {
|
if (addrTried++ >= MAX_LOOPS) {
|
||||||
log("too many loops tried - giving up");
|
log("isMobileOk: too many loops tried - giving up");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SystemClock.elapsedRealtime() >= endTime) {
|
if (SystemClock.elapsedRealtime() >= endTime) {
|
||||||
log("spend too much time - giving up");
|
log("isMobileOk: spend too much time - giving up");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4300,25 +4358,37 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
// Wait a short time to be sure the route is established ??
|
// Wait a short time to be sure the route is established ??
|
||||||
log("isMobileOk:"
|
log("isMobileOk:"
|
||||||
+ " wait to establish route to hostAddr=" + hostAddr);
|
+ " wait to establish route to hostAddr=" + hostAddr);
|
||||||
sleep(3);
|
sleep(NET_ROUTE_ESTABLISHMENT_SLEEP_SEC);
|
||||||
} else {
|
} else {
|
||||||
log("isMobileOk:"
|
log("isMobileOk:"
|
||||||
+ " could not establish route to hostAddr=" + hostAddr);
|
+ " could not establish route to hostAddr=" + hostAddr);
|
||||||
|
// Wait a short time before the next attempt
|
||||||
|
sleep(NET_ERROR_SLEEP_SEC);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite the url to have numeric address to use the specific route.
|
// Rewrite the url to have numeric address to use the specific route
|
||||||
// Add a pointless random query param to fool proxies into not caching.
|
// using http for half the attempts and https for the other half.
|
||||||
URL newUrl = new URL(orgUri.getScheme(),
|
// Doing https first and http second as on a redirected walled garden
|
||||||
hostAddr.getHostAddress(),
|
// such as t-mobile uses we get a SocketTimeoutException: "SSL
|
||||||
orgUri.getPath() + "?q=" + rand.nextInt(Integer.MAX_VALUE));
|
// handshake timed out" which we declare as
|
||||||
|
// CMP_RESULT_CODE_NO_TCP_CONNECTION. We could change this, but by
|
||||||
|
// having http second we will be using logic used for some time.
|
||||||
|
URL newUrl;
|
||||||
|
String scheme = (addrTried <= (MAX_LOOPS/2)) ? "https" : "http";
|
||||||
|
newUrl = new URL(scheme, hostAddr.getHostAddress(),
|
||||||
|
orgUri.getPath());
|
||||||
log("isMobileOk: newUrl=" + newUrl);
|
log("isMobileOk: newUrl=" + newUrl);
|
||||||
|
|
||||||
HttpURLConnection urlConn = null;
|
HttpURLConnection urlConn = null;
|
||||||
try {
|
try {
|
||||||
// Open the connection set the request header and get the response
|
// Open the connection set the request headers and get the response
|
||||||
urlConn = (HttpURLConnection) newUrl.openConnection(
|
urlConn = (HttpURLConnection)newUrl.openConnection(
|
||||||
java.net.Proxy.NO_PROXY);
|
java.net.Proxy.NO_PROXY);
|
||||||
|
if (scheme.equals("https")) {
|
||||||
|
((HttpsURLConnection)urlConn).setHostnameVerifier(
|
||||||
|
new CheckMpHostnameVerifier(orgUri));
|
||||||
|
}
|
||||||
urlConn.setInstanceFollowRedirects(false);
|
urlConn.setInstanceFollowRedirects(false);
|
||||||
urlConn.setConnectTimeout(SOCKET_TIMEOUT_MS);
|
urlConn.setConnectTimeout(SOCKET_TIMEOUT_MS);
|
||||||
urlConn.setReadTimeout(SOCKET_TIMEOUT_MS);
|
urlConn.setReadTimeout(SOCKET_TIMEOUT_MS);
|
||||||
@@ -4337,10 +4407,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
urlConn.disconnect();
|
urlConn.disconnect();
|
||||||
urlConn = null;
|
urlConn = null;
|
||||||
|
|
||||||
|
if (mTestingFailures) {
|
||||||
|
// Pretend no connection, this tests using http and https
|
||||||
|
result = CMP_RESULT_CODE_NO_CONNECTION;
|
||||||
|
log("isMobileOk: TESTING_FAILURES, pretend no connction");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (responseCode == 204) {
|
if (responseCode == 204) {
|
||||||
// Return
|
// Return
|
||||||
result = CMP_RESULT_CODE_CONNECTABLE;
|
result = CMP_RESULT_CODE_CONNECTABLE;
|
||||||
log("isMobileOk: X expected responseCode=" + responseCode
|
log("isMobileOk: X got expected responseCode=" + responseCode
|
||||||
+ " result=" + result);
|
+ " result=" + result);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@@ -4354,12 +4431,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
result = CMP_RESULT_CODE_REDIRECTED;
|
result = CMP_RESULT_CODE_REDIRECTED;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log("isMobileOk: HttpURLConnection Exception e=" + e);
|
log("isMobileOk: HttpURLConnection Exception" + e);
|
||||||
result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
|
result = CMP_RESULT_CODE_NO_TCP_CONNECTION;
|
||||||
if (urlConn != null) {
|
if (urlConn != null) {
|
||||||
urlConn.disconnect();
|
urlConn.disconnect();
|
||||||
urlConn = null;
|
urlConn = null;
|
||||||
}
|
}
|
||||||
|
sleep(NET_ERROR_SLEEP_SEC);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log("isMobileOk: X loops|timed out result=" + result);
|
log("isMobileOk: X loops|timed out result=" + result);
|
||||||
@@ -4387,7 +4466,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
log("isMobileOk: connected ni=" +
|
log("isMobileOk: connected ni=" +
|
||||||
mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
|
mCs.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI));
|
||||||
}
|
}
|
||||||
sleep(1);
|
sleep(POLLING_SLEEP_SEC);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4452,7 +4531,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void log(String s) {
|
private static void log(String s) {
|
||||||
Slog.d(ConnectivityService.TAG, "[" + CHECKMP_TAG + "] " + s);
|
Slog.d(ConnectivityService.TAG, "[" + CHECKMP_TAG + "] " + s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4484,8 +4563,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
mdst.enableMobileProvisioning(url);
|
mdst.enableMobileProvisioning(url);
|
||||||
} else {
|
} else {
|
||||||
if (DBG) log("handleMobileProvisioningAction: on default network");
|
if (DBG) log("handleMobileProvisioningAction: on default network");
|
||||||
Intent newIntent =
|
Intent newIntent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN,
|
||||||
new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
Intent.CATEGORY_APP_BROWSER);
|
||||||
|
newIntent.setData(Uri.parse(url));
|
||||||
newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
|
newIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
|
||||||
Intent.FLAG_ACTIVITY_NEW_TASK);
|
Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user