Refactor su database

This commit is contained in:
topjohnwu 2017-06-01 00:19:52 +08:00
parent 27879c3f01
commit 9a1dc8ee0e
10 changed files with 228 additions and 209 deletions

View File

@ -6,12 +6,11 @@ import android.content.pm.ApplicationInfo;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseArray;
import android.widget.Toast; import android.widget.Toast;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo; import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.utils.CallbackEvent; import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.SafetyNetHelper; import com.topjohnwu.magisk.utils.SafetyNetHelper;
import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Shell;
@ -24,7 +23,6 @@ import java.util.List;
public class MagiskManager extends Application { public class MagiskManager extends Application {
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk"; public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
public static final String MAGISK_HIDE_PATH = "/magisk/.core/magiskhide/";
public static final String TMP_FOLDER_PATH = "/dev/tmp"; public static final String TMP_FOLDER_PATH = "/dev/tmp";
public static final String MAGISK_PATH = "/magisk"; public static final String MAGISK_PATH = "/magisk";
public static final String UNINSTALLER = "magisk_uninstaller.sh"; public static final String UNINSTALLER = "magisk_uninstaller.sh";
@ -43,7 +41,6 @@ public class MagiskManager extends Application {
public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>(); public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>(); public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>();
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>(); public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
public final SparseArray<CallbackEvent<Policy>> uidSuRequest = new SparseArray<>();
// Info // Info
public String magiskVersionString; public String magiskVersionString;
@ -80,7 +77,9 @@ public class MagiskManager extends Application {
public int suResponseType; public int suResponseType;
public int suNotificationType; public int suNotificationType;
// Global resources
public SharedPreferences prefs; public SharedPreferences prefs;
public SuDatabaseHelper suDB;
private static Handler mHandler = new Handler(); private static Handler mHandler = new Handler();
@ -88,6 +87,7 @@ public class MagiskManager extends Application {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs = PreferenceManager.getDefaultSharedPreferences(this);
suDB = new SuDatabaseHelper(this);
} }
public void toast(String msg, int duration) { public void toast(String msg, int duration) {

View File

@ -13,7 +13,6 @@ import android.widget.TextView;
import com.topjohnwu.magisk.adapters.SuLogAdapter; import com.topjohnwu.magisk.adapters.SuLogAdapter;
import com.topjohnwu.magisk.components.Fragment; import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
import com.topjohnwu.magisk.superuser.SuLogEntry; import com.topjohnwu.magisk.superuser.SuLogEntry;
import java.util.List; import java.util.List;
@ -28,7 +27,7 @@ public class SuLogFragment extends Fragment {
@BindView(R.id.recyclerView) RecyclerView recyclerView; @BindView(R.id.recyclerView) RecyclerView recyclerView;
private Unbinder unbinder; private Unbinder unbinder;
private SuLogDatabaseHelper dbHelper; private MagiskManager magiskManager;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
@ -48,8 +47,7 @@ public class SuLogFragment extends Fragment {
// Inflate the layout for this fragment // Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_su_log, container, false); View v = inflater.inflate(R.layout.fragment_su_log, container, false);
unbinder = ButterKnife.bind(this, v); unbinder = ButterKnife.bind(this, v);
magiskManager = getApplication();
dbHelper = new SuLogDatabaseHelper(getActivity());
updateList(); updateList();
@ -57,7 +55,7 @@ public class SuLogFragment extends Fragment {
} }
private void updateList() { private void updateList() {
List<SuLogEntry> logs = dbHelper.getLogList(); List<SuLogEntry> logs = magiskManager.suDB.getLogList();
if (logs.size() == 0) { if (logs.size() == 0) {
emptyRv.setVisibility(View.VISIBLE); emptyRv.setVisibility(View.VISIBLE);
@ -76,7 +74,7 @@ public class SuLogFragment extends Fragment {
updateList(); updateList();
return true; return true;
case R.id.menu_clear: case R.id.menu_clear:
dbHelper.clearLogs(); magiskManager.suDB.clearLogs();
updateList(); updateList();
return true; return true;
default: default:

View File

@ -11,7 +11,6 @@ import android.widget.TextView;
import com.topjohnwu.magisk.adapters.PolicyAdapter; import com.topjohnwu.magisk.adapters.PolicyAdapter;
import com.topjohnwu.magisk.components.Fragment; import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.superuser.Policy; import com.topjohnwu.magisk.superuser.Policy;
import java.util.List; import java.util.List;
@ -33,15 +32,15 @@ public class SuperuserFragment extends Fragment {
unbinder = ButterKnife.bind(this, view); unbinder = ButterKnife.bind(this, view);
PackageManager pm = getActivity().getPackageManager(); PackageManager pm = getActivity().getPackageManager();
MagiskManager magiskManager = getApplication();
SuDatabaseHelper dbHelper = new SuDatabaseHelper(getActivity()); List<Policy> policyList = magiskManager.suDB.getPolicyList(pm);
List<Policy> policyList = dbHelper.getPolicyList(pm);
if (policyList.size() == 0) { if (policyList.size() == 0) {
emptyRv.setVisibility(View.VISIBLE); emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE); recyclerView.setVisibility(View.GONE);
} else { } else {
recyclerView.setAdapter(new PolicyAdapter(policyList, dbHelper, pm)); recyclerView.setAdapter(new PolicyAdapter(policyList, magiskManager.suDB, pm));
emptyRv.setVisibility(View.GONE); emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE); recyclerView.setVisibility(View.VISIBLE);
} }

View File

@ -49,78 +49,72 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
@Override @Override
public void onBindViewHolder(ViewHolder holder, int position) { public void onBindViewHolder(ViewHolder holder, int position) {
Policy policy = policyList.get(position); Policy policy = policyList.get(position);
try {
holder.setExpanded(expandList.contains(policy));
holder.itemView.setOnClickListener(view -> { holder.setExpanded(expandList.contains(policy));
if (holder.mExpanded) {
holder.collapse();
expandList.remove(policy);
} else {
holder.expand();
expandList.add(policy);
}
});
holder.appName.setText(policy.appName); holder.itemView.setOnClickListener(view -> {
holder.packageName.setText(policy.packageName); if (holder.mExpanded) {
holder.appIcon.setImageDrawable(pm.getPackageInfo(policy.packageName, 0).applicationInfo.loadIcon(pm)); holder.collapse();
holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> { expandList.remove(policy);
if ((isChecked && policy.policy == Policy.DENY) || } else {
(!isChecked && policy.policy == Policy.ALLOW)) { holder.expand();
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY; expandList.add(policy);
String message = v.getContext().getString( }
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName); });
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
dbHelper.updatePolicy(policy);
}
});
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
if ((isChecked && !policy.notification) ||
(!isChecked && policy.notification)) {
policy.notification = isChecked;
String message = v.getContext().getString(
isChecked ? R.string.su_snack_notif_on : R.string.su_snack_notif_off, policy.appName);
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
dbHelper.updatePolicy(policy);
}
});
holder.loggingSwitch.setOnCheckedChangeListener((v, isChecked) -> {
if ((isChecked && !policy.logging) ||
(!isChecked && policy.logging)) {
policy.logging = isChecked;
String message = v.getContext().getString(
isChecked ? R.string.su_snack_log_on : R.string.su_snack_log_off, policy.appName);
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
dbHelper.updatePolicy(policy);
}
});
holder.delete.setOnClickListener(v -> new AlertDialogBuilder(v.getContext())
.setTitle(R.string.su_revoke_title)
.setMessage(v.getContext().getString(R.string.su_revoke_msg, policy.appName))
.setPositiveButton(R.string.yes, (dialog, which) -> {
policyList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, policyList.size());
SnackbarMaker.make(holder.itemView, v.getContext().getString(R.string.su_snack_revoke, policy.appName),
Snackbar.LENGTH_SHORT).show();
dbHelper.deletePolicy(policy);
})
.setNegativeButton(R.string.no_thanks, null)
.setCancelable(true)
.show());
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
holder.notificationSwitch.setChecked(policy.notification);
holder.loggingSwitch.setChecked(policy.logging);
// Hide for now holder.appName.setText(policy.appName);
holder.moreInfo.setVisibility(View.GONE); holder.packageName.setText(policy.packageName);
holder.appIcon.setImageDrawable(policy.info.loadIcon(pm));
holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> {
if ((isChecked && policy.policy == Policy.DENY) ||
(!isChecked && policy.policy == Policy.ALLOW)) {
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY;
String message = v.getContext().getString(
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName);
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
dbHelper.updatePolicy(policy);
}
});
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
if ((isChecked && !policy.notification) ||
(!isChecked && policy.notification)) {
policy.notification = isChecked;
String message = v.getContext().getString(
isChecked ? R.string.su_snack_notif_on : R.string.su_snack_notif_off, policy.appName);
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
dbHelper.updatePolicy(policy);
}
});
holder.loggingSwitch.setOnCheckedChangeListener((v, isChecked) -> {
if ((isChecked && !policy.logging) ||
(!isChecked && policy.logging)) {
policy.logging = isChecked;
String message = v.getContext().getString(
isChecked ? R.string.su_snack_log_on : R.string.su_snack_log_off, policy.appName);
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
dbHelper.updatePolicy(policy);
}
});
holder.delete.setOnClickListener(v -> new AlertDialogBuilder(v.getContext())
.setTitle(R.string.su_revoke_title)
.setMessage(v.getContext().getString(R.string.su_revoke_msg, policy.appName))
.setPositiveButton(R.string.yes, (dialog, which) -> {
policyList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, policyList.size());
SnackbarMaker.make(holder.itemView, v.getContext().getString(R.string.su_snack_revoke, policy.appName),
Snackbar.LENGTH_SHORT).show();
dbHelper.deletePolicy(policy);
})
.setNegativeButton(R.string.no_thanks, null)
.setCancelable(true)
.show());
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
holder.notificationSwitch.setChecked(policy.notification);
holder.loggingSwitch.setChecked(policy.logging);
} catch (PackageManager.NameNotFoundException e) { // Hide for now
policyList.remove(position); holder.moreInfo.setVisibility(View.GONE);
dbHelper.deletePolicy(policy);
onBindViewHolder(holder, position);
}
} }
@Override @Override

View File

@ -6,18 +6,30 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.superuser.Policy; import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.superuser.SuLogEntry;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public class SuDatabaseHelper extends SQLiteOpenHelper { public class SuDatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VER = 1; private static final int DATABASE_VER = 2;
private static final String TABLE_NAME = "policies"; private static final String POLICY_TABLE = "policies";
private static final String LOG_TABLE = "logs";
private static final String SETTINGS_TABLE = "settings";
private MagiskManager magiskManager;
private PackageManager pm;
public SuDatabaseHelper(Context context) { public SuDatabaseHelper(Context context) {
super(context, "su.db", null, DATABASE_VER); super(context, "su.db", null, DATABASE_VER);
magiskManager = Utils.getMagiskManager(context);
pm = context.getPackageManager();
} }
@Override @Override
@ -28,29 +40,78 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
@Override @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 0) { if (oldVersion == 0) {
db.execSQL( createTables(db);
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " + oldVersion = 2;
"(uid INT, package_name TEXT, app_name TEXT, policy INT, " + }
"until INT, logging INT, notification INT, " + if (oldVersion == 1) {
"PRIMARY KEY(uid))"); // We're dropping column app_name, rename and re-construct table
db.execSQL("ALTER TABLE " + POLICY_TABLE + " RENAME TO " + POLICY_TABLE + "_old");
// Create the new tables
createTables(db);
// Migrate old data to new tables
db.execSQL(
"INSERT INTO " + POLICY_TABLE + " SELECT " +
"uid, package_name, policy, until, logging, notification " +
"FROM " + POLICY_TABLE + "_old");
db.execSQL("DROP TABLE " + POLICY_TABLE + "_old");
File oldDB = magiskManager.getDatabasePath("sulog.db");
if (oldDB.exists()) {
migrateLegacyLogList(oldDB, db);
magiskManager.deleteDatabase("sulog.db");
}
++oldVersion;
} }
// Currently new database, no upgrading
} }
public boolean deletePolicy(Policy policy) { private void createTables(SQLiteDatabase db) {
// Policies
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + POLICY_TABLE + " " +
"(uid INT, package_name TEXT, policy INT, " +
"until INT, logging INT, notification INT, " +
"PRIMARY KEY(uid))");
// Logs
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + LOG_TABLE + " " +
"(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
"to_uid INT, action INT, time INT, command TEXT)");
// Settings
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + SETTINGS_TABLE + " " +
"(key TEXT, value INT, PRIMARY KEY(key))");
}
public void deletePolicy(Policy policy) {
deletePolicy(policy.packageName);
}
public void deletePolicy(String pkg) {
SQLiteDatabase db = getWritableDatabase(); SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_NAME, "package_name=?", new String[] { policy.packageName }); db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
db.close();
}
public void deletePolicy(int uid) {
SQLiteDatabase db = getWritableDatabase();
db.delete(POLICY_TABLE, "uid=?", new String[]{String.valueOf(uid)});
db.close(); db.close();
return getPolicy(policy.packageName) == null;
} }
public Policy getPolicy(int uid) { public Policy getPolicy(int uid) {
Policy policy = null; Policy policy = null;
SQLiteDatabase db = getReadableDatabase(); SQLiteDatabase db = getReadableDatabase();
try (Cursor c = db.query(TABLE_NAME, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) { try (Cursor c = db.query(POLICY_TABLE, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
if (c.moveToNext()) { if (c.moveToNext()) {
policy = new Policy(c); policy = new Policy(c, pm);
} }
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(uid);
return null;
} }
db.close(); db.close();
return policy; return policy;
@ -59,10 +120,13 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
public Policy getPolicy(String pkg) { public Policy getPolicy(String pkg) {
Policy policy = null; Policy policy = null;
SQLiteDatabase db = getReadableDatabase(); SQLiteDatabase db = getReadableDatabase();
try (Cursor c = db.query(TABLE_NAME, null, "package_name=?", new String[] { pkg }, null, null, null)) { try (Cursor c = db.query(POLICY_TABLE, null, "package_name=?", new String[] { pkg }, null, null, null)) {
if (c.moveToNext()) { if (c.moveToNext()) {
policy = new Policy(c); policy = new Policy(c, pm);
} }
} catch (PackageManager.NameNotFoundException e) {
deletePolicy(pkg);
return null;
} }
db.close(); db.close();
return policy; return policy;
@ -70,13 +134,13 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
public void addPolicy(Policy policy) { public void addPolicy(Policy policy) {
SQLiteDatabase db = getWritableDatabase(); SQLiteDatabase db = getWritableDatabase();
db.replace(TABLE_NAME, null, policy.getContentValues()); db.replace(POLICY_TABLE, null, policy.getContentValues());
db.close(); db.close();
} }
public void updatePolicy(Policy policy) { public void updatePolicy(Policy policy) {
SQLiteDatabase db = getWritableDatabase(); SQLiteDatabase db = getWritableDatabase();
db.update(TABLE_NAME, policy.getContentValues(), "package_name=?", db.update(POLICY_TABLE, policy.getContentValues(), "package_name=?",
new String[] { policy.packageName }); new String[] { policy.packageName });
db.close(); db.close();
} }
@ -86,15 +150,60 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
SQLiteDatabase db = getWritableDatabase(); SQLiteDatabase db = getWritableDatabase();
Policy policy; Policy policy;
// Clear outdated policies // Clear outdated policies
db.delete(TABLE_NAME, "until > 0 AND until < ?", db.delete(POLICY_TABLE, "until > 0 AND until < ?",
new String[] { String.valueOf(System.currentTimeMillis()) }); new String[] { String.valueOf(System.currentTimeMillis()) });
try (Cursor c = db.query(TABLE_NAME, null, null, null, null, null, "app_name ASC")) { try (Cursor c = db.query(POLICY_TABLE, null, null, null, null, null, null)) {
while (c.moveToNext()) { while (c.moveToNext()) {
policy = new Policy(c); policy = new Policy(c, pm);
ret.add(policy); ret.add(policy);
} }
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
db.close();
Collections.sort(ret);
return ret;
}
private List<SuLogEntry> getLogList(SQLiteDatabase db, String selection) {
List<SuLogEntry> ret = new ArrayList<>();
// Clear outdated logs
db.delete(LOG_TABLE, "time < ?", new String[] { String.valueOf(
System.currentTimeMillis() / 1000 - magiskManager.suLogTimeout * 86400) });
try (Cursor c = db.query(LOG_TABLE, null, selection, null, null, null, "time DESC")) {
while (c.moveToNext()) {
ret.add(new SuLogEntry(c));
}
} }
db.close(); db.close();
return ret; return ret;
} }
private void migrateLegacyLogList(File oldDB, SQLiteDatabase newDB) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(oldDB.getPath(), null, SQLiteDatabase.OPEN_READWRITE);
List<SuLogEntry> logs = getLogList(db, null);
for (SuLogEntry log : logs) {
newDB.insert(LOG_TABLE, null, log.getContentValues());
}
}
public List<SuLogEntry> getLogList() {
return getLogList(null);
}
public List<SuLogEntry> getLogList(String selection) {
return getLogList(getWritableDatabase(), selection);
}
public void addLog(SuLogEntry log) {
SQLiteDatabase db = getWritableDatabase();
db.insert(LOG_TABLE, null, log.getContentValues());
db.close();
}
public void clearLogs() {
SQLiteDatabase db = getWritableDatabase();
db.delete(LOG_TABLE, null, null);
db.close();
}
} }

View File

@ -1,76 +0,0 @@
package com.topjohnwu.magisk.database;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.superuser.SuLogEntry;
import java.util.ArrayList;
import java.util.List;
public class SuLogDatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VER = 1;
private static final String TABLE_NAME = "logs";
private MagiskManager magiskManager;
public SuLogDatabaseHelper(Context context) {
super(context, "sulog.db", null, DATABASE_VER);
magiskManager = (MagiskManager) context.getApplicationContext();
}
@Override
public void onCreate(SQLiteDatabase db) {
onUpgrade(db, 0, DATABASE_VER);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 0) {
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
"to_uid INT, action INT, time INT, command TEXT)");
}
// Currently new database, no upgrading
}
public void addLog(SuLogEntry log) {
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_NAME, null, log.getContentValues());
db.close();
}
public void clearLogs() {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_NAME, null, null);
db.close();
}
public List<SuLogEntry> getLogList() {
return getLogList(null);
}
public List<SuLogEntry> getLogList(int uid) {
return getLogList("uid=" + uid);
}
public List<SuLogEntry> getLogList(String selection) {
List<SuLogEntry> ret = new ArrayList<>();
SQLiteDatabase db = getWritableDatabase();
// Clear outdated logs
db.delete(TABLE_NAME, "time < ?", new String[] { String.valueOf(
System.currentTimeMillis() / 1000 - magiskManager.suLogTimeout * 86400) });
try (Cursor c = db.query(TABLE_NAME, null, selection, null, null, null, "time DESC")) {
while (c.moveToNext()) {
ret.add(new SuLogEntry(c));
}
}
db.close();
return ret;
}
}

View File

@ -5,21 +5,18 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.superuser.Policy; import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
public class PackageReceiver extends BroadcastReceiver { public class PackageReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
SuDatabaseHelper suDB = new SuDatabaseHelper(context); MagiskManager magiskManager = Utils.getMagiskManager(context);
String pkg = intent.getData().getEncodedSchemeSpecificPart(); String pkg = intent.getData().getEncodedSchemeSpecificPart();
Policy policy = suDB.getPolicy(pkg); Policy policy = magiskManager.suDB.getPolicy(pkg);
if (policy == null) if (policy == null)
return; return;
MagiskManager magiskManager = Utils.getMagiskManager(context);
magiskManager.initSUConfig(); magiskManager.initSUConfig();
switch (intent.getAction()) { switch (intent.getAction()) {
@ -29,12 +26,12 @@ public class PackageReceiver extends BroadcastReceiver {
if (uid > 0) { if (uid > 0) {
policy.uid = uid % 100000; policy.uid = uid % 100000;
} }
suDB.updatePolicy(policy); magiskManager.suDB.updatePolicy(policy);
return; return;
case Intent.ACTION_PACKAGE_REMOVED: case Intent.ACTION_PACKAGE_REMOVED:
boolean isUpdate = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); boolean isUpdate = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
if (!isUpdate || magiskManager.suReauth) { if (!isUpdate || magiskManager.suReauth) {
suDB.deletePolicy(policy); magiskManager.suDB.deletePolicy(policy);
} }
break; break;
} }

View File

@ -1,12 +1,13 @@
package com.topjohnwu.magisk.superuser; package com.topjohnwu.magisk.superuser;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.pm.PackageInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.support.annotation.NonNull;
public class Policy { public class Policy implements Comparable<Policy>{
public static final int INTERACTIVE = 0; public static final int INTERACTIVE = 0;
public static final int DENY = 1; public static final int DENY = 1;
public static final int ALLOW = 2; public static final int ALLOW = 2;
@ -15,37 +16,42 @@ public class Policy {
public long until; public long until;
public boolean logging = true, notification = true; public boolean logging = true, notification = true;
public String packageName, appName; public String packageName, appName;
public PackageInfo info; public ApplicationInfo info;
public Policy(int uid, PackageManager pm) throws PackageManager.NameNotFoundException { public Policy(int uid, PackageManager pm) throws PackageManager.NameNotFoundException {
String[] pkgs = pm.getPackagesForUid(uid); String[] pkgs = pm.getPackagesForUid(uid);
if (pkgs != null && pkgs.length > 0) { if (pkgs != null && pkgs.length > 0) {
info = pm.getPackageInfo(pkgs[0], 0);
this.uid = uid; this.uid = uid;
packageName = pkgs[0]; packageName = pkgs[0];
appName = info.applicationInfo.loadLabel(pm).toString(); info = pm.getApplicationInfo(packageName, 0);
appName = info.loadLabel(pm).toString();
} else throw new PackageManager.NameNotFoundException(); } else throw new PackageManager.NameNotFoundException();
} }
public Policy(Cursor c) { public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException {
uid = c.getInt(c.getColumnIndex("uid")); uid = c.getInt(c.getColumnIndex("uid"));
packageName = c.getString(c.getColumnIndex("package_name")); packageName = c.getString(c.getColumnIndex("package_name"));
appName = c.getString(c.getColumnIndex("app_name"));
policy = c.getInt(c.getColumnIndex("policy")); policy = c.getInt(c.getColumnIndex("policy"));
until = c.getLong(c.getColumnIndex("until")); until = c.getLong(c.getColumnIndex("until"));
logging = c.getInt(c.getColumnIndex("logging")) != 0; logging = c.getInt(c.getColumnIndex("logging")) != 0;
notification = c.getInt(c.getColumnIndex("notification")) != 0; notification = c.getInt(c.getColumnIndex("notification")) != 0;
info = pm.getApplicationInfo(packageName, 0);
appName = info.loadLabel(pm).toString();
} }
public ContentValues getContentValues() { public ContentValues getContentValues() {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put("uid", uid); values.put("uid", uid);
values.put("package_name", packageName); values.put("package_name", packageName);
values.put("app_name", appName);
values.put("policy", policy); values.put("policy", policy);
values.put("until", until); values.put("until", until);
values.put("logging", logging ? 1 : 0); values.put("logging", logging ? 1 : 0);
values.put("notification", notification ? 1 : 0); values.put("notification", notification ? 1 : 0);
return values; return values;
} }
@Override
public int compareTo(@NonNull Policy policy) {
return appName.toLowerCase().compareTo(policy.appName.toLowerCase());
}
} }

View File

@ -3,13 +3,12 @@ package com.topjohnwu.magisk.superuser;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Process; import android.os.Process;
import android.widget.Toast; import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
import java.util.Date; import java.util.Date;
@ -46,12 +45,12 @@ public class SuReceiver extends BroadcastReceiver {
action = intent.getStringExtra("action"); action = intent.getStringExtra("action");
if (action == null) return; if (action == null) return;
SuDatabaseHelper suDbHelper = new SuDatabaseHelper(context); policy = magiskManager.suDB.getPolicy(fromUid);
policy = suDbHelper.getPolicy(fromUid);
if (policy == null) { if (policy == null) {
try { try {
policy = new Policy(fromUid, context.getPackageManager()); policy = new Policy(fromUid, context.getPackageManager());
} catch (Throwable throwable) { } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return; return;
} }
} }
@ -89,8 +88,7 @@ public class SuReceiver extends BroadcastReceiver {
log.fromPid = pid; log.fromPid = pid;
log.command = command; log.command = command;
log.date = new Date(); log.date = new Date();
SuLogDatabaseHelper logDbHelper = new SuLogDatabaseHelper(context); magiskManager.suDB.addLog(log);
logDbHelper.addLog(log);
} }
} }
} }

View File

@ -21,13 +21,9 @@ import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.ParallelTask; import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.Activity; import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
@ -51,7 +47,6 @@ public class SuRequestActivity extends Activity {
private LocalSocket socket; private LocalSocket socket;
private PackageManager pm; private PackageManager pm;
private MagiskManager magiskManager; private MagiskManager magiskManager;
private SuDatabaseHelper suDB;
private boolean hasTimeout; private boolean hasTimeout;
private Policy policy; private Policy policy;
@ -64,7 +59,6 @@ public class SuRequestActivity extends Activity {
pm = getPackageManager(); pm = getPackageManager();
magiskManager = getApplicationContext(); magiskManager = getApplicationContext();
suDB = new SuDatabaseHelper(this);
Intent intent = getIntent(); Intent intent = getIntent();
socketPath = intent.getStringExtra("socket"); socketPath = intent.getStringExtra("socket");
@ -109,7 +103,7 @@ public class SuRequestActivity extends Activity {
setContentView(R.layout.activity_request); setContentView(R.layout.activity_request);
ButterKnife.bind(this); ButterKnife.bind(this);
appIcon.setImageDrawable(policy.info.applicationInfo.loadIcon(pm)); appIcon.setImageDrawable(policy.info.loadIcon(pm));
appNameView.setText(policy.appName); appNameView.setText(policy.appName);
packageNameView.setText(policy.packageName); packageNameView.setText(policy.packageName);
@ -180,7 +174,7 @@ public class SuRequestActivity extends Activity {
policy.policy = action; policy.policy = action;
if (time >= 0) { if (time >= 0) {
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60); policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
new SuDatabaseHelper(this).addPolicy(policy); magiskManager.suDB.addPolicy(policy);
} }
handleAction(); handleAction();
} }
@ -220,7 +214,7 @@ public class SuRequestActivity extends Activity {
} }
int uid = payload.getAsInteger("uid"); int uid = payload.getAsInteger("uid");
policy = suDB.getPolicy(uid); policy = magiskManager.suDB.getPolicy(uid);
if (policy == null) { if (policy == null) {
policy = new Policy(uid, pm); policy = new Policy(uid, pm);
} }