summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Greenwalt <rgreenwalt@google.com>2010-10-11 16:00:27 -0700
committerRobert Greenwalt <rgreenwalt@google.com>2010-11-19 10:24:30 -0800
commit434203a277cd2f237a71508a3d5a7d1602126cd5 (patch)
tree2981f403196d1df7f2ec322a89a4dac1342d86de
parent5af53d4363342b383fd1e4439b5a2c71a47c593d (diff)
downloadframeworks_base-434203a277cd2f237a71508a3d5a7d1602126cd5.zip
frameworks_base-434203a277cd2f237a71508a3d5a7d1602126cd5.tar.gz
frameworks_base-434203a277cd2f237a71508a3d5a7d1602126cd5.tar.bz2
Notify all VMs when proxy changes.
bug:2700664 Change-Id: I74cc6e0bd6e66847bf18f524ce851e3e9d2c4e87
-rw-r--r--core/java/android/app/ActivityThread.java19
-rw-r--r--core/java/android/app/ApplicationThreadNative.java23
-rw-r--r--core/java/android/app/IApplicationThread.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java35
-rw-r--r--core/java/android/net/IConnectivityManager.aidl7
-rw-r--r--core/java/android/net/Proxy.java286
-rw-r--r--core/java/android/net/ProxyProperties.aidl21
-rw-r--r--core/java/android/net/ProxyProperties.java142
-rw-r--r--core/java/android/provider/Settings.java19
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--services/java/com/android/server/ConnectivityService.java143
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java13
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java33
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java9
-rw-r--r--wifi/java/android/net/wifi/WifiConfigStore.java47
15 files changed, 498 insertions, 302 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3cead11..c0714e3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -42,6 +42,9 @@ import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.net.IConnectivityManager;
+import android.net.Proxy;
+import android.net.ProxyProperties;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
@@ -272,7 +275,7 @@ public final class ActivityThread {
super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
this.intent = intent;
}
-
+
Intent intent;
ActivityInfo info;
public String toString() {
@@ -592,6 +595,10 @@ public final class ActivityThread {
InetAddress.clearDnsCache();
}
+ public void setHttpProxy(String host, String port, String exclList) {
+ Proxy.setHttpProxySystemProperty(host, port, exclList);
+ }
+
public void processInBackground() {
mH.removeMessages(H.GC_WHEN_IDLE);
mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
@@ -3253,6 +3260,16 @@ public final class ActivityThread {
}
}
+ /**
+ * Initialize the default http proxy in this process for the reasons we set the time zone.
+ */
+ IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+ IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
+ try {
+ ProxyProperties proxyProperties = service.getProxy();
+ Proxy.setHttpProxySystemProperty(proxyProperties);
+ } catch (RemoteException e) {}
+
if (data.instrumentationName != null) {
ContextImpl appContext = new ContextImpl();
appContext.init(data.info, null, this);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index b19fb59..801c3f9 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -276,7 +276,7 @@ public abstract class ApplicationThreadNative extends Binder
requestThumbnail(b);
return true;
}
-
+
case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
@@ -297,12 +297,21 @@ public abstract class ApplicationThreadNative extends Binder
return true;
}
+ case SET_HTTP_PROXY_TRANSACTION: {
+ data.enforceInterface(IApplicationThread.descriptor);
+ final String proxy = data.readString();
+ final String port = data.readString();
+ final String exclList = data.readString();
+ setHttpProxy(proxy, port, exclList);
+ return true;
+ }
+
case PROCESS_IN_BACKGROUND_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
processInBackground();
return true;
}
-
+
case DUMP_SERVICE_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
ParcelFileDescriptor fd = data.readFileDescriptor();
@@ -758,6 +767,16 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
}
+ public void setHttpProxy(String proxy, String port, String exclList) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeString(proxy);
+ data.writeString(port);
+ data.writeString(exclList);
+ mRemote.transact(SET_HTTP_PROXY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+ data.recycle();
+ }
+
public void processInBackground() throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 830c702..eca84ef 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -88,6 +88,7 @@ public interface IApplicationThread extends IInterface {
void scheduleConfigurationChanged(Configuration config) throws RemoteException;
void updateTimeZone() throws RemoteException;
void clearDnsCache() throws RemoteException;
+ void setHttpProxy(String proxy, String port, String exclList) throws RemoteException;
void processInBackground() throws RemoteException;
void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args)
throws RemoteException;
@@ -148,4 +149,5 @@ public interface IApplicationThread extends IInterface {
int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
int CLEAR_DNS_CACHE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+37;
+ int SET_HTTP_PROXY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+38;
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index dd9c8f0..ecfa2c1 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -624,4 +624,39 @@ public class ConnectivityManager
} catch (RemoteException e) {
}
}
+
+ /**
+ * @param proxyProperties The definition for the new global http proxy
+ * {@hide}
+ */
+ public void setGlobalProxy(ProxyProperties p) {
+ try {
+ mService.setGlobalProxy(p);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * @return proxyProperties for the current global proxy
+ * {@hide}
+ */
+ public ProxyProperties getGlobalProxy() {
+ try {
+ return mService.getGlobalProxy();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * @return proxyProperties for the current proxy (global if set, network specific if not)
+ * {@hide}
+ */
+ public ProxyProperties getProxy() {
+ try {
+ return mService.getProxy();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 35054d6..70ab4f1 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@ package android.net;
import android.net.LinkProperties;
import android.net.NetworkInfo;
+import android.net.ProxyProperties;
import android.os.IBinder;
/**
@@ -85,4 +86,10 @@ interface IConnectivityManager
void requestNetworkTransitionWakelock(in String forWhom);
void reportInetCondition(int networkType, int percentage);
+
+ ProxyProperties getGlobalProxy();
+
+ void setGlobalProxy(in ProxyProperties p);
+
+ ProxyProperties getProxy();
}
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 21c485e..3b9b9fe 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -16,9 +16,12 @@
package android.net;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
+import android.net.ProxyProperties;
import android.os.Handler;
import android.os.SystemProperties;
import android.text.TextUtils;
@@ -55,17 +58,22 @@ public final class Proxy {
// Set to true to enable extra debugging.
private static final boolean DEBUG = false;
+ private static final String TAG = "Proxy";
- // Used to notify an app that's caching the default connection proxy
- // that either the default connection or its proxy has changed
- public static final String PROXY_CHANGE_ACTION =
- "android.intent.action.PROXY_CHANGE";
-
- private static ReadWriteLock sProxyInfoLock = new ReentrantReadWriteLock();
-
- private static SettingsObserver sGlobalProxyChangedObserver = null;
-
- private static ProxySpec sGlobalProxySpec = null;
+ /**
+ * Used to notify an app that's caching the default connection proxy
+ * that either the default connection or its proxy has changed.
+ * The intent will have the following extra value:</p>
+ * <ul>
+ * <li><em>EXTRA_PROXY_INFO</em> - The ProxyProperties for the proxy
+ * </ul>
+ *
+ * <p class="note">This is a protected intent that can only be sent by the system
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
+ /** {@hide} **/
+ public static final String EXTRA_PROXY_INFO = "proxy";
private static ConnectivityManager sConnectivityManager = null;
@@ -88,62 +96,6 @@ public final class Proxy {
EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
}
- // useful because it holds the processed exclusion list - don't want to reparse it each time
- private static class ProxySpec {
- String[] exclusionList;
- InetSocketAddress address = null;
- public ProxySpec() {
- exclusionList = new String[0];
- };
- }
-
- private static boolean isURLInExclusionList(String url, String[] exclusionList) {
- if (url == null) {
- return false;
- }
- Uri u = Uri.parse(url);
- String urlDomain = u.getHost();
- // If the domain is defined as ".android.com" or "android.com", we wish to match
- // http://android.com as well as http://xxx.android.com , but not
- // http://myandroid.com . This code works out the logic.
- for (String excludedDomain : exclusionList) {
- String dotDomain = "." + excludedDomain;
- if (urlDomain.equals(excludedDomain)) {
- return true;
- }
- if (urlDomain.endsWith(dotDomain)) {
- return true;
- }
- }
- // No match
- return false;
- }
-
- private static String parseHost(String proxySpec) {
- int i = proxySpec.indexOf(':');
- if (i == -1) {
- if (DEBUG) {
- Assert.assertTrue(proxySpec.length() == 0);
- }
- return null;
- }
- return proxySpec.substring(0, i);
- }
-
- private static int parsePort(String proxySpec) {
- int i = proxySpec.indexOf(':');
- if (i == -1) {
- if (DEBUG) {
- Assert.assertTrue(proxySpec.length() == 0);
- }
- return -1;
- }
- if (DEBUG) {
- Assert.assertTrue(i < proxySpec.length());
- }
- return Integer.parseInt(proxySpec.substring(i+1));
- }
-
/**
* Return the proxy object to be used for the URL given as parameter.
* @param ctx A Context used to get the settings for the proxy host.
@@ -154,34 +106,31 @@ public final class Proxy {
* {@hide}
*/
public static final java.net.Proxy getProxy(Context ctx, String url) {
- sProxyInfoLock.readLock().lock();
- java.net.Proxy retval;
- try {
- if (sGlobalProxyChangedObserver == null) {
- registerContentObserversReadLocked(ctx);
- parseGlobalProxyInfoReadLocked(ctx);
+ String host = "";
+ if (url != null) {
+ URI uri = URI.create(url);
+ host = uri.getHost();
+ }
+
+ if (!isLocalHost(host)) {
+ if (sConnectivityManager == null) {
+ sConnectivityManager = (ConnectivityManager)ctx.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
}
- if (sGlobalProxySpec != null) {
- // Proxy defined - Apply exclusion rules
- if (isURLInExclusionList(url, sGlobalProxySpec.exclusionList)) {
- // Return no proxy
- retval = java.net.Proxy.NO_PROXY;
- } else {
- retval =
- new java.net.Proxy(java.net.Proxy.Type.HTTP, sGlobalProxySpec.address);
+ if (sConnectivityManager == null) return java.net.Proxy.NO_PROXY;
+
+ ProxyProperties proxyProperties = sConnectivityManager.getProxy();
+
+ if (proxyProperties != null) {
+ if (!proxyProperties.isExcluded(host)) {
+ return proxyProperties.makeProxy();
}
- } else {
- retval = getDefaultProxy(ctx, url);
}
- } finally {
- sProxyInfoLock.readLock().unlock();
- }
- if ((retval != java.net.Proxy.NO_PROXY) && (isLocalHost(url))) {
- retval = java.net.Proxy.NO_PROXY;
}
- return retval;
+ return java.net.Proxy.NO_PROXY;
}
+
// TODO: deprecate this function
/**
* Return the proxy host set by the user.
@@ -236,35 +185,6 @@ public final class Proxy {
return -1;
}
- // 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
/**
* Returns the preferred proxy to be used by clients. This is a wrapper
@@ -291,13 +211,11 @@ public final class Proxy {
}
}
- private static final boolean isLocalHost(String url) {
- if (url == null) {
+ private static final boolean isLocalHost(String host) {
+ if (host == null) {
return false;
}
try {
- final URI uri = URI.create(url);
- final String host = uri.getHost();
if (host != null) {
if (host.equalsIgnoreCase("localhost")) {
return true;
@@ -317,92 +235,6 @@ public final class Proxy {
return false;
}
- private static class SettingsObserver extends ContentObserver {
-
- private Context mContext;
-
- SettingsObserver(Context ctx) {
- super(new Handler(ctx.getMainLooper()));
- mContext = ctx;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- sProxyInfoLock.readLock().lock();
- parseGlobalProxyInfoReadLocked(mContext);
- sProxyInfoLock.readLock().unlock();
- }
- }
-
- private static final void registerContentObserversReadLocked(Context ctx) {
- Uri uriGlobalProxy = Settings.Secure.getUriFor(Settings.Secure.HTTP_PROXY);
- Uri uriGlobalExclList =
- Settings.Secure.getUriFor(Settings.Secure.HTTP_PROXY_EXCLUSION_LIST);
-
- // No lock upgrading (from read to write) allowed
- sProxyInfoLock.readLock().unlock();
- sProxyInfoLock.writeLock().lock();
- try {
- sGlobalProxyChangedObserver = new SettingsObserver(ctx);
- } finally {
- // Downgrading locks (from write to read) is allowed
- sProxyInfoLock.readLock().lock();
- sProxyInfoLock.writeLock().unlock();
- }
- ctx.getContentResolver().registerContentObserver(uriGlobalProxy, false,
- sGlobalProxyChangedObserver);
- ctx.getContentResolver().registerContentObserver(uriGlobalExclList, false,
- sGlobalProxyChangedObserver);
- }
-
- private static final void parseGlobalProxyInfoReadLocked(Context ctx) {
- ContentResolver contentResolver = ctx.getContentResolver();
- String proxyHost = Settings.Secure.getString(
- contentResolver,
- Settings.Secure.HTTP_PROXY);
- if (TextUtils.isEmpty(proxyHost)) {
- // Clear signal
- sProxyInfoLock.readLock().unlock();
- sProxyInfoLock.writeLock().lock();
- sGlobalProxySpec = null;
- sProxyInfoLock.readLock().lock();
- sProxyInfoLock.writeLock().unlock();
- return;
- }
- String exclusionListSpec = Settings.Secure.getString(
- contentResolver,
- Settings.Secure.HTTP_PROXY_EXCLUSION_LIST);
- String host = parseHost(proxyHost);
- int port = parsePort(proxyHost);
- ProxySpec tmpProxySpec = null;
- if (proxyHost != 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}
@@ -480,4 +312,44 @@ public final class Proxy {
new SchemeRegistry(), ProxySelector.getDefault(), context);
return ret;
}
+
+ /** @hide */
+ public static final void setHttpProxySystemProperty(ProxyProperties p) {
+ String host = null;
+ String port = null;
+ String exclList = null;
+ if (p != null) {
+ host = p.getHost();
+ port = Integer.toString(p.getPort());
+ exclList = p.getExclusionList();
+ }
+ setHttpProxySystemProperty(host, port, exclList);
+ }
+
+ /** @hide */
+ public static final void setHttpProxySystemProperty(String host, String port, String exclList) {
+ if (exclList != null) exclList = exclList.replace(",", "|");
+ if (false) Log.d(TAG, "setHttpProxySystemProperty :"+host+":"+port+" - "+exclList);
+ if (host != null) {
+ System.setProperty("http.proxyHost", host);
+ System.setProperty("https.proxyHost", host);
+ } else {
+ System.clearProperty("http.proxyHost");
+ System.clearProperty("https.proxyHost");
+ }
+ if (port != null) {
+ System.setProperty("http.proxyPort", port);
+ System.setProperty("https.proxyPort", port);
+ } else {
+ System.clearProperty("http.proxyPort");
+ System.clearProperty("https.proxyPort");
+ }
+ if (exclList != null) {
+ System.setProperty("http.nonProxyHosts", exclList);
+ System.setProperty("https.nonProxyHosts", exclList);
+ } else {
+ System.clearProperty("http.nonProxyHosts");
+ System.clearProperty("https.nonProxyHosts");
+ }
+ }
}
diff --git a/core/java/android/net/ProxyProperties.aidl b/core/java/android/net/ProxyProperties.aidl
new file mode 100644
index 0000000..02ea15d
--- /dev/null
+++ b/core/java/android/net/ProxyProperties.aidl
@@ -0,0 +1,21 @@
+/*
+**
+** Copyright (C) 2010 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.net;
+
+parcelable ProxyProperties;
+
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 5fd0d89..cbe4445 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -19,6 +19,8 @@ package android.net;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -30,44 +32,108 @@ import java.net.UnknownHostException;
*/
public class ProxyProperties implements Parcelable {
- private InetSocketAddress mProxy;
+ private String mHost;
+ private int mPort;
private String mExclusionList;
+ private String[] mParsedExclusionList;
- public ProxyProperties() {
+ public ProxyProperties(String host, int port, String exclList) {
+ mHost = host;
+ mPort = port;
+ setExclusionList(exclList);
+ }
+
+ private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
+ mHost = host;
+ mPort = port;
+ mExclusionList = exclList;
+ mParsedExclusionList = parsedExclList;
}
// copy constructor instead of clone
public ProxyProperties(ProxyProperties source) {
if (source != null) {
- mProxy = source.getSocketAddress();
- String exclusionList = source.getExclusionList();
- if (exclusionList != null) {
- mExclusionList = new String(exclusionList);
- }
+ mHost = source.getHost();
+ mPort = source.getPort();
+ mExclusionList = source.getExclusionList();
+ mParsedExclusionList = source.mParsedExclusionList;
}
}
public InetSocketAddress getSocketAddress() {
- return mProxy;
+ InetSocketAddress inetSocketAddress = null;
+ try {
+ inetSocketAddress = new InetSocketAddress(mHost, mPort);
+ } catch (IllegalArgumentException e) { }
+ return inetSocketAddress;
}
- public void setSocketAddress(InetSocketAddress proxy) {
- mProxy = proxy;
+ public String getHost() {
+ return mHost;
}
+ public int getPort() {
+ return mPort;
+ }
+
+ // comma separated
public String getExclusionList() {
return mExclusionList;
}
- public void setExclusionList(String exclusionList) {
+ // comma separated
+ private void setExclusionList(String exclusionList) {
mExclusionList = exclusionList;
+ if (mExclusionList == null) {
+ mParsedExclusionList = new String[0];
+ } else {
+ String splitExclusionList[] = exclusionList.toLowerCase().split(",");
+ mParsedExclusionList = new String[splitExclusionList.length * 2];
+ for (int i = 0; i < splitExclusionList.length; i++) {
+ String s = splitExclusionList[i].trim();
+ if (s.startsWith(".")) s = s.substring(1);
+ mParsedExclusionList[i*2] = s;
+ mParsedExclusionList[(i*2)+1] = "." + s;
+ }
+ }
+ }
+
+ public boolean isExcluded(String url) {
+ if (TextUtils.isEmpty(url) || mParsedExclusionList == null ||
+ mParsedExclusionList.length == 0) return false;
+
+ Uri u = Uri.parse(url);
+ String urlDomain = u.getHost();
+ if (urlDomain == null) return false;
+ for (int i = 0; i< mParsedExclusionList.length; i+=2) {
+ if (urlDomain.equals(mParsedExclusionList[i]) ||
+ urlDomain.endsWith(mParsedExclusionList[i+1])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public java.net.Proxy makeProxy() {
+ java.net.Proxy proxy = java.net.Proxy.NO_PROXY;
+ if (mHost != null) {
+ try {
+ InetSocketAddress inetSocketAddress = new InetSocketAddress(mHost, mPort);
+ proxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, inetSocketAddress);
+ } catch (IllegalArgumentException e) {
+ }
+ }
+ return proxy;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- if (mProxy != null) {
- sb.append(mProxy.toString());
+ if (mHost != null) {
+ sb.append("[");
+ sb.append(mHost);
+ sb.append("] ");
+ sb.append(Integer.toString(mPort));
if (mExclusionList != null) {
sb.append(" xl=").append(mExclusionList);
}
@@ -75,6 +141,20 @@ public class ProxyProperties implements Parcelable {
return sb.toString();
}
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ProxyProperties)) return false;
+ ProxyProperties p = (ProxyProperties)o;
+ if (mExclusionList != null && !mExclusionList.equals(p.getExclusionList())) return false;
+ if (mHost != null && p.getHost() != null && mHost.equals(p.getHost()) == false) {
+ return false;
+ }
+ if (mHost != null && p.mHost == null) return false;
+ if (mHost == null && p.mHost != null) return false;
+ if (mPort != p.mPort) return false;
+ return true;
+ }
+
/**
* Implement the Parcelable interface
* @hide
@@ -88,27 +168,15 @@ public class ProxyProperties implements Parcelable {
* @hide
*/
public void writeToParcel(Parcel dest, int flags) {
- String host = null;
- if (mProxy != null) {
- try {
- InetAddress addr = mProxy.getAddress();
- if (addr != null) {
- host = addr.getHostAddress();
- } else {
- /* Does not resolve when addr is null */
- host = mProxy.getHostName();
- }
- } catch (Exception e) { }
- }
-
- if (host != null) {
+ if (mHost != null) {
dest.writeByte((byte)1);
- dest.writeString(host);
- dest.writeInt(mProxy.getPort());
+ dest.writeString(mHost);
+ dest.writeInt(mPort);
} else {
dest.writeByte((byte)0);
}
dest.writeString(mExclusionList);
+ dest.writeStringArray(mParsedExclusionList);
}
/**
@@ -118,16 +186,16 @@ public class ProxyProperties implements Parcelable {
public static final Creator<ProxyProperties> CREATOR =
new Creator<ProxyProperties>() {
public ProxyProperties createFromParcel(Parcel in) {
- ProxyProperties proxyProperties = new ProxyProperties();
+ String host = null;
+ int port = 0;
if (in.readByte() == 1) {
- try {
- String host = in.readString();
- int port = in.readInt();
- proxyProperties.setSocketAddress(InetSocketAddress.createUnresolved(
- host, port));
- } catch (IllegalArgumentException e) { }
+ host = in.readString();
+ port = in.readInt();
}
- proxyProperties.setExclusionList(in.readString());
+ String exclList = in.readString();
+ String[] parsedExclList = in.readStringArray();
+ ProxyProperties proxyProperties =
+ new ProxyProperties(host, port, exclList, parsedExclList);
return proxyProperties;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1fe2c5a..7075774 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2424,17 +2424,32 @@ public final class Settings {
public static final String DISABLED_SYSTEM_INPUT_METHODS = "disabled_system_input_methods";
/**
- * Host name and port for global proxy.
+ * Host name and port for global http proxy. Uses ':' seperator for between host and port
+ * TODO - deprecate in favor of global_http_proxy_host, etc
*/
public static final String HTTP_PROXY = "http_proxy";
/**
+ * Host name for global http proxy. Set via ConnectivityManager.
+ * @hide
+ */
+ public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host";
+
+ /**
+ * Integer host port for global http proxy. Set via ConnectivityManager.
+ * @hide
+ */
+ public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port";
+
+ /**
* Exclusion list for global proxy. This string contains a list of comma-separated
* domains where the global proxy does not apply. Domains should be listed in a comma-
* separated list. Example of acceptable formats: ".domain1.com,my.domain2.com"
+ * Use ConnectivityManager to set/get.
* @hide
*/
- public static final String HTTP_PROXY_EXCLUSION_LIST = "http_proxy_exclusion_list";
+ public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST =
+ "global_http_proxy_exclusion_list";
/**
* Enables the UI setting to allow the user to specify the global HTTP proxy
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d02ca64..ddc63dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -92,6 +92,7 @@
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
<protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" />
+ <protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c18262e..5c67da7 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -22,6 +22,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.MobileDataStateTracker;
@@ -29,8 +30,9 @@ import android.net.NetworkInfo;
import android.net.LinkProperties;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
+import android.net.Proxy;
+import android.net.ProxyProperties;
import android.net.wifi.WifiStateTracker;
-import android.net.NetworkUtils;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -55,13 +57,12 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.List;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
/**
* @hide
@@ -179,6 +180,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
MAX_NETWORK_STATE_TRACKER_EVENT + 8;
+ /**
+ * used internally to reload global proxy settings
+ */
+ private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 9;
+
private Handler mHandler;
// list of DeathRecipients used to make sure features are turned off when
@@ -199,6 +206,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
private ArrayList mInetLog;
+ // track the current default http proxy - tell the world if we get a new one (real change)
+ private ProxyProperties mDefaultProxy = null;
+ // track the global proxy.
+ private ProxyProperties mGlobalProxy = null;
+ private final Object mGlobalProxyLock = new Object();
+
+ private SettingsObserver mSettingsObserver;
+
private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
@@ -412,6 +427,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (DBG) {
mInetLog = new ArrayList();
}
+
+ mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY);
+ mSettingsObserver.observe(mContext);
}
@@ -1303,6 +1321,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mInitialBroadcast = null;
}
}
+ // load the global proxy at startup
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY));
}
private void handleConnect(NetworkInfo info) {
@@ -1380,6 +1400,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
if (mNetAttributes[netType].isDefault()) {
+ handleApplyDefaultProxy(netType);
addDefaultRoute(mNetTrackers[netType]);
} else {
addPrivateDnsRoutes(mNetTrackers[netType]);
@@ -1783,10 +1804,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
break;
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
- // TODO - make this handle ip/proxy/gateway/dns changes
info = (NetworkInfo) msg.obj;
type = info.getType();
- handleDnsConfigurationChange(type);
+ handleConnectivityChange(type);
break;
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
String causedBy = null;
@@ -1838,6 +1858,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
handleSetMobileData(enabled);
break;
}
+ case EVENT_APPLY_GLOBAL_HTTP_PROXY:
+ {
+ handleDeprecatedGlobalHttpProxy();
+ }
}
}
}
@@ -2037,4 +2061,113 @@ public class ConnectivityService extends IConnectivityManager.Stub {
sendInetConditionBroadcast(networkInfo);
return;
}
+
+ public synchronized ProxyProperties getProxy() {
+ if (mGlobalProxy != null) return mGlobalProxy;
+ if (mDefaultProxy != null) return mDefaultProxy;
+ return null;
+ }
+
+ public void setGlobalProxy(ProxyProperties proxyProperties) {
+ enforceChangePermission();
+ synchronized (mGlobalProxyLock) {
+ if (proxyProperties == mGlobalProxy) return;
+ if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return;
+ if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return;
+
+ String host = "";
+ int port = 0;
+ String exclList = "";
+ if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) {
+ mGlobalProxy = new ProxyProperties(proxyProperties);
+ host = mGlobalProxy.getHost();
+ port = mGlobalProxy.getPort();
+ exclList = mGlobalProxy.getExclusionList();
+ } else {
+ mGlobalProxy = null;
+ }
+ ContentResolver res = mContext.getContentResolver();
+ Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host);
+ Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port);
+ Settings.Secure.putString(res,Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+ exclList);
+ }
+
+ if (mGlobalProxy == null) {
+ proxyProperties = mDefaultProxy;
+ }
+ sendProxyBroadcast(proxyProperties);
+ }
+
+ public ProxyProperties getGlobalProxy() {
+ synchronized (mGlobalProxyLock) {
+ return mGlobalProxy;
+ }
+ }
+
+ private void handleApplyDefaultProxy(int type) {
+ // check if new default - push it out to all VM if so
+ ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy();
+ synchronized (this) {
+ if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return;
+ if (mDefaultProxy == proxy) return;
+ if (!TextUtils.isEmpty(proxy.getHost())) {
+ mDefaultProxy = proxy;
+ } else {
+ mDefaultProxy = null;
+ }
+ }
+ if (DBG) Slog.d(TAG, "changing default proxy to " + proxy);
+ if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return;
+ if (mGlobalProxy != null) return;
+ sendProxyBroadcast(proxy);
+ }
+
+ private void handleDeprecatedGlobalHttpProxy() {
+ String proxy = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.HTTP_PROXY);
+ if (!TextUtils.isEmpty(proxy)) {
+ String data[] = proxy.split(":");
+ String proxyHost = data[0];
+ int proxyPort = 8080;
+ if (data.length > 1) {
+ try {
+ proxyPort = Integer.parseInt(data[1]);
+ } catch (NumberFormatException e) {
+ return;
+ }
+ }
+ ProxyProperties p = new ProxyProperties(data[0], proxyPort, "");
+ setGlobalProxy(p);
+ }
+ }
+
+ private void sendProxyBroadcast(ProxyProperties proxy) {
+ Slog.d(TAG, "sending Proxy Broadcast for " + proxy);
+ Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
+ mContext.sendBroadcast(intent);
+ }
+
+ private static class SettingsObserver extends ContentObserver {
+ private int mWhat;
+ private Handler mHandler;
+ SettingsObserver(Handler handler, int what) {
+ super(handler);
+ mHandler = handler;
+ mWhat = what;
+ }
+
+ void observe(Context context) {
+ ContentResolver resolver = context.getContentResolver();
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.HTTP_PROXY), false, this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mHandler.obtainMessage(mWhat).sendToTarget();
+ }
+ }
}
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 3dcad38..2b43b01 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -1757,10 +1757,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
// Remove white spaces
proxySpec = proxySpec.trim();
+ String data[] = proxySpec.split(":");
+ int proxyPort = 8080;
+ if (data.length > 1) {
+ try {
+ proxyPort = Integer.parseInt(data[1]);
+ } catch (NumberFormatException e) {}
+ }
exclusionList = exclusionList.trim();
ContentResolver res = mContext.getContentResolver();
- Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, proxySpec);
- Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST, exclusionList);
+ Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]);
+ Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort);
+ Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+ exclusionList);
}
@Override
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1ec8a22..e815524 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -76,6 +76,8 @@ import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.net.Proxy;
+import android.net.ProxyProperties;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -127,6 +129,7 @@ import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
+import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -960,6 +963,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int SHOW_STRICT_MODE_VIOLATION_MSG = 26;
static final int CHECK_EXCESSIVE_WAKE_LOCKS_MSG = 27;
static final int CLEAR_DNS_CACHE = 28;
+ static final int UPDATE_HTTP_PROXY = 29;
AlertDialog mUidAlert;
@@ -1125,6 +1129,30 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
} break;
+ case UPDATE_HTTP_PROXY: {
+ ProxyProperties proxy = (ProxyProperties)msg.obj;
+ String host = "";
+ String port = "";
+ String exclList = "";
+ if (proxy != null) {
+ host = proxy.getHost();
+ port = Integer.toString(proxy.getPort());
+ exclList = proxy.getExclusionList();
+ }
+ synchronized (ActivityManagerService.this) {
+ for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ if (r.thread != null) {
+ try {
+ r.thread.setHttpProxy(host, port, exclList);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to update http proxy for: " +
+ r.info.processName);
+ }
+ }
+ }
+ }
+ } break;
case SHOW_UID_ERROR_MSG: {
// XXX This is a temporary dialog, no need to localize.
AlertDialog d = new BaseErrorDialog(mContext);
@@ -10402,6 +10430,11 @@ public final class ActivityManagerService extends ActivityManagerNative
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
}
+ if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
+ ProxyProperties proxy = intent.getParcelableExtra("proxy");
+ mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
+ }
+
/*
* Prevent non-system code (defined here to be non-persistent
* processes) from sending protected broadcasts.
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 70328f7..06c7c1b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -1007,14 +1007,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
ApnSetting apn = mPendingDataConnection.getApn();
if (apn.proxy != null && apn.proxy.length() != 0) {
try {
- ProxyProperties proxy = new ProxyProperties();
- proxy.setSocketAddress(new InetSocketAddress(InetAddress.getByName(apn.proxy),
- Integer.parseInt(apn.port)));
+ ProxyProperties proxy = new ProxyProperties(apn.proxy,
+ Integer.parseInt(apn.port), null);
mLinkProperties.setHttpProxy(proxy);
- } catch (UnknownHostException e) {
- loge("UnknownHostException making ProxyProperties: " + e);
- } catch (SecurityException e) {
- loge("SecurityException making ProxyProperties: " + e);
} catch (NumberFormatException e) {
loge("NumberFormatException making ProxyProperties (" + apn.port +
"): " + e);
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 04b3891..24f6f31 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -595,9 +595,9 @@ class WifiConfigStore {
out.writeUTF(PROXY_SETTINGS_KEY);
out.writeUTF(config.proxySettings.toString());
out.writeUTF(PROXY_HOST_KEY);
- out.writeUTF(proxyProperties.getSocketAddress().getHostName());
+ out.writeUTF(proxyProperties.getHost());
out.writeUTF(PROXY_PORT_KEY);
- out.writeInt(proxyProperties.getSocketAddress().getPort());
+ out.writeInt(proxyProperties.getPort());
out.writeUTF(EXCLUSION_LIST_KEY);
out.writeUTF(exclusionList);
writeToFile = true;
@@ -716,10 +716,8 @@ class WifiConfigStore {
switch (proxySettings) {
case STATIC:
config.proxySettings = proxySettings;
- ProxyProperties proxyProperties = new ProxyProperties();
- proxyProperties.setSocketAddress(
- new InetSocketAddress(proxyHost, proxyPort));
- proxyProperties.setExclusionList(exclusionList);
+ ProxyProperties proxyProperties =
+ new ProxyProperties(proxyHost, proxyPort, exclusionList);
linkProperties.setHttpProxy(proxyProperties);
break;
case NONE:
@@ -1012,42 +1010,13 @@ class WifiConfigStore {
switch (newConfig.proxySettings) {
case STATIC:
- InetSocketAddress newSockAddr = null;
- String newExclusionList = null;
- InetSocketAddress currentSockAddr = null;
- String currentExclusionList = null;
-
ProxyProperties newHttpProxy = newConfig.linkProperties.getHttpProxy();
- if (newHttpProxy != null) {
- newSockAddr = newHttpProxy.getSocketAddress();
- newExclusionList = newHttpProxy.getExclusionList();
- }
-
ProxyProperties currentHttpProxy = currentConfig.linkProperties.getHttpProxy();
- if (currentHttpProxy != null) {
- currentSockAddr = currentHttpProxy.getSocketAddress();
- currentExclusionList = currentHttpProxy.getExclusionList();
- }
-
- boolean socketAddressDiffers = false;
- boolean exclusionListDiffers = false;
- if (newSockAddr != null && currentSockAddr != null ) {
- socketAddressDiffers = !currentSockAddr.equals(newSockAddr);
- } else if (newSockAddr != null || currentSockAddr != null) {
- socketAddressDiffers = true;
- }
-
- if (newExclusionList != null && currentExclusionList != null) {
- exclusionListDiffers = !currentExclusionList.equals(newExclusionList);
- } else if (newExclusionList != null || currentExclusionList != null) {
- exclusionListDiffers = true;
- }
-
- if ((currentConfig.proxySettings != newConfig.proxySettings) ||
- socketAddressDiffers ||
- exclusionListDiffers) {
- proxyChanged = true;
+ if (newHttpProxy != null) {
+ proxyChanged = !newHttpProxy.equals(currentHttpProxy);
+ } else {
+ proxyChanged = (currentHttpProxy != null);
}
break;
case NONE: