diff options
| author | Robert Greenwalt <rgreenwalt@google.com> | 2010-09-14 09:18:02 -0700 |
|---|---|---|
| committer | Robert Greenwalt <rgreenwalt@google.com> | 2010-09-17 16:14:10 -0700 |
| commit | d192dad69e9e5a820c5c11d8cd34460c9cc2ed11 (patch) | |
| tree | c73984b5acaa497fa30f207ba2ed5fff8cdb8e9b /core/java/android | |
| parent | aca11c0cf401147a075f72f110e0e27336066127 (diff) | |
Enhance http proxy support
Make it read proxys the correct way from CS so it works for all network types.
Add utility class for apache http client support.
bug:2700664
Change-Id: If81917b19b5f0636247a6519a1ec78bd8dbf3596
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/net/ConnectivityManager.java | 18 | ||||
| -rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 5 | ||||
| -rw-r--r-- | core/java/android/net/Proxy.java | 226 |
3 files changed, 147 insertions, 102 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index b483f6cfdf1b..dd9c8f09bd16 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -264,6 +264,24 @@ public class ConnectivityManager } } + /** @hide */ + public LinkProperties getActiveLinkProperties() { + try { + return mService.getActiveLinkProperties(); + } catch (RemoteException e) { + return null; + } + } + + /** @hide */ + public LinkProperties getLinkProperties(int networkType) { + try { + return mService.getLinkProperties(networkType); + } catch (RemoteException e) { + return null; + } + } + /** {@hide} */ public boolean setRadios(boolean turnOn) { try { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 9f2fc17ae215..35054d6c4094 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -16,6 +16,7 @@ package android.net; +import android.net.LinkProperties; import android.net.NetworkInfo; import android.os.IBinder; @@ -36,6 +37,10 @@ interface IConnectivityManager NetworkInfo[] getAllNetworkInfo(); + LinkProperties getActiveLinkProperties(); + + LinkProperties getLinkProperties(int networkType); + boolean setRadios(boolean onOff); boolean setRadio(int networkType, boolean turnOn); diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java index 9c63cd9c33e5..830ff06b5c62 100644 --- a/core/java/android/net/Proxy.java +++ b/core/java/android/net/Proxy.java @@ -21,21 +21,31 @@ import android.content.Context; import android.database.ContentObserver; import android.os.Handler; import android.os.SystemProperties; +import android.text.TextUtils; import android.provider.Settings; +import android.util.Log; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; import java.net.UnknownHostException; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import junit.framework.Assert; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.conn.routing.HttpRoutePlanner; +import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.impl.conn.ProxySelectorRoutePlanner; +import org.apache.http.protocol.HttpContext; /** * A convenience class for accessing the user and default proxy @@ -57,6 +67,8 @@ public final class Proxy { private static ProxySpec sGlobalProxySpec = null; + private static ConnectivityManager sConnectivityManager = null; + // Hostname / IP REGEX validation // Matches blank input, ips, and domain names private static final String NAME_IP_REGEX = @@ -78,13 +90,15 @@ public final class Proxy { // useful because it holds the processed exclusion list - don't want to reparse it each time private static class ProxySpec { - String[] exclusionList = null; + String[] exclusionList; InetSocketAddress address = null; - public ProxySpec() { }; + public ProxySpec() { + exclusionList = new String[0]; + }; } - private static boolean isURLInExclusionListReadLocked(String url, String[] exclusionList) { - if (exclusionList == null) { + private static boolean isURLInExclusionList(String url, String[] exclusionList) { + if (url == null) { return false; } Uri u = Uri.parse(url); @@ -149,7 +163,7 @@ public final class Proxy { } if (sGlobalProxySpec != null) { // Proxy defined - Apply exclusion rules - if (isURLInExclusionListReadLocked(url, sGlobalProxySpec.exclusionList)) { + if (isURLInExclusionList(url, sGlobalProxySpec.exclusionList)) { // Return no proxy retval = java.net.Proxy.NO_PROXY; } else { @@ -157,13 +171,7 @@ public final class Proxy { new java.net.Proxy(java.net.Proxy.Type.HTTP, sGlobalProxySpec.address); } } else { - // If network is WiFi, return no proxy. - // Otherwise, return the Mobile Operator proxy. - if (!isNetworkWifi(ctx)) { - retval = getDefaultProxy(url); - } else { - retval = java.net.Proxy.NO_PROXY; - } + retval = getDefaultProxy(ctx, url); } } finally { sProxyInfoLock.readLock().unlock(); @@ -183,19 +191,12 @@ public final class Proxy { * host is to be used. */ public static final String getHost(Context ctx) { - sProxyInfoLock.readLock().lock(); + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return null; try { - if (sGlobalProxyChangedObserver == null) { - registerContentObserversReadLocked(ctx); - parseGlobalProxyInfoReadLocked(ctx); - } - if (sGlobalProxySpec != null) { - InetSocketAddress sa = sGlobalProxySpec.address; - return sa.getHostName(); - } - return getDefaultHost(); - } finally { - sProxyInfoLock.readLock().unlock(); + return ((InetSocketAddress)(proxy.address())).getHostName(); + } catch (Exception e) { + return null; } } @@ -206,19 +207,12 @@ public final class Proxy { * @return The port number to use or -1 if no proxy is to be used. */ public static final int getPort(Context ctx) { - sProxyInfoLock.readLock().lock(); + java.net.Proxy proxy = getProxy(ctx, null); + if (proxy == java.net.Proxy.NO_PROXY) return -1; try { - if (sGlobalProxyChangedObserver == null) { - registerContentObserversReadLocked(ctx); - parseGlobalProxyInfoReadLocked(ctx); - } - if (sGlobalProxySpec != null) { - InetSocketAddress sa = sGlobalProxySpec.address; - return sa.getPort(); - } - return getDefaultPort(); - } finally { - sProxyInfoLock.readLock().unlock(); + return ((InetSocketAddress)(proxy.address())).getPort(); + } catch (Exception e) { + return -1; } } @@ -229,14 +223,7 @@ public final class Proxy { * this carrier. */ public static final String getDefaultHost() { - String host = SystemProperties.get("net.gprs.http-proxy"); - if ((host != null) && (host.length() != 0)) { - Uri u = Uri.parse(host); - host = u.getHost(); - return host; - } else { - return null; - } + return null; } // TODO: deprecate this function @@ -246,26 +233,36 @@ public final class Proxy { * no proxy for this carrier. */ public static final int getDefaultPort() { - String host = SystemProperties.get("net.gprs.http-proxy"); - if ((host != null) && (host.length() != 0)) { - Uri u = Uri.parse(host); - return u.getPort(); - } else { - return -1; - } + return -1; } - private static final java.net.Proxy getDefaultProxy(String url) { - // TODO: This will go away when information is collected from ConnectivityManager... - // There are broadcast of network proxies, so they are parse manually. - String host = SystemProperties.get("net.gprs.http-proxy"); - if ((host != null) && (host.length() != 0)) { - Uri u = Uri.parse(host); - return new java.net.Proxy(java.net.Proxy.Type.HTTP, - new InetSocketAddress(u.getHost(), u.getPort())); - } else { - return java.net.Proxy.NO_PROXY; + // TODO - cache the details for each network so we don't have to fetch and parse + // on each request + private static final java.net.Proxy getDefaultProxy(Context context, String url) { + if (sConnectivityManager == null) { + sConnectivityManager = (ConnectivityManager)context.getSystemService( + Context.CONNECTIVITY_SERVICE); + } + if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY; + + LinkProperties linkProperties = sConnectivityManager.getActiveLinkProperties(); + + if (linkProperties != null) { + ProxyProperties proxyProperties = linkProperties.getHttpProxy(); + + if (proxyProperties != null) { + String exclusionList = proxyProperties.getExclusionList(); + SocketAddress socketAddr = proxyProperties.getSocketAddress(); + if (socketAddr != null) { + String[] parsedExclusionArray = + parsedExclusionArray = parseExclusionList(exclusionList); + if (!isURLInExclusionList(url, parsedExclusionArray)) { + return new java.net.Proxy(java.net.Proxy.Type.HTTP, socketAddr); + } + } + } } + return java.net.Proxy.NO_PROXY; } // TODO: remove this function / deprecate @@ -317,22 +314,6 @@ public final class Proxy { return false; } - private static final boolean isNetworkWifi(Context context) { - if (context == null) { - return false; - } - final ConnectivityManager connectivity = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivity != null) { - final NetworkInfo info = connectivity.getActiveNetworkInfo(); - if (info != null && - info.getType() == ConnectivityManager.TYPE_WIFI) { - return true; - } - } - return false; - } - private static class SettingsObserver extends ContentObserver { private Context mContext; @@ -376,7 +357,7 @@ public final class Proxy { String proxyHost = Settings.Secure.getString( contentResolver, Settings.Secure.HTTP_PROXY); - if ((proxyHost == null) || (proxyHost.length() == 0)) { + if (TextUtils.isEmpty(proxyHost)) { // Clear signal sProxyInfoLock.readLock().unlock(); sProxyInfoLock.writeLock().lock(); @@ -390,36 +371,35 @@ public final class Proxy { Settings.Secure.HTTP_PROXY_EXCLUSION_LIST); String host = parseHost(proxyHost); int port = parsePort(proxyHost); + ProxySpec tmpProxySpec = null; if (proxyHost != null) { - sGlobalProxySpec = new ProxySpec(); - sGlobalProxySpec.address= new InetSocketAddress(host, port); - if ((exclusionListSpec != null) && (exclusionListSpec.length() != 0)) { - String[] exclusionListEntries = exclusionListSpec.toLowerCase().split(","); - String[] processedEntries = new String[exclusionListEntries.length]; - for (int i = 0; i < exclusionListEntries.length; i++) { - String entry = exclusionListEntries[i].trim(); - if (entry.startsWith(".")) { - entry = entry.substring(1); - } - processedEntries[i] = entry; - } - sProxyInfoLock.readLock().unlock(); - sProxyInfoLock.writeLock().lock(); - sGlobalProxySpec.exclusionList = processedEntries; - } else { - sProxyInfoLock.readLock().unlock(); - sProxyInfoLock.writeLock().lock(); - sGlobalProxySpec.exclusionList = null; - } - } else { - sProxyInfoLock.readLock().unlock(); - sProxyInfoLock.writeLock().lock(); - sGlobalProxySpec = null; + tmpProxySpec = new ProxySpec(); + tmpProxySpec.address = new InetSocketAddress(host, port); + tmpProxySpec.exclusionList = parseExclusionList(exclusionListSpec); } + sProxyInfoLock.readLock().unlock(); + sProxyInfoLock.writeLock().lock(); + sGlobalProxySpec = tmpProxySpec; sProxyInfoLock.readLock().lock(); sProxyInfoLock.writeLock().unlock(); } + private static String[] parseExclusionList(String exclusionList) { + String[] processedArray = new String[0]; + if (!TextUtils.isEmpty(exclusionList)) { + String[] exclusionListArray = exclusionList.toLowerCase().split(","); + processedArray = new String[exclusionListArray.length]; + for (int i = 0; i < exclusionListArray.length; i++) { + String entry = exclusionListArray[i].trim(); + if (entry.startsWith(".")) { + entry = entry.substring(1); + } + processedArray[i] = entry; + } + } + return processedArray; + } + /** * Validate syntax of hostname, port and exclusion list entries * {@hide} @@ -455,4 +435,46 @@ public final class Proxy { } } } + + static class AndroidProxySelectorRoutePlanner + extends org.apache.http.impl.conn.ProxySelectorRoutePlanner { + + private Context mContext; + + public AndroidProxySelectorRoutePlanner(SchemeRegistry schreg, ProxySelector prosel, + Context context) { + super(schreg, prosel); + mContext = context; + } + + @Override + protected java.net.Proxy chooseProxy(List<java.net.Proxy> proxies, HttpHost target, + HttpRequest request, HttpContext context) { + return getProxy(mContext, target.getHostName()); + } + + @Override + protected HttpHost determineProxy(HttpHost target, HttpRequest request, + HttpContext context) { + return getPreferredHttpHost(mContext, target.getHostName()); + } + + @Override + public HttpRoute determineRoute(HttpHost target, HttpRequest request, + HttpContext context) { + HttpHost proxy = getPreferredHttpHost(mContext, target.getHostName()); + if (proxy == null) { + return new HttpRoute(target); + } else { + return new HttpRoute(target, null, proxy, false); + } + } + } + + /** @hide */ + public static final HttpRoutePlanner getAndroidProxySelectorRoutePlanner(Context context) { + AndroidProxySelectorRoutePlanner ret = new AndroidProxySelectorRoutePlanner( + new SchemeRegistry(), ProxySelector.getDefault(), context); + return ret; + } } |
