Removed direct static usages of database from app

This commit is contained in:
Viktor De Pasquale 2019-05-12 15:49:42 +02:00
parent d4561507b8
commit c275326d59
16 changed files with 375 additions and 296 deletions

View File

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import android.content.res.Configuration
import android.os.AsyncTask
import android.os.Build
@ -29,8 +28,6 @@ open class App : Application(), Application.ActivityLifecycleCallbacks {
lateinit var protectedContext: Context
@Deprecated("Use dependency injection", level = DeprecationLevel.ERROR)
val prefs: SharedPreferences by inject()
@Deprecated("Use dependency injection", level = DeprecationLevel.ERROR)
val DB: MagiskDB by inject()

View File

@ -1,5 +1,6 @@
package com.topjohnwu.magisk;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Xml;
@ -15,26 +16,29 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.IOException;
import androidx.annotation.Nullable;
import androidx.collection.ArrayMap;
public class Config {
import static com.topjohnwu.magisk.ConfigLeanback.getPrefs;
import static com.topjohnwu.magisk.utils.XAndroidKt.getPackageName;
// Current status
public static String magiskVersionString;
public final class Config {
private static final ArrayMap<String, Object> defs = new ArrayMap<>();
public static int magiskVersionCode = -1;
private static boolean magiskHide;
// Current status
public static String magiskVersionString = "";
// Update Info
public static String remoteMagiskVersionString;
public static String remoteMagiskVersionString = "";
public static int remoteMagiskVersionCode = -1;
public static String magiskLink;
public static String magiskNoteLink;
public static String magiskMD5;
public static String remoteManagerVersionString;
public static String magiskLink = "";
public static String magiskNoteLink = "";
public static String magiskMD5 = "";
public static String remoteManagerVersionString = "";
public static int remoteManagerVersionCode = -1;
public static String managerLink;
public static String managerNoteLink;
public static String uninstallerLink;
public static String managerLink = "";
public static String managerNoteLink = "";
public static String uninstallerLink = "";
// Install flags
public static boolean keepVerity = false;
@ -98,25 +102,76 @@ public class Config {
public static final int ORDER_DATE = 1;
}
private static boolean magiskHide = false;
public static void loadMagiskInfo() {
try {
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
magiskHide = Shell.su("magiskhide --status").exec().isSuccess();
} catch (NumberFormatException ignored) {}
} catch (NumberFormatException ignored) {
}
}
public static void export() {
// Flush prefs to disk
App app = App.self;
app.getPrefs().edit().commit();
File xml = new File(App.deContext.getFilesDir().getParent() + "/shared_prefs",
app.getPackageName() + "_preferences.xml");
getPrefs().edit().apply();
Context context = ConfigLeanback.getProtectedContext();
File xml = new File(context.getFilesDir().getParent() + "/shared_prefs",
getPackageName() + "_preferences.xml");
Shell.su(Utils.fmt("cat %s > /data/adb/%s", xml, Const.MANAGER_CONFIGS)).exec();
}
private static final int PREF_INT = 0;
private static final int PREF_STR_INT = 1;
private static final int PREF_BOOL = 2;
private static final int PREF_STR = 3;
private static final int DB_INT = 4;
private static final int DB_BOOL = 5;
private static final int DB_STR = 6;
private static int getConfigType(String key) {
switch (key) {
case Key.REPO_ORDER:
return PREF_INT;
case Key.SU_REQUEST_TIMEOUT:
case Key.SU_AUTO_RESPONSE:
case Key.SU_NOTIFICATION:
case Key.UPDATE_CHANNEL:
return PREF_STR_INT;
case Key.DARK_THEME:
case Key.SU_REAUTH:
case Key.CHECK_UPDATES:
case Key.MAGISKHIDE:
case Key.COREONLY:
case Key.SHOW_SYSTEM_APP:
return PREF_BOOL;
case Key.CUSTOM_CHANNEL:
case Key.LOCALE:
case Key.ETAG_KEY:
return PREF_STR;
case Key.ROOT_ACCESS:
case Key.SU_MNT_NS:
case Key.SU_MULTIUSER_MODE:
return DB_INT;
case Key.SU_FINGERPRINT:
return DB_BOOL;
case Key.SU_MANAGER:
return DB_STR;
default:
throw new IllegalArgumentException();
}
}
public static void initialize() {
SharedPreferences pref = App.self.getPrefs();
SharedPreferences pref = getPrefs();
SharedPreferences.Editor editor = pref.edit();
File config = SuFile.open("/data/adb", Const.MANAGER_CONFIGS);
if (config.exists()) {
@ -185,125 +240,72 @@ public class Config {
.apply();
}
private static final int PREF_INT = 0;
private static final int PREF_STR_INT = 1;
private static final int PREF_BOOL = 2;
private static final int PREF_STR = 3;
private static final int DB_INT = 4;
private static final int DB_BOOL = 5;
private static final int DB_STR = 6;
private static int getConfigType(String key) {
switch (key) {
case Key.REPO_ORDER:
return PREF_INT;
case Key.SU_REQUEST_TIMEOUT:
case Key.SU_AUTO_RESPONSE:
case Key.SU_NOTIFICATION:
case Key.UPDATE_CHANNEL:
return PREF_STR_INT;
case Key.DARK_THEME:
case Key.SU_REAUTH:
case Key.CHECK_UPDATES:
case Key.MAGISKHIDE:
case Key.COREONLY:
case Key.SHOW_SYSTEM_APP:
return PREF_BOOL;
case Key.CUSTOM_CHANNEL:
case Key.LOCALE:
case Key.ETAG_KEY:
return PREF_STR;
case Key.ROOT_ACCESS:
case Key.SU_MNT_NS:
case Key.SU_MULTIUSER_MODE:
return DB_INT;
case Key.SU_FINGERPRINT:
return DB_BOOL;
case Key.SU_MANAGER:
return DB_STR;
default:
throw new IllegalArgumentException();
}
}
@SuppressWarnings("unchecked")
public static <T> T get(String key) {
App app = App.self;
switch (getConfigType(key)) {
case PREF_INT:
return (T) (Integer) app.getPrefs().getInt(key, getDef(key));
return (T) (Integer) getPrefs().getInt(key, getDef(key));
case PREF_STR_INT:
return (T) (Integer) Utils.getPrefsInt(app.getPrefs(), key, getDef(key));
return (T) (Integer) Utils.getPrefsInt(getPrefs(), key, getDef(key));
case PREF_BOOL:
return (T) (Boolean) app.getPrefs().getBoolean(key, getDef(key));
return (T) (Boolean) getPrefs().getBoolean(key, getDef(key));
case PREF_STR:
return (T) app.getPrefs().getString(key, getDef(key));
return (T) getPrefs().getString(key, getDef(key));
case DB_INT:
return (T) (Integer) app.getDB().getSettings(key, getDef(key));
return (T) (Integer) ConfigLeanback.get(key, (Integer) getDef(key));
case DB_BOOL:
return (T) (Boolean) (app.getDB().getSettings(key, getDef(key) ? 1 : 0) != 0);
return (T) (Boolean) (ConfigLeanback.get(key, getDef(key) ? 1 : 0) != 0);
case DB_STR:
return (T) app.getDB().getStrings(key, getDef(key));
return (T) ConfigLeanback.get(key, getDef(key));
}
/* Will never get here (IllegalArgumentException in getConfigType) */
return null;
}
public static void set(String key, Object val) {
App app = App.self;
switch (getConfigType(key)) {
case PREF_INT:
app.getPrefs().edit().putInt(key, (int) val).apply();
getPrefs().edit().putInt(key, (int) val).apply();
break;
case PREF_STR_INT:
app.getPrefs().edit().putString(key, String.valueOf(val)).apply();
getPrefs().edit().putString(key, String.valueOf(val)).apply();
break;
case PREF_BOOL:
app.getPrefs().edit().putBoolean(key, (boolean) val).apply();
getPrefs().edit().putBoolean(key, (boolean) val).apply();
break;
case PREF_STR:
app.getPrefs().edit().putString(key, (String) val).apply();
getPrefs().edit().putString(key, (String) val).apply();
break;
case DB_INT:
app.getDB().setSettings(key, (int) val);
ConfigLeanback.put(key, (int) val);
break;
case DB_BOOL:
app.getDB().setSettings(key, (boolean) val ? 1 : 0);
ConfigLeanback.put(key, (boolean) val ? 1 : 0);
break;
case DB_STR:
app.getDB().setStrings(key, (String) val);
ConfigLeanback.put(key, (String) val);
break;
}
}
public static void remove(String key) {
App app = App.self;
switch (getConfigType(key)) {
case PREF_INT:
case PREF_STR_INT:
case PREF_BOOL:
case PREF_STR:
app.getPrefs().edit().remove(key).apply();
getPrefs().edit().remove(key).apply();
break;
case DB_BOOL:
case DB_INT:
app.getDB().rmSettings(key);
ConfigLeanback.delete(key);
break;
case DB_STR:
app.getDB().setStrings(key, null);
ConfigLeanback.put(key, null);
break;
}
}
private static ArrayMap<String, Object> defs = new ArrayMap<>();
static {
/* Set default configurations */
@ -340,7 +342,9 @@ public class Config {
//defs.put(Key.SU_MANAGER, null);
}
private static <T> T getDef(String key) {
@SuppressWarnings("unchecked")
@Nullable
private static <T> T getDef(String key) throws IllegalArgumentException {
Object val = defs.get(key);
switch (getConfigType(key)) {
case PREF_INT:
@ -359,36 +363,35 @@ public class Config {
}
private static void setDefs(SharedPreferences pref, SharedPreferences.Editor editor) {
App app = App.self;
for (String key : defs.keySet()) {
Object value = defs.get(key);
int type = getConfigType(key);
switch (type) {
case DB_INT:
editor.putString(key, String.valueOf(
app.getDB().getSettings(key, (Integer) defs.get(key))));
editor.putString(key, String.valueOf(ConfigLeanback.get(key, (Integer) value)));
continue;
case DB_STR:
editor.putString(key, app.getDB().getStrings(key, (String) defs.get(key)));
editor.putString(key, ConfigLeanback.get(key, String.valueOf(value)));
continue;
case DB_BOOL:
int bs = app.getDB().getSettings(key, -1);
editor.putBoolean(key, bs < 0 ? (Boolean) defs.get(key) : bs != 0);
int bs = ConfigLeanback.get(key, -1);
editor.putBoolean(key, bs < 0 ? (Boolean) value : bs != 0);
continue;
}
if (pref.contains(key))
continue;
switch (type) {
case PREF_INT:
editor.putInt(key, (Integer) defs.get(key));
editor.putInt(key, (Integer) value);
break;
case PREF_STR_INT:
editor.putString(key, String.valueOf(defs.get(key)));
editor.putString(key, String.valueOf(value));
break;
case PREF_STR:
editor.putString(key, (String) defs.get(key));
editor.putString(key, (String) value);
break;
case PREF_BOOL:
editor.putBoolean(key, (Boolean) defs.get(key));
editor.putBoolean(key, (Boolean) value);
break;
}
}

View File

@ -0,0 +1,52 @@
package com.topjohnwu.magisk
import android.content.Context
import android.content.SharedPreferences
import androidx.annotation.AnyThread
import androidx.annotation.WorkerThread
import com.skoumal.teanity.extensions.subscribeK
import com.topjohnwu.magisk.data.repository.SettingRepository
import com.topjohnwu.magisk.data.repository.StringRepository
import com.topjohnwu.magisk.di.Protected
import com.topjohnwu.magisk.utils.inject
object ConfigLeanback {
@JvmStatic
val protectedContext: Context by inject(Protected)
@JvmStatic
val prefs: SharedPreferences by inject()
private val settingRepo: SettingRepository by inject()
private val stringRepo: StringRepository by inject()
@JvmStatic
@AnyThread
fun put(key: String, value: Int) {
settingRepo.put(key, value).subscribeK()
}
@JvmStatic
@WorkerThread
fun get(key: String, defaultValue: Int): Int =
settingRepo.fetch(key, defaultValue).blockingGet()
@JvmStatic
@AnyThread
fun put(key: String, value: String?) {
val task = value?.let { stringRepo.put(key, it) } ?: stringRepo.delete(key)
task.subscribeK()
}
@JvmStatic
@WorkerThread
fun get(key: String, defaultValue: String?): String =
stringRepo.fetch(key, defaultValue.orEmpty()).blockingGet()
@JvmStatic
@AnyThread
fun delete(key: String) {
settingRepo.delete(key).subscribeK()
}
}

View File

@ -14,8 +14,8 @@ class SettingsDao : BaseDao() {
values(key to value.toString())
}.ignoreElement()
fun fetch(key: String) = query<Select> {
fun fetch(key: String, default: Int = -1) = query<Select> {
condition { equals("key", key) }
}.map { it.first().values.first().toIntOrNull() ?: -1 }
}.map { it.firstOrNull()?.values?.firstOrNull()?.toIntOrNull() ?: default }
}

View File

@ -31,6 +31,8 @@ class LogRepository(
.toSingle()
.map { it.exec() }
fun put(log: MagiskLog) = logDao.put(log)
private fun List<MagiskLog>.wrap(): List<WrappedMagiskLog> {
val day = TimeUnit.DAYS.toMillis(1)
return groupBy { it.date.time / day }

View File

@ -4,7 +4,7 @@ import com.topjohnwu.magisk.data.database.SettingsDao
class SettingRepository(private val settingsDao: SettingsDao) {
fun fetch(key: String) = settingsDao.fetch(key)
fun fetch(key: String, default: Int) = settingsDao.fetch(key, default)
fun put(key: String, value: Int) = settingsDao.put(key, value)
fun delete(key: String) = settingsDao.delete(key)

View File

@ -4,7 +4,7 @@ import com.topjohnwu.magisk.data.database.StringDao
class StringRepository(private val stringDao: StringDao) {
fun fetch(key: String) = stringDao.fetch(key)
fun fetch(key: String, default: String) = stringDao.fetch(key, default)
fun put(key: String, value: String) = stringDao.put(key, value)
fun delete(key: String) = stringDao.delete(key)

View File

@ -12,8 +12,7 @@ val applicationModule = module {
factory { get<Context>().resources }
factory { get<Context>() as App }
factory { get<Context>().packageManager }
single(SUTimeout) {
get<App>().protectedContext.getSharedPreferences("su_timeout", 0)
}
single { PreferenceManager.getDefaultSharedPreferences(get<App>().protectedContext) }
factory(Protected) { get<App>().protectedContext }
single(SUTimeout) { get<Context>(Protected).getSharedPreferences("su_timeout", 0) }
single { PreferenceManager.getDefaultSharedPreferences(get<Context>(Protected)) }
}

View File

@ -2,4 +2,5 @@ package com.topjohnwu.magisk.di
import org.koin.core.qualifier.named
val SUTimeout = named("su_timeout")
val SUTimeout = named("su_timeout")
val Protected = named("protected")

View File

@ -1,5 +1,6 @@
package com.topjohnwu.magisk.model.entity
import com.topjohnwu.magisk.model.entity.MagiskPolicy.Companion.ALLOW
import com.topjohnwu.magisk.utils.timeFormatTime
import com.topjohnwu.magisk.utils.toTime
import java.util.*
@ -47,4 +48,11 @@ fun MagiskLog.toMap() = mapOf(
"command" to command,
"action" to action,
"time" to date
).mapValues { it.toString() }
).mapValues { it.toString() }
fun MagiskPolicy.toLog(
toUid: Int,
fromPid: Int,
command: String,
date: Date
) = MagiskLog(uid, toUid, fromPid, packageName, appName, command, policy == ALLOW, date)

View File

@ -2,18 +2,27 @@ package com.topjohnwu.magisk.model.entity
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import com.topjohnwu.magisk.model.entity.MagiskPolicy.Companion.INTERACTIVE
data class MagiskPolicy(
val uid: Int,
val packageName: String,
val appName: String,
val policy: Int,
val until: Long,
val logging: Boolean,
val notification: Boolean,
val policy: Int = INTERACTIVE,
val until: Long = -1L,
val logging: Boolean = true,
val notification: Boolean = true,
val applicationInfo: ApplicationInfo
)
) {
companion object {
const val INTERACTIVE = 0
const val DENY = 1
const val ALLOW = 2
}
}
/*@Throws(PackageManager.NameNotFoundException::class)
fun ContentValues.toPolicy(pm: PackageManager): MagiskPolicy {
@ -64,11 +73,24 @@ fun Map<String, String>.toPolicy(pm: PackageManager): MagiskPolicy {
return MagiskPolicy(
uid = uid,
packageName = packageName,
policy = get("policy")?.toIntOrNull() ?: -1,
policy = get("policy")?.toIntOrNull() ?: INTERACTIVE,
until = get("until")?.toLongOrNull() ?: -1L,
logging = get("logging")?.toIntOrNull() != 0,
notification = get("notification")?.toIntOrNull() != 0,
applicationInfo = info,
appName = info.loadLabel(pm).toString()
)
}
@Throws(PackageManager.NameNotFoundException::class)
fun Int.toPolicy(pm: PackageManager): MagiskPolicy {
val pkg = pm.getPackagesForUid(this)?.firstOrNull()
?: throw PackageManager.NameNotFoundException()
val info = pm.getApplicationInfo(pkg, 0)
return MagiskPolicy(
uid = this,
packageName = pkg,
applicationInfo = info,
appName = info.loadLabel(pm).toString()
)
}

View File

@ -15,11 +15,11 @@ public class SuLogEntry {
public boolean action;
public Date date;
public SuLogEntry(Policy policy) {
fromUid = policy.uid;
packageName = policy.packageName;
appName = policy.appName;
action = policy.policy == Policy.ALLOW;
public SuLogEntry(MagiskPolicy policy) {
fromUid = policy.getUid();
packageName = policy.getPackageName();
appName = policy.getAppName();
action = policy.getPolicy() == Policy.ALLOW;
}
public SuLogEntry(ContentValues values) {

View File

@ -1,84 +0,0 @@
package com.topjohnwu.magisk.model.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.ClassMap;
import com.topjohnwu.magisk.Config;
import com.topjohnwu.magisk.Const;
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity;
import com.topjohnwu.magisk.utils.DownloadApp;
import com.topjohnwu.magisk.utils.SuLogger;
import com.topjohnwu.magisk.view.Notifications;
import com.topjohnwu.magisk.view.Shortcuts;
import com.topjohnwu.superuser.Shell;
public class GeneralReceiver extends BroadcastReceiver {
private String getPkg(Intent i) {
return i.getData() == null ? "" : i.getData().getEncodedSchemeSpecificPart();
}
@Override
public void onReceive(Context context, Intent intent) {
App app = App.self;
if (intent == null)
return;
String action = intent.getAction();
if (action == null)
return;
switch (action) {
case Intent.ACTION_REBOOT:
case Intent.ACTION_BOOT_COMPLETED:
action = intent.getStringExtra("action");
if (action == null) {
// Actual boot completed event
Shell.su("mm_patch_dtbo").submit(result -> {
if (result.isSuccess())
Notifications.dtboPatched();
});
break;
}
switch (action) {
case SuRequestActivity.REQUEST:
Intent i = new Intent(app, ClassMap.get(SuRequestActivity.class))
.setAction(action)
.putExtra("socket", intent.getStringExtra("socket"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
app.startActivity(i);
break;
case SuRequestActivity.LOG:
SuLogger.handleLogs(intent);
break;
case SuRequestActivity.NOTIFY:
SuLogger.handleNotify(intent);
break;
}
break;
case Intent.ACTION_PACKAGE_REPLACED:
// This will only work pre-O
if (Config.get(Config.Key.SU_REAUTH)) {
app.getDB().deletePolicy(getPkg(intent));
}
break;
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
String pkg = getPkg(intent);
app.getDB().deletePolicy(pkg);
Shell.su("magiskhide --rm " + pkg).submit();
break;
case Intent.ACTION_LOCALE_CHANGED:
Shortcuts.setup(context);
break;
case Const.Key.BROADCAST_MANAGER_UPDATE:
Config.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK);
DownloadApp.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME));
break;
case Const.Key.BROADCAST_REBOOT:
Shell.su("/system/bin/reboot").submit();
break;
}
}
}

View File

@ -0,0 +1,73 @@
package com.topjohnwu.magisk.model.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.topjohnwu.magisk.ClassMap
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Const
import com.topjohnwu.magisk.data.database.base.su
import com.topjohnwu.magisk.data.repository.AppRepository
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import com.topjohnwu.magisk.utils.DownloadApp
import com.topjohnwu.magisk.utils.SuLogger
import com.topjohnwu.magisk.utils.inject
import com.topjohnwu.magisk.view.Notifications
import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
open class GeneralReceiver : BroadcastReceiver() {
private val appRepo: AppRepository by inject()
private fun getPkg(i: Intent): String {
return if (i.data == null) "" else i.data!!.encodedSchemeSpecificPart
}
override fun onReceive(context: Context, intent: Intent?) {
if (intent == null)
return
var action: String? = intent.action ?: return
when (action) {
Intent.ACTION_REBOOT, Intent.ACTION_BOOT_COMPLETED -> {
action = intent.getStringExtra("action")
if (action == null) {
// Actual boot completed event
Shell.su("mm_patch_dtbo").submit { result ->
if (result.isSuccess)
Notifications.dtboPatched()
}
return
}
when (action) {
SuRequestActivity.REQUEST -> {
val i = Intent(context, ClassMap.get<Any>(SuRequestActivity::class.java))
.setAction(action)
.putExtra("socket", intent.getStringExtra("socket"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
context.startActivity(i)
}
SuRequestActivity.LOG -> SuLogger.handleLogs(intent)
SuRequestActivity.NOTIFY -> SuLogger.handleNotify(intent)
}
}
Intent.ACTION_PACKAGE_REPLACED ->
// This will only work pre-O
if (Config.get<Boolean>(Config.Key.SU_REAUTH)!!) {
appRepo.delete(getPkg(intent)).blockingGet()
}
Intent.ACTION_PACKAGE_FULLY_REMOVED -> {
val pkg = getPkg(intent)
appRepo.delete(pkg).blockingGet()
"magiskhide --rm $pkg".su().blockingGet()
}
Intent.ACTION_LOCALE_CHANGED -> Shortcuts.setup(context)
Const.Key.BROADCAST_MANAGER_UPDATE -> {
Config.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK)
DownloadApp.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME))
}
Const.Key.BROADCAST_REBOOT -> Shell.su("/system/bin/reboot").submit()
}
}
}

View File

@ -1,88 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Process;
import android.widget.Toast;
import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.Config;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.model.entity.Policy;
import com.topjohnwu.magisk.model.entity.SuLogEntry;
import java.util.Date;
public class SuLogger {
public static void handleLogs(Intent intent) {
int fromUid = intent.getIntExtra("from.uid", -1);
if (fromUid < 0) return;
if (fromUid == Process.myUid()) return;
App app = App.self;
PackageManager pm = app.getPackageManager();
Policy policy;
boolean notify;
Bundle data = intent.getExtras();
if (data.containsKey("notify")) {
notify = data.getBoolean("notify");
try {
policy = new Policy(fromUid, pm);
} catch (PackageManager.NameNotFoundException e) {
return;
}
} else {
// Doesn't report whether notify or not, check database ourselves
policy = app.getDB().getPolicy(fromUid);
if (policy == null)
return;
notify = policy.notification;
}
policy.policy = data.getInt("policy", -1);
if (policy.policy < 0)
return;
if (notify)
handleNotify(policy);
SuLogEntry log = new SuLogEntry(policy);
int toUid = intent.getIntExtra("to.uid", -1);
if (toUid < 0) return;
int pid = intent.getIntExtra("pid", -1);
if (pid < 0) return;
String command = intent.getStringExtra("command");
if (command == null) return;
log.toUid = toUid;
log.fromPid = pid;
log.command = command;
log.date = new Date();
app.getDB().addLog(log);
}
private static void handleNotify(Policy policy) {
if (policy.notification &&
(int) Config.get(Config.Key.SU_NOTIFICATION) == Config.Value.NOTIFICATION_TOAST) {
Utils.toast(App.self.getString(policy.policy == Policy.ALLOW ?
R.string.su_allow_toast : R.string.su_deny_toast, policy.appName),
Toast.LENGTH_SHORT);
}
}
public static void handleNotify(Intent intent) {
int fromUid = intent.getIntExtra("from.uid", -1);
if (fromUid < 0) return;
if (fromUid == Process.myUid()) return;
try {
Policy policy = new Policy(fromUid, App.self.getPackageManager());
policy.policy = intent.getIntExtra("policy", -1);
if (policy.policy >= 0)
handleNotify(policy);
} catch (PackageManager.NameNotFoundException ignored) {}
}
}

View File

@ -0,0 +1,94 @@
package com.topjohnwu.magisk.utils
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Process
import android.widget.Toast
import com.topjohnwu.magisk.App
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.AppRepository
import com.topjohnwu.magisk.data.repository.LogRepository
import com.topjohnwu.magisk.model.entity.MagiskPolicy
import com.topjohnwu.magisk.model.entity.Policy
import com.topjohnwu.magisk.model.entity.toLog
import com.topjohnwu.magisk.model.entity.toPolicy
import java.util.*
object SuLogger {
@JvmStatic
fun handleLogs(intent: Intent) {
val fromUid = intent.getIntExtra("from.uid", -1)
if (fromUid < 0) return
if (fromUid == Process.myUid()) return
val pm: PackageManager by inject()
val notify: Boolean
val data = intent.extras
val policy: MagiskPolicy = if (data!!.containsKey("notify")) {
notify = data.getBoolean("notify")
runCatching {
fromUid.toPolicy(pm)
}.getOrElse { return }
} else {
// Doesn't report whether notify or not, check database ourselves
val appRepo: AppRepository by inject()
val policy = appRepo.fetch(fromUid).blockingGet() ?: return
notify = policy.notification
policy
}.copy(policy = data.getInt("policy", -1))
if (policy.policy < 0)
return
if (notify)
handleNotify(policy)
val toUid = intent.getIntExtra("to.uid", -1)
if (toUid < 0) return
val pid = intent.getIntExtra("pid", -1)
if (pid < 0) return
val command = intent.getStringExtra("command") ?: return
val log = policy.toLog(
toUid = toUid,
fromPid = pid,
command = command,
date = Date()
)
val logRepo: LogRepository by inject()
logRepo.put(log).blockingGet()?.printStackTrace()
}
private fun handleNotify(policy: MagiskPolicy) {
if (policy.notification && Config.get<Any>(Config.Key.SU_NOTIFICATION) as Int == Config.Value.NOTIFICATION_TOAST) {
Utils.toast(
App.self.getString(
if (policy.policy == Policy.ALLOW)
R.string.su_allow_toast
else
R.string.su_deny_toast, policy.appName
),
Toast.LENGTH_SHORT
)
}
}
fun handleNotify(intent: Intent) {
val fromUid = intent.getIntExtra("from.uid", -1)
if (fromUid < 0) return
if (fromUid == Process.myUid()) return
runCatching {
val packageManager: PackageManager by inject()
val policy = fromUid.toPolicy(packageManager)
.copy(policy = intent.getIntExtra("policy", -1))
if (policy.policy >= 0)
handleNotify(policy)
}
}
}