| Index: src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| diff --git a/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java b/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| index 34611e11de0c3b4f55ec776cbe2360951a9090a5..67c58c4220d8a63dc180716688e4ef7e88d34f89 100644 |
| --- a/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| +++ b/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| @@ -19,16 +19,23 @@ package org.adblockplus.android.configurators; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| +import java.io.IOException; |
| import java.net.InetAddress; |
| +import java.util.ArrayList; |
| import java.util.List; |
| +import java.util.concurrent.Semaphore; |
| +import java.util.concurrent.TimeoutException; |
| import org.adblockplus.android.Utils; |
| -import com.stericson.RootTools.RootTools; |
| - |
| import android.content.Context; |
| import android.util.Log; |
| +import com.stericson.RootTools.RootTools; |
| +import com.stericson.RootTools.exceptions.RootDeniedException; |
| +import com.stericson.RootTools.execution.Command; |
| +import com.stericson.RootTools.execution.Shell; |
| + |
| /** |
| * Proxy registration using RootTools and iptables. |
| */ |
| @@ -48,11 +55,28 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| this.context = context; |
| } |
| + private static List<String> runRootCommand(final String command, final int timeout) throws IOException, TimeoutException, |
| + RootDeniedException |
| + { |
| + final CapturingOutputCommand cmd = new CapturingOutputCommand(0, DEFAULT_TIMEOUT, command); |
| + |
| + Shell.runRootCommand(cmd); |
| + |
| + cmd.waitForCompletion(); |
| + |
| + return cmd.output; |
| + } |
| + |
| @Override |
| public boolean initialize() |
| { |
| try |
| { |
| + // If we don't set `handlerEnabled` to `false`, RootTools uses Handlers |
| + // which get executed on the UI thread which in fact renders it useless |
| + // for our purpose (as it either finished too late or blocks forever). |
| + RootTools.handlerEnabled = false; |
| + |
| if (!RootTools.isAccessGiven()) |
| { |
| throw new IllegalStateException("No root access"); |
| @@ -60,14 +84,14 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| final String path = getIptablesExecutablePath(); |
| - RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
| + runRootCommand("chmod 700 " + path, DEFAULT_TIMEOUT); |
| boolean compatible = false; |
| boolean version = false; |
| final String command = path + " --version\n" + path + " -L -t nat -n\n"; |
| - final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); |
| + final List<String> result = runRootCommand(command, DEFAULT_TIMEOUT); |
| for (final String line : result) |
| { |
| @@ -123,7 +147,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| cmd.append(this.iptables); |
| cmd.append(IPTABLES_ADD_HTTP.replace("{{PORT}}", String.valueOf(port))); |
| - RootTools.sendShell(cmd.toString(), DEFAULT_TIMEOUT); |
| + runRootCommand(cmd.toString(), DEFAULT_TIMEOUT); |
| this.isRegistered = true; |
| @@ -142,7 +166,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| { |
| try |
| { |
| - RootTools.sendShell(this.iptables + " -t nat -F OUTPUT", DEFAULT_TIMEOUT); |
| + runRootCommand(this.iptables + " -t nat -F OUTPUT", DEFAULT_TIMEOUT); |
| } |
| catch (final Exception e) |
| { |
| @@ -178,14 +202,14 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| final String path = ipt.getAbsolutePath(); |
| - RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
| + runRootCommand("chmod 700 " + path, DEFAULT_TIMEOUT); |
| boolean compatible = false; |
| boolean version = false; |
| String command = path + " --version\n" + path + " -L -t nat -n\n"; |
| - final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); |
| + final List<String> result = runRootCommand(command, DEFAULT_TIMEOUT); |
| for (final String line : result) |
| { |
| @@ -206,7 +230,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| command = path + " -L -t nat -n\n"; |
| - return RootTools.sendShell(command, DEFAULT_TIMEOUT); |
| + return runRootCommand(command, DEFAULT_TIMEOUT); |
| } |
| catch (final Throwable t) |
| { |
| @@ -237,4 +261,41 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| { |
| return "[ProxyConfigurator: " + this.getType() + "]"; |
| } |
| + |
| + private final static class CapturingOutputCommand extends Command |
| + { |
| + private final Semaphore running = new Semaphore(1); |
| + |
| + public List<String> output = new ArrayList<String>(); |
| + |
| + public CapturingOutputCommand(final int id, final int timeout, final String command) |
| + { |
| + super(id, timeout, command); |
| + |
| + this.running.acquireUninterruptibly(); |
| + } |
| + |
| + @Override |
| + public void commandOutput(int id, String line) |
| + { |
| + this.output.add(line); |
| + } |
| + |
| + @Override |
| + public void commandCompleted(int id, int exitCode) |
| + { |
| + this.running.release(); |
| + } |
| + |
| + @Override |
| + public void commandTerminated(int id, String reason) |
| + { |
| + this.running.release(); |
| + } |
| + |
| + public void waitForCompletion() |
| + { |
| + this.running.acquireUninterruptibly(); |
| + } |
| + } |
| } |