Refactor su database
This commit is contained in:
parent
27879c3f01
commit
9a1dc8ee0e
@ -6,12 +6,11 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.SparseArray;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.module.Module;
|
||||
import com.topjohnwu.magisk.module.Repo;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.SafetyNetHelper;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
@ -24,7 +23,6 @@ import java.util.List;
|
||||
public class MagiskManager extends Application {
|
||||
|
||||
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 MAGISK_PATH = "/magisk";
|
||||
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> updateCheckDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
|
||||
public final SparseArray<CallbackEvent<Policy>> uidSuRequest = new SparseArray<>();
|
||||
|
||||
// Info
|
||||
public String magiskVersionString;
|
||||
@ -80,7 +77,9 @@ public class MagiskManager extends Application {
|
||||
public int suResponseType;
|
||||
public int suNotificationType;
|
||||
|
||||
// Global resources
|
||||
public SharedPreferences prefs;
|
||||
public SuDatabaseHelper suDB;
|
||||
|
||||
private static Handler mHandler = new Handler();
|
||||
|
||||
@ -88,6 +87,7 @@ public class MagiskManager extends Application {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
suDB = new SuDatabaseHelper(this);
|
||||
}
|
||||
|
||||
public void toast(String msg, int duration) {
|
||||
|
@ -13,7 +13,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.SuLogEntry;
|
||||
|
||||
import java.util.List;
|
||||
@ -28,7 +27,7 @@ public class SuLogFragment extends Fragment {
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
|
||||
private Unbinder unbinder;
|
||||
private SuLogDatabaseHelper dbHelper;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@ -48,8 +47,7 @@ public class SuLogFragment extends Fragment {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
|
||||
dbHelper = new SuLogDatabaseHelper(getActivity());
|
||||
magiskManager = getApplication();
|
||||
|
||||
updateList();
|
||||
|
||||
@ -57,7 +55,7 @@ public class SuLogFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
List<SuLogEntry> logs = dbHelper.getLogList();
|
||||
List<SuLogEntry> logs = magiskManager.suDB.getLogList();
|
||||
|
||||
if (logs.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
@ -76,7 +74,7 @@ public class SuLogFragment extends Fragment {
|
||||
updateList();
|
||||
return true;
|
||||
case R.id.menu_clear:
|
||||
dbHelper.clearLogs();
|
||||
magiskManager.suDB.clearLogs();
|
||||
updateList();
|
||||
return true;
|
||||
default:
|
||||
|
@ -11,7 +11,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.PolicyAdapter;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
|
||||
import java.util.List;
|
||||
@ -33,15 +32,15 @@ public class SuperuserFragment extends Fragment {
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
PackageManager pm = getActivity().getPackageManager();
|
||||
MagiskManager magiskManager = getApplication();
|
||||
|
||||
SuDatabaseHelper dbHelper = new SuDatabaseHelper(getActivity());
|
||||
List<Policy> policyList = dbHelper.getPolicyList(pm);
|
||||
List<Policy> policyList = magiskManager.suDB.getPolicyList(pm);
|
||||
|
||||
if (policyList.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, dbHelper, pm));
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, magiskManager.suDB, pm));
|
||||
emptyRv.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
@ -49,78 +49,72 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Policy policy = policyList.get(position);
|
||||
try {
|
||||
holder.setExpanded(expandList.contains(policy));
|
||||
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.mExpanded) {
|
||||
holder.collapse();
|
||||
expandList.remove(policy);
|
||||
} else {
|
||||
holder.expand();
|
||||
expandList.add(policy);
|
||||
}
|
||||
});
|
||||
holder.setExpanded(expandList.contains(policy));
|
||||
|
||||
holder.appName.setText(policy.appName);
|
||||
holder.packageName.setText(policy.packageName);
|
||||
holder.appIcon.setImageDrawable(pm.getPackageInfo(policy.packageName, 0).applicationInfo.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);
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.mExpanded) {
|
||||
holder.collapse();
|
||||
expandList.remove(policy);
|
||||
} else {
|
||||
holder.expand();
|
||||
expandList.add(policy);
|
||||
}
|
||||
});
|
||||
|
||||
// Hide for now
|
||||
holder.moreInfo.setVisibility(View.GONE);
|
||||
holder.appName.setText(policy.appName);
|
||||
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) {
|
||||
policyList.remove(position);
|
||||
dbHelper.deletePolicy(policy);
|
||||
onBindViewHolder(holder, position);
|
||||
}
|
||||
// Hide for now
|
||||
holder.moreInfo.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,18 +6,30 @@ import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final int DATABASE_VER = 1;
|
||||
private static final String TABLE_NAME = "policies";
|
||||
private static final int DATABASE_VER = 2;
|
||||
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) {
|
||||
super(context, "su.db", null, DATABASE_VER);
|
||||
magiskManager = Utils.getMagiskManager(context);
|
||||
pm = context.getPackageManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -28,29 +40,78 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 0) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||
"(uid INT, package_name TEXT, app_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
createTables(db);
|
||||
oldVersion = 2;
|
||||
}
|
||||
if (oldVersion == 1) {
|
||||
// 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();
|
||||
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();
|
||||
return getPolicy(policy.packageName) == null;
|
||||
}
|
||||
|
||||
public Policy getPolicy(int uid) {
|
||||
Policy policy = null;
|
||||
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()) {
|
||||
policy = new Policy(c);
|
||||
policy = new Policy(c, pm);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
deletePolicy(uid);
|
||||
return null;
|
||||
}
|
||||
db.close();
|
||||
return policy;
|
||||
@ -59,10 +120,13 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
public Policy getPolicy(String pkg) {
|
||||
Policy policy = null;
|
||||
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()) {
|
||||
policy = new Policy(c);
|
||||
policy = new Policy(c, pm);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
deletePolicy(pkg);
|
||||
return null;
|
||||
}
|
||||
db.close();
|
||||
return policy;
|
||||
@ -70,13 +134,13 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
public void addPolicy(Policy policy) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.replace(TABLE_NAME, null, policy.getContentValues());
|
||||
db.replace(POLICY_TABLE, null, policy.getContentValues());
|
||||
db.close();
|
||||
}
|
||||
|
||||
public void updatePolicy(Policy policy) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.update(TABLE_NAME, policy.getContentValues(), "package_name=?",
|
||||
db.update(POLICY_TABLE, policy.getContentValues(), "package_name=?",
|
||||
new String[] { policy.packageName });
|
||||
db.close();
|
||||
}
|
||||
@ -86,15 +150,60 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
Policy policy;
|
||||
// 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()) });
|
||||
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()) {
|
||||
policy = new Policy(c);
|
||||
policy = new Policy(c, pm);
|
||||
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();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -5,21 +5,18 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class PackageReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SuDatabaseHelper suDB = new SuDatabaseHelper(context);
|
||||
MagiskManager magiskManager = Utils.getMagiskManager(context);
|
||||
String pkg = intent.getData().getEncodedSchemeSpecificPart();
|
||||
Policy policy = suDB.getPolicy(pkg);
|
||||
Policy policy = magiskManager.suDB.getPolicy(pkg);
|
||||
if (policy == null)
|
||||
return;
|
||||
|
||||
MagiskManager magiskManager = Utils.getMagiskManager(context);
|
||||
magiskManager.initSUConfig();
|
||||
|
||||
switch (intent.getAction()) {
|
||||
@ -29,12 +26,12 @@ public class PackageReceiver extends BroadcastReceiver {
|
||||
if (uid > 0) {
|
||||
policy.uid = uid % 100000;
|
||||
}
|
||||
suDB.updatePolicy(policy);
|
||||
magiskManager.suDB.updatePolicy(policy);
|
||||
return;
|
||||
case Intent.ACTION_PACKAGE_REMOVED:
|
||||
boolean isUpdate = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
|
||||
if (!isUpdate || magiskManager.suReauth) {
|
||||
suDB.deletePolicy(policy);
|
||||
magiskManager.suDB.deletePolicy(policy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
package com.topjohnwu.magisk.superuser;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
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 DENY = 1;
|
||||
public static final int ALLOW = 2;
|
||||
@ -15,37 +16,42 @@ public class Policy {
|
||||
public long until;
|
||||
public boolean logging = true, notification = true;
|
||||
public String packageName, appName;
|
||||
public PackageInfo info;
|
||||
public ApplicationInfo info;
|
||||
|
||||
public Policy(int uid, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||
String[] pkgs = pm.getPackagesForUid(uid);
|
||||
if (pkgs != null && pkgs.length > 0) {
|
||||
info = pm.getPackageInfo(pkgs[0], 0);
|
||||
this.uid = uid;
|
||||
packageName = pkgs[0];
|
||||
appName = info.applicationInfo.loadLabel(pm).toString();
|
||||
info = pm.getApplicationInfo(packageName, 0);
|
||||
appName = info.loadLabel(pm).toString();
|
||||
} else throw new PackageManager.NameNotFoundException();
|
||||
}
|
||||
|
||||
public Policy(Cursor c) {
|
||||
public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||
uid = c.getInt(c.getColumnIndex("uid"));
|
||||
packageName = c.getString(c.getColumnIndex("package_name"));
|
||||
appName = c.getString(c.getColumnIndex("app_name"));
|
||||
policy = c.getInt(c.getColumnIndex("policy"));
|
||||
until = c.getLong(c.getColumnIndex("until"));
|
||||
logging = c.getInt(c.getColumnIndex("logging")) != 0;
|
||||
notification = c.getInt(c.getColumnIndex("notification")) != 0;
|
||||
info = pm.getApplicationInfo(packageName, 0);
|
||||
appName = info.loadLabel(pm).toString();
|
||||
}
|
||||
|
||||
public ContentValues getContentValues() {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("uid", uid);
|
||||
values.put("package_name", packageName);
|
||||
values.put("app_name", appName);
|
||||
values.put("policy", policy);
|
||||
values.put("until", until);
|
||||
values.put("logging", logging ? 1 : 0);
|
||||
values.put("notification", notification ? 1 : 0);
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull Policy policy) {
|
||||
return appName.toLowerCase().compareTo(policy.appName.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,12 @@ package com.topjohnwu.magisk.superuser;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Process;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ -46,12 +45,12 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
action = intent.getStringExtra("action");
|
||||
if (action == null) return;
|
||||
|
||||
SuDatabaseHelper suDbHelper = new SuDatabaseHelper(context);
|
||||
policy = suDbHelper.getPolicy(fromUid);
|
||||
policy = magiskManager.suDB.getPolicy(fromUid);
|
||||
if (policy == null) {
|
||||
try {
|
||||
policy = new Policy(fromUid, context.getPackageManager());
|
||||
} catch (Throwable throwable) {
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -89,8 +88,7 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
log.fromPid = pid;
|
||||
log.command = command;
|
||||
log.date = new Date();
|
||||
SuLogDatabaseHelper logDbHelper = new SuLogDatabaseHelper(context);
|
||||
logDbHelper.addLog(log);
|
||||
magiskManager.suDB.addLog(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,9 @@ import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
||||
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.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
@ -51,7 +47,6 @@ public class SuRequestActivity extends Activity {
|
||||
private LocalSocket socket;
|
||||
private PackageManager pm;
|
||||
private MagiskManager magiskManager;
|
||||
private SuDatabaseHelper suDB;
|
||||
|
||||
private boolean hasTimeout;
|
||||
private Policy policy;
|
||||
@ -64,7 +59,6 @@ public class SuRequestActivity extends Activity {
|
||||
|
||||
pm = getPackageManager();
|
||||
magiskManager = getApplicationContext();
|
||||
suDB = new SuDatabaseHelper(this);
|
||||
|
||||
Intent intent = getIntent();
|
||||
socketPath = intent.getStringExtra("socket");
|
||||
@ -109,7 +103,7 @@ public class SuRequestActivity extends Activity {
|
||||
setContentView(R.layout.activity_request);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
appIcon.setImageDrawable(policy.info.applicationInfo.loadIcon(pm));
|
||||
appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||
appNameView.setText(policy.appName);
|
||||
packageNameView.setText(policy.packageName);
|
||||
|
||||
@ -180,7 +174,7 @@ public class SuRequestActivity extends Activity {
|
||||
policy.policy = action;
|
||||
if (time >= 0) {
|
||||
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
|
||||
new SuDatabaseHelper(this).addPolicy(policy);
|
||||
magiskManager.suDB.addPolicy(policy);
|
||||
}
|
||||
handleAction();
|
||||
}
|
||||
@ -220,7 +214,7 @@ public class SuRequestActivity extends Activity {
|
||||
}
|
||||
|
||||
int uid = payload.getAsInteger("uid");
|
||||
policy = suDB.getPolicy(uid);
|
||||
policy = magiskManager.suDB.getPolicy(uid);
|
||||
if (policy == null) {
|
||||
policy = new Policy(uid, pm);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user