Merge "Guarantee that PAC Local Proxy owns Port" into klp-dev

This commit is contained in:
Jason Monk
2013-09-13 20:31:53 +00:00
committed by Android (Google) Code Review
8 changed files with 184 additions and 15 deletions

View File

@@ -265,6 +265,8 @@ LOCAL_SRC_FILES += \
wifi/java/android/net/wifi/IWifiManager.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \ wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.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 # FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)

View File

@@ -38,7 +38,7 @@ public class ProxyProperties implements Parcelable {
private String mPacFileUrl; private String mPacFileUrl;
public static final String LOCAL_EXCL_LIST = ""; 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 static final String LOCAL_HOST = "localhost";
public ProxyProperties(String host, int port, String exclList) { public ProxyProperties(String host, int port, String exclList) {
@@ -54,6 +54,14 @@ public class ProxyProperties implements Parcelable {
mPacFileUrl = pacFileUrl; 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) { private ProxyProperties(String host, int port, String exclList, String[] parsedExclList) {
mHost = host; mHost = host;
mPort = port; mPort = port;

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -15,8 +15,11 @@
*/ */
package com.android.proxyhandler; package com.android.proxyhandler;
import android.net.ProxyProperties;
import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import com.android.net.IProxyPortListener;
import com.google.android.collect.Lists; import com.google.android.collect.Lists;
import java.io.IOException; import java.io.IOException;
@@ -49,6 +52,8 @@ public class ProxyServer extends Thread {
public boolean mIsRunning = false; public boolean mIsRunning = false;
private ServerSocket serverSocket; private ServerSocket serverSocket;
private int mPort;
private IProxyPortListener mCallback;
private class ProxyConnection implements Runnable { private class ProxyConnection implements Runnable {
private Socket connection; private Socket connection;
@@ -179,33 +184,59 @@ public class ProxyServer extends Thread {
public ProxyServer() { public ProxyServer() {
threadExecutor = Executors.newCachedThreadPool(); threadExecutor = Executors.newCachedThreadPool();
mPort = -1;
mCallback = null;
} }
@Override @Override
public void run() { public void run() {
try { try {
serverSocket = new ServerSocket(ProxyService.PORT); serverSocket = new ServerSocket(0);
serverSocket.setReuseAddress(true); if (serverSocket != null) {
setPort(serverSocket.getLocalPort());
while (mIsRunning) { while (mIsRunning) {
try { try {
ProxyConnection parser = new ProxyConnection(serverSocket.accept()); ProxyConnection parser = new ProxyConnection(serverSocket.accept());
threadExecutor.execute(parser); threadExecutor.execute(parser);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
}
} }
} }
} catch (SocketException e) { } catch (SocketException e) {
e.printStackTrace(); Log.e(TAG, "Failed to start proxy server", e);
} catch (IOException e) { } catch (IOException e1) {
e.printStackTrace(); Log.e(TAG, "Failed to start proxy server", e1);
} }
mIsRunning = false; 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() { public synchronized void startServer() {
mIsRunning = true; mIsRunning = true;
start(); start();
@@ -222,4 +253,12 @@ public class ProxyServer extends Thread {
} }
} }
} }
public boolean isBound() {
return (mPort != -1);
}
public int getPort() {
return mPort;
}
} }

View File

@@ -21,8 +21,12 @@ import android.net.Proxy;
import android.net.ProxyProperties; import android.net.ProxyProperties;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.net.IProxyCallback;
import com.android.net.IProxyPortListener;
/** /**
* @hide * @hide
*/ */
@@ -56,6 +60,16 @@ public class ProxyService extends Service {
@Override @Override
public IBinder onBind(Intent intent) { 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);
}
}
}
};
} }
} }

View File

@@ -3463,7 +3463,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void sendProxyBroadcast(ProxyProperties proxy) { private void sendProxyBroadcast(ProxyProperties proxy) {
if (proxy == null) proxy = new ProxyProperties("", 0, ""); if (proxy == null) proxy = new ProxyProperties("", 0, "");
mPacManager.setCurrentProxyScriptUrl(proxy); if (mPacManager.setCurrentProxyScriptUrl(proxy)) return;
if (DBG) log("sending Proxy Broadcast for " + proxy); if (DBG) log("sending Proxy Broadcast for " + proxy);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |

View File

@@ -24,17 +24,22 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.net.Proxy;
import android.net.ProxyProperties; import android.net.ProxyProperties;
import android.os.Binder;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.net.IProxyCallback;
import com.android.net.IProxyPortListener;
import com.android.net.IProxyService; import com.android.net.IProxyService;
import com.android.server.IoThread; import com.android.server.IoThread;
@@ -79,6 +84,7 @@ public class PacManager {
private Context mContext; private Context mContext;
private int mCurrentDelay; private int mCurrentDelay;
private int mLastPort;
/** /**
* Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac. * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
@@ -119,6 +125,7 @@ public class PacManager {
public PacManager(Context context) { public PacManager(Context context) {
mContext = context; mContext = context;
mLastPort = -1;
mPacRefreshIntent = PendingIntent.getBroadcast( mPacRefreshIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_PAC_REFRESH), 0); context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -133,7 +140,16 @@ public class PacManager {
return mAlarmManager; 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())) { if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
synchronized (mProxyLock) { synchronized (mProxyLock) {
mPacUrl = proxy.getPacFileUrl(); mPacUrl = proxy.getPacFileUrl();
@@ -141,6 +157,7 @@ public class PacManager {
mCurrentDelay = DELAY_1; mCurrentDelay = DELAY_1;
getAlarmManager().cancel(mPacRefreshIntent); getAlarmManager().cancel(mPacRefreshIntent);
bind(); bind();
return true;
} else { } else {
getAlarmManager().cancel(mPacRefreshIntent); getAlarmManager().cancel(mPacRefreshIntent);
synchronized (mProxyLock) { synchronized (mProxyLock) {
@@ -156,6 +173,7 @@ public class PacManager {
} }
} }
} }
return false;
} }
} }
@@ -233,6 +251,16 @@ public class PacManager {
} }
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClassName(PAC_PACKAGE, PAC_SERVICE); 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() { mConnection = new ServiceConnection() {
@Override @Override
public void onServiceDisconnected(ComponentName component) { public void onServiceDisconnected(ComponentName component) {
@@ -277,6 +305,26 @@ public class PacManager {
@Override @Override
public void onServiceConnected(ComponentName component, IBinder binder) { 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, mContext.bindService(intent, mProxyConnection,
@@ -287,5 +335,19 @@ public class PacManager {
mContext.unbindService(mConnection); mContext.unbindService(mConnection);
mContext.unbindService(mProxyConnection); mContext.unbindService(mProxyConnection);
mConnection = null; 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);
}
} }
} }