mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-28 04:25:27 +00:00
Rewrite root shell
This commit is contained in:
parent
cc14a1c361
commit
87ea2a2bef
@ -197,7 +197,7 @@ public class MagiskFragment extends Fragment
|
|||||||
@Override
|
@Override
|
||||||
public void onFinish() {
|
public void onFinish() {
|
||||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||||
Shell.su(true,
|
magiskManager.rootShell.su(
|
||||||
"mv -f " + uninstaller + " /cache/" + MagiskManager.UNINSTALLER,
|
"mv -f " + uninstaller + " /cache/" + MagiskManager.UNINSTALLER,
|
||||||
"mv -f " + utils + " /data/magisk/" + MagiskManager.UTIL_FUNCTIONS,
|
"mv -f " + utils + " /data/magisk/" + MagiskManager.UTIL_FUNCTIONS,
|
||||||
"reboot"
|
"reboot"
|
||||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -24,10 +25,9 @@ import android.widget.ScrollView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.asyncs.RootTask;
|
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
||||||
import com.topjohnwu.magisk.components.Fragment;
|
import com.topjohnwu.magisk.components.Fragment;
|
||||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -67,7 +67,7 @@ public class MagiskLogFragment extends Fragment {
|
|||||||
|
|
||||||
txtLog.setTextIsSelectable(true);
|
txtLog.setTextIsSelectable(true);
|
||||||
|
|
||||||
new LogManager().read();
|
new LogManager(getActivity()).read();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ public class MagiskLogFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
new LogManager().read();
|
new LogManager(getActivity()).read();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,13 +100,13 @@ public class MagiskLogFragment extends Fragment {
|
|||||||
mClickedMenuItem = item;
|
mClickedMenuItem = item;
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_refresh:
|
case R.id.menu_refresh:
|
||||||
new LogManager().read();
|
new LogManager(getActivity()).read();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_save:
|
case R.id.menu_save:
|
||||||
new LogManager().save();
|
new LogManager(getActivity()).save();
|
||||||
return true;
|
return true;
|
||||||
case R.id.menu_clear:
|
case R.id.menu_clear:
|
||||||
new LogManager().clear();
|
new LogManager(getActivity()).clear();
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
@ -127,18 +127,22 @@ public class MagiskLogFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LogManager extends RootTask<Object, Void, Object> {
|
private class LogManager extends ParallelTask<Object, Void, Object> {
|
||||||
|
|
||||||
int mode;
|
int mode;
|
||||||
File targetFile;
|
File targetFile;
|
||||||
|
|
||||||
|
LogManager(Activity activity) {
|
||||||
|
super(activity);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
@Override
|
@Override
|
||||||
protected Object doInRoot(Object... params) {
|
protected Object doInBackground(Object... params) {
|
||||||
mode = (int) params[0];
|
mode = (int) params[0];
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0:
|
case 0:
|
||||||
List<String> logList = Utils.readFile(MAGISK_LOG);
|
List<String> logList = Utils.readFile(magiskManager.rootShell, MAGISK_LOG);
|
||||||
|
|
||||||
if (Utils.isValidShellResponse(logList)) {
|
if (Utils.isValidShellResponse(logList)) {
|
||||||
StringBuilder llog = new StringBuilder(15 * 10 * 1024);
|
StringBuilder llog = new StringBuilder(15 * 10 * 1024);
|
||||||
@ -150,7 +154,7 @@ public class MagiskLogFragment extends Fragment {
|
|||||||
return "";
|
return "";
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
Shell.su("echo > " + MAGISK_LOG);
|
magiskManager.rootShell.su("echo > " + MAGISK_LOG);
|
||||||
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
@ -180,7 +184,7 @@ public class MagiskLogFragment extends Fragment {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> in = Utils.readFile(MAGISK_LOG);
|
List<String> in = Utils.readFile(magiskManager.rootShell, MAGISK_LOG);
|
||||||
|
|
||||||
if (Utils.isValidShellResponse(in)) {
|
if (Utils.isValidShellResponse(in)) {
|
||||||
try (FileWriter out = new FileWriter(targetFile)) {
|
try (FileWriter out = new FileWriter(targetFile)) {
|
||||||
|
@ -88,13 +88,16 @@ public class MagiskManager extends Application {
|
|||||||
// Global resources
|
// Global resources
|
||||||
public SharedPreferences prefs;
|
public SharedPreferences prefs;
|
||||||
public SuDatabaseHelper suDB;
|
public SuDatabaseHelper suDB;
|
||||||
|
public Shell rootShell;
|
||||||
|
|
||||||
private static Handler mHandler = new Handler();
|
private static Handler mHandler = new Handler();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
new File(getApplicationInfo().dataDir).mkdirs(); /* Create the app data directory */
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
rootShell = Shell.getRootShell();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toast(String msg, int duration) {
|
public void toast(String msg, int duration) {
|
||||||
@ -117,14 +120,12 @@ public class MagiskManager extends Application {
|
|||||||
magiskHide = prefs.getBoolean("magiskhide", true);
|
magiskHide = prefs.getBoolean("magiskhide", true);
|
||||||
updateNotification = prefs.getBoolean("notification", true);
|
updateNotification = prefs.getBoolean("notification", true);
|
||||||
initSU();
|
initSU();
|
||||||
// Always start a new root shell manually, just for safety
|
|
||||||
Shell.init();
|
|
||||||
updateMagiskInfo();
|
updateMagiskInfo();
|
||||||
// Initialize busybox
|
// Initialize busybox
|
||||||
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
|
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
|
||||||
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
|
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
|
||||||
busybox.getParentFile().mkdirs();
|
busybox.getParentFile().mkdirs();
|
||||||
Shell.su(
|
rootShell.su(
|
||||||
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
|
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
|
||||||
"chmod -R 755 " + busybox.getParent(),
|
"chmod -R 755 " + busybox.getParent(),
|
||||||
busybox + " --install -s " + busybox.getParent()
|
busybox + " --install -s " + busybox.getParent()
|
||||||
@ -136,7 +137,7 @@ public class MagiskManager extends Application {
|
|||||||
.putBoolean("magiskhide", magiskHide)
|
.putBoolean("magiskhide", magiskHide)
|
||||||
.putBoolean("notification", updateNotification)
|
.putBoolean("notification", updateNotification)
|
||||||
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
|
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
|
||||||
.putBoolean("disable", Utils.itemExist(MAGISK_DISABLE_FILE))
|
.putBoolean("disable", Utils.itemExist(rootShell, MAGISK_DISABLE_FILE))
|
||||||
.putBoolean("su_reauth", suReauth)
|
.putBoolean("su_reauth", suReauth)
|
||||||
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
|
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
|
||||||
.putString("su_auto_response", String.valueOf(suResponseType))
|
.putString("su_auto_response", String.valueOf(suResponseType))
|
||||||
@ -147,7 +148,7 @@ public class MagiskManager extends Application {
|
|||||||
.putString("busybox_version", BUSYBOX_VERSION)
|
.putString("busybox_version", BUSYBOX_VERSION)
|
||||||
.apply();
|
.apply();
|
||||||
// Add busybox to PATH
|
// Add busybox to PATH
|
||||||
Shell.su("PATH=$PATH:" + busybox.getParent());
|
rootShell.su("PATH=$PATH:" + busybox.getParent());
|
||||||
|
|
||||||
// Create notification channel on Android O
|
// Create notification channel on Android O
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
@ -167,9 +168,6 @@ public class MagiskManager extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initSU() {
|
public void initSU() {
|
||||||
// Create the app data directory, so su binary can work properly
|
|
||||||
new File(getApplicationInfo().dataDir).mkdirs();
|
|
||||||
|
|
||||||
initSUConfig();
|
initSUConfig();
|
||||||
|
|
||||||
List<String> ret = Shell.sh("su -v");
|
List<String> ret = Shell.sh("su -v");
|
||||||
|
@ -20,6 +20,7 @@ import com.topjohnwu.magisk.components.Fragment;
|
|||||||
import com.topjohnwu.magisk.module.Module;
|
import com.topjohnwu.magisk.module.Module;
|
||||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
|
import com.topjohnwu.magisk.utils.Shell;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -149,9 +149,9 @@ public class SettingsActivity extends Activity {
|
|||||||
case "disable":
|
case "disable":
|
||||||
enabled = prefs.getBoolean("disable", false);
|
enabled = prefs.getBoolean("disable", false);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
Utils.createFile(MagiskManager.MAGISK_DISABLE_FILE);
|
Utils.createFile(magiskManager.rootShell, MagiskManager.MAGISK_DISABLE_FILE);
|
||||||
} else {
|
} else {
|
||||||
Utils.removeItem(MagiskManager.MAGISK_DISABLE_FILE);
|
Utils.removeItem(magiskManager.rootShell, MagiskManager.MAGISK_DISABLE_FILE);
|
||||||
}
|
}
|
||||||
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
|
||||||
break;
|
break;
|
||||||
@ -175,11 +175,11 @@ public class SettingsActivity extends Activity {
|
|||||||
case "hosts":
|
case "hosts":
|
||||||
enabled = prefs.getBoolean("hosts", false);
|
enabled = prefs.getBoolean("hosts", false);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
Shell.su_async(null,
|
magiskManager.rootShell.su(
|
||||||
"cp -af /system/etc/hosts /magisk/.core/hosts",
|
"cp -af /system/etc/hosts /magisk/.core/hosts",
|
||||||
"mount -o bind /magisk/.core/hosts /system/etc/hosts");
|
"mount -o bind /magisk/.core/hosts /system/etc/hosts");
|
||||||
} else {
|
} else {
|
||||||
Shell.su_async(null,
|
magiskManager.rootShell.su(
|
||||||
"umount -l /system/etc/hosts",
|
"umount -l /system/etc/hosts",
|
||||||
"rm -f /magisk/.core/hosts");
|
"rm -f /magisk/.core/hosts");
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||||
Context context = holder.itemView.getContext();
|
Context context = holder.itemView.getContext();
|
||||||
|
Shell rootShell = Shell.getRootShell(context);
|
||||||
final Module module = mList.get(position);
|
final Module module = mList.get(position);
|
||||||
|
|
||||||
String version = module.getVersion();
|
String version = module.getVersion();
|
||||||
@ -55,10 +56,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
||||||
int snack;
|
int snack;
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
module.removeDisableFile();
|
module.removeDisableFile(rootShell);
|
||||||
snack = R.string.disable_file_removed;
|
snack = R.string.disable_file_removed;
|
||||||
} else {
|
} else {
|
||||||
module.createDisableFile();
|
module.createDisableFile(rootShell);
|
||||||
snack = R.string.disable_file_created;
|
snack = R.string.disable_file_created;
|
||||||
}
|
}
|
||||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||||
@ -68,10 +69,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
boolean removed = module.willBeRemoved();
|
boolean removed = module.willBeRemoved();
|
||||||
int snack;
|
int snack;
|
||||||
if (removed) {
|
if (removed) {
|
||||||
module.deleteRemoveFile();
|
module.deleteRemoveFile(rootShell);
|
||||||
snack = R.string.remove_file_deleted;
|
snack = R.string.remove_file_deleted;
|
||||||
} else {
|
} else {
|
||||||
module.createRemoveFile();
|
module.createRemoveFile(rootShell);
|
||||||
snack = R.string.remove_file_created;
|
snack = R.string.remove_file_created;
|
||||||
}
|
}
|
||||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||||
|
@ -9,7 +9,6 @@ import com.topjohnwu.magisk.MagiskManager;
|
|||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||||
|
|
||||||
@ -21,7 +20,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class FlashZip extends RootTask<Void, String, Integer> {
|
public class FlashZip extends ParallelTask<Void, String, Integer> {
|
||||||
|
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
private File mCachedFile, mScriptFile, mCheckFile;
|
private File mCachedFile, mScriptFile, mCheckFile;
|
||||||
@ -71,12 +70,12 @@ public class FlashZip extends RootTask<Void, String, Integer> {
|
|||||||
private boolean unzipAndCheck() throws Exception {
|
private boolean unzipAndCheck() throws Exception {
|
||||||
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
|
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
|
||||||
List<String> ret;
|
List<String> ret;
|
||||||
ret = Utils.readFile(mCheckFile.getPath());
|
ret = Utils.readFile(magiskManager.rootShell, mCheckFile.getPath());
|
||||||
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cleanup(int ret) {
|
private int cleanup(int ret) {
|
||||||
Shell.su(
|
magiskManager.rootShell.su(
|
||||||
"rm -rf " + mCachedFile.getParent() + "/*",
|
"rm -rf " + mCachedFile.getParent() + "/*",
|
||||||
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
|
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
|
||||||
);
|
);
|
||||||
@ -96,14 +95,14 @@ public class FlashZip extends RootTask<Void, String, Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Integer doInRoot(Void... voids) {
|
protected Integer doInBackground(Void... voids) {
|
||||||
Logger.dev("FlashZip Running... " + mFilename);
|
Logger.dev("FlashZip Running... " + mFilename);
|
||||||
List<String> ret;
|
List<String> ret;
|
||||||
try {
|
try {
|
||||||
copyToCache();
|
copyToCache();
|
||||||
if (!unzipAndCheck()) return cleanup(0);
|
if (!unzipAndCheck()) return cleanup(0);
|
||||||
publishProgress(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
|
publishProgress(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
|
||||||
ret = Shell.su(
|
ret = magiskManager.rootShell.su(
|
||||||
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile,
|
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile,
|
||||||
"if [ $? -eq 0 ]; then echo true; else echo false; fi"
|
"if [ $? -eq 0 ]; then echo true; else echo false; fi"
|
||||||
);
|
);
|
||||||
@ -147,7 +146,7 @@ public class FlashZip extends RootTask<Void, String, Integer> {
|
|||||||
new AlertDialogBuilder(activity)
|
new AlertDialogBuilder(activity)
|
||||||
.setTitle(R.string.reboot_title)
|
.setTitle(R.string.reboot_title)
|
||||||
.setMessage(R.string.reboot_msg)
|
.setMessage(R.string.reboot_msg)
|
||||||
.setPositiveButton(R.string.reboot, (dialogInterface, i) -> Shell.su(true, "reboot"))
|
.setPositiveButton(R.string.reboot, (dialogInterface, i) -> magiskManager.rootShell.su("reboot"))
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
@ -2,22 +2,21 @@ package com.topjohnwu.magisk.asyncs;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
public class GetBootBlocks extends RootTask<Void, Void, Void> {
|
public class GetBootBlocks extends ParallelTask<Void, Void, Void> {
|
||||||
|
|
||||||
public GetBootBlocks(Activity context) {
|
public GetBootBlocks(Activity context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInRoot(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
magiskManager.blockList = Shell.su(
|
magiskManager.blockList = magiskManager.rootShell.su(
|
||||||
"find /dev/block -type b -maxdepth 1 | grep -v -E \"loop|ram|dm-0\""
|
"find /dev/block -type b -maxdepth 1 | grep -v -E \"loop|ram|dm-0\""
|
||||||
);
|
);
|
||||||
if (magiskManager.bootBlock == null) {
|
if (magiskManager.bootBlock == null) {
|
||||||
magiskManager.bootBlock = Utils.detectBootImage();
|
magiskManager.bootBlock = Utils.detectBootImage(magiskManager.rootShell);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -9,23 +9,22 @@ import com.topjohnwu.magisk.utils.Logger;
|
|||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.magisk.utils.ValueSortedMap;
|
import com.topjohnwu.magisk.utils.ValueSortedMap;
|
||||||
|
|
||||||
public class LoadModules extends RootTask<Void, Void, Void> {
|
public class LoadModules extends ParallelTask<Void, Void, Void> {
|
||||||
|
|
||||||
public LoadModules(Activity context) {
|
public LoadModules(Activity context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInRoot(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
Logger.dev("LoadModules: Loading modules");
|
Logger.dev("LoadModules: Loading modules");
|
||||||
|
|
||||||
magiskManager.moduleMap = new ValueSortedMap<>();
|
magiskManager.moduleMap = new ValueSortedMap<>();
|
||||||
|
|
||||||
for (String path : Utils.getModList(MagiskManager.MAGISK_PATH)) {
|
for (String path : Utils.getModList(magiskManager.rootShell, MagiskManager.MAGISK_PATH)) {
|
||||||
Logger.dev("LoadModules: Adding modules from " + path);
|
Logger.dev("LoadModules: Adding modules from " + path);
|
||||||
Module module;
|
|
||||||
try {
|
try {
|
||||||
module = new Module(path);
|
Module module = new Module(magiskManager.rootShell, path);
|
||||||
magiskManager.moduleMap.put(module.getId(), module);
|
magiskManager.moduleMap.put(module.getId(), module);
|
||||||
} catch (BaseModule.CacheModException ignored) {}
|
} catch (BaseModule.CacheModException ignored) {}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package com.topjohnwu.magisk.asyncs;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MagiskHide extends RootTask<Object, Void, Void> {
|
public class MagiskHide extends ParallelTask<Object, Void, Void> {
|
||||||
|
|
||||||
private boolean isList = false;
|
private boolean isList = false;
|
||||||
|
|
||||||
@ -17,9 +15,9 @@ public class MagiskHide extends RootTask<Object, Void, Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInRoot(Object... params) {
|
protected Void doInBackground(Object... params) {
|
||||||
String command = (String) params[0];
|
String command = (String) params[0];
|
||||||
List<String> ret = Shell.su("magiskhide --" + command);
|
List<String> ret = magiskManager.rootShell.su("magiskhide --" + command);
|
||||||
if (isList) {
|
if (isList) {
|
||||||
magiskManager.magiskHideList = ret;
|
magiskManager.magiskHideList = ret;
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,11 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
|||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground(Void... params) {
|
protected Boolean doInBackground(Void... params) {
|
||||||
if (Shell.rootAccess()) {
|
if (Shell.rootAccess()) {
|
||||||
synchronized (Shell.lock) {
|
magiskManager.rootShell.su("rm -f /dev/.magisk",
|
||||||
Shell.su("rm -f /dev/.magisk",
|
(mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "",
|
||||||
(mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "",
|
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
|
||||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
|
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk"
|
||||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk"
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.asyncs;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
|
|
||||||
public abstract class RootTask <Params, Progress, Result> extends ParallelTask<Params, Progress, Result> {
|
|
||||||
|
|
||||||
public RootTask() {}
|
|
||||||
|
|
||||||
public RootTask(Activity context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
@Override
|
|
||||||
final protected Result doInBackground(Params... params) {
|
|
||||||
synchronized (Shell.lock) {
|
|
||||||
return doInRoot(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
abstract protected Result doInRoot(Params... params);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public void exec(Params... params) {
|
|
||||||
if (Shell.rootAccess()) {
|
|
||||||
super.exec(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.module;
|
package com.topjohnwu.magisk.module;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
|
import com.topjohnwu.magisk.utils.Shell;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
public class Module extends BaseModule {
|
public class Module extends BaseModule {
|
||||||
@ -8,9 +9,9 @@ public class Module extends BaseModule {
|
|||||||
private String mRemoveFile, mDisableFile, mUpdateFile;
|
private String mRemoveFile, mDisableFile, mUpdateFile;
|
||||||
private boolean mEnable, mRemove, mUpdated;
|
private boolean mEnable, mRemove, mUpdated;
|
||||||
|
|
||||||
public Module(String path) throws CacheModException {
|
public Module(Shell shell, String path) throws CacheModException {
|
||||||
|
|
||||||
parseProps(Utils.readFile(path + "/module.prop"));
|
parseProps(Utils.readFile(shell, path + "/module.prop"));
|
||||||
|
|
||||||
mRemoveFile = path + "/remove";
|
mRemoveFile = path + "/remove";
|
||||||
mDisableFile = path + "/disable";
|
mDisableFile = path + "/disable";
|
||||||
@ -27,33 +28,33 @@ public class Module extends BaseModule {
|
|||||||
|
|
||||||
Logger.dev("Creating Module, id: " + getId());
|
Logger.dev("Creating Module, id: " + getId());
|
||||||
|
|
||||||
mEnable = !Utils.itemExist(mDisableFile);
|
mEnable = !Utils.itemExist(shell, mDisableFile);
|
||||||
mRemove = Utils.itemExist(mRemoveFile);
|
mRemove = Utils.itemExist(shell, mRemoveFile);
|
||||||
mUpdated = Utils.itemExist(mUpdateFile);
|
mUpdated = Utils.itemExist(shell, mUpdateFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createDisableFile() {
|
public void createDisableFile(Shell shell) {
|
||||||
mEnable = false;
|
mEnable = false;
|
||||||
Utils.createFile(mDisableFile);
|
Utils.createFile(shell, mDisableFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeDisableFile() {
|
public void removeDisableFile(Shell shell) {
|
||||||
mEnable = true;
|
mEnable = true;
|
||||||
Utils.removeItem(mDisableFile);
|
Utils.removeItem(shell, mDisableFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return mEnable;
|
return mEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createRemoveFile() {
|
public void createRemoveFile(Shell shell) {
|
||||||
mRemove = true;
|
mRemove = true;
|
||||||
Utils.createFile(mRemoveFile);
|
Utils.createFile(shell, mRemoveFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteRemoveFile() {
|
public void deleteRemoveFile(Shell shell) {
|
||||||
mRemove = false;
|
mRemove = false;
|
||||||
Utils.removeItem(mRemoveFile);
|
Utils.removeItem(shell, mRemoveFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean willBeRemoved() {
|
public boolean willBeRemoved() {
|
||||||
|
@ -11,23 +11,39 @@ public class Logger {
|
|||||||
public static final String MAIN_TAG = "Magisk";
|
public static final String MAIN_TAG = "Magisk";
|
||||||
public static final String DEBUG_TAG = "MagiskManager";
|
public static final String DEBUG_TAG = "MagiskManager";
|
||||||
|
|
||||||
|
public static void debug(String line) {
|
||||||
|
Log.d(DEBUG_TAG, "DEBUG: " + line);
|
||||||
|
}
|
||||||
|
|
||||||
public static void debug(String fmt, Object... args) {
|
public static void debug(String fmt, Object... args) {
|
||||||
Log.d(DEBUG_TAG, "DEBUG: " + String.format(Locale.US, fmt, args));
|
debug(String.format(Locale.US, fmt, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void error(String line) {
|
||||||
|
Log.e(MAIN_TAG, "MANAGERERROR: " + line);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void error(String fmt, Object... args) {
|
public static void error(String fmt, Object... args) {
|
||||||
Log.e(MAIN_TAG, "MANAGERERROR: " + String.format(Locale.US, fmt, args));
|
error(String.format(Locale.US, fmt, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dev(String line) {
|
||||||
|
if (MagiskManager.devLogging) {
|
||||||
|
Log.d(DEBUG_TAG, line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dev(String fmt, Object... args) {
|
public static void dev(String fmt, Object... args) {
|
||||||
if (MagiskManager.devLogging) {
|
dev(String.format(Locale.US, fmt, args));
|
||||||
Log.d(DEBUG_TAG, String.format(Locale.US, fmt, args));
|
}
|
||||||
|
|
||||||
|
public static void shell(boolean root, String line) {
|
||||||
|
if (MagiskManager.shellLogging) {
|
||||||
|
Log.d(DEBUG_TAG, (root ? "MANAGERSU: " : "MANAGERSH: ") + line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void shell(boolean root, String fmt, Object... args) {
|
public static void shell(boolean root, String fmt, Object... args) {
|
||||||
if (MagiskManager.shellLogging) {
|
shell(root, String.format(Locale.US, fmt, args));
|
||||||
Log.d(DEBUG_TAG, (root ? "MANAGERSU: " : "MANAGERSH: ") + String.format(Locale.US, fmt, args));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.asyncs.RootTask;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -16,37 +17,35 @@ public class Shell {
|
|||||||
|
|
||||||
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
|
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
|
||||||
public static int rootStatus;
|
public static int rootStatus;
|
||||||
public static final Object lock = new Object();
|
|
||||||
|
|
||||||
private static boolean isInit = false;
|
private static boolean isInit = false;
|
||||||
private static Process rootShell;
|
|
||||||
private static DataOutputStream rootSTDIN;
|
|
||||||
private static StreamGobbler rootSTDOUT;
|
|
||||||
private static List<String> rootOutList = Collections.synchronizedList(new ArrayList<String>());
|
|
||||||
|
|
||||||
public static void init() {
|
private final Process rootShell;
|
||||||
|
private final DataOutputStream rootSTDIN;
|
||||||
isInit = true;
|
private final DataInputStream rootSTDOUT;
|
||||||
|
|
||||||
|
private Shell() {
|
||||||
|
Process process;
|
||||||
try {
|
try {
|
||||||
rootShell = Runtime.getRuntime().exec("su");
|
process = Runtime.getRuntime().exec("su");
|
||||||
rootStatus = 1;
|
} catch (IOException e) {
|
||||||
} catch (IOException err) {
|
|
||||||
// No root
|
// No root
|
||||||
rootStatus = 0;
|
rootStatus = 0;
|
||||||
|
rootShell = null;
|
||||||
|
rootSTDIN = null;
|
||||||
|
rootSTDOUT = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootStatus = 1;
|
||||||
|
rootShell = process;
|
||||||
rootSTDIN = new DataOutputStream(rootShell.getOutputStream());
|
rootSTDIN = new DataOutputStream(rootShell.getOutputStream());
|
||||||
rootSTDOUT = new StreamGobbler(rootShell.getInputStream(), rootOutList, true);
|
rootSTDOUT = new DataInputStream(rootShell.getInputStream());
|
||||||
rootSTDOUT.start();
|
|
||||||
|
|
||||||
// Setup umask and PATH
|
|
||||||
su("umask 022");
|
su("umask 022");
|
||||||
|
|
||||||
List<String> ret = su("echo -BOC-", "id");
|
List<String> ret = su("echo -BOC-", "id");
|
||||||
|
|
||||||
if (ret == null) {
|
if (ret.isEmpty()) {
|
||||||
// Something wrong with root, not allowed?
|
// Something wrong with root, not allowed?
|
||||||
rootStatus = -1;
|
rootStatus = -1;
|
||||||
return;
|
return;
|
||||||
@ -55,7 +54,7 @@ public class Shell {
|
|||||||
for (String line : ret) {
|
for (String line : ret) {
|
||||||
if (line.contains("uid=")) {
|
if (line.contains("uid=")) {
|
||||||
// id command is working, let's see if we are actually root
|
// id command is working, let's see if we are actually root
|
||||||
rootStatus = line.contains("uid=0") ? rootStatus : -1;
|
rootStatus = line.contains("uid=0") ? 1 : -1;
|
||||||
return;
|
return;
|
||||||
} else if (!line.contains("-BOC-")) {
|
} else if (!line.contains("-BOC-")) {
|
||||||
rootStatus = -1;
|
rootStatus = -1;
|
||||||
@ -64,8 +63,16 @@ public class Shell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Shell getRootShell() {
|
||||||
|
return new Shell();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Shell getRootShell(Context context) {
|
||||||
|
return Utils.getMagiskManager(context).rootShell;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean rootAccess() {
|
public static boolean rootAccess() {
|
||||||
return isInit && rootStatus > 0;
|
return rootStatus > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> sh(String... commands) {
|
public static List<String> sh(String... commands) {
|
||||||
@ -110,120 +117,34 @@ public class Shell {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run with the same shell by default
|
public List<String> su(String... commands) {
|
||||||
public static List<String> su(String... commands) {
|
List<String> res = new ArrayList<>();
|
||||||
return su(false, commands);
|
su(res, commands);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> su(boolean newShell, String... commands) {
|
public void su(List<String> res, String... commands) {
|
||||||
List<String> res;
|
|
||||||
Process process;
|
|
||||||
DataOutputStream STDIN;
|
|
||||||
StreamGobbler STDOUT;
|
|
||||||
|
|
||||||
// Create the default shell if not init
|
|
||||||
if (!newShell && !isInit) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!newShell && !rootAccess()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newShell) {
|
|
||||||
res = Collections.synchronizedList(new ArrayList<String>());
|
|
||||||
try {
|
|
||||||
process = Runtime.getRuntime().exec("su");
|
|
||||||
STDIN = new DataOutputStream(process.getOutputStream());
|
|
||||||
STDOUT = new StreamGobbler(process.getInputStream(), res);
|
|
||||||
|
|
||||||
// Run the new shell with busybox and proper umask
|
|
||||||
STDIN.write(("umask 022\n").getBytes("UTF-8"));
|
|
||||||
STDIN.flush();
|
|
||||||
} catch (IOException err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
STDOUT.start();
|
|
||||||
} else {
|
|
||||||
process = rootShell;
|
|
||||||
STDIN = rootSTDIN;
|
|
||||||
STDOUT = rootSTDOUT;
|
|
||||||
res = rootOutList;
|
|
||||||
res.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (String write : commands) {
|
rootShell.exitValue();
|
||||||
STDIN.write((write + "\n").getBytes("UTF-8"));
|
return; // The process is dead, return
|
||||||
STDIN.flush();
|
} catch (IllegalThreadStateException ignored) {
|
||||||
Logger.shell(true, write);
|
// This should be the expected result
|
||||||
}
|
|
||||||
if (newShell) {
|
|
||||||
STDIN.write("exit\n".getBytes("UTF-8"));
|
|
||||||
STDIN.flush();
|
|
||||||
process.waitFor();
|
|
||||||
|
|
||||||
try {
|
|
||||||
STDIN.close();
|
|
||||||
} catch (IOException ignore) {
|
|
||||||
// might be closed already
|
|
||||||
}
|
|
||||||
|
|
||||||
STDOUT.join();
|
|
||||||
process.destroy();
|
|
||||||
} else {
|
|
||||||
STDIN.write(("echo\n").getBytes("UTF-8"));
|
|
||||||
STDIN.flush();
|
|
||||||
STDIN.write(("echo \'-root-done-\'\n").getBytes("UTF-8"));
|
|
||||||
STDIN.flush();
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
// Process terminated, it means the interactive shell has some issues
|
|
||||||
process.exitValue();
|
|
||||||
rootStatus = -1;
|
|
||||||
return null;
|
|
||||||
} catch (IllegalThreadStateException e) {
|
|
||||||
// Process still running, gobble output until done
|
|
||||||
int end = res.size() - 1;
|
|
||||||
if (end > 0) {
|
|
||||||
if (res.get(end).equals("-root-done-")) {
|
|
||||||
res.remove(end);
|
|
||||||
if (res.get(end -1).isEmpty()) {
|
|
||||||
res.remove(end -1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try { STDOUT.join(100); } catch (InterruptedException err) {
|
|
||||||
rootStatus = -1;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (!e.getMessage().contains("EPIPE")) {
|
|
||||||
Logger.dev("Shell: Root shell error...");
|
|
||||||
rootStatus = -1;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
Logger.dev("Shell: Root shell error...");
|
|
||||||
rootStatus = -1;
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
synchronized (rootShell) {
|
||||||
return new ArrayList<>(res);
|
StreamGobbler STDOUT = new StreamGobbler(rootSTDOUT, Collections.synchronizedList(res), true);
|
||||||
}
|
STDOUT.start();
|
||||||
|
try {
|
||||||
public static void su_async(List<String> result, String... commands) {
|
for (String command : commands) {
|
||||||
new RootTask<Void, Void, Void>() {
|
rootSTDIN.write((command + "\n").getBytes("UTF-8"));
|
||||||
@Override
|
rootSTDIN.flush();
|
||||||
protected Void doInRoot(Void... params) {
|
}
|
||||||
List<String> ret = Shell.su(commands);
|
rootSTDIN.write(("echo \'-root-done-\'\n").getBytes("UTF-8"));
|
||||||
if (result != null) result.addAll(ret);
|
rootSTDIN.flush();
|
||||||
return null;
|
STDOUT.join();
|
||||||
|
} catch (InterruptedException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
rootShell.destroy();
|
||||||
}
|
}
|
||||||
}.exec();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -43,10 +45,10 @@ public class StreamGobbler extends Thread {
|
|||||||
try {
|
try {
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (TextUtils.equals(line, "-root-done-"))
|
||||||
|
return;
|
||||||
writer.add(line);
|
writer.add(line);
|
||||||
if (!line.equals("-root-done-") && !line.isEmpty()) {
|
Logger.shell(isRoot, "OUT: " + line);
|
||||||
Logger.shell(isRoot, "OUT: " + line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// reader probably closed, expected exit condition
|
// reader probably closed, expected exit condition
|
||||||
|
@ -43,33 +43,33 @@ public class Utils {
|
|||||||
private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1;
|
private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1;
|
||||||
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
|
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
|
||||||
|
|
||||||
public static boolean itemExist(String path) {
|
public static boolean itemExist(Shell shell, String path) {
|
||||||
String command = "if [ -e " + path + " ]; then echo true; else echo false; fi";
|
String command = "if [ -e " + path + " ]; then echo true; else echo false; fi";
|
||||||
List<String> ret = Shell.su(command);
|
List<String> ret = shell.su(command);
|
||||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createFile(String path) {
|
public static void createFile(Shell shell, String path) {
|
||||||
String folder = path.substring(0, path.lastIndexOf('/'));
|
String folder = path.substring(0, path.lastIndexOf('/'));
|
||||||
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi";
|
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi";
|
||||||
Shell.su_async(null, command);
|
shell.su(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeItem(String path) {
|
public static void removeItem(Shell shell, String path) {
|
||||||
String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi";
|
String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi";
|
||||||
Shell.su_async(null, command);
|
shell.su(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> getModList(String path) {
|
public static List<String> getModList(Shell shell, String path) {
|
||||||
String command = "find " + path + " -type d -maxdepth 1 ! -name \"*.core\" ! -name \"*lost+found\" ! -name \"*magisk\"";
|
String command = "find " + path + " -type d -maxdepth 1 ! -name \"*.core\" ! -name \"*lost+found\" ! -name \"*magisk\"";
|
||||||
return Shell.su(command);
|
return shell.su(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> readFile(String path) {
|
public static List<String> readFile(Shell shell, String path) {
|
||||||
List<String> ret;
|
List<String> ret;
|
||||||
String command = "cat " + path;
|
String command = "cat " + path;
|
||||||
if (Shell.rootAccess()) {
|
if (Shell.rootAccess()) {
|
||||||
ret = Shell.su(command);
|
ret = shell.su(command);
|
||||||
} else {
|
} else {
|
||||||
ret = Shell.sh(command);
|
ret = Shell.sh(command);
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ public class Utils {
|
|||||||
.replace("#", "").replace("@", "").replace("*", "");
|
.replace("#", "").replace("@", "").replace("*", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String detectBootImage() {
|
public static String detectBootImage(Shell shell) {
|
||||||
String[] commands = {
|
String[] commands = {
|
||||||
"for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do",
|
"for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do",
|
||||||
"BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || " +
|
"BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || " +
|
||||||
@ -124,7 +124,7 @@ public class Utils {
|
|||||||
"done",
|
"done",
|
||||||
"echo \"$BOOTIMAGE\""
|
"echo \"$BOOTIMAGE\""
|
||||||
};
|
};
|
||||||
List<String> ret = Shell.su(commands);
|
List<String> ret = shell.su(commands);
|
||||||
if (isValidShellResponse(ret)) {
|
if (isValidShellResponse(ret)) {
|
||||||
return ret.get(0);
|
return ret.get(0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user