summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jason Monk <jmonk@google.com> 2013-08-23 19:21:25 -0400
committer Jason Monk <jmonk@google.com> 2013-09-13 09:53:26 -0400
commit6f8a68f49a7e8cf86104e721a1e8be7568b5f730 (patch)
treedbe5e5d7001b191c376d3ba3510cbf6f7f309279
parent86d9c457de3285f01552d4046a8a260c7a75147f (diff)
Guarantee that PAC Local Proxy owns Port
This changes the PAC support to not broadcast the Proxy information until the Local Proxy has started up and successfully bound to a port so that the local proxy information can be guaranteed to be owned by the proxy. Bug: 10459877 Change-Id: I175cd3388c758c55e341115e4a8241884b90d633
-rw-r--r--Android.mk2
-rw-r--r--core/java/android/net/ProxyProperties.java10
-rw-r--r--packages/services/Proxy/com/android/net/IProxyCallback.aidl22
-rw-r--r--packages/services/Proxy/com/android/net/IProxyPortListener.aidl22
-rw-r--r--packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java61
-rw-r--r--packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java16
-rw-r--r--services/java/com/android/server/ConnectivityService.java3
-rw-r--r--services/java/com/android/server/connectivity/PacManager.java64
8 files changed, 184 insertions, 16 deletions
diff --git a/Android.mk b/Android.mk
index 30b17f5ac2c8..6d4a763aac6c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -266,6 +266,8 @@ LOCAL_SRC_FILES += \
wifi/java/android/net/wifi/IWifiManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
+ packages/services/Proxy/com/android/net/IProxyCallback.aidl \
+ packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
# FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 76aea9f58e85..648a4b37ebb3 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -38,7 +38,7 @@ public class ProxyProperties implements Parcelable {
private String mPacFileUrl;
public static final String LOCAL_EXCL_LIST = "";
- public static final int LOCAL_PORT = 8182;
+ public static final int LOCAL_PORT = -1;
public static final String LOCAL_HOST = "localhost";
public ProxyProperties(String host, int port, String exclList) {
@@ -54,6 +54,14 @@ public class ProxyProperties implements Parcelable {
mPacFileUrl = pacFileUrl;
}
+ // Only used in PacManager after Local Proxy is bound.
+ public ProxyProperties(String pacFileUrl, int localProxyPort) {
+ mHost = LOCAL_HOST;
+ mPort = localProxyPort;
+ setExclusionList(LOCAL_EXCL_LIST);
+ mPacFileUrl = pacFileUrl;
+ }
+
private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
mHost = host;
mPort = port;
diff --git a/packages/services/Proxy/com/android/net/IProxyCallback.aidl b/packages/services/Proxy/com/android/net/IProxyCallback.aidl
new file mode 100644
index 000000000000..26b2a3f9da2d
--- /dev/null
+++ b/packages/services/Proxy/com/android/net/IProxyCallback.aidl
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2013, 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 com.android.net;
+
+/** @hide */
+interface IProxyCallback
+{
+ oneway void getProxyPort(IBinder callback);
+}
diff --git a/packages/services/Proxy/com/android/net/IProxyPortListener.aidl b/packages/services/Proxy/com/android/net/IProxyPortListener.aidl
new file mode 100644
index 000000000000..fa4caf3dba91
--- /dev/null
+++ b/packages/services/Proxy/com/android/net/IProxyPortListener.aidl
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2013, 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 com.android.net;
+
+/** @hide */
+interface IProxyPortListener
+{
+ oneway void setProxyPort(int port);
+}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
index 77f3c8c21cc6..4bf1db8b3ca1 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
@@ -15,8 +15,11 @@
*/
package com.android.proxyhandler;
+import android.net.ProxyProperties;
+import android.os.RemoteException;
import android.util.Log;
+import com.android.net.IProxyPortListener;
import com.google.android.collect.Lists;
import java.io.IOException;
@@ -49,6 +52,8 @@ public class ProxyServer extends Thread {
public boolean mIsRunning = false;
private ServerSocket serverSocket;
+ private int mPort;
+ private IProxyPortListener mCallback;
private class ProxyConnection implements Runnable {
private Socket connection;
@@ -179,33 +184,59 @@ public class ProxyServer extends Thread {
public ProxyServer() {
threadExecutor = Executors.newCachedThreadPool();
+ mPort = -1;
+ mCallback = null;
}
@Override
public void run() {
try {
- serverSocket = new ServerSocket(ProxyService.PORT);
+ serverSocket = new ServerSocket(0);
- serverSocket.setReuseAddress(true);
+ if (serverSocket != null) {
+ setPort(serverSocket.getLocalPort());
- while (mIsRunning) {
- try {
- ProxyConnection parser = new ProxyConnection(serverSocket.accept());
+ while (mIsRunning) {
+ try {
+ ProxyConnection parser = new ProxyConnection(serverSocket.accept());
- threadExecutor.execute(parser);
- } catch (IOException e) {
- e.printStackTrace();
+ threadExecutor.execute(parser);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
}
} catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ Log.e(TAG, "Failed to start proxy server", e);
+ } catch (IOException e1) {
+ Log.e(TAG, "Failed to start proxy server", e1);
}
mIsRunning = false;
}
+ public synchronized void setPort(int port) {
+ if (mCallback != null) {
+ try {
+ mCallback.setProxyPort(port);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Proxy failed to report port to PacManager", e);
+ }
+ }
+ mPort = port;
+ }
+
+ public synchronized void setCallback(IProxyPortListener callback) {
+ if (mPort != -1) {
+ try {
+ callback.setProxyPort(mPort);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Proxy failed to report port to PacManager", e);
+ }
+ }
+ mCallback = callback;
+ }
+
public synchronized void startServer() {
mIsRunning = true;
start();
@@ -222,4 +253,12 @@ public class ProxyServer extends Thread {
}
}
}
+
+ public boolean isBound() {
+ return (mPort != -1);
+ }
+
+ public int getPort() {
+ return mPort;
+ }
}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
index cef36593b306..109435c30e58 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
@@ -21,8 +21,12 @@ import android.net.Proxy;
import android.net.ProxyProperties;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
import android.text.TextUtils;
+import com.android.net.IProxyCallback;
+import com.android.net.IProxyPortListener;
+
/**
* @hide
*/
@@ -56,6 +60,16 @@ public class ProxyService extends Service {
@Override
public IBinder onBind(Intent intent) {
- return null;
+ return new IProxyCallback.Stub() {
+ @Override
+ public void getProxyPort(IBinder callback) throws RemoteException {
+ if (server != null) {
+ IProxyPortListener portListener = IProxyPortListener.Stub.asInterface(callback);
+ if (portListener != null) {
+ server.setCallback(portListener);
+ }
+ }
+ }
+ };
}
} \ No newline at end of file
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 4e3faca51af6..47f18e733561 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -114,7 +114,6 @@ import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
-import com.android.net.IProxyService;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.Nat464Xlat;
@@ -3471,7 +3470,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, "");
- mPacManager.setCurrentProxyScriptUrl(proxy);
+ if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index c8cc85e8d1cd..772921aa97dc 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -24,17 +24,22 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.net.Proxy;
import android.net.ProxyProperties;
+import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.net.IProxyCallback;
+import com.android.net.IProxyPortListener;
import com.android.net.IProxyService;
import com.android.server.IoThread;
@@ -79,6 +84,7 @@ public class PacManager {
private Context mContext;
private int mCurrentDelay;
+ private int mLastPort;
/**
* Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
@@ -119,6 +125,7 @@ public class PacManager {
public PacManager(Context context) {
mContext = context;
+ mLastPort = -1;
mPacRefreshIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -133,7 +140,16 @@ public class PacManager {
return mAlarmManager;
}
- public synchronized void setCurrentProxyScriptUrl(ProxyProperties proxy) {
+ /**
+ * Updates the PAC Manager with current Proxy information. This is called by
+ * the ConnectivityService directly before a broadcast takes place to allow
+ * the PacManager to indicate that the broadcast should not be sent and the
+ * PacManager will trigger a new broadcast when it is ready.
+ *
+ * @param proxy Proxy information that is about to be broadcast.
+ * @return Returns true when the broadcast should not be sent
+ */
+ public synchronized boolean setCurrentProxyScriptUrl(ProxyProperties proxy) {
if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
synchronized (mProxyLock) {
mPacUrl = proxy.getPacFileUrl();
@@ -141,6 +157,7 @@ public class PacManager {
mCurrentDelay = DELAY_1;
getAlarmManager().cancel(mPacRefreshIntent);
bind();
+ return true;
} else {
getAlarmManager().cancel(mPacRefreshIntent);
synchronized (mProxyLock) {
@@ -156,6 +173,7 @@ public class PacManager {
}
}
}
+ return false;
}
}
@@ -233,6 +251,16 @@ public class PacManager {
}
Intent intent = new Intent();
intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
+ // Already bound no need to bind again.
+ if (mProxyConnection != null) {
+ if (mLastPort != -1) {
+ sendPacBroadcast(new ProxyProperties(mPacUrl, mLastPort));
+ } else {
+ Log.e(TAG, "Received invalid port from Local Proxy,"
+ + " PAC will not be operational");
+ }
+ return;
+ }
mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName component) {
@@ -277,6 +305,26 @@ public class PacManager {
@Override
public void onServiceConnected(ComponentName component, IBinder binder) {
+ IProxyCallback callbackService = IProxyCallback.Stub.asInterface(binder);
+ if (callbackService != null) {
+ try {
+ callbackService.getProxyPort(new IProxyPortListener.Stub() {
+ @Override
+ public void setProxyPort(int port) throws RemoteException {
+ mLastPort = port;
+ if (port != -1) {
+ Log.d(TAG, "Local proxy is bound on " + port);
+ sendPacBroadcast(new ProxyProperties(mPacUrl, port));
+ } else {
+ Log.e(TAG, "Received invalid port from Local Proxy,"
+ + " PAC will not be operational");
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
}
};
mContext.bindService(intent, mProxyConnection,
@@ -287,5 +335,19 @@ public class PacManager {
mContext.unbindService(mConnection);
mContext.unbindService(mProxyConnection);
mConnection = null;
+ mProxyConnection = null;
+ }
+
+ private void sendPacBroadcast(ProxyProperties proxy) {
+ Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}