| Index: src/org/adblockplus/android/ProxyService.java |
| =================================================================== |
| --- a/src/org/adblockplus/android/ProxyService.java |
| +++ b/src/org/adblockplus/android/ProxyService.java |
| @@ -43,6 +43,7 @@ |
| import android.content.res.Resources; |
| import android.net.ConnectivityManager; |
| import android.net.NetworkInfo; |
| +import android.net.Proxy; |
| import android.os.Binder; |
| import android.os.Build; |
| import android.os.Handler; |
| @@ -102,10 +103,13 @@ |
| */ |
| private boolean transparent = false; |
| /** |
| - * Indicates that service has autoconfigured Android proxy settings (version |
| - * 3.1+). |
| + * Indicates that service has autoconfigured Android proxy settings (version 3.1+). |
| */ |
| private boolean nativeProxy = false; |
| + /** |
| + * Indicates that Android proxy settings are correctly configured (version 4.1.2+ 4.2.2+). |
| + */ |
| + private boolean proxyManualyConfigured = false; |
| private String iptables = null; |
| @@ -117,7 +121,7 @@ |
| // Get port for local proxy |
| SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); |
| Resources resources = getResources(); |
| - |
| + |
| String p = prefs.getString(getString(R.string.pref_port), null); |
| try |
| { |
| @@ -144,7 +148,8 @@ |
| proxyExcl = System.getProperty("http.nonProxyHosts"); |
| Log.d(TAG, "PRX: " + proxyHost + ":" + proxyPort + "(" + proxyExcl + ")"); |
| - String[] px = ProxySettings.getUserProxy(getApplicationContext()); // not used but left for future reference |
| + // not used but left for future reference |
|
Felix Dahlke
2013/02/22 09:11:14
Why would we need that in the future? Even if, we
Andrey Novikov
2013/02/22 09:25:05
You asked me this already in previous reviews. :)
|
| + String[] px = ProxySettings.getUserProxy(getApplicationContext()); |
| if (px != null) |
| Log.d(TAG, "PRX: " + px[0] + ":" + px[1] + "(" + px[2] + ")"); |
| } |
| @@ -201,10 +206,10 @@ |
| // Try to set native proxy |
| nativeProxy = ProxySettings.setConnectionProxy(getApplicationContext(), LOCALHOST, port, ""); |
| - if (nativeProxy) |
| + if (hasNativeProxy) |
| { |
| registerReceiver(connectionReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); |
| - registerReceiver(connectionReceiver, new IntentFilter("android.net.wifi.LINK_CONFIGURATION_CHANGED")); |
| + registerReceiver(connectionReceiver, new IntentFilter(Proxy.PROXY_CHANGE_ACTION)); |
| } |
| } |
| @@ -257,15 +262,9 @@ |
| prefs.registerOnSharedPreferenceChangeListener(this); |
| - String msg = getString(transparent ? R.string.notif_all : nativeProxy ? R.string.notif_wifi : R.string.notif_waiting); |
| - if (!transparent && !nativeProxy) |
| - { |
| - // Initiate no traffic check |
| - notrafficHandler = new Handler(); |
| - notrafficHandler.postDelayed(noTraffic, NO_TRAFFIC_TIMEOUT); |
| - } |
| // Lock service |
| boolean hideIcon = prefs.getBoolean(getString(R.string.pref_hideicon), resources.getBoolean(R.bool.def_hideicon)); |
| + String msg = getString(transparent ? R.string.notif_all : nativeProxy ? R.string.notif_wifi : R.string.notif_waiting); |
| ongoingNotification = new Notification(); |
| ongoingNotification.when = 0; |
| contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Preferences.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK), 0); |
| @@ -273,7 +272,15 @@ |
| ongoingNotification.setLatestEventInfo(getApplicationContext(), getText(R.string.app_name), msg, contentIntent); |
| startForeground(ONGOING_NOTIFICATION_ID, ongoingNotification); |
| - sendBroadcast(new Intent(BROADCAST_STATE_CHANGED).putExtra("enabled", true).putExtra("port", port).putExtra("manual", isManual())); |
| + // If automatic setting of proxy was blocked, check if user has set it manually |
| + boolean manual = isManual(); |
| + if (manual && hasNativeProxy) |
| + { |
| + ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); |
| + updateNoTrafficCheck(connectivityManager); |
| + } |
| + |
| + sendStateChangedBroadcast(); |
| Log.i(TAG, "Service started"); |
| } |
| @@ -288,7 +295,7 @@ |
| { |
| super.onDestroy(); |
| - stopNoTrafficCheck(false); |
| + stopNoTrafficCheck(false, false); |
| unregisterReceiver(matchesReceiver); |
| unregisterReceiver(proxyReceiver); |
| @@ -296,7 +303,8 @@ |
| // Stop IP redirecting |
| if (transparent) |
| { |
| - new Thread() { |
| + new Thread() |
| + { |
| @Override |
| public void run() |
| { |
| @@ -312,10 +320,12 @@ |
| }.start(); |
| } |
| + if (hasNativeProxy) |
| + unregisterReceiver(connectionReceiver); |
| + |
| // Clear native proxy |
| if (nativeProxy) |
| { |
| - unregisterReceiver(connectionReceiver); |
| clearConnectionProxy(); |
| } |
| @@ -335,8 +345,8 @@ |
| } |
| /** |
| - * Restores system proxy settings via native call on Android 3.1+ devices using |
| - * Java reflection. |
| + * Restores system proxy settings via native call on Android 3.1+ devices |
| + * using Java reflection. |
| */ |
| private void clearConnectionProxy() |
| { |
| @@ -478,6 +488,14 @@ |
| { |
| return !transparent && !nativeProxy; |
| } |
| + |
| + /** |
| + * Checks whether traffic check is pending |
| + */ |
| + public boolean noTraffic() |
| + { |
| + return notrafficHandler != null; |
| + } |
| /** |
| * Checks if specified host is local. |
| @@ -512,8 +530,9 @@ |
| /** |
| * Initializes iptables executable. |
| - * |
| - * @throws FileNotFoundException If iptables initialization failed due to provided reasons. |
| + * |
| + * @throws FileNotFoundException |
| + * If iptables initialization failed due to provided reasons. |
| */ |
| private void initIptables() throws IOException, RootToolsException, TimeoutException, FileNotFoundException |
| { |
| @@ -573,34 +592,95 @@ |
| } |
| /** |
| + * Raises or removes no traffic notification based on current link proxy |
| + * settings |
| + */ |
| + private void updateNoTrafficCheck(ConnectivityManager connectivityManager) |
| + { |
| + try |
| + { |
| + Object pp = ProxySettings.getActiveLinkProxy(connectivityManager); |
| + String[] userProxy = ProxySettings.getUserProxy(pp); |
| + if (userProxy != null) |
| + Log.i(TAG, "Proxy settings: " + userProxy[0] + ":" + userProxy[1] + "(" + userProxy[2] + ")"); |
| + updateNoTrafficCheck(userProxy); |
| + } |
| + catch (Exception e) |
| + { |
| + // This should not happen |
| + Log.e(TAG, null, e); |
| + } |
| + } |
| + |
| + /** |
| + * Raises or removes no traffic notification based on the user proxy settings |
| + */ |
| + private void updateNoTrafficCheck(String[] userProxy) |
| + { |
| + boolean ourProxy = userProxy != null && isLocalHost(userProxy[0]) && Integer.valueOf(userProxy[1]) == port; |
| + if (ourProxy) |
| + { |
| + stopNoTrafficCheck(true, true); |
| + } |
| + else |
| + { |
| + // Initiate no traffic check |
| + notrafficHandler = new Handler(); |
| + notrafficHandler.postDelayed(noTraffic, NO_TRAFFIC_TIMEOUT); |
| + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
| + ongoingNotification.setLatestEventInfo(ProxyService.this, getText(R.string.app_name), getText(R.string.notif_waiting), contentIntent); |
| + notificationManager.notify(ONGOING_NOTIFICATION_ID, ongoingNotification); |
| + } |
| + if (ourProxy != proxyManualyConfigured) |
| + { |
| + proxyManualyConfigured = ourProxy; |
| + sendStateChangedBroadcast(); |
| + } |
| + } |
| + |
| + /** |
| * Stops no traffic check, optionally resetting notification message. |
| - * |
| + * |
| * @param changeStatus |
| * true if notification message should be set to normal operating |
| * mode |
| + * @param forceMessageReset |
| + * if true unconditionally reset main notification message |
| */ |
| - private void stopNoTrafficCheck(boolean changeStatus) |
| + private void stopNoTrafficCheck(boolean changeStatus, boolean forceMessageReset) |
| { |
| if (notrafficHandler != null) |
| { |
| notrafficHandler.removeCallbacks(noTraffic); |
| - if (changeStatus) |
| - { |
| - NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
| - ongoingNotification.setLatestEventInfo(ProxyService.this, getText(R.string.app_name), getText(R.string.notif_wifi), contentIntent); |
| - notificationManager.notify(ONGOING_NOTIFICATION_ID, ongoingNotification); |
| - } |
| + proxyManualyConfigured = true; |
| + sendStateChangedBroadcast(); |
| + } |
| + if (changeStatus && (notrafficHandler != null || forceMessageReset)) |
| + { |
| + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
| + ongoingNotification.setLatestEventInfo(ProxyService.this, getText(R.string.app_name), getText(R.string.notif_wifi), contentIntent); |
| + notificationManager.notify(ONGOING_NOTIFICATION_ID, ongoingNotification); |
| } |
| notrafficHandler = null; |
| } |
| - |
| + |
| public void setEmptyIcon(boolean empty) |
| { |
| ongoingNotification.icon = empty ? R.drawable.transparent : R.drawable.ic_stat_blocking; |
| - NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
| + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
| notificationManager.notify(ONGOING_NOTIFICATION_ID, ongoingNotification); |
| } |
| + public void sendStateChangedBroadcast() |
| + { |
| + Log.i(TAG, "Broadcasting " + BROADCAST_STATE_CHANGED); |
| + boolean manual = isManual(); |
| + Intent stateIntent = new Intent(BROADCAST_STATE_CHANGED).putExtra("enabled", true).putExtra("port", port).putExtra("manual", manual); |
| + if (manual) |
| + stateIntent.putExtra("configured", proxyManualyConfigured); |
| + sendBroadcast(stateIntent); |
| + } |
| + |
| private final IBinder binder = new LocalBinder(); |
| public final class LocalBinder extends Binder |
| @@ -621,7 +701,8 @@ |
| * Executed if no traffic is detected after a period of time. Notifies user |
| * about possible configuration problems. |
| */ |
| - private Runnable noTraffic = new Runnable() { |
| + private Runnable noTraffic = new Runnable() |
| + { |
| public void run() |
| { |
| // Show warning notification |
| @@ -642,19 +723,21 @@ |
| /** |
| * Stops no traffic check if traffic is detected by proxy service. |
| */ |
| - private BroadcastReceiver matchesReceiver = new BroadcastReceiver() { |
| + private BroadcastReceiver matchesReceiver = new BroadcastReceiver() |
| + { |
| @Override |
| public void onReceive(final Context context, Intent intent) |
| { |
| if (intent.getAction().equals(AdblockPlus.BROADCAST_FILTER_MATCHES)) |
| - stopNoTrafficCheck(true); |
| + stopNoTrafficCheck(true, false); |
| } |
| }; |
| /** |
| * Stops service if proxy fails. |
| */ |
| - private BroadcastReceiver proxyReceiver = new BroadcastReceiver() { |
| + private BroadcastReceiver proxyReceiver = new BroadcastReceiver() |
| + { |
| @Override |
| public void onReceive(final Context context, Intent intent) |
| { |
| @@ -669,12 +752,14 @@ |
| * Monitors system network connection settings changes and updates proxy |
| * settings accordingly. |
| */ |
| - private BroadcastReceiver connectionReceiver = new BroadcastReceiver() { |
| + private BroadcastReceiver connectionReceiver = new BroadcastReceiver() |
| + { |
| @Override |
| public void onReceive(Context ctx, Intent intent) |
| { |
| String action = intent.getAction(); |
| Log.i(TAG, "Action: " + action); |
| + // Connectivity change |
| if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) |
| { |
| ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); |
| @@ -684,39 +769,50 @@ |
| String typeName = info.getTypeName(); |
| String subtypeName = info.getSubtypeName(); |
| boolean available = info.isAvailable(); |
| + |
| Log.i(TAG, "Network Type: " + typeName + ", subtype: " + subtypeName + ", available: " + available); |
| if (info.getType() == ConnectivityManager.TYPE_WIFI) |
| - ProxySettings.setConnectionProxy(getApplicationContext(), LOCALHOST, port, ""); |
| + { |
| + if (nativeProxy) |
| + { |
| + ProxySettings.setConnectionProxy(getApplicationContext(), LOCALHOST, port, ""); |
| + } |
| + else |
| + { |
| + updateNoTrafficCheck(connectivityManager); |
| + } |
| + } |
| } |
| - else if ("android.net.wifi.LINK_CONFIGURATION_CHANGED".equals(action)) |
| + // Proxy change |
| + else if (Proxy.PROXY_CHANGE_ACTION.equals(action)) |
| { |
| - Object lp = intent.getParcelableExtra("linkProperties"); |
| - Method method; |
| + Object pp = intent.getParcelableExtra("proxy"); |
| try |
| { |
| - /* |
| - * lp.getHttpProxy(); |
| - */ |
| - method = lp.getClass().getMethod("getHttpProxy"); |
| - Object pp = method.invoke(lp); |
| - |
| String[] userProxy = ProxySettings.getUserProxy(pp); |
| - if (userProxy != null && Integer.valueOf(userProxy[1]) != port) |
| + if (nativeProxy) |
| { |
| - Log.i(TAG, "User has set new proxy: " + userProxy[0] + ":" + userProxy[1] + "(" + userProxy[2] + ")"); |
| - if (proxy != null) |
| + if (userProxy != null && Integer.valueOf(userProxy[1]) != port) |
| { |
| - configureUserProxy(proxyConfiguration, userProxy[0], userProxy[1], userProxy[2], null, null); |
| - proxy.restart(proxyConfiguration.getProperty("handler")); |
| + Log.i(TAG, "User has set new proxy: " + userProxy[0] + ":" + userProxy[1] + "(" + userProxy[2] + ")"); |
| + if (proxy != null) |
| + { |
| + configureUserProxy(proxyConfiguration, userProxy[0], userProxy[1], userProxy[2], null, null); |
| + proxy.restart(proxyConfiguration.getProperty("handler")); |
| + } |
| } |
| } |
| + else |
| + { |
| + Log.i(TAG, "User has set proxy: " + userProxy[0] + ":" + userProxy[1] + "(" + userProxy[2] + ")"); |
| + updateNoTrafficCheck(userProxy); |
| + } |
| } |
| catch (Exception e) |
| { |
| // This should not happen |
| Log.e(TAG, null, e); |
| } |
| - |
| } |
| } |
| }; |