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; 2883520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monkimport android.net.Uri; 29decd295b1371238c97c170226c6145948492eda1Jason Monkimport android.os.Handler; 309ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport android.os.IBinder; 31602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.RemoteException; 32602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.ServiceManager; 33602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.SystemClock; 34602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.os.SystemProperties; 35602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.provider.Settings; 36602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport android.util.Log; 37602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 389ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport com.android.internal.annotations.GuardedBy; 396f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monkimport com.android.net.IProxyCallback; 406f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monkimport com.android.net.IProxyPortListener; 41602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport com.android.net.IProxyService; 429ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport com.android.server.IoThread; 43602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 449ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkimport libcore.io.Streams; 45602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 46602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.io.IOException; 47602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.URL; 48602b232a06ede86999aa362a12eb28cbc782dc1dJason Monkimport java.net.URLConnection; 49602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 50602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk/** 51602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * @hide 52602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk */ 539ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkpublic class PacManager { 54da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PAC_PACKAGE = "com.android.pacprocessor"; 55da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PAC_SERVICE = "com.android.pacprocessor.PacService"; 56da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PAC_SERVICE_NAME = "com.android.net.IProxyService"; 57602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 58da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PROXY_PACKAGE = "com.android.proxyhandler"; 59da205a749fadb3a87357d9bd607f094c7717764aJason Monk public static final String PROXY_SERVICE = "com.android.proxyhandler.ProxyService"; 60602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 619ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private static final String TAG = "PacManager"; 62602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 63602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH"; 64602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 65602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final String DEFAULT_DELAYS = "8 32 120 14400 43200"; 66602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final int DELAY_1 = 0; 67602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final int DELAY_4 = 3; 68602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private static final int DELAY_LONG = 4; 69602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 70602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk /** Keep these values up-to-date with ProxyService.java */ 71602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk public static final String KEY_PROXY = "keyProxy"; 72602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private String mCurrentPac; 739ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @GuardedBy("mProxyLock") 74f6b46cb8b108cc8feee8ae68b979271fd6f72bf5Jason Monk private Uri mPacUrl = Uri.EMPTY; 75602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 76602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private AlarmManager mAlarmManager; 779ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @GuardedBy("mProxyLock") 78602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private IProxyService mProxyService; 79602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private PendingIntent mPacRefreshIntent; 809ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private ServiceConnection mConnection; 81da205a749fadb3a87357d9bd607f094c7717764aJason Monk private ServiceConnection mProxyConnection; 82602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private Context mContext; 83602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 84602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private int mCurrentDelay; 856f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk private int mLastPort; 86602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 87d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk private boolean mHasSentBroadcast; 88d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk private boolean mHasDownloaded; 89d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk 90decd295b1371238c97c170226c6145948492eda1Jason Monk private Handler mConnectivityHandler; 91decd295b1371238c97c170226c6145948492eda1Jason Monk private int mProxyMessage; 92decd295b1371238c97c170226c6145948492eda1Jason Monk 939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk /** 949ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac. 959ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk */ 969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private final Object mProxyLock = new Object(); 979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 989ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private Runnable mPacDownloader = new Runnable() { 999ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @Override 1009ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk public void run() { 1019ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk String file; 1029ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 10383520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk if (Uri.EMPTY.equals(mPacUrl)) return; 1049ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 1059ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk file = get(mPacUrl); 1069ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (IOException ioe) { 1079ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk file = null; 1089ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.w(TAG, "Failed to load PAC file: " + ioe); 1099ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (file != null) { 1129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 1139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (!file.equals(mCurrentPac)) { 1149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk setCurrentProxyScript(file); 1159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1169ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 117d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasDownloaded = true; 118d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk sendProxyIfNeeded(); 1199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk longSchedule(); 1209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } else { 1219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk reschedule(); 1229ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1239ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1249ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk }; 1259ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 126602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk class PacRefreshIntentReceiver extends BroadcastReceiver { 127602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk public void onReceive(Context context, Intent intent) { 1289ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk IoThread.getHandler().post(mPacDownloader); 129602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 130602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 131602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 132decd295b1371238c97c170226c6145948492eda1Jason Monk public PacManager(Context context, Handler handler, int proxyMessage) { 133602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mContext = context; 1346f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk mLastPort = -1; 135602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 136602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mPacRefreshIntent = PendingIntent.getBroadcast( 137602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk context, 0, new Intent(ACTION_PAC_REFRESH), 0); 138602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk context.registerReceiver(new PacRefreshIntentReceiver(), 139602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk new IntentFilter(ACTION_PAC_REFRESH)); 140decd295b1371238c97c170226c6145948492eda1Jason Monk mConnectivityHandler = handler; 141decd295b1371238c97c170226c6145948492eda1Jason Monk mProxyMessage = proxyMessage; 142602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 143602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 144602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private AlarmManager getAlarmManager() { 145602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk if (mAlarmManager == null) { 146602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 147602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 148602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return mAlarmManager; 149602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 150602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 1516f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk /** 1526f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * Updates the PAC Manager with current Proxy information. This is called by 1536f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * the ConnectivityService directly before a broadcast takes place to allow 1546f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * the PacManager to indicate that the broadcast should not be sent and the 1556f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * PacManager will trigger a new broadcast when it is ready. 1566f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * 1576f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * @param proxy Proxy information that is about to be broadcast. 1586f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk * @return Returns true when the broadcast should not be sent 1596f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk */ 160207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk public synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) { 16183520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) { 16290760c8fa36574d6cc9224046758317ca6f640bfJason Monk if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) { 163decd295b1371238c97c170226c6145948492eda1Jason Monk // Allow to send broadcast, nothing to do. 164decd295b1371238c97c170226c6145948492eda1Jason Monk return false; 165decd295b1371238c97c170226c6145948492eda1Jason Monk } 1669ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 16783520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk mPacUrl = proxy.getPacFileUrl(); 168602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 1699ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mCurrentDelay = DELAY_1; 170d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasSentBroadcast = false; 171d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasDownloaded = false; 1729ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk getAlarmManager().cancel(mPacRefreshIntent); 1739ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk bind(); 1746f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk return true; 175602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } else { 1769ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk getAlarmManager().cancel(mPacRefreshIntent); 1779ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 178f6b46cb8b108cc8feee8ae68b979271fd6f72bf5Jason Monk mPacUrl = Uri.EMPTY; 1799ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mCurrentPac = null; 1809ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (mProxyService != null) { 1819ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 1829ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService.stopPacSystem(); 1839ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (RemoteException e) { 1849ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.w(TAG, "Failed to stop PAC service", e); 1859ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } finally { 1869ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk unbind(); 1879ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 1889ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 189602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 1906f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk return false; 191602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 192602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 193602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 194602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk /** 195602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * Does a post and reports back the status code. 196602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * 197602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk * @throws IOException 198602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk */ 19983520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk private static String get(Uri pacUri) throws IOException { 20083520b95124e0fcaaf3154a7a267f6be0205bc74Jason Monk URL url = new URL(pacUri.toString()); 201602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY); 2029ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk return new String(Streams.readFully(urlConnection.getInputStream())); 203602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 204602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 205602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private int getNextDelay(int currentDelay) { 206602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk if (++currentDelay > DELAY_4) { 207602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return DELAY_4; 208602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 209602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return currentDelay; 210602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 211602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 212602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private void longSchedule() { 213602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mCurrentDelay = DELAY_1; 214602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk setDownloadIn(DELAY_LONG); 215602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 216602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 217602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private void reschedule() { 218602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mCurrentDelay = getNextDelay(mCurrentDelay); 219602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk setDownloadIn(mCurrentDelay); 220602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 221602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 222602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private String getPacChangeDelay() { 223602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk final ContentResolver cr = mContext.getContentResolver(); 224602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 225602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk /** Check system properties for the default value then use secure settings value, if any. */ 226602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk String defaultDelay = SystemProperties.get( 227602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk "conn." + Settings.Global.PAC_CHANGE_DELAY, 228602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk DEFAULT_DELAYS); 229602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk String val = Settings.Global.getString(cr, Settings.Global.PAC_CHANGE_DELAY); 230602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return (val == null) ? defaultDelay : val; 231602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 232602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 233602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private long getDownloadDelay(int delayIndex) { 234602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk String[] list = getPacChangeDelay().split(" "); 235602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk if (delayIndex < list.length) { 236602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return Long.parseLong(list[delayIndex]); 237602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 238602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return 0; 239602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 240602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 241602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private void setDownloadIn(int delayIndex) { 242602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk long delay = getDownloadDelay(delayIndex); 243602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk long timeTillTrigger = 1000 * delay + SystemClock.elapsedRealtime(); 244602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk getAlarmManager().set(AlarmManager.ELAPSED_REALTIME, timeTillTrigger, mPacRefreshIntent); 245602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 246602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk 247602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk private boolean setCurrentProxyScript(String script) { 248a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville if (mProxyService == null) { 249a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville Log.e(TAG, "setCurrentProxyScript: no proxy service"); 250a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville return false; 251a48ad8bd858d6ffe77838a282dbf71e01967957cWink Saville } 252602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk try { 2539ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService.setPacFile(script); 254602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk mCurrentPac = script; 255602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } catch (RemoteException e) { 256602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk Log.e(TAG, "Unable to set PAC file", e); 257602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 258602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk return true; 259602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk } 2609ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 2619ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private void bind() { 2629ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (mContext == null) { 2639ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "No context for binding"); 2649ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk return; 2659ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 2669ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Intent intent = new Intent(); 267da205a749fadb3a87357d9bd607f094c7717764aJason Monk intent.setClassName(PAC_PACKAGE, PAC_SERVICE); 268bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk if ((mProxyConnection != null) && (mConnection != null)) { 2694bf1d218576fa5721bab589cd5945dbe49f0d117Jason Monk // Already bound no need to bind again, just download the new file. 2704bf1d218576fa5721bab589cd5945dbe49f0d117Jason Monk IoThread.getHandler().post(mPacDownloader); 2716f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk return; 2726f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 2739ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mConnection = new ServiceConnection() { 2749ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @Override 2759ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk public void onServiceDisconnected(ComponentName component) { 2769ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 2779ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService = null; 2789ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 2799ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 2809ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 2819ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk @Override 2829ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk public void onServiceConnected(ComponentName component, IBinder binder) { 2839ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk synchronized (mProxyLock) { 2849ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 285da205a749fadb3a87357d9bd607f094c7717764aJason Monk Log.d(TAG, "Adding service " + PAC_SERVICE_NAME + " " 2869ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk + binder.getInterfaceDescriptor()); 2879ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (RemoteException e1) { 2889ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "Remote Exception", e1); 2899ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 290da205a749fadb3a87357d9bd607f094c7717764aJason Monk ServiceManager.addService(PAC_SERVICE_NAME, binder); 2919ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService = IProxyService.Stub.asInterface(binder); 2929ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk if (mProxyService == null) { 2939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "No proxy service"); 2949ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } else { 2959ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk try { 2969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mProxyService.startPacSystem(); 2979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } catch (RemoteException e) { 2989ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e); 2999ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3009ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk IoThread.getHandler().post(mPacDownloader); 3019ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3029ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3039ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3049ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk }; 3059ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk mContext.bindService(intent, mConnection, 3069ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE); 307da205a749fadb3a87357d9bd607f094c7717764aJason Monk 308da205a749fadb3a87357d9bd607f094c7717764aJason Monk intent = new Intent(); 309da205a749fadb3a87357d9bd607f094c7717764aJason Monk intent.setClassName(PROXY_PACKAGE, PROXY_SERVICE); 310da205a749fadb3a87357d9bd607f094c7717764aJason Monk mProxyConnection = new ServiceConnection() { 311da205a749fadb3a87357d9bd607f094c7717764aJason Monk @Override 312da205a749fadb3a87357d9bd607f094c7717764aJason Monk public void onServiceDisconnected(ComponentName component) { 313da205a749fadb3a87357d9bd607f094c7717764aJason Monk } 314da205a749fadb3a87357d9bd607f094c7717764aJason Monk 315da205a749fadb3a87357d9bd607f094c7717764aJason Monk @Override 316da205a749fadb3a87357d9bd607f094c7717764aJason Monk public void onServiceConnected(ComponentName component, IBinder binder) { 3176f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk IProxyCallback callbackService = IProxyCallback.Stub.asInterface(binder); 3186f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk if (callbackService != null) { 3196f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk try { 3206f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk callbackService.getProxyPort(new IProxyPortListener.Stub() { 3216f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk @Override 3226f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk public void setProxyPort(int port) throws RemoteException { 323d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk if (mLastPort != -1) { 324d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk // Always need to send if port changed 325d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasSentBroadcast = false; 326d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 3276f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk mLastPort = port; 3286f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk if (port != -1) { 3296f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk Log.d(TAG, "Local proxy is bound on " + port); 330d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk sendProxyIfNeeded(); 3316f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } else { 3326f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk Log.e(TAG, "Received invalid port from Local Proxy," 3336f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk + " PAC will not be operational"); 3346f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3356f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3366f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk }); 3376f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } catch (RemoteException e) { 3386f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk e.printStackTrace(); 3396f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3406f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 341da205a749fadb3a87357d9bd607f094c7717764aJason Monk } 342da205a749fadb3a87357d9bd607f094c7717764aJason Monk }; 343da205a749fadb3a87357d9bd607f094c7717764aJason Monk mContext.bindService(intent, mProxyConnection, 344da205a749fadb3a87357d9bd607f094c7717764aJason Monk Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE); 3459ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 3469ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk 3479ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk private void unbind() { 348bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk if (mConnection != null) { 349bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mContext.unbindService(mConnection); 350bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mConnection = null; 351bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk } 352bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk if (mProxyConnection != null) { 353bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mContext.unbindService(mProxyConnection); 354bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mProxyConnection = null; 355bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk } 356bc018d89c27cdd93d1c0222a6e27965455974b9eJason Monk mProxyService = null; 357d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mLastPort = -1; 3586f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk } 3596f8a68f49a7e8cf86104e721a1e8be7568b5f730Jason Monk 360207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk private void sendPacBroadcast(ProxyInfo proxy) { 361decd295b1371238c97c170226c6145948492eda1Jason Monk mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy)); 3629ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk } 363d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk 364d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk private synchronized void sendProxyIfNeeded() { 365d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk if (!mHasDownloaded || (mLastPort == -1)) { 366d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk return; 367d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 368d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk if (!mHasSentBroadcast) { 369207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk sendPacBroadcast(new ProxyInfo(mPacUrl, mLastPort)); 370d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk mHasSentBroadcast = true; 371d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 372d443479a45279f8f52daf4034698f2ab3c3e62f1Jason Monk } 373602b232a06ede86999aa362a12eb28cbc782dc1dJason Monk} 374