import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.Method;
import java.security.MessageDigest;
+import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import android.util.Base64;
+import android.util.Log;
import com.koushikdutta.superuser.Helper;
+import com.koushikdutta.superuser.db.SuperuserDatabaseHelper;
public class Settings {
+ static final String TAG = "Superuser";
SQLiteDatabase mDatabase;
Context mContext;
- private Settings(Context context) {
- mContext = context;
- SQLiteOpenHelper helper = new SQLiteOpenHelper(mContext, "settings.db", null, 1) {
- private final static String mDDL = "CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);";
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- onCreate(db);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(mDDL);
- }
- };
- mDatabase = helper.getWritableDatabase();
- }
-
- private static Settings mInstance;
-
- public static Settings getInstance(Context context) {
- if (mInstance == null) {
- mInstance = new Settings(context.getApplicationContext());
- }
- return mInstance;
- }
-
- public void setString(String name, String value) {
+ public static void setString(Context context, String name, String value) {
ContentValues cv = new ContentValues();
cv.put("key", name);
cv.put("value", value);
- mDatabase.replace("settings", null, cv);
+ SQLiteDatabase db = new SuperuserDatabaseHelper(context).getWritableDatabase();
+ try {
+ db.replace("settings", null, cv);
+ }
+ finally {
+ db.close();
+ }
}
- public String getString(String name) {
- return getString(name, null);
+ public static String getString(Context context, String name) {
+ return getString(context, name, null);
}
- public String getString(String name, String defaultValue) {
- Cursor cursor = mDatabase.query("settings", new String[] { "value" }, "key='" + name + "'", null, null, null, null);
+ public static String getString(Context context, String name, String defaultValue) {
+ SQLiteDatabase db = new SuperuserDatabaseHelper(context).getReadableDatabase();
+ Cursor cursor = db.query("settings", new String[] { "value" }, "key='" + name + "'", null, null, null, null);
try {
if (cursor.moveToNext())
return cursor.getString(0);
}
finally {
cursor.close();
+ db.close();
}
return defaultValue;
}
- public void setInt(String name, int value) {
- setString(name, ((Integer) value).toString());
+ public static void setInt(Context context, String name, int value) {
+ setString(context, name, ((Integer) value).toString());
}
- public int getInt(String name, int defaultValue) {
+ public static int getInt(Context context, String name, int defaultValue) {
try {
- return Integer.parseInt(getString(name, null));
+ return Integer.parseInt(getString(context, name, null));
}
catch (Exception ex) {
return defaultValue;
}
}
- public void setLong(String name, long value) {
- setString(name, ((Long) value).toString());
+ public static void setLong(Context context, String name, long value) {
+ setString(context, name, ((Long) value).toString());
}
- public long getLong(String name, long defaultValue) {
+ public static long getLong(Context context, String name, long defaultValue) {
try {
- return Long.parseLong(getString(name, null));
+ return Long.parseLong(getString(context, name, null));
}
catch (Exception ex) {
return defaultValue;
}
}
- public void setBoolean(String name, boolean value) {
- setString(name, ((Boolean) value).toString());
+ public static void setBoolean(Context context, String name, boolean value) {
+ setString(context, name, ((Boolean) value).toString());
}
- public boolean getBoolean(String name, boolean defaultValue) {
+ public static boolean getBoolean(Context context, String name, boolean defaultValue) {
try {
- return Boolean.parseBoolean(getString(name, ((Boolean) defaultValue).toString()));
+ return Boolean.parseBoolean(getString(context, name, ((Boolean) defaultValue).toString()));
}
catch (Exception ex) {
ex.printStackTrace();
return defaultValue;
}
}
-
+
private static final String KEY_LOGGING = "logging";
public static boolean getLogging(Context context) {
- return getInstance(context).getBoolean(KEY_LOGGING, true);
+ return getBoolean(context, KEY_LOGGING, true);
}
-
+
public static void setLogging(Context context, boolean logging) {
- getInstance(context).setBoolean(KEY_LOGGING, logging);
+ setBoolean(context, KEY_LOGGING, logging);
}
-
+
private static final String KEY_TIMEOUT = "timeout";
public static final int REQUEST_TIMEOUT_DEFAULT = 30;
public static int getRequestTimeout(Context context) {
- return getInstance(context).getInt(KEY_TIMEOUT, REQUEST_TIMEOUT_DEFAULT);
+ return getInt(context, KEY_TIMEOUT, REQUEST_TIMEOUT_DEFAULT);
}
-
+
public static void setTimeout(Context context, int timeout) {
- getInstance(context).setInt(KEY_TIMEOUT, timeout);
+ setInt(context, KEY_TIMEOUT, timeout);
}
private static final String KEY_NOTIFICATION = "notification";
public static final int NOTIFICATION_TYPE_NOTIFICATION = 2;
public static final int NOTIFICATION_TYPE_DEFAULT = NOTIFICATION_TYPE_TOAST;
public static int getNotificationType(Context context) {
- switch (getInstance(context).getInt(KEY_NOTIFICATION, NOTIFICATION_TYPE_DEFAULT)) {
+ switch (getInt(context, KEY_NOTIFICATION, NOTIFICATION_TYPE_DEFAULT)) {
case NOTIFICATION_TYPE_NONE:
return NOTIFICATION_TYPE_NONE;
case NOTIFICATION_TYPE_NOTIFICATION:
return NOTIFICATION_TYPE_DEFAULT;
}
}
-
+
public static void setNotificationType(Context context, int notification) {
- getInstance(context).setInt(KEY_NOTIFICATION, notification);
+ setInt(context, KEY_NOTIFICATION, notification);
}
-
+
public static final String KEY_PIN = "pin";
public static final boolean isPinProtected(Context context) {
- return Settings.getInstance(context).getString(KEY_PIN) != null;
+ return Settings.getString(context, KEY_PIN) != null;
}
-
+
private static String digest(String value) {
// ok, there's honestly no point in digesting the pin.
// if someone gets a hold of the hash, there's really only like
return value;
}
}
-
+
public static void setPin(Context context, String pin) {
- Settings.getInstance(context).setString(KEY_PIN, digest(pin));
+ Settings.setString(context, KEY_PIN, digest(pin));
}
-
+
public static boolean checkPin(Context context, String pin) {
pin = digest(pin);
- String hashed = Settings.getInstance(context).getString(KEY_PIN);
+ String hashed = Settings.getString(context, KEY_PIN);
if (TextUtils.isEmpty(pin))
return TextUtils.isEmpty(hashed);
return pin.equals(hashed);
private static final String KEY_REQUIRE_PREMISSION = "require_permission";
public static boolean getRequirePermission(Context context) {
- return getInstance(context).getBoolean(KEY_REQUIRE_PREMISSION, false);
+ return getBoolean(context, KEY_REQUIRE_PREMISSION, false);
}
-
+
public static void setRequirePermission(Context context, boolean require) {
- getInstance(context).setBoolean(KEY_REQUIRE_PREMISSION, require);
+ setBoolean(context, KEY_REQUIRE_PREMISSION, require);
}
-
+
private static final String KEY_AUTOMATIC_RESPONSE = "automatic_response";
public static final int AUTOMATIC_RESPONSE_PROMPT = 0;
public static final int AUTOMATIC_RESPONSE_ALLOW = 1;
public static final int AUTOMATIC_RESPONSE_DENY = 2;
public static final int AUTOMATIC_RESPONSE_DEFAULT = AUTOMATIC_RESPONSE_PROMPT;
public static int getAutomaticResponse(Context context) {
- switch (getInstance(context).getInt(KEY_AUTOMATIC_RESPONSE, AUTOMATIC_RESPONSE_DEFAULT)) {
+ switch (getInt(context, KEY_AUTOMATIC_RESPONSE, AUTOMATIC_RESPONSE_DEFAULT)) {
case AUTOMATIC_RESPONSE_ALLOW:
return AUTOMATIC_RESPONSE_ALLOW;
case AUTOMATIC_RESPONSE_PROMPT:
}
public static void setAutomaticResponse(Context context, int response) {
- getInstance(context).setInt(KEY_AUTOMATIC_RESPONSE, response);
+ setInt(context, KEY_AUTOMATIC_RESPONSE, response);
}
-
-
+
+
static public String readFile(String filename) throws IOException {
return readFile(new File(filename));
}
-
+
static public String readFile(File file) throws IOException {
byte[] buffer = new byte[(int) file.length()];
DataInputStream input = new DataInputStream(new FileInputStream(file));
input.readFully(buffer);
+ input.close();
return new String(buffer);
}
-
+
public static void writeFile(File file, String string) throws IOException {
writeFile(file.getAbsolutePath(), string);
}
-
+
public static void writeFile(String file, String string) throws IOException {
File f = new File(file);
f.getParentFile().mkdirs();
dout.write(string.getBytes());
dout.close();
}
-
+
public static byte[] readToEndAsArray(InputStream input) throws IOException {
DataInputStream dis = new DataInputStream(input);
byte[] stuff = new byte[1024];
public static final int MULTIUSER_MODE_OWNER_MANAGED = 1;
public static final int MULTIUSER_MODE_USER = 2;
public static final int MULTIUSER_MODE_NONE = 3;
-
+
private static final String MULTIUSER_VALUE_OWNER_ONLY = "owner";
private static final String MULTIUSER_VALUE_OWNER_MANAGED = "managed";
private static final String MULTIUSER_VALUE_USER = "user";
if (!Helper.supportsMultipleUsers(context))
return MULTIUSER_MODE_NONE;
-
+
try {
String mode;
if (Helper.isAdminUser(context)) {
Process p = Runtime.getRuntime().exec("su -u");
mode = readToEnd(p.getInputStream()).trim();
}
-
+
if (MULTIUSER_VALUE_OWNER_MANAGED.equals(mode))
return MULTIUSER_MODE_OWNER_MANAGED;
if (MULTIUSER_VALUE_USER.equals(mode))
}
return MULTIUSER_MODE_OWNER_ONLY;
}
-
+
public static void setMultiuserMode(Context context, int mode) {
if (!Helper.isAdminUser(context))
return;
catch (Exception ex) {
}
}
+
+
+ public static final int SUPERUSER_ACCESS_DISABLED = 0;
+ public static final int SUPERUSER_ACCESS_APPS_ONLY = 1;
+ public static final int SUPERUSER_ACCESS_ADB_ONLY = 2;
+ public static final int SUPERUSER_ACCESS_APPS_AND_ADB = 3;
+ public static int getSuperuserAccess() {
+ try {
+ Class<?> c = Class.forName("android.os.SystemProperties");
+ Method m = c.getMethod("get", String.class);
+ String value = (String)m.invoke(null, "persist.sys.root_access");
+ int val = Integer.valueOf(value);
+ switch (val) {
+ case SUPERUSER_ACCESS_DISABLED:
+ case SUPERUSER_ACCESS_APPS_ONLY:
+ case SUPERUSER_ACCESS_ADB_ONLY:
+ case SUPERUSER_ACCESS_APPS_AND_ADB:
+ return val;
+ default:
+ return SUPERUSER_ACCESS_DISABLED;
+ }
+ }
+ catch (Exception e) {
+ return SUPERUSER_ACCESS_DISABLED;
+ }
+ }
+
+ public static void setSuperuserAccess(int mode) {
+ try {
+ if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
+ Class<?> c = Class.forName("android.os.SystemProperties");
+ Method m = c.getMethod("set", String.class, String.class);
+ m.invoke(null, "persist.sys.root_access", String.valueOf(mode));
+ if (mode == getSuperuserAccess()) return;
+ }
+ String command = "setprop persist.sys.root_access " + mode;
+ Process p = Runtime.getRuntime().exec("su");
+ p.getOutputStream().write(command.getBytes());
+ p.getOutputStream().close();
+ int ret = p.waitFor();
+ if (ret != 0) Log.w(TAG, "su failed: " + ret);
+ }
+ catch (Exception ex) {
+ Log.w(TAG, "got exception: ", ex);
+ }
+ }
+
+ private static final String CHECK_SU_QUIET = "check_su_quiet";
+ public static final int getCheckSuQuietCounter(Context context) {
+ return getInt(context, CHECK_SU_QUIET, 0);
+ }
+
+ public static final void setCheckSuQuietCounter(Context context, int counter) {
+ setInt(context, CHECK_SU_QUIET, counter);
+ }
+
+ private static final String KEY_THEME = "theme";
+ public static final int THEME_LIGHT = 0;
+ public static final int THEME_DARK = 1;
+ public static void applyDarkThemeSetting(Activity activity, int dark) {
+ if (!"com.koushikdutta.superuser".equals(activity.getPackageName()))
+ return;
+ try {
+ if (getTheme(activity) == THEME_DARK)
+ activity.setTheme(dark);
+ }
+ catch (Exception e) {
+ }
+ }
+
+ public static final int getTheme(Context context) {
+ return getInt(context, KEY_THEME, THEME_LIGHT);
+ }
+
+ public static final void setTheme(Context context, int theme) {
+ setInt(context, KEY_THEME, theme);
+ }
}