cleaned up iptables binary handling
This commit is contained in:
parent
4bbca2927d
commit
b8af143d5f
|
@ -43,5 +43,6 @@ public interface TorConstants {
|
||||||
public final static String PREF_HAS_ROOT = "has_root";
|
public final static String PREF_HAS_ROOT = "has_root";
|
||||||
public final static int RESULT_CLOSE_ALL = 0;
|
public final static int RESULT_CLOSE_ALL = 0;
|
||||||
|
|
||||||
|
public final static String PREF_USE_SYSTEM_IPTABLES = "pref_use_sys_iptables";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
package org.torproject.android.service;
|
package org.torproject.android.service;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -22,6 +24,7 @@ import org.torproject.android.TorConstants;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class TorBinaryInstaller implements TorServiceConstants {
|
public class TorBinaryInstaller implements TorServiceConstants {
|
||||||
|
|
||||||
|
@ -29,6 +32,8 @@ public class TorBinaryInstaller implements TorServiceConstants {
|
||||||
File installFolder;
|
File installFolder;
|
||||||
Context context;
|
Context context;
|
||||||
|
|
||||||
|
private static int isARMv6 = -1;
|
||||||
|
|
||||||
public TorBinaryInstaller (Context context, File installFolder)
|
public TorBinaryInstaller (Context context, File installFolder)
|
||||||
{
|
{
|
||||||
this.installFolder = installFolder;
|
this.installFolder = installFolder;
|
||||||
|
@ -151,4 +156,97 @@ public class TorBinaryInstaller implements TorServiceConstants {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this is an ARMv6 device
|
||||||
|
* @return true if this is ARMv6
|
||||||
|
*/
|
||||||
|
private static boolean isARMv6() {
|
||||||
|
if (isARMv6 == -1) {
|
||||||
|
BufferedReader r = null;
|
||||||
|
try {
|
||||||
|
isARMv6 = 0;
|
||||||
|
r = new BufferedReader(new FileReader("/proc/cpuinfo"));
|
||||||
|
for (String line = r.readLine(); line != null; line = r.readLine()) {
|
||||||
|
if (line.startsWith("Processor") && line.contains("ARMv6")) {
|
||||||
|
isARMv6 = 1;
|
||||||
|
break;
|
||||||
|
} else if (line.startsWith("CPU architecture") && (line.contains("6TE") || line.contains("5TE"))) {
|
||||||
|
isARMv6 = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
} finally {
|
||||||
|
if (r != null) try {r.close();} catch (Exception ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (isARMv6 == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a raw resource file, given its ID to the given location
|
||||||
|
* @param ctx context
|
||||||
|
* @param resid resource id
|
||||||
|
* @param file destination file
|
||||||
|
* @param mode file permissions (E.g.: "755")
|
||||||
|
* @throws IOException on error
|
||||||
|
* @throws InterruptedException when interrupted
|
||||||
|
*/
|
||||||
|
private static void copyRawFile(Context ctx, int resid, File file, String mode) throws IOException, InterruptedException
|
||||||
|
{
|
||||||
|
final String abspath = file.getAbsolutePath();
|
||||||
|
// Write the iptables binary
|
||||||
|
final FileOutputStream out = new FileOutputStream(file);
|
||||||
|
final InputStream is = ctx.getResources().openRawResource(resid);
|
||||||
|
byte buf[] = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = is.read(buf)) > 0) {
|
||||||
|
out.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
is.close();
|
||||||
|
// Change the permissions
|
||||||
|
Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Asserts that the binary files are installed in the cache directory.
|
||||||
|
* @param ctx context
|
||||||
|
* @param showErrors indicates if errors should be alerted
|
||||||
|
* @return false if the binary files could not be installed
|
||||||
|
*/
|
||||||
|
public static boolean assertIpTablesBinaries(Context ctx, boolean showErrors) throws Exception {
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
// Check iptables_g1
|
||||||
|
File file = new File(ctx.getDir("bin",0), "iptables");
|
||||||
|
|
||||||
|
if ((!file.exists()) && isARMv6()) {
|
||||||
|
copyRawFile(ctx, R.raw.iptables_g1, file, "755");
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check iptables_n1
|
||||||
|
file = new File(ctx.getDir("bin",0), "iptables");
|
||||||
|
if ((!file.exists()) && (!isARMv6())) {
|
||||||
|
copyRawFile(ctx, R.raw.iptables_n1, file, "755");
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check busybox
|
||||||
|
/*
|
||||||
|
file = new File(ctx.getDir("bin",0), "busybox_g1");
|
||||||
|
if (!file.exists()) {
|
||||||
|
copyRawFile(ctx, R.raw.busybox_g1, file, "755");
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
Toast.makeText(ctx, R.string.status_install_success, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
/* Copyright (c) 2009-2011, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||||
/* See LICENSE for licensing information */
|
/* See LICENSE for licensing information */
|
||||||
|
/*
|
||||||
|
* Code for iptables binary management taken from DroidWall GPLv3
|
||||||
|
* Copyright (C) 2009-2010 Rodrigo Zechin Rosauro
|
||||||
|
*/
|
||||||
|
|
||||||
package org.torproject.android.service;
|
package org.torproject.android.service;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -39,6 +48,7 @@ import android.os.RemoteCallbackList;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler
|
public class TorService extends Service implements TorServiceConstants, TorConstants, Runnable, EventHandler
|
||||||
{
|
{
|
||||||
|
@ -414,8 +424,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
private boolean checkTorBinaries () throws Exception
|
private boolean checkTorBinaries () throws Exception
|
||||||
{
|
{
|
||||||
//check and install iptables
|
//check and install iptables
|
||||||
IptablesManager.assertBinaries(this, true);
|
TorBinaryInstaller.assertIpTablesBinaries(this, true);
|
||||||
|
|
||||||
|
|
||||||
appBinHome = getDir("bin",0);
|
appBinHome = getDir("bin",0);
|
||||||
appDataHome = getCacheDir();
|
appDataHome = getCacheDir();
|
||||||
|
@ -520,6 +529,8 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
|
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
|
||||||
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
|
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
|
||||||
|
|
||||||
|
TorTransProxy ttProxy = new TorTransProxy();
|
||||||
|
|
||||||
if (hasRoot && enableTransparentProxy)
|
if (hasRoot && enableTransparentProxy)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -544,7 +555,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
int status = code;
|
int status = code;
|
||||||
while (st.hasMoreTokens())
|
while (st.hasMoreTokens())
|
||||||
{
|
{
|
||||||
status = TorTransProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken()));
|
status = ttProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken()));
|
||||||
if(status != 0)
|
if(status != 0)
|
||||||
code = status;
|
code = status;
|
||||||
}
|
}
|
||||||
|
@ -554,12 +565,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
if(transProxyAll)
|
if(transProxyAll)
|
||||||
{
|
{
|
||||||
showAlert(getString(R.string.status), getString(R.string.setting_up_full_transparent_proxying_));
|
showAlert(getString(R.string.status), getString(R.string.setting_up_full_transparent_proxying_));
|
||||||
code = TorTransProxy.setTransparentProxyingAll(this);
|
code = ttProxy.setTransparentProxyingAll(this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
showAlert(getString(R.string.status), getString(R.string.setting_up_app_based_transparent_proxying_));
|
showAlert(getString(R.string.status), getString(R.string.setting_up_app_based_transparent_proxying_));
|
||||||
code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
|
code = ttProxy.setTransparentProxyingByApp(this,AppManager.getApps(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -576,7 +587,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
{
|
{
|
||||||
showAlert(getString(R.string.status), getString(R.string.transproxy_enabled_for_tethering_));
|
showAlert(getString(R.string.status), getString(R.string.transproxy_enabled_for_tethering_));
|
||||||
|
|
||||||
TorTransProxy.enableTetheringRules(this);
|
ttProxy.enableTetheringRules(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,12 +615,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
|
||||||
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
|
boolean hasRoot = prefs.getBoolean(PREF_HAS_ROOT,false);
|
||||||
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
|
boolean enableTransparentProxy = prefs.getBoolean("pref_transparent", false);
|
||||||
|
|
||||||
|
|
||||||
if (hasRoot && enableTransparentProxy)
|
if (hasRoot && enableTransparentProxy)
|
||||||
{
|
{
|
||||||
|
|
||||||
TorService.logMessage ("Clearing TransProxy rules");
|
TorService.logMessage ("Clearing TransProxy rules");
|
||||||
|
|
||||||
TorTransProxy.flushIptables(this);
|
new TorTransProxy().flushIptables(this);
|
||||||
|
|
||||||
showAlert(getString(R.string.status), getString(R.string.transproxy_rules_cleared));
|
showAlert(getString(R.string.status), getString(R.string.transproxy_rules_cleared));
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,58 @@ import org.torproject.android.TorConstants;
|
||||||
import org.torproject.android.settings.TorifiedApp;
|
import org.torproject.android.settings.TorifiedApp;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class TorTransProxy implements TorServiceConstants {
|
public class TorTransProxy implements TorServiceConstants {
|
||||||
|
|
||||||
private final static String TAG = TorConstants.TAG;
|
private String ipTablesPath;
|
||||||
|
|
||||||
|
public String getIpTablesPath (Context context)
|
||||||
|
{
|
||||||
|
|
||||||
public static int flushIptables(Context context) throws Exception {
|
if (ipTablesPath == null)
|
||||||
|
{
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
if (prefs.getBoolean(TorConstants.PREF_USE_SYSTEM_IPTABLES, false))
|
||||||
|
{
|
||||||
|
//if the user wants us to use the built-in iptables, then we have to find it
|
||||||
|
File fileIpt = new File("/system/bin/iptables");
|
||||||
|
|
||||||
|
if (fileIpt.exists())
|
||||||
|
ipTablesPath = fileIpt.getAbsolutePath();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
fileIpt = new File("/system/xbin/iptables");
|
||||||
|
|
||||||
|
if (fileIpt.exists())
|
||||||
|
return (ipTablesPath = fileIpt.getAbsolutePath());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//use the bundled version
|
||||||
|
ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//use the bundled version
|
||||||
|
|
||||||
|
ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipTablesPath;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int flushIptables(Context context) throws Exception {
|
||||||
|
|
||||||
|
String ipTablesPath = getIpTablesPath(context);
|
||||||
|
|
||||||
final StringBuilder script = new StringBuilder();
|
final StringBuilder script = new StringBuilder();
|
||||||
|
|
||||||
|
@ -124,16 +166,17 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static int testOwnerModule(Context context) throws Exception
|
public int testOwnerModule(Context context) throws Exception
|
||||||
{
|
{
|
||||||
|
|
||||||
|
TorBinaryInstaller.assertIpTablesBinaries(context, false);
|
||||||
|
|
||||||
boolean runRoot = true;
|
boolean runRoot = true;
|
||||||
boolean waitFor = true;
|
boolean waitFor = true;
|
||||||
|
|
||||||
//redirectDNSResolvConf(); //not working yet
|
|
||||||
int torUid = context.getApplicationInfo().uid;
|
int torUid = context.getApplicationInfo().uid;
|
||||||
|
|
||||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
String ipTablesPath = getIpTablesPath(context);
|
||||||
|
|
||||||
StringBuilder script = new StringBuilder();
|
StringBuilder script = new StringBuilder();
|
||||||
|
|
||||||
|
@ -161,7 +204,7 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static int setTransparentProxyingByApp(Context context, TorifiedApp[] apps) throws Exception
|
public int setTransparentProxyingByApp(Context context, TorifiedApp[] apps) throws Exception
|
||||||
{
|
{
|
||||||
|
|
||||||
boolean runRoot = true;
|
boolean runRoot = true;
|
||||||
|
@ -169,7 +212,7 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
|
|
||||||
//redirectDNSResolvConf(); //not working yet
|
//redirectDNSResolvConf(); //not working yet
|
||||||
|
|
||||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
String ipTablesPath = getIpTablesPath(context);
|
||||||
|
|
||||||
StringBuilder script = new StringBuilder();
|
StringBuilder script = new StringBuilder();
|
||||||
|
|
||||||
|
@ -261,7 +304,7 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int setTransparentProxyingByPort(Context context, int port) throws Exception
|
public int setTransparentProxyingByPort(Context context, int port) throws Exception
|
||||||
{
|
{
|
||||||
|
|
||||||
//android.os.Debug.waitForDebugger();
|
//android.os.Debug.waitForDebugger();
|
||||||
|
@ -269,7 +312,7 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
//redirectDNSResolvConf(); //not working yet
|
//redirectDNSResolvConf(); //not working yet
|
||||||
|
|
||||||
//String baseDir = context.getDir("bin",0).getAbsolutePath() + '/';
|
//String baseDir = context.getDir("bin",0).getAbsolutePath() + '/';
|
||||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
String ipTablesPath = getIpTablesPath(context);
|
||||||
|
|
||||||
StringBuilder script = new StringBuilder();
|
StringBuilder script = new StringBuilder();
|
||||||
|
|
||||||
|
@ -318,13 +361,13 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int enableTetheringRules (Context context) throws Exception
|
public int enableTetheringRules (Context context) throws Exception
|
||||||
{
|
{
|
||||||
|
|
||||||
boolean runRoot = true;
|
boolean runRoot = true;
|
||||||
boolean waitFor = true;
|
boolean waitFor = true;
|
||||||
|
|
||||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
String ipTablesPath = getIpTablesPath(context);
|
||||||
|
|
||||||
StringBuilder script = new StringBuilder();
|
StringBuilder script = new StringBuilder();
|
||||||
|
|
||||||
|
@ -360,14 +403,14 @@ public class TorTransProxy implements TorServiceConstants {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int setTransparentProxyingAll(Context context) throws Exception
|
public int setTransparentProxyingAll(Context context) throws Exception
|
||||||
{
|
{
|
||||||
boolean runRoot = true;
|
boolean runRoot = true;
|
||||||
boolean waitFor = true;
|
boolean waitFor = true;
|
||||||
|
|
||||||
//redirectDNSResolvConf(); //not working yet
|
//redirectDNSResolvConf(); //not working yet
|
||||||
|
|
||||||
String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath();
|
String ipTablesPath = getIpTablesPath(context);
|
||||||
|
|
||||||
StringBuilder script = new StringBuilder();
|
StringBuilder script = new StringBuilder();
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ public class Permissions extends Activity implements TorConstants {
|
||||||
if (hasRoot)
|
if (hasRoot)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
int resp = TorTransProxy.testOwnerModule(context);
|
int resp = new TorTransProxy().testOwnerModule(context);
|
||||||
|
|
||||||
if (resp < 0)
|
if (resp < 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,17 +93,16 @@ public class WizardHelper implements TorConstants {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
|
|
||||||
|
boolean iCanHazRoot = TorServiceUtils.isRootPossible();
|
||||||
|
|
||||||
boolean isRootPossible = TorServiceUtils.isRootPossible();
|
if (iCanHazRoot)
|
||||||
|
|
||||||
if (isRootPossible)
|
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
int resp = TorTransProxy.testOwnerModule(context);
|
int resp = new TorTransProxy().testOwnerModule(context);
|
||||||
|
|
||||||
if (resp < 0)
|
if (resp < 0)
|
||||||
{
|
{
|
||||||
isRootPossible = false;
|
iCanHazRoot = false;
|
||||||
Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show();
|
Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available");
|
Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available");
|
||||||
|
@ -111,21 +110,12 @@ public class WizardHelper implements TorConstants {
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
||||||
isRootPossible = false;
|
iCanHazRoot = false;
|
||||||
Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e);
|
Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (iCanHazRoot)
|
||||||
* we shouldn't store root here, as this step is just chekcing to see if root is possible
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
|
|
||||||
Editor pEdit = prefs.edit();
|
|
||||||
pEdit.putBoolean("has_root",hasRoot);
|
|
||||||
pEdit.commit();
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (isRootPossible)
|
|
||||||
{
|
{
|
||||||
currentDialog.dismiss();
|
currentDialog.dismiss();
|
||||||
showWizardStep2Root();
|
showWizardStep2Root();
|
||||||
|
|
Loading…
Reference in New Issue