Magisk/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java

198 lines
7.4 KiB
Java
Raw Normal View History

2017-02-06 18:01:32 +00:00
package com.topjohnwu.magisk;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
2017-02-06 22:02:06 +00:00
import android.os.Handler;
2017-02-06 18:01:32 +00:00
import android.preference.PreferenceManager;
import android.text.TextUtils;
2017-02-06 18:01:32 +00:00
import android.util.SparseArray;
2017-02-06 22:02:06 +00:00
import android.widget.Toast;
2017-02-06 18:01:32 +00:00
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
2017-02-06 20:09:49 +00:00
import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.utils.CallbackEvent;
2017-02-06 18:01:32 +00:00
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ValueSortedMap;
import java.io.File;
import java.util.List;
public class MagiskManager extends Application {
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
2017-02-12 11:49:46 +00:00
public static final String MAGISK_HIDE_PATH = "/magisk/.core/magiskhide/";
public static final String TMP_FOLDER_PATH = "/dev/tmp";
2017-02-12 12:53:41 +00:00
public static final String MAGISK_PATH = "/magisk";
public static final String INTENT_SECTION = "section";
public static final String BUSYBOX_VERSION = "1.26.2";
2017-02-06 18:01:32 +00:00
// Events
2017-02-06 20:09:49 +00:00
public final CallbackEvent<Void> blockDetectionDone = new CallbackEvent<>();
public final CallbackEvent<Void> magiskHideDone = new CallbackEvent<>();
2017-02-06 20:09:49 +00:00
public final CallbackEvent<Void> reloadMainActivity = new CallbackEvent<>();
public final CallbackEvent<Void> moduleLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>();
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
2017-02-12 12:53:41 +00:00
public final SparseArray<CallbackEvent<Policy>> uidSuRequest = new SparseArray<>();
2017-02-06 18:01:32 +00:00
// Info
public String magiskVersionString;
2017-05-11 18:25:07 +00:00
public int magiskVersionCode = -1;
public String remoteMagiskVersionString;
public int remoteMagiskVersionCode = -1;
2017-02-06 18:01:32 +00:00
public String magiskLink;
public String releaseNoteLink;
public int SNCheckResult = -1;
public String bootBlock = null;
public boolean isSuClient = false;
public String suVersion = null;
public boolean disabled;
public boolean magiskHideStarted;
2017-02-06 18:01:32 +00:00
// Data
public ValueSortedMap<String, Repo> repoMap;
public ValueSortedMap<String, Module> moduleMap;
public List<String> blockList;
public List<ApplicationInfo> appList;
public List<String> magiskHideList;
// Configurations
public static boolean shellLogging;
public static boolean devLogging;
2017-02-06 23:32:40 +00:00
public boolean magiskHide;
2017-02-06 18:01:32 +00:00
public boolean isDarkTheme;
2017-02-21 20:58:03 +00:00
public boolean updateNotification;
2017-02-06 18:01:32 +00:00
public int suRequestTimeout;
public int suLogTimeout = 14;
public int suAccessState;
public int suResponseType;
public int suNotificationType;
public SharedPreferences prefs;
2017-02-06 22:02:06 +00:00
private static Handler mHandler = new Handler();
2017-02-06 18:01:32 +00:00
@Override
public void onCreate() {
super.onCreate();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
}
2017-02-06 22:02:06 +00:00
public void toast(String msg, int duration) {
mHandler.post(() -> Toast.makeText(this, msg, duration).show());
}
public void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(this, resId, duration).show());
}
2017-02-06 18:01:32 +00:00
public void init() {
isDarkTheme = prefs.getBoolean("dark_theme", false);
2017-05-11 18:25:07 +00:00
if (BuildConfig.DEBUG) {
devLogging = prefs.getBoolean("developer_logging", false);
shellLogging = prefs.getBoolean("shell_logging", false);
} else {
devLogging = false;
shellLogging = false;
}
2017-02-06 18:01:32 +00:00
magiskHide = prefs.getBoolean("magiskhide", false);
2017-02-21 20:58:03 +00:00
updateNotification = prefs.getBoolean("notification", true);
// Always start a new root shell manually, just for safety
Shell.init();
2017-02-06 18:01:32 +00:00
updateMagiskInfo();
initSuAccess();
initSuConfigs();
// Initialize busybox
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
busybox.getParentFile().mkdirs();
Shell.su(
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
"chmod -R 755 " + busybox.getParent(),
busybox + " --install -s " + busybox.getParent()
);
}
2017-02-06 18:01:32 +00:00
// Initialize prefs
prefs.edit()
.putBoolean("dark_theme", isDarkTheme)
.putBoolean("magiskhide", magiskHide)
2017-02-21 20:58:03 +00:00
.putBoolean("notification", updateNotification)
2017-02-06 18:01:32 +00:00
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
.putBoolean("disable", Utils.itemExist(MAGISK_DISABLE_FILE))
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
.putString("su_auto_response", String.valueOf(suResponseType))
.putString("su_notification", String.valueOf(suNotificationType))
.putString("su_access", String.valueOf(suAccessState))
.putString("busybox_version", BUSYBOX_VERSION)
2017-02-06 18:01:32 +00:00
.apply();
// Add busybox to PATH
Shell.su("PATH=$PATH:" + busybox.getParent());
2017-02-06 18:01:32 +00:00
}
public void initSuConfigs() {
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
}
public void initSuAccess() {
List<String> ret = Shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) {
suVersion = ret.get(0);
isSuClient = suVersion.toUpperCase().contains("MAGISK");
}
if (isSuClient) {
ret = Shell.sh("getprop persist.sys.root_access");
if (Utils.isValidShellResponse(ret)) {
2017-02-06 18:01:32 +00:00
suAccessState = Integer.parseInt(ret.get(0));
} else {
2017-02-06 18:01:32 +00:00
Shell.su(true, "setprop persist.sys.root_access 3");
suAccessState = 3;
}
}
}
public void updateMagiskInfo() {
2017-05-11 18:25:07 +00:00
List<String> ret;
ret = Shell.sh("magisk -v");
2017-02-06 18:01:32 +00:00
if (!Utils.isValidShellResponse(ret)) {
2017-05-11 18:25:07 +00:00
ret = Shell.sh("getprop magisk.version");
if (Utils.isValidShellResponse(ret)) {
try {
magiskVersionString = ret.get(0);
magiskVersionCode = (int) Double.parseDouble(ret.get(0)) * 10;
} catch (NumberFormatException ignored) {}
}
2017-02-06 18:01:32 +00:00
} else {
2017-05-11 18:25:07 +00:00
magiskVersionString = ret.get(0).split(":")[0];
ret = Shell.sh("magisk -V");
2017-02-06 18:01:32 +00:00
try {
2017-05-11 18:25:07 +00:00
magiskVersionCode = Integer.parseInt(ret.get(0));
} catch (NumberFormatException ignored) {}
2017-02-06 18:01:32 +00:00
}
ret = Shell.sh("getprop ro.magisk.disable");
try {
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
disabled = false;
}
ret = Shell.sh("getprop persist.magisk.hide");
try {
magiskHideStarted = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
magiskHideStarted = false;
}
if (magiskHideStarted) {
magiskHide = true;
}
2017-02-06 18:01:32 +00:00
}
}