PacManager.java revision 619a511d4f5b5cc74b9a8ab853db386489e02e6f
19ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk/** 29ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Copyright (c) 2013, The Android Open Source Project 39ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * 49ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 59ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * you may not use this file except in compliance with the License. 69ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * You may obtain a copy of the License at 79ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * 89ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 99ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * 109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Unless required by applicable law or agreed to in writing, software 119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * See the License for the specific language governing permissions and 149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * limitations under the License. 159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk */ 16602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkpackage com.android.server.connectivity; 17602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 18602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.app.AlarmManager; 19602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.app.PendingIntent; 20602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.content.BroadcastReceiver; 219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.content.ComponentName; 22602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.content.ContentResolver; 23602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.content.Context; 24602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.content.Intent; 25602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.content.IntentFilter; 269ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.content.ServiceConnection; 27207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monkimport android.net.ProxyInfo; 28619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkeyimport android.net.TrafficStats; 2983520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monkimport android.net.Uri; 30decd295b1371238c97c170226c6145948492eda1Jason Monkimport android.os.Handler; 317d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensenimport android.os.HandlerThread; 329ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.os.IBinder; 33602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.RemoteException; 34602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.ServiceManager; 35602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.SystemClock; 36602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.SystemProperties; 37602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.provider.Settings; 38602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.util.Log; 39602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 409ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport com.android.internal.annotations.GuardedBy; 416f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monkimport com.android.net.IProxyCallback; 426f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monkimport com.android.net.IProxyPortListener; 43602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport com.android.net.IProxyService; 44602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 459ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport libcore.io.Streams; 46602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 477d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensenimport java.io.ByteArrayOutputStream; 48602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.io.IOException; 49602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.URL; 50602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.URLConnection; 51602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 52602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk/** 53602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * @hide 54602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk */ 559ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkpublic class PacManager { 56da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PAC_PACKAGE = "com.android.pacprocessor"; 57da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PAC_SERVICE = "com.android.pacprocessor.PacService"; 58da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PAC_SERVICE_NAME = "com.android.net.IProxyService"; 59602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 60da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PROXY_PACKAGE = "com.android.proxyhandler"; 61da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PROXY_SERVICE = "com.android.proxyhandler.ProxyService"; 62602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 639ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private static final String TAG = "PacManager"; 64602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 65602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH"; 66602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 67602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final String DEFAULT_DELAYS = "8 32 120 14400 43200"; 68602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final int DELAY_1 = 0; 69602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final int DELAY_4 = 3; 70602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final int DELAY_LONG = 4; 717d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen private static final long MAX_PAC_SIZE = 20 * 1000 * 1000; 72602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 73602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk /** Keep these values up-to-date with ProxyService.java */ 74602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk public static final String KEY_PROXY = "keyProxy"; 75602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private String mCurrentPac; 769ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @GuardedBy("mProxyLock") 77f6b46cb8b108cc8feee8ae68b979271fd6f72bf5Jason Monk private Uri mPacUrl = Uri.EMPTY; 78602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 79602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private AlarmManager mAlarmManager; 809ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @GuardedBy("mProxyLock") 81602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private IProxyService mProxyService; 82602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private PendingIntent mPacRefreshIntent; 839ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private ServiceConnection mConnection; 84da205a749fadb3a87357d9bd607f094c7717764aJason Monk private ServiceConnection mProxyConnection; 85602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private Context mContext; 86602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 87602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private int mCurrentDelay; 886f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk private int mLastPort; 89602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 90d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk private boolean mHasSentBroadcast; 91d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk private boolean mHasDownloaded; 92d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk 93decd295b1371238c97c170226c6145948492eda1Jason Monk private Handler mConnectivityHandler; 94decd295b1371238c97c170226c6145948492eda1Jason Monk private int mProxyMessage; 95decd295b1371238c97c170226c6145948492eda1Jason Monk 969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk /** 979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac. 989ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk */ 999ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private final Object mProxyLock = new Object(); 1009ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 1019ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private Runnable mPacDownloader = new Runnable() { 1029ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @Override 1039ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk public void run() { 1049ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk String file; 1059ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 10683520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk if (Uri.EMPTY.equals(mPacUrl)) return; 107619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey final int oldTag = TrafficStats 108619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey .getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PAC); 1099ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 1109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk file = get(mPacUrl); 1119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (IOException ioe) { 1129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk file = null; 1139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.w(TAG, "Failed to load PAC file: " + ioe); 114619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey } finally { 115619a511d4f5b5cc74b9a8ab853db386489e02e6fJeff Sharkey TrafficStats.setThreadStatsTag(oldTag); 1169ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1179ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1189ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (file != null) { 1199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 1209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (!file.equals(mCurrentPac)) { 1219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk setCurrentProxyScript(file); 1229ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1239ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 124d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasDownloaded = true; 125d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk sendProxyIfNeeded(); 1269ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk longSchedule(); 1279ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } else { 1289ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk reschedule(); 1299ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1309ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1319ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk }; 1329ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 1337d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen private final HandlerThread mNetThread = new HandlerThread("android.pacmanager", 1347d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen android.os.Process.THREAD_PRIORITY_DEFAULT); 1357d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen private final Handler mNetThreadHandler; 1367d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen 137602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk class PacRefreshIntentReceiver extends BroadcastReceiver { 138602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk public void onReceive(Context context, Intent intent) { 1397d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen mNetThreadHandler.post(mPacDownloader); 140602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 141602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 142602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 143decd295b1371238c97c170226c6145948492eda1Jason Monk public PacManager(Context context, Handler handler, int proxyMessage) { 144602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mContext = context; 1456f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk mLastPort = -1; 1467d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen mNetThread.start(); 1477d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen mNetThreadHandler = new Handler(mNetThread.getLooper()); 148602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 149602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mPacRefreshIntent = PendingIntent.getBroadcast( 150602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk context, 0, new Intent(ACTION_PAC_REFRESH), 0); 151602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk context.registerReceiver(new PacRefreshIntentReceiver(), 152602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk new IntentFilter(ACTION_PAC_REFRESH)); 153decd295b1371238c97c170226c6145948492eda1Jason Monk mConnectivityHandler = handler; 154decd295b1371238c97c170226c6145948492eda1Jason Monk mProxyMessage = proxyMessage; 155602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 156602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 157602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private AlarmManager getAlarmManager() { 158602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk if (mAlarmManager == null) { 159602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 160602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 161602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return mAlarmManager; 162602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 163602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 1646f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk /** 1656f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * Updates the PAC Manager with current Proxy information. This is called by 1666f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * the ConnectivityService directly before a broadcast takes place to allow 1676f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * the PacManager to indicate that the broadcast should not be sent and the 1686f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * PacManager will trigger a new broadcast when it is ready. 1696f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * 1706f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * @param proxy Proxy information that is about to be broadcast. 1716f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * @return Returns true when the broadcast should not be sent 1726f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk */ 173207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk public synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) { 17483520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) { 17590760c8fa36574d6cc9224046758317ca6f640bfJason Monk if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) { 176decd295b1371238c97c170226c6145948492eda1Jason Monk // Allow to send broadcast, nothing to do. 177decd295b1371238c97c170226c6145948492eda1Jason Monk return false; 178decd295b1371238c97c170226c6145948492eda1Jason Monk } 1799ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 18083520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk mPacUrl = proxy.getPacFileUrl(); 181602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 1829ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mCurrentDelay = DELAY_1; 183d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasSentBroadcast = false; 184d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasDownloaded = false; 1859ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk getAlarmManager().cancel(mPacRefreshIntent); 1869ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk bind(); 1876f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk return true; 188602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } else { 1899ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk getAlarmManager().cancel(mPacRefreshIntent); 1909ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 191f6b46cb8b108cc8feee8ae68b979271fd6f72bf5Jason Monk mPacUrl = Uri.EMPTY; 1929ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mCurrentPac = null; 1939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (mProxyService != null) { 1949ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 1959ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService.stopPacSystem(); 1969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (RemoteException e) { 1979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.w(TAG, "Failed to stop PAC service", e); 1989ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } finally { 1999ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk unbind(); 2009ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 2019ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 202602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 2036f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk return false; 204602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 205602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 206602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 207602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk /** 208602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * Does a post and reports back the status code. 209602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * 210602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * @throws IOException 211602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk */ 21283520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk private static String get(Uri pacUri) throws IOException { 21383520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk URL url = new URL(pacUri.toString()); 214602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY); 2157d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen long contentLength = -1; 2167d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen try { 2177d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length")); 2187d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen } catch (NumberFormatException e) { 2197d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen // Ignore 2207d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen } 2217d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen if (contentLength > MAX_PAC_SIZE) { 2227d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen throw new IOException("PAC too big: " + contentLength + " bytes"); 2237d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen } 2247d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 2257d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen byte[] buffer = new byte[1024]; 2267d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen int count; 2277d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen while ((count = urlConnection.getInputStream().read(buffer)) != -1) { 2287d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen bytes.write(buffer, 0, count); 2297d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen if (bytes.size() > MAX_PAC_SIZE) { 2307d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen throw new IOException("PAC too big"); 2317d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen } 2327d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen } 2337d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen return bytes.toString(); 234602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 235602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 236602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private int getNextDelay(int currentDelay) { 237602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk if (++currentDelay > DELAY_4) { 238602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return DELAY_4; 239602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 240602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return currentDelay; 241602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 242602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 243602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private void longSchedule() { 244602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mCurrentDelay = DELAY_1; 245602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk setDownloadIn(DELAY_LONG); 246602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 247602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 248602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private void reschedule() { 249602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mCurrentDelay = getNextDelay(mCurrentDelay); 250602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk setDownloadIn(mCurrentDelay); 251602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 252602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 253602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private String getPacChangeDelay() { 254602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk final ContentResolver cr = mContext.getContentResolver(); 255602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 256602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk /** Check system properties for the default value then use secure settings value, if any. */ 257602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk String defaultDelay = SystemProperties.get( 258602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk "conn." + Settings.Global.PAC_CHANGE_DELAY, 259602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk DEFAULT_DELAYS); 260602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk String val = Settings.Global.getString(cr, Settings.Global.PAC_CHANGE_DELAY); 261602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return (val == null) ? defaultDelay : val; 262602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 263602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 264602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private long getDownloadDelay(int delayIndex) { 265602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk String[] list = getPacChangeDelay().split(" "); 266602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk if (delayIndex < list.length) { 267602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return Long.parseLong(list[delayIndex]); 268602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 269602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return 0; 270602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 271602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 272602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private void setDownloadIn(int delayIndex) { 273602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk long delay = getDownloadDelay(delayIndex); 274602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk long timeTillTrigger = 1000 * delay + SystemClock.elapsedRealtime(); 275602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk getAlarmManager().set(AlarmManager.ELAPSED_REALTIME, timeTillTrigger, mPacRefreshIntent); 276602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 277602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 278602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private boolean setCurrentProxyScript(String script) { 279a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville if (mProxyService == null) { 280a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville Log.e(TAG, "setCurrentProxyScript: no proxy service"); 281a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville return false; 282a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville } 283602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk try { 2849ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService.setPacFile(script); 285602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mCurrentPac = script; 286602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } catch (RemoteException e) { 287602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk Log.e(TAG, "Unable to set PAC file", e); 288602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 289602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return true; 290602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 2919ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 2929ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private void bind() { 2939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (mContext == null) { 2949ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "No context for binding"); 2959ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk return; 2969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 2979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Intent intent = new Intent(); 298da205a749fadb3a87357d9bd607f094c7717764aJason Monk intent.setClassName(PAC_PACKAGE, PAC_SERVICE); 299bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk if ((mProxyConnection != null) && (mConnection != null)) { 3004bf1d218576fa5721bab589cd5945dbe49f0d117Jason Monk // Already bound no need to bind again, just download the new file. 301baae57ab24db7d3b0bf7f84c05954173f1ee15fePaul Jensen mNetThreadHandler.post(mPacDownloader); 3026f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk return; 3036f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3049ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mConnection = new ServiceConnection() { 3059ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @Override 3069ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk public void onServiceDisconnected(ComponentName component) { 3079ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 3089ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService = null; 3099ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 3129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @Override 3139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk public void onServiceConnected(ComponentName component, IBinder binder) { 3149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 3159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 316da205a749fadb3a87357d9bd607f094c7717764aJason Monk Log.d(TAG, "Adding service " + PAC_SERVICE_NAME + " " 3179ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk + binder.getInterfaceDescriptor()); 3189ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (RemoteException e1) { 3199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "Remote Exception", e1); 3209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 321da205a749fadb3a87357d9bd607f094c7717764aJason Monk ServiceManager.addService(PAC_SERVICE_NAME, binder); 3229ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService = IProxyService.Stub.asInterface(binder); 3239ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (mProxyService == null) { 3249ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "No proxy service"); 3259ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } else { 3269ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 3279ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService.startPacSystem(); 3289ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (RemoteException e) { 3299ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e); 3309ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3317d2198b586bcfbf96fb627021a0eb85d32829cc0Paul Jensen mNetThreadHandler.post(mPacDownloader); 3329ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3339ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3349ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3359ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk }; 3369ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mContext.bindService(intent, mConnection, 3379ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE); 338da205a749fadb3a87357d9bd607f094c7717764aJason Monk 339da205a749fadb3a87357d9bd607f094c7717764aJason Monk intent = new Intent(); 340da205a749fadb3a87357d9bd607f094c7717764aJason Monk intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE); 341da205a749fadb3a87357d9bd607f094c7717764aJason Monk mProxyConnection = new ServiceConnection() { 342da205a749fadb3a87357d9bd607f094c7717764aJason Monk @Override 343da205a749fadb3a87357d9bd607f094c7717764aJason Monk public void onServiceDisconnected(ComponentName component) { 344da205a749fadb3a87357d9bd607f094c7717764aJason Monk } 345da205a749fadb3a87357d9bd607f094c7717764aJason Monk 346da205a749fadb3a87357d9bd607f094c7717764aJason Monk @Override 347da205a749fadb3a87357d9bd607f094c7717764aJason Monk public void onServiceConnected(ComponentName component, IBinder binder) { 3486f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk IProxyCallback callbackService = IProxyCallback.Stub.asInterface(binder); 3496f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk if (callbackService != null) { 3506f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk try { 3516f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk callbackService.getProxyPort(new IProxyPortListener.Stub() { 3526f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk @Override 3536f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk public void setProxyPort(int port) throws RemoteException { 354d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk if (mLastPort != -1) { 355d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk // Always need to send if port changed 356d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasSentBroadcast = false; 357d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 3586f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk mLastPort = port; 3596f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk if (port != -1) { 3606f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk Log.d(TAG, "Local proxy is bound on " + port); 361d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk sendProxyIfNeeded(); 3626f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } else { 3636f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk Log.e(TAG, "Received invalid port from Local Proxy," 3646f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk + " PAC will not be operational"); 3656f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3666f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3676f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk }); 3686f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } catch (RemoteException e) { 3696f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk e.printStackTrace(); 3706f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3716f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 372da205a749fadb3a87357d9bd607f094c7717764aJason Monk } 373da205a749fadb3a87357d9bd607f094c7717764aJason Monk }; 374da205a749fadb3a87357d9bd607f094c7717764aJason Monk mContext.bindService(intent, mProxyConnection, 375da205a749fadb3a87357d9bd607f094c7717764aJason Monk Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE); 3769ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3779ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 3789ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private void unbind() { 379bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk if (mConnection != null) { 380bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mContext.unbindService(mConnection); 381bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mConnection = null; 382bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk } 383bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk if (mProxyConnection != null) { 384bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mContext.unbindService(mProxyConnection); 385bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mProxyConnection = null; 386bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk } 387bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mProxyService = null; 388d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mLastPort = -1; 3896f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3906f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk 391207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk private void sendPacBroadcast(ProxyInfo proxy) { 392decd295b1371238c97c170226c6145948492eda1Jason Monk mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy)); 3939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 394d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk 395d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk private synchronized void sendProxyIfNeeded() { 396d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk if (!mHasDownloaded || (mLastPort == -1)) { 397d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk return; 398d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 399d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk if (!mHasSentBroadcast) { 400207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk sendPacBroadcast(new ProxyInfo(mPacUrl, mLastPort)); 401d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasSentBroadcast = true; 402d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 403d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 404602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk} 405