OSDN Git Service

Fix several compiler warnings
[android-x86/external-koush-Superuser.git] / Superuser / src / com / koushikdutta / superuser / util / Settings.java
1 package com.koushikdutta.superuser.util;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.DataInputStream;
5 import java.io.DataOutputStream;
6 import java.io.File;
7 import java.io.FileInputStream;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.lang.reflect.Method;
12 import java.security.MessageDigest;
13
14 import android.app.Activity;
15 import android.content.ContentValues;
16 import android.content.Context;
17 import android.database.Cursor;
18 import android.database.sqlite.SQLiteDatabase;
19 import android.os.Build;
20 import android.text.TextUtils;
21 import android.util.Base64;
22 import android.util.Log;
23
24 import com.koushikdutta.superuser.Helper;
25 import com.koushikdutta.superuser.db.SuperuserDatabaseHelper;
26
27 public class Settings {
28     static final String TAG = "Superuser";
29     SQLiteDatabase mDatabase;
30     Context mContext;
31
32     public static void setString(Context context, String name, String value) {
33         ContentValues cv = new ContentValues();
34         cv.put("key", name);
35         cv.put("value", value);
36         SQLiteDatabase db = new SuperuserDatabaseHelper(context).getWritableDatabase();
37         try {
38             db.replace("settings", null, cv);
39         }
40         finally {
41             db.close();
42         }
43     }
44
45     public static String getString(Context context, String name) {
46         return getString(context, name, null);
47     }
48
49     public static String getString(Context context, String name, String defaultValue) {
50         SQLiteDatabase db = new SuperuserDatabaseHelper(context).getReadableDatabase();
51         Cursor cursor = db.query("settings", new String[] { "value" }, "key='" + name + "'", null, null, null, null);
52         try {
53             if (cursor.moveToNext())
54                 return cursor.getString(0);
55         }
56         finally {
57             cursor.close();
58             db.close();
59         }
60         return defaultValue;
61     }
62
63     public static void setInt(Context context, String name, int value) {
64         setString(context, name, ((Integer) value).toString());
65     }
66
67     public static int getInt(Context context, String name, int defaultValue) {
68         try {
69             return Integer.parseInt(getString(context, name, null));
70         }
71         catch (Exception ex) {
72             return defaultValue;
73         }
74     }
75
76     public static void setLong(Context context, String name, long value) {
77         setString(context, name, ((Long) value).toString());
78     }
79
80     public static long getLong(Context context, String name, long defaultValue) {
81         try {
82             return Long.parseLong(getString(context, name, null));
83         }
84         catch (Exception ex) {
85             return defaultValue;
86         }
87     }
88
89     public static void setBoolean(Context context, String name, boolean value) {
90         setString(context, name, ((Boolean) value).toString());
91     }
92
93     public static boolean getBoolean(Context context, String name, boolean defaultValue) {
94         try {
95             return Boolean.parseBoolean(getString(context, name, ((Boolean) defaultValue).toString()));
96         }
97         catch (Exception ex) {
98             ex.printStackTrace();
99             return defaultValue;
100         }
101     }
102
103     private static final String KEY_LOGGING = "logging";
104     public static boolean getLogging(Context context) {
105         return getBoolean(context, KEY_LOGGING, true);
106     }
107
108     public static void setLogging(Context context, boolean logging) {
109         setBoolean(context, KEY_LOGGING, logging);
110     }
111
112     private static final String KEY_TIMEOUT = "timeout";
113     public static final int REQUEST_TIMEOUT_DEFAULT = 30;
114     public static int getRequestTimeout(Context context) {
115         return getInt(context, KEY_TIMEOUT, REQUEST_TIMEOUT_DEFAULT);
116     }
117
118     public static void setTimeout(Context context, int timeout) {
119         setInt(context, KEY_TIMEOUT, timeout);
120     }
121
122     private static final String KEY_NOTIFICATION = "notification";
123     public static final int NOTIFICATION_TYPE_NONE = 0;
124     public static final int NOTIFICATION_TYPE_TOAST = 1;
125     public static final int NOTIFICATION_TYPE_NOTIFICATION = 2;
126     public static final int NOTIFICATION_TYPE_DEFAULT = NOTIFICATION_TYPE_TOAST;
127     public static int getNotificationType(Context context) {
128         switch (getInt(context, KEY_NOTIFICATION, NOTIFICATION_TYPE_DEFAULT)) {
129         case NOTIFICATION_TYPE_NONE:
130             return NOTIFICATION_TYPE_NONE;
131         case NOTIFICATION_TYPE_NOTIFICATION:
132             return NOTIFICATION_TYPE_NOTIFICATION;
133         case NOTIFICATION_TYPE_TOAST:
134             return NOTIFICATION_TYPE_TOAST;
135         default:
136             return NOTIFICATION_TYPE_DEFAULT;
137         }
138     }
139
140     public static void setNotificationType(Context context, int notification) {
141         setInt(context, KEY_NOTIFICATION, notification);
142     }
143
144     public static final String KEY_PIN = "pin";
145     public static final boolean isPinProtected(Context context) {
146         return Settings.getString(context, KEY_PIN) != null;
147     }
148
149     private static String digest(String value) {
150         // ok, there's honestly no point in digesting the pin.
151         // if someone gets a hold of the hash, there's really only like
152         // 10^n possible values to brute force, where N is generally
153         // 4. Ie, 10000. Yay, security theater. This really ought
154         // to be a password.
155         if (TextUtils.isEmpty(value))
156             return null;
157         try {
158             MessageDigest digester = MessageDigest.getInstance("MD5");
159             return Base64.encodeToString(digester.digest(value.getBytes()), Base64.DEFAULT);
160         }
161         catch (Exception e) {
162             return value;
163         }
164     }
165
166     public static void setPin(Context context, String pin) {
167         Settings.setString(context, KEY_PIN, digest(pin));
168     }
169
170     public static boolean checkPin(Context context, String pin) {
171         pin = digest(pin);
172         String hashed = Settings.getString(context, KEY_PIN);
173         if (TextUtils.isEmpty(pin))
174             return TextUtils.isEmpty(hashed);
175         return pin.equals(hashed);
176     }
177
178     private static final String KEY_REQUIRE_PREMISSION = "require_permission";
179     public static boolean getRequirePermission(Context context) {
180         return getBoolean(context, KEY_REQUIRE_PREMISSION, false);
181     }
182
183     public static void setRequirePermission(Context context, boolean require) {
184         setBoolean(context, KEY_REQUIRE_PREMISSION, require);
185     }
186
187     private static final String KEY_AUTOMATIC_RESPONSE = "automatic_response";
188     public static final int AUTOMATIC_RESPONSE_PROMPT = 0;
189     public static final int AUTOMATIC_RESPONSE_ALLOW = 1;
190     public static final int AUTOMATIC_RESPONSE_DENY = 2;
191     public static final int AUTOMATIC_RESPONSE_DEFAULT = AUTOMATIC_RESPONSE_PROMPT;
192     public static int getAutomaticResponse(Context context) {
193         switch (getInt(context, KEY_AUTOMATIC_RESPONSE, AUTOMATIC_RESPONSE_DEFAULT)) {
194         case AUTOMATIC_RESPONSE_ALLOW:
195             return AUTOMATIC_RESPONSE_ALLOW;
196         case AUTOMATIC_RESPONSE_PROMPT:
197             return AUTOMATIC_RESPONSE_PROMPT;
198         case AUTOMATIC_RESPONSE_DENY:
199             return AUTOMATIC_RESPONSE_DENY;
200         default:
201             return AUTOMATIC_RESPONSE_DEFAULT;
202         }
203     }
204
205     public static void setAutomaticResponse(Context context, int response) {
206         setInt(context, KEY_AUTOMATIC_RESPONSE, response);
207     }
208
209
210     static public String readFile(String filename) throws IOException {
211         return readFile(new File(filename));
212     }
213
214     static public String readFile(File file) throws IOException {
215         byte[] buffer = new byte[(int) file.length()];
216         DataInputStream input = new DataInputStream(new FileInputStream(file));
217         input.readFully(buffer);
218         input.close();
219         return new String(buffer);
220     }
221
222     public static void writeFile(File file, String string) throws IOException {
223         writeFile(file.getAbsolutePath(), string);
224     }
225
226     public static void writeFile(String file, String string) throws IOException {
227         File f = new File(file);
228         f.getParentFile().mkdirs();
229         DataOutputStream dout = new DataOutputStream(new FileOutputStream(f));
230         dout.write(string.getBytes());
231         dout.close();
232     }
233
234     public static byte[] readToEndAsArray(InputStream input) throws IOException {
235         DataInputStream dis = new DataInputStream(input);
236         byte[] stuff = new byte[1024];
237         ByteArrayOutputStream buff = new ByteArrayOutputStream();
238         int read = 0;
239         while ((read = dis.read(stuff)) != -1)
240         {
241             buff.write(stuff, 0, read);
242         }
243         input.close();
244         return buff.toByteArray();
245     }
246
247     public static String readToEnd(InputStream input) throws IOException {
248         return new String(readToEndAsArray(input));
249     }
250
251     public static final int MULTIUSER_MODE_OWNER_ONLY = 0;
252     public static final int MULTIUSER_MODE_OWNER_MANAGED = 1;
253     public static final int MULTIUSER_MODE_USER = 2;
254     public static final int MULTIUSER_MODE_NONE = 3;
255
256     private static final String MULTIUSER_VALUE_OWNER_ONLY  = "owner";
257     private static final String MULTIUSER_VALUE_OWNER_MANAGED = "managed";
258     private static final String MULTIUSER_VALUE_USER = "user";
259
260     public static final int getMultiuserMode(Context context) {
261         if (Build.VERSION.SDK_INT < 17)
262             return MULTIUSER_MODE_NONE;
263
264         if (!Helper.supportsMultipleUsers(context))
265             return MULTIUSER_MODE_NONE;
266
267         try {
268             String mode;
269             if (Helper.isAdminUser(context)) {
270                 File file = context.getFileStreamPath("multiuser_mode");
271                 mode = readFile(file);
272             }
273             else {
274                 Process p = Runtime.getRuntime().exec("su -u");
275                 mode = readToEnd(p.getInputStream()).trim();
276             }
277
278             if (MULTIUSER_VALUE_OWNER_MANAGED.equals(mode))
279                 return MULTIUSER_MODE_OWNER_MANAGED;
280             if (MULTIUSER_VALUE_USER.equals(mode))
281                 return MULTIUSER_MODE_USER;
282             if (MULTIUSER_VALUE_OWNER_ONLY.equals(mode))
283                 return MULTIUSER_MODE_OWNER_ONLY;
284         }
285         catch (Exception e) {
286         }
287         return MULTIUSER_MODE_OWNER_ONLY;
288     }
289
290     public static void setMultiuserMode(Context context, int mode) {
291         if (!Helper.isAdminUser(context))
292             return;
293         try {
294             File file = context.getFileStreamPath("multiuser_mode");
295             switch (mode) {
296             case MULTIUSER_MODE_OWNER_MANAGED:
297                 writeFile(file, MULTIUSER_VALUE_OWNER_MANAGED);
298                 break;
299             case MULTIUSER_MODE_USER:
300                 writeFile(file, MULTIUSER_VALUE_USER);
301                 break;
302             case MULTIUSER_MODE_NONE:
303                 file.delete();
304                 break;
305             default:
306                 writeFile(file, MULTIUSER_VALUE_OWNER_ONLY);
307                 break;
308             }
309         }
310         catch (Exception ex) {
311         }
312     }
313
314
315     public static final int SUPERUSER_ACCESS_DISABLED = 0;
316     public static final int SUPERUSER_ACCESS_APPS_ONLY = 1;
317     public static final int SUPERUSER_ACCESS_ADB_ONLY = 2;
318     public static final int SUPERUSER_ACCESS_APPS_AND_ADB = 3;
319     public static int getSuperuserAccess() {
320         try {
321             Class<?> c = Class.forName("android.os.SystemProperties");
322             Method m = c.getMethod("get", String.class);
323             String value = (String)m.invoke(null, "persist.sys.root_access");
324             int val = Integer.valueOf(value);
325             switch (val) {
326             case SUPERUSER_ACCESS_DISABLED:
327             case SUPERUSER_ACCESS_APPS_ONLY:
328             case SUPERUSER_ACCESS_ADB_ONLY:
329             case SUPERUSER_ACCESS_APPS_AND_ADB:
330                 return val;
331             default:
332                 return SUPERUSER_ACCESS_APPS_AND_ADB;
333             }
334         }
335         catch (Exception e) {
336             return SUPERUSER_ACCESS_APPS_AND_ADB;
337         }
338     }
339
340     public static void setSuperuserAccess(int mode) {
341         try {
342             if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
343                 Class<?> c = Class.forName("android.os.SystemProperties");
344                 Method m = c.getMethod("set", String.class, String.class);
345                 m.invoke(null, "persist.sys.root_access", String.valueOf(mode));
346                 if (mode == getSuperuserAccess()) return;
347             }
348             String command = "setprop persist.sys.root_access " + mode;
349             Process p = Runtime.getRuntime().exec("su");
350             p.getOutputStream().write(command.getBytes());
351             p.getOutputStream().close();
352             int ret = p.waitFor();
353             if (ret != 0) Log.w(TAG, "su failed: " + ret);
354         }
355         catch (Exception ex) {
356             Log.w(TAG, "got exception: ", ex);
357         }
358     }
359
360     private static final String CHECK_SU_QUIET = "check_su_quiet";
361     public static final int getCheckSuQuietCounter(Context context) {
362         return getInt(context, CHECK_SU_QUIET, 0);
363     }
364
365     public static final void setCheckSuQuietCounter(Context context, int counter) {
366         setInt(context, CHECK_SU_QUIET, counter);
367     }
368
369     private static final String KEY_THEME = "theme";
370     public static final int THEME_LIGHT = 0;
371     public static final int THEME_DARK = 1;
372     public static void applyDarkThemeSetting(Activity activity, int dark) {
373         if (!"com.koushikdutta.superuser".equals(activity.getPackageName()))
374             return;
375         try {
376             if (getTheme(activity) == THEME_DARK)
377                 activity.setTheme(dark);
378         }
379         catch (Exception e) {
380         }
381     }
382
383     public static final int getTheme(Context context) {
384         return getInt(context, KEY_THEME, THEME_LIGHT);
385     }
386
387     public static final void setTheme(Context context, int theme) {
388         setInt(context, KEY_THEME, theme);
389     }
390 }