diff --git a/app/src/main/java/com/topjohnwu/magisk/App.kt b/app/src/main/java/com/topjohnwu/magisk/App.kt index b4b3ef86d..c2251968d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/App.kt +++ b/app/src/main/java/com/topjohnwu/magisk/App.kt @@ -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() diff --git a/app/src/main/java/com/topjohnwu/magisk/Config.java b/app/src/main/java/com/topjohnwu/magisk/Config.java index 76f4580ba..7a583c912 100644 --- a/app/src/main/java/com/topjohnwu/magisk/Config.java +++ b/app/src/main/java/com/topjohnwu/magisk/Config.java @@ -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 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 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 defs = new ArrayMap<>(); - static { /* Set default configurations */ @@ -340,7 +342,9 @@ public class Config { //defs.put(Key.SU_MANAGER, null); } - private static T getDef(String key) { + @SuppressWarnings("unchecked") + @Nullable + private static 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; } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ConfigLeanback.kt b/app/src/main/java/com/topjohnwu/magisk/ConfigLeanback.kt new file mode 100644 index 000000000..6fbf6a069 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/ConfigLeanback.kt @@ -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() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt b/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt index 19c10f6d7..22cb370e2 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/database/SettingsDao.kt @@ -14,8 +14,8 @@ class SettingsDao : BaseDao() { values(key to value.toString()) }.ignoreElement() - fun fetch(key: String) = query { condition { equals("key", key) } - }.map { it.first().values.first().toIntOrNull() ?: -1 } + }.map { it.firstOrNull()?.values?.firstOrNull()?.toIntOrNull() ?: default } } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/data/repository/LogRepository.kt b/app/src/main/java/com/topjohnwu/magisk/data/repository/LogRepository.kt index caf60174a..34a82b995 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/repository/LogRepository.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/repository/LogRepository.kt @@ -31,6 +31,8 @@ class LogRepository( .toSingle() .map { it.exec() } + fun put(log: MagiskLog) = logDao.put(log) + private fun List.wrap(): List { val day = TimeUnit.DAYS.toMillis(1) return groupBy { it.date.time / day } diff --git a/app/src/main/java/com/topjohnwu/magisk/data/repository/SettingRepository.kt b/app/src/main/java/com/topjohnwu/magisk/data/repository/SettingRepository.kt index 5140ccc7a..e8535730c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/repository/SettingRepository.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/repository/SettingRepository.kt @@ -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) diff --git a/app/src/main/java/com/topjohnwu/magisk/data/repository/StringRepository.kt b/app/src/main/java/com/topjohnwu/magisk/data/repository/StringRepository.kt index 0756cd63d..70fd9ef69 100644 --- a/app/src/main/java/com/topjohnwu/magisk/data/repository/StringRepository.kt +++ b/app/src/main/java/com/topjohnwu/magisk/data/repository/StringRepository.kt @@ -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) diff --git a/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt b/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt index f58961dda..07830c11a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/ApplicationModule.kt @@ -12,8 +12,7 @@ val applicationModule = module { factory { get().resources } factory { get() as App } factory { get().packageManager } - single(SUTimeout) { - get().protectedContext.getSharedPreferences("su_timeout", 0) - } - single { PreferenceManager.getDefaultSharedPreferences(get().protectedContext) } + factory(Protected) { get().protectedContext } + single(SUTimeout) { get(Protected).getSharedPreferences("su_timeout", 0) } + single { PreferenceManager.getDefaultSharedPreferences(get(Protected)) } } diff --git a/app/src/main/java/com/topjohnwu/magisk/di/NamedInjection.kt b/app/src/main/java/com/topjohnwu/magisk/di/NamedInjection.kt index c6ab30319..7840947af 100644 --- a/app/src/main/java/com/topjohnwu/magisk/di/NamedInjection.kt +++ b/app/src/main/java/com/topjohnwu/magisk/di/NamedInjection.kt @@ -2,4 +2,5 @@ package com.topjohnwu.magisk.di import org.koin.core.qualifier.named -val SUTimeout = named("su_timeout") \ No newline at end of file +val SUTimeout = named("su_timeout") +val Protected = named("protected") \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLog.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLog.kt index 4a4ea7187..cfc02c979 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLog.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskLog.kt @@ -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() } \ No newline at end of file +).mapValues { it.toString() } + +fun MagiskPolicy.toLog( + toUid: Int, + fromPid: Int, + command: String, + date: Date +) = MagiskLog(uid, toUid, fromPid, packageName, appName, command, policy == ALLOW, date) diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskPolicy.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskPolicy.kt index a56621d6f..6111325f3 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskPolicy.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/MagiskPolicy.kt @@ -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.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() + ) } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/SuLogEntry.java b/app/src/main/java/com/topjohnwu/magisk/model/entity/SuLogEntry.java index a63159f9b..c6c6ff7fa 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/SuLogEntry.java +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/SuLogEntry.java @@ -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) { diff --git a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.java b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.java deleted file mode 100644 index 0a7432c4d..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.java +++ /dev/null @@ -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; - } - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt new file mode 100644 index 000000000..725736b50 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt @@ -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(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(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() + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.java b/app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.java deleted file mode 100644 index 17d7c9286..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.java +++ /dev/null @@ -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) {} - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.kt b/app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.kt new file mode 100644 index 000000000..a7374bbe4 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/utils/SuLogger.kt @@ -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(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) + } + } +}