Optimize magisk database handling

This commit is contained in:
topjohnwu 2018-04-06 01:54:09 +08:00
parent fb5e8ef40c
commit 315fa9d7d3
12 changed files with 70 additions and 73 deletions

View File

@ -16,7 +16,7 @@ import android.widget.Toast;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Topic;
@ -85,7 +85,7 @@ public class MagiskManager extends Shell.ContainerApp {
// Global resources
public SharedPreferences prefs;
public SuDatabaseHelper suDB;
public MagiskDatabaseHelper mDB;
public RepoDatabaseHelper repoDB;
public Runnable permissionGrantCallback = null;
@ -106,7 +106,7 @@ public class MagiskManager extends Shell.ContainerApp {
@Override
public void onRootShellInit(@NonNull Shell shell) {
try (InputStream utils = getAssets().open(Const.UTIL_FUNCTIONS);
InputStream sudb = getResources().openRawResource(R.raw.sudb)) {
InputStream sudb = getResources().openRawResource(R.raw.magiskdb)) {
shell.loadInputStream(null, null, utils);
shell.loadInputStream(null, null, sudb);
} catch (IOException e) {
@ -131,13 +131,13 @@ public class MagiskManager extends Shell.ContainerApp {
} catch (PackageManager.NameNotFoundException ignored) { /* Expected */ }
}
suDB = SuDatabaseHelper.getInstance(this);
mDB = MagiskDatabaseHelper.getInstance(this);
String pkg = suDB.getStrings(Const.Key.SU_REQUESTER, Const.ORIG_PKG_NAME);
String pkg = mDB.getStrings(Const.Key.SU_REQUESTER, Const.ORIG_PKG_NAME);
if (getPackageName().equals(Const.ORIG_PKG_NAME) && !pkg.equals(Const.ORIG_PKG_NAME)) {
suDB.setStrings(Const.Key.SU_REQUESTER, null);
mDB.setStrings(Const.Key.SU_REQUESTER, null);
Utils.uninstallPkg(pkg);
suDB = SuDatabaseHelper.getInstance(this);
mDB = MagiskDatabaseHelper.getInstance(this);
}
repoDB = new RepoDatabaseHelper(this);
@ -168,9 +168,9 @@ public class MagiskManager extends Shell.ContainerApp {
suRequestTimeout = Utils.getPrefsInt(prefs, Const.Key.SU_REQUEST_TIMEOUT, Const.Value.timeoutList[2]);
suResponseType = Utils.getPrefsInt(prefs, Const.Key.SU_AUTO_RESPONSE, Const.Value.SU_PROMPT);
suNotificationType = Utils.getPrefsInt(prefs, Const.Key.SU_NOTIFICATION, Const.Value.NOTIFICATION_TOAST);
suAccessState = suDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB);
multiuserMode = suDB.getSettings(Const.Key.SU_MULTIUSER_MODE, Const.Value.MULTIUSER_MODE_OWNER_ONLY);
suNamespaceMode = suDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER);
suAccessState = mDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB);
multiuserMode = mDB.getSettings(Const.Key.SU_MULTIUSER_MODE, Const.Value.MULTIUSER_MODE_OWNER_ONLY);
suNamespaceMode = mDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER);
// config
isDarkTheme = prefs.getBoolean(Const.Key.DARK_THEME, false);

View File

@ -276,7 +276,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
case Const.Key.ROOT_ACCESS:
case Const.Key.SU_MULTIUSER_MODE:
case Const.Key.SU_MNT_NS:
mm.suDB.setSettings(key, Utils.getPrefsInt(prefs, key));
mm.mDB.setSettings(key, Utils.getPrefsInt(prefs, key));
break;
case Const.Key.LOCALE:
mm.setLocale();

View File

@ -46,7 +46,7 @@ public class SuLogFragment extends Fragment {
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
unbinder = ButterKnife.bind(this, v);
mm = getApplication();
adapter = new SuLogAdapter(mm.suDB);
adapter = new SuLogAdapter(mm.mDB);
recyclerView.setAdapter(adapter);
updateList();
@ -73,7 +73,7 @@ public class SuLogFragment extends Fragment {
updateList();
return true;
case R.id.menu_clear:
mm.suDB.clearLogs();
mm.mDB.clearLogs();
updateList();
return true;
default:

View File

@ -34,13 +34,13 @@ public class SuperuserFragment extends Fragment {
PackageManager pm = getActivity().getPackageManager();
MagiskManager mm = getApplication();
List<Policy> policyList = mm.suDB.getPolicyList(pm);
List<Policy> policyList = mm.mDB.getPolicyList(pm);
if (policyList.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
recyclerView.setAdapter(new PolicyAdapter(policyList, mm.suDB, pm));
recyclerView.setAdapter(new PolicyAdapter(policyList, mm.mDB, pm));
emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}

View File

@ -16,7 +16,7 @@ import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
import java.util.HashSet;
import java.util.List;
@ -28,11 +28,11 @@ import butterknife.ButterKnife;
public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder> {
private List<Policy> policyList;
private SuDatabaseHelper dbHelper;
private MagiskDatabaseHelper dbHelper;
private PackageManager pm;
private Set<Policy> expandList = new HashSet<>();
public PolicyAdapter(List<Policy> list, SuDatabaseHelper db, PackageManager pm) {
public PolicyAdapter(List<Policy> list, MagiskDatabaseHelper db, PackageManager pm) {
policyList = list;
dbHelper = db;
this.pm = pm;

View File

@ -13,7 +13,7 @@ import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
import java.util.Collections;
import java.util.HashSet;
@ -27,10 +27,10 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
private List<List<Integer>> logEntryList;
private Set<Integer> itemExpanded, sectionExpanded;
private SuDatabaseHelper suDB;
private MagiskDatabaseHelper suDB;
private Cursor suLogCursor = null;
public SuLogAdapter(SuDatabaseHelper db) {
public SuLogAdapter(MagiskDatabaseHelper db) {
suDB = db;
logEntryList = Collections.emptyList();
sectionExpanded = new HashSet<>();

View File

@ -135,7 +135,7 @@ public class HideManager extends ParallelTask<Void, Void, Boolean> {
repack.delete();
mm.suDB.setStrings(Const.Key.SU_REQUESTER, pkg);
mm.mDB.setStrings(Const.Key.SU_REQUESTER, pkg);
Utils.dumpPrefs();
Utils.uninstallPkg(Const.ORIG_PKG_NAME);

View File

@ -27,7 +27,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.List;
public class SuDatabaseHelper {
public class MagiskDatabaseHelper {
private static final int DATABASE_VER = 5;
private static final String POLICY_TABLE = "policies";
@ -36,60 +36,57 @@ public class SuDatabaseHelper {
private static final String STRINGS_TABLE = "strings";
private PackageManager pm;
private SQLiteDatabase mDb;
private File DB_FILE;
private SQLiteDatabase db;
@NonNull
public static SuDatabaseHelper getInstance(MagiskManager mm) {
public static MagiskDatabaseHelper getInstance(MagiskManager mm) {
try {
return new SuDatabaseHelper(mm);
return new MagiskDatabaseHelper(mm);
} catch (Exception e) {
// Let's cleanup everything and try again
Shell.Sync.su("sudb_clean '*'");
return new SuDatabaseHelper(mm);
Shell.Sync.su("db_clean '*'");
return new MagiskDatabaseHelper(mm);
}
}
private SuDatabaseHelper(MagiskManager mm) {
private MagiskDatabaseHelper(MagiskManager mm) {
pm = mm.getPackageManager();
mDb = openDatabase(mm);
mDb.disableWriteAheadLogging();
int version = mDb.getVersion();
db = openDatabase(mm);
db.disableWriteAheadLogging();
int version = db.getVersion();
if (version < DATABASE_VER) {
onUpgrade(mDb, version);
onUpgrade(db, version);
} else if (version > DATABASE_VER) {
onDowngrade(mDb);
onDowngrade(db);
}
mDb.setVersion(DATABASE_VER);
db.setVersion(DATABASE_VER);
clearOutdated();
}
private SQLiteDatabase openDatabase(MagiskManager mm) {
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db", true);
DB_FILE = new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID));
final File DB_FILE = new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID));
Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
? mm.createDeviceProtectedStorageContext() : mm;
if (!DB_FILE.canWrite()) {
if (!Shell.rootAccess()) {
// We don't want the app to crash, create a db and return
DB_FILE = mm.getDatabasePath("su.db");
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
}
mm.loadMagiskInfo();
// Cleanup
Shell.Sync.su("sudb_clean " + Const.USER_ID);
Shell.Sync.su("db_clean " + Const.USER_ID);
if (mm.magiskVersionCode < 1410) {
// Super old legacy mode
DB_FILE = mm.getDatabasePath("su.db");
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
} else if (mm.magiskVersionCode < 1450) {
// Legacy mode with FBE aware
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
de.moveDatabaseFrom(mm, "su.db");
}
DB_FILE = de.getDatabasePath("su.db");
return de.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
} else {
// Global database
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db", true);
mm.deleteDatabase("su.db");
de.deleteDatabase("su.db");
if (mm.magiskVersionCode < 1460) {
@ -105,11 +102,11 @@ public class SuDatabaseHelper {
"'create su_file' 'allow * su_file file *' 'allow * su_file dir *'");
}
if (!GLOBAL_DB.exists()) {
Shell.Sync.su("sudb_init");
Shell.Sync.su("db_init");
SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
Shell.Sync.su("sudb_restore");
Shell.Sync.su("db_restore");
}
Shell.Sync.su("sudb_setup " + Process.myUid());
Shell.Sync.su("db_setup " + Process.myUid());
}
}
// Not using legacy mode, open the mounted global DB
@ -183,9 +180,9 @@ public class SuDatabaseHelper {
public void clearOutdated() {
// Clear outdated policies
mDb.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
// Clear outdated logs
mDb.delete(LOG_TABLE, Utils.fmt("time < %d", System.currentTimeMillis() - MagiskManager.get().suLogTimeout * 86400000), null);
db.delete(LOG_TABLE, Utils.fmt("time < %d", System.currentTimeMillis() - MagiskManager.get().suLogTimeout * 86400000), null);
}
public void deletePolicy(Policy policy) {
@ -193,16 +190,16 @@ public class SuDatabaseHelper {
}
public void deletePolicy(String pkg) {
mDb.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
}
public void deletePolicy(int uid) {
mDb.delete(POLICY_TABLE, Utils.fmt("uid=%d", uid), null);
db.delete(POLICY_TABLE, Utils.fmt("uid=%d", uid), null);
}
public Policy getPolicy(int uid) {
Policy policy = null;
try (Cursor c = mDb.query(POLICY_TABLE, null, Utils.fmt("uid=%d", uid), null, null, null, null)) {
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid=%d", uid), null, null, null, null)) {
if (c.moveToNext()) {
policy = new Policy(c, pm);
}
@ -214,15 +211,15 @@ public class SuDatabaseHelper {
}
public void addPolicy(Policy policy) {
mDb.replace(POLICY_TABLE, null, policy.getContentValues());
db.replace(POLICY_TABLE, null, policy.getContentValues());
}
public void updatePolicy(Policy policy) {
mDb.update(POLICY_TABLE, policy.getContentValues(), Utils.fmt("uid=%d", policy.uid), null);
db.update(POLICY_TABLE, policy.getContentValues(), Utils.fmt("uid=%d", policy.uid), null);
}
public List<Policy> getPolicyList(PackageManager pm) {
try (Cursor c = mDb.query(POLICY_TABLE, null, Utils.fmt("uid/100000=%d", Const.USER_ID),
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid/100000=%d", Const.USER_ID),
null, null, null, null)) {
List<Policy> ret = new ArrayList<>(c.getCount());
while (c.moveToNext()) {
@ -240,7 +237,7 @@ public class SuDatabaseHelper {
}
public List<List<Integer>> getLogStructure() {
try (Cursor c = mDb.query(LOG_TABLE, new String[] { "time" }, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
try (Cursor c = db.query(LOG_TABLE, new String[] { "time" }, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
null, null, null, "time DESC")) {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> list = null;
@ -260,28 +257,28 @@ public class SuDatabaseHelper {
}
public Cursor getLogCursor() {
return mDb.query(LOG_TABLE, null, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
return db.query(LOG_TABLE, null, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
null, null, null, "time DESC");
}
public void addLog(SuLogEntry log) {
mDb.insert(LOG_TABLE, null, log.getContentValues());
db.insert(LOG_TABLE, null, log.getContentValues());
}
public void clearLogs() {
mDb.delete(LOG_TABLE, null, null);
db.delete(LOG_TABLE, null, null);
}
public void setSettings(String key, int value) {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
mDb.replace(SETTINGS_TABLE, null, data);
db.replace(SETTINGS_TABLE, null, data);
}
public int getSettings(String key, int defaultValue) {
int value = defaultValue;
try (Cursor c = mDb.query(SETTINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
try (Cursor c = db.query(SETTINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
if (c.moveToNext()) {
value = c.getInt(c.getColumnIndex("value"));
}
@ -291,18 +288,18 @@ public class SuDatabaseHelper {
public void setStrings(String key, String value) {
if (value == null) {
mDb.delete(STRINGS_TABLE, "key=?", new String[] { key });
db.delete(STRINGS_TABLE, "key=?", new String[] { key });
} else {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
mDb.replace(STRINGS_TABLE, null, data);
db.replace(STRINGS_TABLE, null, data);
}
}
public String getStrings(String key, String defaultValue) {
String value = defaultValue;
try (Cursor c = mDb.query(STRINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
try (Cursor c = db.query(STRINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
if (c.moveToNext()) {
value = c.getString(c.getColumnIndex("value"));
}

View File

@ -20,11 +20,11 @@ public class PackageReceiver extends BroadcastReceiver {
case Intent.ACTION_PACKAGE_REPLACED:
// This will only work pre-O
if (mm.prefs.getBoolean(Const.Key.SU_REAUTH, false)) {
mm.suDB.deletePolicy(pkg);
mm.mDB.deletePolicy(pkg);
}
break;
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
mm.suDB.deletePolicy(pkg);
mm.mDB.deletePolicy(pkg);
Shell.Async.su("magiskhide --rm " + pkg);
break;
}

View File

@ -68,7 +68,7 @@ public class RequestActivity extends Activity {
pm = getPackageManager();
mm = Utils.getMagiskManager(this);
mm.suDB.clearOutdated();
mm.mDB.clearOutdated();
Intent intent = getIntent();
socketPath = intent.getStringExtra("socket");
@ -233,7 +233,7 @@ public class RequestActivity extends Activity {
policy.policy = action;
if (time >= 0) {
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
mm.suDB.addPolicy(policy);
mm.mDB.addPolicy(policy);
}
handleAction();
}
@ -273,7 +273,7 @@ public class RequestActivity extends Activity {
}
int uid = payload.getAsInteger("uid");
policy = mm.suDB.getPolicy(uid);
policy = mm.mDB.getPolicy(uid);
if (policy == null) {
policy = new Policy(uid, pm);
}

View File

@ -43,7 +43,7 @@ public class SuReceiver extends BroadcastReceiver {
action = intent.getStringExtra("action");
if (action == null) return;
policy = mm.suDB.getPolicy(fromUid);
policy = mm.mDB.getPolicy(fromUid);
if (policy == null) {
try {
policy = new Policy(fromUid, context.getPackageManager());
@ -84,7 +84,7 @@ public class SuReceiver extends BroadcastReceiver {
log.fromPid = pid;
log.command = command;
log.date = new Date();
mm.suDB.addLog(log);
mm.mDB.addLog(log);
}
}
}

View File

@ -1,4 +1,4 @@
sudb_clean() {
db_clean() {
local USERID=$1
local DIR="/sbin/.core/db-${USERID}"
umount -l /data/user*/*/*/databases/su.db $DIR $DIR/*
@ -6,18 +6,18 @@ sudb_clean() {
[ "$USERID" = "*" ] && rm -f /data/adb/magisk.db
}
sudb_init() {
db_init() {
ADB_CONTEXT=`/system/bin/ls -dZ /data/adb | awk '{print $1}'`
chcon u:object_r:su_file:s0 /data/adb
chmod 777 /data/adb
}
sudb_restore() {
db_restore() {
chcon $ADB_CONTEXT /data/adb
chmod 700 /data/adb
}
sudb_setup() {
db_setup() {
local USER=$1
local USERID=$(($USER / 100000))
local DIR=/sbin/.core/db-${USERID}