Remove all backwards compatibility nonsense
This also allows full obfuscation
This commit is contained in:
parent
a54eaf5371
commit
c91f809eba
1
app/proguard-rules.pro
vendored
1
app/proguard-rules.pro
vendored
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
# Snet extention
|
# Snet extention
|
||||||
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
|
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
|
||||||
|
-keepclassmembers class com.topjohnwu.magisk.utils.BootSigner { *; }
|
||||||
|
|
||||||
# Fast Android Networking Library
|
# Fast Android Networking Library
|
||||||
-dontwarn okhttp3.**
|
-dontwarn okhttp3.**
|
||||||
|
@ -53,15 +53,6 @@
|
|||||||
android:taskAffinity="internal.superuser"
|
android:taskAffinity="internal.superuser"
|
||||||
android:theme="@style/SuRequest" />
|
android:theme="@style/SuRequest" />
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".superuser.RequestActivity"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:taskAffinity="internal.superuser"
|
|
||||||
android:theme="@style/AppTheme.Translucent" />
|
|
||||||
|
|
||||||
<receiver android:name=".superuser.SuReceiver" />
|
|
||||||
|
|
||||||
<!-- Receiver -->
|
<!-- Receiver -->
|
||||||
|
|
||||||
<receiver android:name="a.h">
|
<receiver android:name="a.h">
|
||||||
|
@ -10,7 +10,6 @@ import java.util.List;
|
|||||||
public class Const {
|
public class Const {
|
||||||
|
|
||||||
public static final String DEBUG_TAG = "MagiskManager";
|
public static final String DEBUG_TAG = "MagiskManager";
|
||||||
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
|
|
||||||
|
|
||||||
// APK content
|
// APK content
|
||||||
public static final String ANDROID_MANIFEST = "AndroidManifest.xml";
|
public static final String ANDROID_MANIFEST = "AndroidManifest.xml";
|
||||||
@ -47,11 +46,7 @@ public class Const {
|
|||||||
public static final int USER_ID = Process.myUid() / 100000;
|
public static final int USER_ID = Process.myUid() / 100000;
|
||||||
|
|
||||||
public static final class MAGISK_VER {
|
public static final class MAGISK_VER {
|
||||||
public static final int SEPOL_REFACTOR = 1640;
|
/* Currently no backwards compatibility needed */
|
||||||
public static final int FIX_ENV = 1650;
|
|
||||||
public static final int DBVER_SIX = 17000;
|
|
||||||
public static final int CMDLINE_DB = 17305;
|
|
||||||
public static final int HIDE_STATUS = 17315;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ID {
|
public static class ID {
|
||||||
|
@ -83,12 +83,7 @@ public class Data {
|
|||||||
try {
|
try {
|
||||||
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
|
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
|
||||||
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
|
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
|
||||||
if (magiskVersionCode >= Const.MAGISK_VER.HIDE_STATUS) {
|
|
||||||
magiskHide = Shell.su("magiskhide --status").exec().isSuccess();
|
magiskHide = Shell.su("magiskhide --status").exec().isSuccess();
|
||||||
} else {
|
|
||||||
String s = ShellUtils.fastCmd(("resetprop -p ") + Const.MAGISKHIDE_PROP);
|
|
||||||
magiskHide = s.isEmpty() || Integer.parseInt(s) != 0;
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException ignored) {}
|
} catch (NumberFormatException ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import android.widget.Toast;
|
|||||||
import com.topjohnwu.magisk.asyncs.FlashZip;
|
import com.topjohnwu.magisk.asyncs.FlashZip;
|
||||||
import com.topjohnwu.magisk.asyncs.InstallMagisk;
|
import com.topjohnwu.magisk.asyncs.InstallMagisk;
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
import com.topjohnwu.magisk.utils.RootUtils;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.CallbackList;
|
import com.topjohnwu.superuser.CallbackList;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
@ -160,7 +159,7 @@ public class FlashActivity extends BaseActivity {
|
|||||||
protected void onPostExecute(Integer result) {
|
protected void onPostExecute(Integer result) {
|
||||||
if (result == 1) {
|
if (result == 1) {
|
||||||
Data.mainHandler.postDelayed(() ->
|
Data.mainHandler.postDelayed(() ->
|
||||||
RootUtils.uninstallPkg(getActivity().getPackageName()), 3000);
|
Shell.su("pm uninstall " + getActivity().getPackageName()).exec(), 3000);
|
||||||
} else {
|
} else {
|
||||||
super.onPostExecute(result);
|
super.onPostExecute(result);
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ public class MagiskManager extends ContainerApp {
|
|||||||
|
|
||||||
// Global resources
|
// Global resources
|
||||||
public SharedPreferences prefs;
|
public SharedPreferences prefs;
|
||||||
public MagiskDB mDB;
|
|
||||||
public RepoDatabaseHelper repoDB;
|
public RepoDatabaseHelper repoDB;
|
||||||
|
public MagiskDB mDB;
|
||||||
|
|
||||||
public MagiskManager() {
|
public MagiskManager() {
|
||||||
Data.weakApp = new WeakReference<>(this);
|
Data.weakApp = new WeakReference<>(this);
|
||||||
@ -37,8 +37,8 @@ public class MagiskManager extends ContainerApp {
|
|||||||
Shell.Config.setTimeout(2);
|
Shell.Config.setTimeout(2);
|
||||||
|
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
mDB = MagiskDB.getInstance();
|
|
||||||
repoDB = new RepoDatabaseHelper(this);
|
repoDB = new RepoDatabaseHelper(this);
|
||||||
|
mDB = new MagiskDB(this);
|
||||||
|
|
||||||
LocaleManager.setLocale(this);
|
LocaleManager.setLocale(this);
|
||||||
Data.loadConfig();
|
Data.loadConfig();
|
||||||
|
@ -12,7 +12,6 @@ import com.topjohnwu.magisk.components.Notifications;
|
|||||||
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
||||||
import com.topjohnwu.magisk.utils.Download;
|
import com.topjohnwu.magisk.utils.Download;
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||||
import com.topjohnwu.magisk.utils.RootUtils;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ public class SplashActivity extends BaseActivity {
|
|||||||
try {
|
try {
|
||||||
// We are the manager, remove com.topjohnwu.magisk as it could be malware
|
// We are the manager, remove com.topjohnwu.magisk as it could be malware
|
||||||
getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
|
getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
|
||||||
RootUtils.uninstallPkg(BuildConfig.APPLICATION_ID);
|
Shell.su("pm uninstall " + BuildConfig.APPLICATION_ID).submit();
|
||||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,8 @@ package com.topjohnwu.magisk;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.net.LocalSocketAddress;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
import android.os.CountDownTimer;
|
||||||
import android.os.FileObserver;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
@ -43,48 +41,6 @@ public class SuRequestActivity extends BaseActivity {
|
|||||||
private CountDownTimer timer;
|
private CountDownTimer timer;
|
||||||
private FingerprintHelper fingerprintHelper;
|
private FingerprintHelper fingerprintHelper;
|
||||||
|
|
||||||
class SuConnectorV1 extends SuConnector {
|
|
||||||
|
|
||||||
SuConnectorV1(String name) throws IOException {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect(String name) throws IOException {
|
|
||||||
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.FILESYSTEM));
|
|
||||||
new FileObserver(name) {
|
|
||||||
@Override
|
|
||||||
public void onEvent(int fileEvent, String path) {
|
|
||||||
if (fileEvent == FileObserver.DELETE_SELF) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.startWatching();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse() throws IOException {
|
|
||||||
out.write((policy.policy == Policy.ALLOW ? "socket:ALLOW" : "socket:DENY").getBytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SuConnectorV2 extends SuConnector {
|
|
||||||
|
|
||||||
SuConnectorV2(String name) throws IOException {
|
|
||||||
super(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect(String name) throws IOException {
|
|
||||||
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResponse() throws IOException {
|
|
||||||
out.writeInt(policy.policy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDarkTheme() {
|
public int getDarkTheme() {
|
||||||
return R.style.SuRequest_Dark;
|
return R.style.SuRequest_Dark;
|
||||||
@ -120,8 +76,12 @@ public class SuRequestActivity extends BaseActivity {
|
|||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
try {
|
try {
|
||||||
String socketName = intent.getStringExtra("socket");
|
String socketName = intent.getStringExtra("socket");
|
||||||
connector = intent.getIntExtra("version", 1) == 1 ?
|
connector = new SuConnector(socketName) {
|
||||||
new SuConnectorV1(socketName) : new SuConnectorV2(socketName);
|
@Override
|
||||||
|
protected void onResponse() throws IOException {
|
||||||
|
out.writeInt(policy.policy);
|
||||||
|
}
|
||||||
|
};
|
||||||
Bundle bundle = connector.readSocketInput();
|
Bundle bundle = connector.readSocketInput();
|
||||||
int uid = Integer.parseInt(bundle.getString("uid"));
|
int uid = Integer.parseInt(bundle.getString("uid"));
|
||||||
policy = mm.mDB.getPolicy(uid);
|
policy = mm.mDB.getPolicy(uid);
|
||||||
|
@ -342,18 +342,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
|||||||
console.add("- Target image: " + mBoot);
|
console.add("- Target image: " + mBoot);
|
||||||
|
|
||||||
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
|
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
|
||||||
String arch;
|
String arch = abis.contains("x86") ? "x86" : "arm";
|
||||||
|
|
||||||
if (Data.remoteMagiskVersionCode >= Const.MAGISK_VER.SEPOL_REFACTOR) {
|
|
||||||
// 32-bit only
|
|
||||||
if (abis.contains("x86")) arch = "x86";
|
|
||||||
else arch = "arm";
|
|
||||||
} else {
|
|
||||||
if (abis.contains("x86_64")) arch = "x64";
|
|
||||||
else if (abis.contains("arm64-v8a")) arch = "arm64";
|
|
||||||
else if (abis.contains("x86")) arch = "x86";
|
|
||||||
else arch = "arm";
|
|
||||||
}
|
|
||||||
|
|
||||||
console.add("- Device platform: " + Build.SUPPORTED_ABIS[0]);
|
console.add("- Device platform: " + Build.SUPPORTED_ABIS[0]);
|
||||||
|
|
||||||
|
@ -1,66 +1,197 @@
|
|||||||
package com.topjohnwu.magisk.database;
|
package com.topjohnwu.magisk.database;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.container.Policy;
|
import com.topjohnwu.magisk.container.Policy;
|
||||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
import com.topjohnwu.magisk.container.SuLogEntry;
|
||||||
|
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
import java.io.File;
|
import java.text.DateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public class MagiskDB {
|
public class MagiskDB {
|
||||||
|
|
||||||
static final String POLICY_TABLE = "policies";
|
private static final String POLICY_TABLE = "policies";
|
||||||
static final String LOG_TABLE = "logs";
|
private static final String LOG_TABLE = "logs";
|
||||||
static final String SETTINGS_TABLE = "settings";
|
private static final String SETTINGS_TABLE = "settings";
|
||||||
static final String STRINGS_TABLE = "strings";
|
private static final String STRINGS_TABLE = "strings";
|
||||||
static final File LEGACY_MANAGER_DB =
|
|
||||||
new File(Utils.fmt("/sbin/.magisk/db-%d/magisk.db", Const.USER_ID));
|
|
||||||
|
|
||||||
@NonNull
|
private PackageManager pm;
|
||||||
public static MagiskDB getInstance() {
|
|
||||||
if (LEGACY_MANAGER_DB.canWrite()) {
|
|
||||||
return MagiskDBLegacy.newInstance();
|
|
||||||
} else if (Shell.rootAccess()) {
|
|
||||||
return Data.magiskVersionCode >= Const.MAGISK_VER.CMDLINE_DB ?
|
|
||||||
new MagiskDBCmdline() : MagiskDBLegacy.newInstance();
|
|
||||||
} else {
|
|
||||||
return new MagiskDB();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearOutdated() {}
|
public MagiskDB(Context context) {
|
||||||
|
pm = context.getPackageManager();
|
||||||
|
}
|
||||||
|
|
||||||
public void deletePolicy(Policy policy) {
|
public void deletePolicy(Policy policy) {
|
||||||
deletePolicy(policy.uid);
|
deletePolicy(policy.uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deletePolicy(String pkg) {}
|
private List<String> rawSQL(String fmt, Object... args) {
|
||||||
|
return Shell.su("magisk --sqlite '" + Utils.fmt(fmt, args) + "'").exec().getOut();
|
||||||
public void deletePolicy(int uid) {}
|
}
|
||||||
|
|
||||||
public Policy getPolicy(int uid) { return null; }
|
private List<ContentValues> SQL(String fmt, Object... args) {
|
||||||
|
List<ContentValues> list = new ArrayList<>();
|
||||||
public void updatePolicy(Policy policy) {}
|
for (String raw : rawSQL(fmt, args)) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
public List<Policy> getPolicyList() { return Collections.emptyList(); }
|
String[] cols = raw.split("\\|");
|
||||||
|
for (String col : cols) {
|
||||||
public List<List<SuLogEntry>> getLogs() { return Collections.emptyList(); }
|
String[] pair = col.split("=", 2);
|
||||||
|
if (pair.length != 2)
|
||||||
public void addLog(SuLogEntry log) {}
|
continue;
|
||||||
|
values.put(pair[0], pair[1]);
|
||||||
public void clearLogs() {}
|
}
|
||||||
|
list.add(values);
|
||||||
public void setSettings(String key, int value) {}
|
}
|
||||||
|
return list;
|
||||||
public int getSettings(String key, int defaultValue) { return defaultValue; }
|
}
|
||||||
|
|
||||||
public void setStrings(String key, String value) {}
|
private String toSQL(ContentValues values) {
|
||||||
|
StringBuilder keys = new StringBuilder(), vals = new StringBuilder();
|
||||||
public String getStrings(String key, String defaultValue) { return defaultValue; }
|
keys.append('(');
|
||||||
|
vals.append("VALUES(");
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, Object> entry : values.valueSet()) {
|
||||||
|
if (!first) {
|
||||||
|
keys.append(',');
|
||||||
|
vals.append(',');
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
keys.append(entry.getKey());
|
||||||
|
vals.append('"');
|
||||||
|
vals.append(entry.getValue());
|
||||||
|
vals.append('"');
|
||||||
|
}
|
||||||
|
keys.append(')');
|
||||||
|
vals.append(')');
|
||||||
|
keys.append(vals);
|
||||||
|
return keys.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearOutdated() {
|
||||||
|
rawSQL(
|
||||||
|
"DELETE FROM %s WHERE until > 0 AND until < %d;" +
|
||||||
|
"DELETE FROM %s WHERE time < %d",
|
||||||
|
POLICY_TABLE, System.currentTimeMillis() / 1000,
|
||||||
|
LOG_TABLE, System.currentTimeMillis() - Data.suLogTimeout * 86400000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deletePolicy(String pkg) {
|
||||||
|
rawSQL("DELETE FROM %s WHERE package_name=\"%s\"", POLICY_TABLE, pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void deletePolicy(int uid) {
|
||||||
|
rawSQL("DELETE FROM %s WHERE uid=%d", POLICY_TABLE, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Policy getPolicy(int uid) {
|
||||||
|
List<ContentValues> res =
|
||||||
|
SQL("SELECT * FROM %s WHERE uid=%d", POLICY_TABLE, uid);
|
||||||
|
if (!res.isEmpty()) {
|
||||||
|
try {
|
||||||
|
return new Policy(res.get(0), pm);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
deletePolicy(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updatePolicy(Policy policy) {
|
||||||
|
rawSQL("REPLACE INTO %s %s", POLICY_TABLE, toSQL(policy.getContentValues()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Policy> getPolicyList() {
|
||||||
|
List<Policy> list = new ArrayList<>();
|
||||||
|
for (ContentValues values : SQL("SELECT * FROM %s WHERE uid/100000=%d", POLICY_TABLE, Const.USER_ID)) {
|
||||||
|
try {
|
||||||
|
list.add(new Policy(values, pm));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
deletePolicy(values.getAsInteger("uid"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.sort(list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<List<SuLogEntry>> getLogs() {
|
||||||
|
List<List<SuLogEntry>> ret = new ArrayList<>();
|
||||||
|
List<SuLogEntry> list = null;
|
||||||
|
String dateString = null, newString;
|
||||||
|
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
|
||||||
|
Date date = new Date(values.getAsLong("time"));
|
||||||
|
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
|
||||||
|
if (!TextUtils.equals(dateString, newString)) {
|
||||||
|
dateString = newString;
|
||||||
|
list = new ArrayList<>();
|
||||||
|
ret.add(list);
|
||||||
|
}
|
||||||
|
list.add(new SuLogEntry(values));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addLog(SuLogEntry log) {
|
||||||
|
rawSQL("INSERT INTO %s %s", LOG_TABLE, toSQL(log.getContentValues()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void clearLogs() {
|
||||||
|
rawSQL("DELETE FROM %s", LOG_TABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setSettings(String key, int value) {
|
||||||
|
ContentValues data = new ContentValues();
|
||||||
|
data.put("key", key);
|
||||||
|
data.put("value", value);
|
||||||
|
rawSQL("REPLACE INTO %s %s", SETTINGS_TABLE, toSQL(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getSettings(String key, int defaultValue) {
|
||||||
|
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", SETTINGS_TABLE, key);
|
||||||
|
if (res.isEmpty())
|
||||||
|
return defaultValue;
|
||||||
|
return res.get(0).getAsInteger("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setStrings(String key, String value) {
|
||||||
|
if (value == null) {
|
||||||
|
rawSQL("DELETE FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ContentValues data = new ContentValues();
|
||||||
|
data.put("key", key);
|
||||||
|
data.put("value", value);
|
||||||
|
rawSQL("REPLACE INTO %s %s", STRINGS_TABLE, toSQL(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getStrings(String key, String defaultValue) {
|
||||||
|
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
|
||||||
|
if (res.isEmpty())
|
||||||
|
return defaultValue;
|
||||||
|
return res.get(0).getAsString("value");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,189 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.database;
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
|
||||||
import com.topjohnwu.magisk.Data;
|
|
||||||
import com.topjohnwu.magisk.container.Policy;
|
|
||||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class MagiskDBCmdline extends MagiskDB {
|
|
||||||
|
|
||||||
private PackageManager pm;
|
|
||||||
|
|
||||||
public MagiskDBCmdline() {
|
|
||||||
pm = Data.MM().getPackageManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> rawSQL(String fmt, Object... args) {
|
|
||||||
return Shell.su("magisk --sqlite '" + Utils.fmt(fmt, args) + "'").exec().getOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<ContentValues> SQL(String fmt, Object... args) {
|
|
||||||
List<ContentValues> list = new ArrayList<>();
|
|
||||||
for (String raw : rawSQL(fmt, args)) {
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
String[] cols = raw.split("\\|");
|
|
||||||
for (String col : cols) {
|
|
||||||
String[] pair = col.split("=", 2);
|
|
||||||
if (pair.length != 2)
|
|
||||||
continue;
|
|
||||||
values.put(pair[0], pair[1]);
|
|
||||||
}
|
|
||||||
list.add(values);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String toSQL(ContentValues values) {
|
|
||||||
StringBuilder keys = new StringBuilder(), vals = new StringBuilder();
|
|
||||||
keys.append('(');
|
|
||||||
vals.append("VALUES(");
|
|
||||||
boolean first = true;
|
|
||||||
for (Map.Entry<String, Object> entry : values.valueSet()) {
|
|
||||||
if (!first) {
|
|
||||||
keys.append(',');
|
|
||||||
vals.append(',');
|
|
||||||
} else {
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
keys.append(entry.getKey());
|
|
||||||
vals.append('"');
|
|
||||||
vals.append(entry.getValue());
|
|
||||||
vals.append('"');
|
|
||||||
}
|
|
||||||
keys.append(')');
|
|
||||||
vals.append(')');
|
|
||||||
keys.append(vals);
|
|
||||||
return keys.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearOutdated() {
|
|
||||||
rawSQL(
|
|
||||||
"DELETE FROM %s WHERE until > 0 AND until < %d;" +
|
|
||||||
"DELETE FROM %s WHERE time < %d",
|
|
||||||
POLICY_TABLE, System.currentTimeMillis() / 1000,
|
|
||||||
LOG_TABLE, System.currentTimeMillis() - Data.suLogTimeout * 86400000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deletePolicy(String pkg) {
|
|
||||||
rawSQL("DELETE FROM %s WHERE package_name=\"%s\"", POLICY_TABLE, pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deletePolicy(int uid) {
|
|
||||||
rawSQL("DELETE FROM %s WHERE uid=%d", POLICY_TABLE, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Policy getPolicy(int uid) {
|
|
||||||
List<ContentValues> res =
|
|
||||||
SQL("SELECT * FROM %s WHERE uid=%d", POLICY_TABLE, uid);
|
|
||||||
if (!res.isEmpty()) {
|
|
||||||
try {
|
|
||||||
return new Policy(res.get(0), pm);
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
deletePolicy(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePolicy(Policy policy) {
|
|
||||||
rawSQL("REPLACE INTO %s %s", POLICY_TABLE, toSQL(policy.getContentValues()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> getPolicyList() {
|
|
||||||
List<Policy> list = new ArrayList<>();
|
|
||||||
for (ContentValues values : SQL("SELECT * FROM %s WHERE uid/100000=%d", POLICY_TABLE, Const.USER_ID)) {
|
|
||||||
try {
|
|
||||||
list.add(new Policy(values, pm));
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
deletePolicy(values.getAsInteger("uid"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Collections.sort(list);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<List<SuLogEntry>> getLogs() {
|
|
||||||
List<List<SuLogEntry>> ret = new ArrayList<>();
|
|
||||||
List<SuLogEntry> list = null;
|
|
||||||
String dateString = null, newString;
|
|
||||||
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
|
|
||||||
Date date = new Date(values.getAsLong("time"));
|
|
||||||
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
|
|
||||||
if (!TextUtils.equals(dateString, newString)) {
|
|
||||||
dateString = newString;
|
|
||||||
list = new ArrayList<>();
|
|
||||||
ret.add(list);
|
|
||||||
}
|
|
||||||
list.add(new SuLogEntry(values));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addLog(SuLogEntry log) {
|
|
||||||
rawSQL("INSERT INTO %s %s", LOG_TABLE, toSQL(log.getContentValues()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearLogs() {
|
|
||||||
rawSQL("DELETE FROM %s", LOG_TABLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSettings(String key, int value) {
|
|
||||||
ContentValues data = new ContentValues();
|
|
||||||
data.put("key", key);
|
|
||||||
data.put("value", value);
|
|
||||||
rawSQL("REPLACE INTO %s %s", SETTINGS_TABLE, toSQL(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSettings(String key, int defaultValue) {
|
|
||||||
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", SETTINGS_TABLE, key);
|
|
||||||
if (res.isEmpty())
|
|
||||||
return defaultValue;
|
|
||||||
return res.get(0).getAsInteger("value");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setStrings(String key, String value) {
|
|
||||||
if (value == null) {
|
|
||||||
rawSQL("DELETE FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ContentValues data = new ContentValues();
|
|
||||||
data.put("key", key);
|
|
||||||
data.put("value", value);
|
|
||||||
rawSQL("REPLACE INTO %s %s", STRINGS_TABLE, toSQL(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStrings(String key, String defaultValue) {
|
|
||||||
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
|
|
||||||
if (res.isEmpty())
|
|
||||||
return defaultValue;
|
|
||||||
return res.get(0).getAsString("value");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,299 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.database;
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.DatabaseUtils;
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
|
||||||
import com.topjohnwu.magisk.Data;
|
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
|
||||||
import com.topjohnwu.magisk.R;
|
|
||||||
import com.topjohnwu.magisk.container.Policy;
|
|
||||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
import com.topjohnwu.superuser.io.SuFile;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MagiskDBLegacy extends MagiskDB {
|
|
||||||
|
|
||||||
private static final int DATABASE_VER = 6;
|
|
||||||
private static final int OLD_DATABASE_VER = 5;
|
|
||||||
|
|
||||||
private PackageManager pm;
|
|
||||||
private SQLiteDatabase db;
|
|
||||||
|
|
||||||
static MagiskDBLegacy newInstance() {
|
|
||||||
try {
|
|
||||||
return new MagiskDBLegacy();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Let's cleanup everything and try again
|
|
||||||
Shell.su("db_clean '*'").exec();
|
|
||||||
return new MagiskDBLegacy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MagiskDBLegacy() {
|
|
||||||
pm = Data.MM().getPackageManager();
|
|
||||||
db = openDatabase();
|
|
||||||
db.disableWriteAheadLogging();
|
|
||||||
int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER;
|
|
||||||
int curVersion = db.getVersion();
|
|
||||||
if (curVersion < version) {
|
|
||||||
onUpgrade(db, curVersion);
|
|
||||||
} else if (curVersion > DATABASE_VER) {
|
|
||||||
/* Higher than we can possibly support */
|
|
||||||
onDowngrade(db);
|
|
||||||
}
|
|
||||||
db.setVersion(version);
|
|
||||||
clearOutdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
private SQLiteDatabase openDatabase() {
|
|
||||||
MagiskManager mm = Data.MM();
|
|
||||||
Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
|
||||||
? mm.createDeviceProtectedStorageContext() : mm;
|
|
||||||
if (!LEGACY_MANAGER_DB.canWrite()) {
|
|
||||||
if (!Shell.rootAccess() || Data.magiskVersionCode < 0) {
|
|
||||||
// We don't want the app to crash, create a db and return
|
|
||||||
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
|
||||||
}
|
|
||||||
// Cleanup
|
|
||||||
Shell.su("db_clean " + Const.USER_ID).exec();
|
|
||||||
// Global database
|
|
||||||
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db");
|
|
||||||
mm.deleteDatabase("su.db");
|
|
||||||
de.deleteDatabase("su.db");
|
|
||||||
if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) {
|
|
||||||
// We need some additional policies on old versions
|
|
||||||
Shell.su("db_sepatch").exec();
|
|
||||||
}
|
|
||||||
if (!GLOBAL_DB.exists()) {
|
|
||||||
Shell.su("db_init").exec();
|
|
||||||
SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
|
|
||||||
Shell.su("db_restore").exec();
|
|
||||||
}
|
|
||||||
Shell.su("db_setup " + Process.myUid()).exec();
|
|
||||||
}
|
|
||||||
// Not using legacy mode, open the mounted global DB
|
|
||||||
return SQLiteDatabase.openOrCreateDatabase(LEGACY_MANAGER_DB, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onUpgrade(SQLiteDatabase db, int oldVersion) {
|
|
||||||
if (oldVersion == 0) {
|
|
||||||
createTables(db);
|
|
||||||
oldVersion = 3;
|
|
||||||
}
|
|
||||||
if (oldVersion == 1) {
|
|
||||||
// We're dropping column app_name, rename and re-construct table
|
|
||||||
db.execSQL(Utils.fmt("ALTER TABLE %s RENAME TO %s_old", POLICY_TABLE));
|
|
||||||
|
|
||||||
// Create the new tables
|
|
||||||
createTables(db);
|
|
||||||
|
|
||||||
// Migrate old data to new tables
|
|
||||||
db.execSQL(Utils.fmt("INSERT INTO %s SELECT " +
|
|
||||||
"uid, package_name, policy, until, logging, notification FROM %s_old",
|
|
||||||
POLICY_TABLE, POLICY_TABLE));
|
|
||||||
db.execSQL(Utils.fmt("DROP TABLE %s_old", POLICY_TABLE));
|
|
||||||
|
|
||||||
Data.MM().deleteDatabase("sulog.db");
|
|
||||||
++oldVersion;
|
|
||||||
}
|
|
||||||
if (oldVersion == 2) {
|
|
||||||
db.execSQL(Utils.fmt("UPDATE %s SET time=time*1000", LOG_TABLE));
|
|
||||||
++oldVersion;
|
|
||||||
}
|
|
||||||
if (oldVersion == 3) {
|
|
||||||
db.execSQL(Utils.fmt("CREATE TABLE IF NOT EXISTS %s (key TEXT, value TEXT, PRIMARY KEY(key))", STRINGS_TABLE));
|
|
||||||
++oldVersion;
|
|
||||||
}
|
|
||||||
if (oldVersion == 4) {
|
|
||||||
db.execSQL(Utils.fmt("UPDATE %s SET uid=uid%%100000", POLICY_TABLE));
|
|
||||||
++oldVersion;
|
|
||||||
}
|
|
||||||
if (oldVersion == 5) {
|
|
||||||
setSettings(Const.Key.SU_FINGERPRINT,
|
|
||||||
Data.MM().prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0);
|
|
||||||
++oldVersion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove everything, we do not support downgrade
|
|
||||||
private void onDowngrade(SQLiteDatabase db) {
|
|
||||||
Utils.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG);
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE);
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE);
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + SETTINGS_TABLE);
|
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + STRINGS_TABLE);
|
|
||||||
onUpgrade(db, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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))");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearOutdated() {
|
|
||||||
// Clear outdated policies
|
|
||||||
db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
|
|
||||||
// Clear outdated logs
|
|
||||||
db.delete(LOG_TABLE, Utils.fmt("time < %d", System.currentTimeMillis() - Data.suLogTimeout * 86400000), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deletePolicy(String pkg) {
|
|
||||||
db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deletePolicy(int uid) {
|
|
||||||
db.delete(POLICY_TABLE, Utils.fmt("uid=%d", uid), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Policy getPolicy(int uid) {
|
|
||||||
Policy policy = null;
|
|
||||||
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid=%d", uid), null, null, null, null)) {
|
|
||||||
if (c.moveToNext()) {
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
DatabaseUtils.cursorRowToContentValues(c, values);
|
|
||||||
policy = new Policy(values, pm);
|
|
||||||
}
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
deletePolicy(uid);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return policy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePolicy(Policy policy) {
|
|
||||||
db.replace(POLICY_TABLE, null, policy.getContentValues());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> getPolicyList() {
|
|
||||||
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid/100000=%d", Const.USER_ID),
|
|
||||||
null, null, null, null)) {
|
|
||||||
List<Policy> ret = new ArrayList<>(c.getCount());
|
|
||||||
while (c.moveToNext()) {
|
|
||||||
try {
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
DatabaseUtils.cursorRowToContentValues(c, values);
|
|
||||||
Policy policy = new Policy(values, pm);
|
|
||||||
ret.add(policy);
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
// The app no longer exist, remove from DB
|
|
||||||
deletePolicy(c.getInt(c.getColumnIndex("uid")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Collections.sort(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<List<SuLogEntry>> getLogs() {
|
|
||||||
try (Cursor c = db.query(LOG_TABLE, null, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
|
|
||||||
null, null, null, "time DESC")) {
|
|
||||||
List<List<SuLogEntry>> ret = new ArrayList<>();
|
|
||||||
List<SuLogEntry> list = null;
|
|
||||||
String dateString = null, newString;
|
|
||||||
while (c.moveToNext()) {
|
|
||||||
Date date = new Date(c.getLong(c.getColumnIndex("time")));
|
|
||||||
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
|
|
||||||
if (!TextUtils.equals(dateString, newString)) {
|
|
||||||
dateString = newString;
|
|
||||||
list = new ArrayList<>();
|
|
||||||
ret.add(list);
|
|
||||||
}
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
DatabaseUtils.cursorRowToContentValues(c, values);
|
|
||||||
list.add(new SuLogEntry(values));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addLog(SuLogEntry log) {
|
|
||||||
db.insert(LOG_TABLE, null, log.getContentValues());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearLogs() {
|
|
||||||
db.delete(LOG_TABLE, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSettings(String key, int value) {
|
|
||||||
ContentValues data = new ContentValues();
|
|
||||||
data.put("key", key);
|
|
||||||
data.put("value", value);
|
|
||||||
db.replace(SETTINGS_TABLE, null, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSettings(String key, int defaultValue) {
|
|
||||||
int value = defaultValue;
|
|
||||||
try (Cursor c = db.query(SETTINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
|
|
||||||
if (c.moveToNext()) {
|
|
||||||
value = c.getInt(c.getColumnIndex("value"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setStrings(String key, String value) {
|
|
||||||
if (value == null) {
|
|
||||||
db.delete(STRINGS_TABLE, "key=?", new String[] { key });
|
|
||||||
} else {
|
|
||||||
ContentValues data = new ContentValues();
|
|
||||||
data.put("key", key);
|
|
||||||
data.put("value", value);
|
|
||||||
db.replace(STRINGS_TABLE, null, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStrings(String key, String defaultValue) {
|
|
||||||
String value = defaultValue;
|
|
||||||
try (Cursor c = db.query(STRINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
|
|
||||||
if (c.moveToNext()) {
|
|
||||||
value = c.getString(c.getColumnIndex("value"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
@ -271,8 +271,7 @@ public class MagiskFragment extends BaseFragment
|
|||||||
if (Data.remoteMagiskVersionCode > Data.magiskVersionCode
|
if (Data.remoteMagiskVersionCode > Data.magiskVersionCode
|
||||||
|| Data.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
|
|| Data.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
|
||||||
install();
|
install();
|
||||||
} else if (Data.remoteMagiskVersionCode >= Const.MAGISK_VER.FIX_ENV &&
|
} else if (!ShellUtils.fastCmdResult("env_check")) {
|
||||||
!ShellUtils.fastCmdResult("env_check")) {
|
|
||||||
new EnvFixDialog(requireActivity()).show();
|
new EnvFixDialog(requireActivity()).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,11 @@ public class GeneralReceiver extends BroadcastReceiver {
|
|||||||
case "request":
|
case "request":
|
||||||
Intent i = new Intent(mm, Data.classMap.get(SuRequestActivity.class))
|
Intent i = new Intent(mm, Data.classMap.get(SuRequestActivity.class))
|
||||||
.putExtra("socket", intent.getStringExtra("socket"))
|
.putExtra("socket", intent.getStringExtra("socket"))
|
||||||
.putExtra("version", 2)
|
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
mm.startActivity(i);
|
mm.startActivity(i);
|
||||||
break;
|
break;
|
||||||
case "log":
|
case "log":
|
||||||
SuConnector.handleLogs(intent, 2);
|
SuConnector.handleLogs(intent);
|
||||||
break;
|
break;
|
||||||
case "notify":
|
case "notify":
|
||||||
SuConnector.handleNotify(intent);
|
SuConnector.handleNotify(intent);
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.superuser;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Data;
|
|
||||||
import com.topjohnwu.magisk.SuRequestActivity;
|
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
|
||||||
|
|
||||||
public class RequestActivity extends BaseActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
Intent intent = new Intent(this, Data.classMap.get(SuRequestActivity.class))
|
|
||||||
.putExtra("socket", getIntent().getStringExtra("socket"))
|
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.superuser;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.SuConnector;
|
|
||||||
|
|
||||||
public class SuReceiver extends BroadcastReceiver {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if (intent != null)
|
|
||||||
SuConnector.handleLogs(intent, 1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,6 @@ import androidx.annotation.Keep;
|
|||||||
|
|
||||||
public class BootSigner {
|
public class BootSigner {
|
||||||
|
|
||||||
@Keep
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
if (args.length > 0 && "-verify".equals(args[0])) {
|
if (args.length > 0 && "-verify".equals(args[0])) {
|
||||||
String certPath = "";
|
String certPath = "";
|
||||||
|
@ -21,10 +21,6 @@ public class RootUtils extends Shell.Initializer {
|
|||||||
BusyBox.BB_PATH = new File(Const.BUSYBOX_PATH);
|
BusyBox.BB_PATH = new File(Const.BUSYBOX_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void uninstallPkg(String pkg) {
|
|
||||||
Shell.su("db_clean " + Const.USER_ID, "pm uninstall " + pkg).exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void rmAndLaunch(String rm, String launch) {
|
public static void rmAndLaunch(String rm, String launch) {
|
||||||
Shell.su(Utils.fmt("(rm_launch %d %s %s)&", Const.USER_ID, rm, launch)).exec();
|
Shell.su(Utils.fmt("(rm_launch %d %s %s)&", Const.USER_ID, rm, launch)).exec();
|
||||||
}
|
}
|
||||||
@ -33,9 +29,6 @@ public class RootUtils extends Shell.Initializer {
|
|||||||
public boolean onInit(Context context, @NonNull Shell shell) {
|
public boolean onInit(Context context, @NonNull Shell shell) {
|
||||||
Shell.Job job = shell.newJob();
|
Shell.Job job = shell.newJob();
|
||||||
if (shell.isRoot()) {
|
if (shell.isRoot()) {
|
||||||
if (!new SuFile("/sbin/.magisk").exists())
|
|
||||||
job.add("ln -s /sbin/.core /sbin/.magisk");
|
|
||||||
|
|
||||||
job.add(context.getResources().openRawResource(R.raw.util_functions))
|
job.add(context.getResources().openRawResource(R.raw.util_functions))
|
||||||
.add(context.getResources().openRawResource(R.raw.utils));
|
.add(context.getResources().openRawResource(R.raw.utils));
|
||||||
Const.MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk");
|
Const.MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk");
|
||||||
|
@ -3,6 +3,7 @@ package com.topjohnwu.magisk.utils;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.LocalSocket;
|
import android.net.LocalSocket;
|
||||||
|
import android.net.LocalSocketAddress;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@ -24,12 +25,13 @@ import java.util.Date;
|
|||||||
|
|
||||||
public abstract class SuConnector {
|
public abstract class SuConnector {
|
||||||
|
|
||||||
protected LocalSocket socket = new LocalSocket();
|
private LocalSocket socket;
|
||||||
protected DataOutputStream out;
|
protected DataOutputStream out;
|
||||||
protected DataInputStream in;
|
protected DataInputStream in;
|
||||||
|
|
||||||
public SuConnector(String name) throws IOException {
|
public SuConnector(String name) throws IOException {
|
||||||
connect(name);
|
socket = new LocalSocket();
|
||||||
|
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
|
||||||
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
|
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
|
||||||
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
|
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
|
||||||
}
|
}
|
||||||
@ -66,11 +68,9 @@ public abstract class SuConnector {
|
|||||||
} catch (IOException ignored) { }
|
} catch (IOException ignored) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void connect(String name) throws IOException;
|
|
||||||
|
|
||||||
protected abstract void onResponse() throws IOException;
|
protected abstract void onResponse() throws IOException;
|
||||||
|
|
||||||
public static void handleLogs(Intent intent, int version) {
|
public static void handleLogs(Intent intent) {
|
||||||
|
|
||||||
int fromUid = intent.getIntExtra("from.uid", -1);
|
int fromUid = intent.getIntExtra("from.uid", -1);
|
||||||
if (fromUid < 0) return;
|
if (fromUid < 0) return;
|
||||||
@ -97,24 +97,9 @@ public abstract class SuConnector {
|
|||||||
notify = policy.notification;
|
notify = policy.notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == 1) {
|
|
||||||
String action = intent.getStringExtra("action");
|
|
||||||
if (action == null) return;
|
|
||||||
switch (action) {
|
|
||||||
case "allow":
|
|
||||||
policy.policy = Policy.ALLOW;
|
|
||||||
break;
|
|
||||||
case "deny":
|
|
||||||
policy.policy = Policy.DENY;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
policy.policy = data.getInt("policy", -1);
|
policy.policy = data.getInt("policy", -1);
|
||||||
if (policy.policy < 0)
|
if (policy.policy < 0)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
handleNotify(policy);
|
handleNotify(policy);
|
||||||
|
@ -1,42 +1,3 @@
|
|||||||
db_sepatch() {
|
|
||||||
magiskpolicy --live 'create magisk_file' 'attradd magisk_file mlstrustedobject' \
|
|
||||||
'allow * magisk_file file *' 'allow * magisk_file dir *' \
|
|
||||||
'allow magisk_file * filesystem associate'
|
|
||||||
}
|
|
||||||
|
|
||||||
db_clean() {
|
|
||||||
local USERID=$1
|
|
||||||
local DIR="/sbin/.magisk/db-${USERID}"
|
|
||||||
umount -l /data/user*/*/*/databases/su.db $DIR $DIR/*
|
|
||||||
rm -rf $DIR
|
|
||||||
[ "$USERID" = "*" ] && rm -fv /data/adb/magisk.db*
|
|
||||||
}
|
|
||||||
|
|
||||||
db_init() {
|
|
||||||
# Temporary let the folder rw by anyone
|
|
||||||
chcon u:object_r:magisk_file:s0 /data/adb
|
|
||||||
chmod 777 /data/adb
|
|
||||||
}
|
|
||||||
|
|
||||||
db_restore() {
|
|
||||||
chmod 700 /data/adb
|
|
||||||
magisk --restorecon
|
|
||||||
}
|
|
||||||
|
|
||||||
db_setup() {
|
|
||||||
local USER=$1
|
|
||||||
local USERID=$(($USER / 100000))
|
|
||||||
local DIR=/sbin/.magisk/db-${USERID}
|
|
||||||
mkdir -p $DIR
|
|
||||||
touch $DIR/magisk.db
|
|
||||||
mount -o bind /data/adb/magisk.db $DIR/magisk.db
|
|
||||||
rm -f /data/adb/magisk.db-*
|
|
||||||
chcon u:object_r:magisk_file:s0 $DIR $DIR/*
|
|
||||||
chmod 700 $DIR
|
|
||||||
chown $USER.$USER $DIR
|
|
||||||
chmod 666 $DIR/*
|
|
||||||
}
|
|
||||||
|
|
||||||
env_check() {
|
env_check() {
|
||||||
for file in busybox magisk magiskboot magiskinit util_functions.sh boot_patch.sh; do
|
for file in busybox magisk magiskboot magiskinit util_functions.sh boot_patch.sh; do
|
||||||
[ -f /data/adb/magisk/$file ] || return 1
|
[ -f /data/adb/magisk/$file ] || return 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user