mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-01-12 17:23:37 +00:00
Refactor shell (again)
This commit is contained in:
parent
13bf1b27b4
commit
6f457c0c59
@ -48,7 +48,7 @@ public class FlashActivity extends Activity {
|
||||
|
||||
@OnClick(R.id.reboot)
|
||||
public void reboot() {
|
||||
getShell().su_raw("reboot");
|
||||
Shell.su_raw("reboot");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,7 +91,7 @@ public class FlashActivity extends Activity {
|
||||
String boot = intent.getStringExtra(SET_BOOT);
|
||||
if (getMagiskManager().remoteMagiskVersionCode < 1370) {
|
||||
// Use legacy installation method
|
||||
getShell().su_raw(
|
||||
Shell.su_raw(
|
||||
"echo \"BOOTIMAGE=" + boot + "\" > /dev/.magisk",
|
||||
"echo \"KEEPFORCEENCRYPT=" + keepEnc + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPVERITY=" + keepVerity + "\" >> /dev/.magisk"
|
||||
|
@ -254,7 +254,7 @@ public class MagiskFragment extends Fragment
|
||||
magiskStatusIcon.setImageResource(image);
|
||||
magiskStatusIcon.setColorFilter(color);
|
||||
|
||||
switch (Shell.rootStatus) {
|
||||
switch (Shell.status) {
|
||||
case 0:
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
|
@ -117,11 +117,11 @@ public class MagiskLogFragment extends Fragment {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
StringBuildingList logList = new StringBuildingList();
|
||||
getShell().su(logList, "cat " + MAGISK_LOG);
|
||||
Shell.su(logList, "cat " + MAGISK_LOG);
|
||||
return logList.toString();
|
||||
|
||||
case 1:
|
||||
getShell().su_raw("echo -n > " + MAGISK_LOG);
|
||||
Shell.su_raw("echo -n > " + MAGISK_LOG);
|
||||
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
||||
return "";
|
||||
|
||||
@ -142,7 +142,7 @@ public class MagiskLogFragment extends Fragment {
|
||||
|
||||
try (FileWriter out = new FileWriter(targetFile)) {
|
||||
FileWritingList fileWritingList = new FileWritingList(out);
|
||||
getShell().su(fileWritingList, "cat " + MAGISK_LOG);
|
||||
Shell.su(fileWritingList, "cat " + MAGISK_LOG);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
|
@ -208,7 +208,7 @@ public class MagiskManager extends Application {
|
||||
|
||||
// Root actions
|
||||
if (Shell.rootAccess()) {
|
||||
if (hasNetwork && !Utils.itemExist(shell, BUSYBOXPATH + "/busybox")) {
|
||||
if (hasNetwork && !Utils.itemExist(BUSYBOXPATH + "/busybox")) {
|
||||
try {
|
||||
// Force synchronous, make sure we have busybox to use
|
||||
new DownloadBusybox(this).exec().get();
|
||||
@ -223,7 +223,7 @@ public class MagiskManager extends Application {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
shell.su_raw(
|
||||
Shell.su_raw(
|
||||
"export PATH=" + BUSYBOXPATH + ":$PATH",
|
||||
"mount_partitions",
|
||||
"BOOTIMAGE=",
|
||||
@ -231,11 +231,11 @@ public class MagiskManager extends Application {
|
||||
"migrate_boot_backup"
|
||||
);
|
||||
|
||||
List<String> res = shell.su("echo \"$BOOTIMAGE\"");
|
||||
List<String> res = Shell.su("echo \"$BOOTIMAGE\"");
|
||||
if (Utils.isValidShellResponse(res)) {
|
||||
bootBlock = res.get(0);
|
||||
} else {
|
||||
blockList = shell.su("find /dev/block -type b | grep -vE 'dm|ram|loop'");
|
||||
blockList = Shell.su("find /dev/block -type b | grep -vE 'dm|ram|loop'");
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,8 +244,8 @@ public class MagiskManager extends Application {
|
||||
.putBoolean("dark_theme", isDarkTheme)
|
||||
.putBoolean("magiskhide", magiskHide)
|
||||
.putBoolean("notification", updateNotification)
|
||||
.putBoolean("hosts", Utils.itemExist(shell, MAGISK_HOST_FILE))
|
||||
.putBoolean("disable", Utils.itemExist(shell, MAGISK_DISABLE_FILE))
|
||||
.putBoolean("hosts", Utils.itemExist(MAGISK_HOST_FILE))
|
||||
.putBoolean("disable", Utils.itemExist(MAGISK_DISABLE_FILE))
|
||||
.putBoolean("su_reauth", suReauth)
|
||||
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
|
||||
.putString("su_auto_response", String.valueOf(suResponseType))
|
||||
@ -284,15 +284,15 @@ public class MagiskManager extends Application {
|
||||
|
||||
public void getMagiskInfo() {
|
||||
List<String> ret;
|
||||
Shell.getShell(this);
|
||||
ret = shell.sh("su -v");
|
||||
Shell.registerShell(this);
|
||||
ret = Shell.sh("su -v");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suVersion = ret.get(0);
|
||||
isSuClient = suVersion.toUpperCase().contains("MAGISK");
|
||||
}
|
||||
ret = shell.sh("magisk -v");
|
||||
ret = Shell.sh("magisk -v");
|
||||
if (!Utils.isValidShellResponse(ret)) {
|
||||
ret = shell.sh("getprop magisk.version");
|
||||
ret = Shell.sh("getprop magisk.version");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
try {
|
||||
magiskVersionString = ret.get(0);
|
||||
@ -301,21 +301,21 @@ public class MagiskManager extends Application {
|
||||
}
|
||||
} else {
|
||||
magiskVersionString = ret.get(0).split(":")[0];
|
||||
ret = shell.sh("magisk -V");
|
||||
ret = Shell.sh("magisk -V");
|
||||
try {
|
||||
magiskVersionCode = Integer.parseInt(ret.get(0));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
ret = shell.sh("getprop " + DISABLE_INDICATION_PROP);
|
||||
ret = Shell.sh("getprop " + DISABLE_INDICATION_PROP);
|
||||
try {
|
||||
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
disabled = false;
|
||||
}
|
||||
if (magiskVersionCode > 1435) {
|
||||
ret = shell.su("resetprop -p " + MAGISKHIDE_PROP);
|
||||
ret = Shell.su("resetprop -p " + MAGISKHIDE_PROP);
|
||||
} else {
|
||||
ret = shell.sh("getprop " + MAGISKHIDE_PROP);
|
||||
ret = Shell.sh("getprop " + MAGISKHIDE_PROP);
|
||||
}
|
||||
try {
|
||||
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
|
||||
|
@ -195,28 +195,28 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
|
||||
case "disable":
|
||||
enabled = prefs.getBoolean("disable", false);
|
||||
if (enabled) {
|
||||
Utils.createFile(getShell(), MagiskManager.MAGISK_DISABLE_FILE);
|
||||
Utils.createFile(MagiskManager.MAGISK_DISABLE_FILE);
|
||||
} else {
|
||||
Utils.removeItem(getShell(), MagiskManager.MAGISK_DISABLE_FILE);
|
||||
Utils.removeItem(MagiskManager.MAGISK_DISABLE_FILE);
|
||||
}
|
||||
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case "magiskhide":
|
||||
enabled = prefs.getBoolean("magiskhide", false);
|
||||
if (enabled) {
|
||||
Utils.enableMagiskHide(getShell());
|
||||
Utils.enableMagiskHide();
|
||||
} else {
|
||||
Utils.disableMagiskHide(getShell());
|
||||
Utils.disableMagiskHide();
|
||||
}
|
||||
break;
|
||||
case "hosts":
|
||||
enabled = prefs.getBoolean("hosts", false);
|
||||
if (enabled) {
|
||||
getShell().su_raw(
|
||||
Shell.su_raw(
|
||||
"cp -af /system/etc/hosts " + MagiskManager.MAGISK_HOST_FILE,
|
||||
"mount -o bind " + MagiskManager.MAGISK_HOST_FILE + " /system/etc/hosts");
|
||||
} else {
|
||||
getShell().su_raw(
|
||||
Shell.su_raw(
|
||||
"umount -l /system/etc/hosts",
|
||||
"rm -f " + MagiskManager.MAGISK_HOST_FILE);
|
||||
}
|
||||
@ -243,10 +243,6 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
|
||||
setSummary();
|
||||
}
|
||||
|
||||
private Shell getShell() {
|
||||
return Shell.getShell(getActivity());
|
||||
}
|
||||
|
||||
private void setSummary() {
|
||||
updateChannel.setSummary(getResources()
|
||||
.getStringArray(R.array.update_channel)[mm.updateChannel]);
|
||||
|
@ -16,7 +16,6 @@ import android.widget.TextView;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
@ -47,7 +46,6 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
private PackageManager pm;
|
||||
private ApplicationFilter filter;
|
||||
private Topic magiskHideDone;
|
||||
private Shell shell;
|
||||
|
||||
public ApplicationAdapter(Context context) {
|
||||
mOriginalList = mList = Collections.emptyList();
|
||||
@ -55,7 +53,6 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
filter = new ApplicationFilter();
|
||||
pm = context.getPackageManager();
|
||||
magiskHideDone = Utils.getMagiskManager(context).magiskHideDone;
|
||||
shell = Shell.getShell(context);
|
||||
new LoadApps().exec();
|
||||
}
|
||||
|
||||
@ -89,10 +86,10 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
holder.checkBox.setChecked(mHideList.contains(info.packageName));
|
||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if (isChecked) {
|
||||
Utils.addMagiskHide(shell, info.packageName);
|
||||
Utils.addMagiskHide(info.packageName);
|
||||
mHideList.add(info.packageName);
|
||||
} else {
|
||||
Utils.rmMagiskHide(shell, info.packageName);
|
||||
Utils.rmMagiskHide(info.packageName);
|
||||
mHideList.remove(info.packageName);
|
||||
}
|
||||
});
|
||||
@ -163,7 +160,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
}
|
||||
Collections.sort(mOriginalList, (a, b) -> a.loadLabel(pm).toString().toLowerCase()
|
||||
.compareTo(b.loadLabel(pm).toString().toLowerCase()));
|
||||
mHideList = Utils.listMagiskHide(shell);
|
||||
mHideList = Utils.listMagiskHide();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,6 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||
Context context = holder.itemView.getContext();
|
||||
Shell rootShell = Shell.getShell(context);
|
||||
final Module module = mList.get(position);
|
||||
|
||||
String version = module.getVersion();
|
||||
@ -56,10 +55,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
int snack;
|
||||
if (isChecked) {
|
||||
module.removeDisableFile(rootShell);
|
||||
module.removeDisableFile();
|
||||
snack = R.string.disable_file_removed;
|
||||
} else {
|
||||
module.createDisableFile(rootShell);
|
||||
module.createDisableFile();
|
||||
snack = R.string.disable_file_created;
|
||||
}
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
@ -69,10 +68,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
boolean removed = module.willBeRemoved();
|
||||
int snack;
|
||||
if (removed) {
|
||||
module.deleteRemoveFile(rootShell);
|
||||
module.deleteRemoveFile();
|
||||
snack = R.string.remove_file_deleted;
|
||||
} else {
|
||||
module.createRemoveFile(rootShell);
|
||||
module.createRemoveFile();
|
||||
snack = R.string.remove_file_created;
|
||||
}
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
|
@ -4,6 +4,7 @@ import android.support.v4.app.FragmentActivity;
|
||||
|
||||
import com.topjohnwu.jarsigner.ByteArrayStream;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
@ -34,7 +35,7 @@ public class CheckSafetyNet extends ParallelTask<Void, Void, Exception> {
|
||||
protected void onPreExecute() {
|
||||
MagiskManager mm = getMagiskManager();
|
||||
if (mm.snet_version != CheckSafetyNet.SNET_VER) {
|
||||
getShell().sh("rm -rf " + dexPath.getParent());
|
||||
Shell.sh("rm -rf " + dexPath.getParent());
|
||||
}
|
||||
mm.snet_version = CheckSafetyNet.SNET_VER;
|
||||
mm.prefs.edit().putInt("snet_version", CheckSafetyNet.SNET_VER).apply();
|
||||
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
@ -28,7 +29,7 @@ public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
Context context = getMagiskManager();
|
||||
Utils.removeItem(getShell(), context.getApplicationInfo().dataDir + "/busybox");
|
||||
Utils.removeItem(context.getApplicationInfo().dataDir + "/busybox");
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(busybox);
|
||||
HttpURLConnection conn = WebService.request(
|
||||
@ -50,7 +51,7 @@ public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (busybox.exists()) {
|
||||
getShell().su(
|
||||
Shell.su(
|
||||
"rm -rf " + MagiskManager.BUSYBOXPATH,
|
||||
"mkdir -p " + MagiskManager.BUSYBOXPATH,
|
||||
"cp " + busybox + " " + MagiskManager.BUSYBOXPATH,
|
||||
|
@ -7,6 +7,7 @@ import android.text.TextUtils;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.container.AdaptiveList;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||
|
||||
@ -35,7 +36,7 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
|
||||
|
||||
private boolean unzipAndCheck() throws Exception {
|
||||
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", true);
|
||||
List<String> ret = Utils.readFile(getShell(), new File(mCachedFile.getParentFile(), "updater-script").getPath());
|
||||
List<String> ret = Utils.readFile(new File(mCachedFile.getParentFile(), "updater-script").getPath());
|
||||
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
||||
}
|
||||
|
||||
@ -77,7 +78,7 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
|
||||
}
|
||||
if (!unzipAndCheck()) return 0;
|
||||
mList.add("- Installing " + Utils.getNameFromUri(mm, mUri));
|
||||
getShell().su(mList,
|
||||
Shell.su(mList,
|
||||
"cd " + mCachedFile.getParent(),
|
||||
"BOOTMODE=true sh update-binary dummy 1 " + mCachedFile +
|
||||
" && echo 'Success!' || echo 'Failed!'"
|
||||
@ -95,7 +96,7 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
|
||||
protected void onPostExecute(Integer result) {
|
||||
MagiskManager mm = getMagiskManager();
|
||||
if (mm == null) return;
|
||||
getShell().su_raw(
|
||||
Shell.su_raw(
|
||||
"rm -rf " + mCachedFile.getParent(),
|
||||
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
|
||||
);
|
||||
|
@ -9,6 +9,7 @@ import com.topjohnwu.jarsigner.JarMap;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.container.Policy;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||
|
||||
@ -78,7 +79,7 @@ public class HideManager extends ParallelTask<Void, Void, Boolean> {
|
||||
}
|
||||
|
||||
// Install the application
|
||||
List<String> ret = getShell().su("pm install " + unhideAPK + ">/dev/null && echo true || echo false");
|
||||
List<String> ret = Shell.su("pm install " + unhideAPK + ">/dev/null && echo true || echo false");
|
||||
unhideAPK.delete();
|
||||
if (!Utils.isValidShellResponse(ret) || !Boolean.parseBoolean(ret.get(0)))
|
||||
return false;
|
||||
@ -98,7 +99,7 @@ public class HideManager extends ParallelTask<Void, Void, Boolean> {
|
||||
}
|
||||
|
||||
// Hide myself!
|
||||
getShell().su_raw("pm hide " + mm.getPackageName());
|
||||
Shell.su_raw("pm hide " + mm.getPackageName());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||
if (mm == null) return false;
|
||||
|
||||
File install = new File(Utils.getEncContext(mm).getFilesDir().getParent(), "install");
|
||||
getShell().sh_raw("rm -rf " + install);
|
||||
Shell.sh_raw("rm -rf " + install);
|
||||
|
||||
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
|
||||
String arch;
|
||||
@ -157,13 +157,16 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||
Shell shell;
|
||||
if (mode == PATCH_MODE && Shell.rootAccess()) {
|
||||
// Force non-root shell
|
||||
shell = Shell.getShell("sh");
|
||||
shell = new Shell("sh");
|
||||
} else {
|
||||
shell = getShell();
|
||||
shell = Shell.getShell();
|
||||
}
|
||||
|
||||
if (shell == null)
|
||||
return false;
|
||||
|
||||
// Patch boot image
|
||||
shell.sh(mList,
|
||||
shell.run(mList,
|
||||
"cd " + install,
|
||||
"KEEPFORCEENCRYPT=" + mKeepEnc + " KEEPVERITY=" + mKeepVerity + " sh " +
|
||||
"update-binary indep boot_patch.sh " + boot +
|
||||
@ -181,7 +184,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||
dest.getParentFile().mkdirs();
|
||||
switch (mm.bootFormat) {
|
||||
case ".img":
|
||||
getShell().sh_raw("cp -f " + patched_boot + " " + dest);
|
||||
shell.run_raw(false, "cp -f " + patched_boot + " " + dest);
|
||||
break;
|
||||
case ".img.tar":
|
||||
TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
|
||||
@ -204,14 +207,14 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||
break;
|
||||
case DIRECT_MODE:
|
||||
// Direct flash boot image
|
||||
getShell().su(mList, "flash_boot_image " + patched_boot + " " + mBootLocation);
|
||||
Shell.su(mList, "flash_boot_image " + patched_boot + " " + mBootLocation);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finals
|
||||
getShell().sh_raw(
|
||||
shell.run_raw(false,
|
||||
"cd " + install,
|
||||
"mv bin/busybox busybox",
|
||||
"rm -rf bin *.img update-binary",
|
||||
|
@ -19,8 +19,8 @@ public class LoadModules extends ParallelTask<Void, Void, Void> {
|
||||
if (mm == null) return null;
|
||||
mm.moduleMap = new ValueSortedMap<>();
|
||||
|
||||
for (String path : Utils.getModList(getShell(), MagiskManager.MAGISK_PATH)) {
|
||||
Module module = new Module(getShell(), path);
|
||||
for (String path : Utils.getModList(MagiskManager.MAGISK_PATH)) {
|
||||
Module module = new Module(path);
|
||||
mm.moduleMap.put(module.getId(), module);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@ -36,11 +35,6 @@ public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<P
|
||||
return weakMagiskManager.get();
|
||||
}
|
||||
|
||||
protected Shell getShell() {
|
||||
MagiskManager magiskManager = getMagiskManager();
|
||||
return magiskManager == null ? null : Shell.getShell(magiskManager);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public ParallelTask<Params, Progress, Result> exec(Params... params) {
|
||||
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
|
||||
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.util.List;
|
||||
@ -19,13 +20,13 @@ public class RestoreStockBoot extends ParallelTask<Void, Void, Boolean> {
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
List<String> ret = getShell().su("cat /init.magisk.rc | grep STOCKSHA1");
|
||||
List<String> ret = Shell.su("cat /init.magisk.rc | grep STOCKSHA1");
|
||||
if (!Utils.isValidShellResponse(ret))
|
||||
return false;
|
||||
String stock_boot = "/data/stock_boot_" + ret.get(0).substring(ret.get(0).indexOf('=') + 1) + ".img.gz";
|
||||
if (!Utils.itemExist(getShell(), stock_boot))
|
||||
if (!Utils.itemExist(stock_boot))
|
||||
return false;
|
||||
getShell().su_raw("flash_boot_image " + stock_boot + " " + mBoot);
|
||||
Shell.su_raw("flash_boot_image " + stock_boot + " " + mBoot);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@ import android.view.WindowManager;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
|
||||
public class Activity extends AppCompatActivity {
|
||||
@ -58,10 +57,6 @@ public class Activity extends AppCompatActivity {
|
||||
return (MagiskManager) super.getApplicationContext();
|
||||
}
|
||||
|
||||
public Shell getShell() {
|
||||
return Shell.getShell(this);
|
||||
}
|
||||
|
||||
protected void setFloating() {
|
||||
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
|
||||
if (isTablet) {
|
||||
|
@ -3,7 +3,6 @@ package com.topjohnwu.magisk.components;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
@ -15,10 +14,6 @@ public class Fragment extends android.support.v4.app.Fragment {
|
||||
return Utils.getMagiskManager(getActivity());
|
||||
}
|
||||
|
||||
public Shell getShell() {
|
||||
return Shell.getShell(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.topjohnwu.magisk.container;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class Module extends BaseModule {
|
||||
@ -8,10 +7,10 @@ public class Module extends BaseModule {
|
||||
private String mRemoveFile, mDisableFile, mUpdateFile;
|
||||
private boolean mEnable, mRemove, mUpdated;
|
||||
|
||||
public Module(Shell shell, String path) {
|
||||
public Module(String path) {
|
||||
|
||||
try {
|
||||
parseProps(Utils.readFile(shell, path + "/module.prop"));
|
||||
parseProps(Utils.readFile(path + "/module.prop"));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
|
||||
mRemoveFile = path + "/remove";
|
||||
@ -27,33 +26,33 @@ public class Module extends BaseModule {
|
||||
setName(getId());
|
||||
}
|
||||
|
||||
mEnable = !Utils.itemExist(shell, mDisableFile);
|
||||
mRemove = Utils.itemExist(shell, mRemoveFile);
|
||||
mUpdated = Utils.itemExist(shell, mUpdateFile);
|
||||
mEnable = !Utils.itemExist(mDisableFile);
|
||||
mRemove = Utils.itemExist(mRemoveFile);
|
||||
mUpdated = Utils.itemExist(mUpdateFile);
|
||||
}
|
||||
|
||||
public void createDisableFile(Shell shell) {
|
||||
public void createDisableFile() {
|
||||
mEnable = false;
|
||||
Utils.createFile(shell, mDisableFile);
|
||||
Utils.createFile(mDisableFile);
|
||||
}
|
||||
|
||||
public void removeDisableFile(Shell shell) {
|
||||
public void removeDisableFile() {
|
||||
mEnable = true;
|
||||
Utils.removeItem(shell, mDisableFile);
|
||||
Utils.removeItem(mDisableFile);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mEnable;
|
||||
}
|
||||
|
||||
public void createRemoveFile(Shell shell) {
|
||||
public void createRemoveFile() {
|
||||
mRemove = true;
|
||||
Utils.createFile(shell, mRemoveFile);
|
||||
Utils.createFile(mRemoveFile);
|
||||
}
|
||||
|
||||
public void deleteRemoveFile(Shell shell) {
|
||||
public void deleteRemoveFile() {
|
||||
mRemove = false;
|
||||
Utils.removeItem(shell, mRemoveFile);
|
||||
Utils.removeItem(mRemoveFile);
|
||||
}
|
||||
|
||||
public boolean willBeRemoved() {
|
||||
|
@ -6,11 +6,11 @@ import android.text.TextUtils;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -21,116 +21,103 @@ import java.util.List;
|
||||
|
||||
public class Shell {
|
||||
|
||||
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
|
||||
public static int rootStatus;
|
||||
private static WeakReference<MagiskManager> weakMm;
|
||||
|
||||
private final Process shellProcess;
|
||||
private final DataOutputStream STDIN;
|
||||
private final DataInputStream STDOUT;
|
||||
// -1 = no shell; 0 = non root shell; 1 = root shell
|
||||
public static int status;
|
||||
|
||||
private boolean isValid;
|
||||
private final Process process;
|
||||
private final OutputStream STDIN;
|
||||
private final InputStream STDOUT;
|
||||
|
||||
private void testRootShell(DataOutputStream in, DataInputStream out) throws IOException {
|
||||
in.write(("id\n").getBytes("UTF-8"));
|
||||
in.flush();
|
||||
String s = new BufferedReader(new InputStreamReader(out)).readLine();
|
||||
private static void testRootShell(Shell shell) throws IOException {
|
||||
shell.STDIN.write(("id\n").getBytes("UTF-8"));
|
||||
shell.STDIN.flush();
|
||||
String s = new BufferedReader(new InputStreamReader(shell.STDOUT)).readLine();
|
||||
if (TextUtils.isEmpty(s) || !s.contains("uid=0")) {
|
||||
in.close();
|
||||
out.close();
|
||||
shell.STDIN.close();
|
||||
shell.STDIN.close();
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
private Shell() {
|
||||
rootStatus = 1;
|
||||
Process process = null;
|
||||
DataOutputStream in = null;
|
||||
DataInputStream out = null;
|
||||
|
||||
try {
|
||||
// Try getting global namespace
|
||||
process = Runtime.getRuntime().exec("su --mount-master");
|
||||
in = new DataOutputStream(process.getOutputStream());
|
||||
out = new DataInputStream(process.getInputStream());
|
||||
testRootShell(in, out);
|
||||
} catch (IOException e) {
|
||||
// Feature not implemented, normal root shell
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("su");
|
||||
in = new DataOutputStream(process.getOutputStream());
|
||||
out = new DataInputStream(process.getInputStream());
|
||||
testRootShell(in, out);
|
||||
} catch (IOException e1) {
|
||||
rootStatus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rootAccess()) {
|
||||
// Try to gain non-root sh
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("sh");
|
||||
in = new DataOutputStream(process.getOutputStream());
|
||||
out = new DataInputStream(process.getInputStream());
|
||||
} catch (IOException e) {
|
||||
// Nothing works....
|
||||
shellProcess = null;
|
||||
STDIN = null;
|
||||
STDOUT = null;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
shellProcess = process;
|
||||
STDIN = in;
|
||||
STDOUT = out;
|
||||
sh_raw("umask 022");
|
||||
public Shell(String command) throws IOException {
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
STDIN = process.getOutputStream();
|
||||
STDOUT = process.getInputStream();
|
||||
}
|
||||
|
||||
private Shell(String command) {
|
||||
Process process;
|
||||
DataOutputStream in;
|
||||
DataInputStream out;
|
||||
|
||||
try {
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
in = new DataOutputStream(process.getOutputStream());
|
||||
out = new DataInputStream(process.getInputStream());
|
||||
} catch (IOException e) {
|
||||
// Nothing works....
|
||||
shellProcess = null;
|
||||
STDIN = null;
|
||||
STDOUT = null;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
shellProcess = process;
|
||||
STDIN = in;
|
||||
STDOUT = out;
|
||||
public static void registerShell(Context context) {
|
||||
weakMm = new WeakReference<>(Utils.getMagiskManager(context));
|
||||
}
|
||||
|
||||
public static Shell getShell() {
|
||||
return new Shell();
|
||||
}
|
||||
MagiskManager mm = weakMm.get();
|
||||
boolean needNewShell = mm.shell == null;
|
||||
|
||||
public static Shell getShell(String command) {
|
||||
return new Shell(command);
|
||||
}
|
||||
|
||||
public static Shell getShell(Context context) {
|
||||
MagiskManager magiskManager = Utils.getMagiskManager(context);
|
||||
if (magiskManager.shell == null || !magiskManager.shell.isValid) {
|
||||
// Get new shell if needed
|
||||
magiskManager.shell = getShell();
|
||||
if (!needNewShell) {
|
||||
try {
|
||||
mm.shell.process.exitValue();
|
||||
// The process is dead
|
||||
needNewShell = true;
|
||||
} catch (IllegalThreadStateException ignored) {
|
||||
// This should be the expected result
|
||||
}
|
||||
}
|
||||
return magiskManager.shell;
|
||||
|
||||
if (needNewShell) {
|
||||
status = 1;
|
||||
try {
|
||||
mm.shell = new Shell("su --mount-master");
|
||||
testRootShell(mm.shell);
|
||||
} catch (IOException e) {
|
||||
// Mount master not implemented
|
||||
try {
|
||||
mm.shell = new Shell("su");
|
||||
testRootShell(mm.shell);
|
||||
} catch (IOException e1) {
|
||||
// No root exists
|
||||
status = 0;
|
||||
try {
|
||||
mm.shell = new Shell("sh");
|
||||
} catch (IOException e2) {
|
||||
status = -1;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mm.shell;
|
||||
}
|
||||
|
||||
public static boolean rootAccess() {
|
||||
return rootStatus > 0;
|
||||
return status > 0;
|
||||
}
|
||||
|
||||
public void run(Collection<String> output, String... commands) {
|
||||
synchronized (process) {
|
||||
StreamGobbler out = new StreamGobbler(STDOUT, output);
|
||||
out.start();
|
||||
run_raw(true, commands);
|
||||
run_raw(true, "echo \'-shell-done-\'");
|
||||
try { out.join(); } catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public void run_raw(boolean stdout, String... commands) {
|
||||
synchronized (process) {
|
||||
try {
|
||||
for (String command : commands) {
|
||||
Logger.shell(command);
|
||||
STDIN.write((command + (stdout ? "\n" : " >/dev/null\n")).getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadInputStream(InputStream in) {
|
||||
@ -146,67 +133,41 @@ public class Shell {
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> sh(String... commands) {
|
||||
public static List<String> sh(String... commands) {
|
||||
List<String> res = new ArrayList<>();
|
||||
if (!isValid) return res;
|
||||
sh(res, commands);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void sh_raw(String... commands) {
|
||||
sh_raw(false, commands);
|
||||
public static void sh(Collection<String> output, String... commands) {
|
||||
Shell shell = getShell();
|
||||
if (shell == null)
|
||||
return;
|
||||
shell.run(output, commands);
|
||||
}
|
||||
|
||||
public void sh_raw(boolean stdout, String... commands) {
|
||||
if (!isValid) return;
|
||||
synchronized (shellProcess) {
|
||||
try {
|
||||
for (String command : commands) {
|
||||
Logger.shell(command);
|
||||
STDIN.write((command + (stdout ? "\n" : " >/dev/null\n")).getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
shellProcess.destroy();
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
public static void sh_raw(String... commands) {
|
||||
Shell shell = getShell();
|
||||
if (shell == null)
|
||||
return;
|
||||
shell.run_raw(false, commands);
|
||||
}
|
||||
|
||||
public void sh(Collection<String> output, String... commands) {
|
||||
if (!isValid) return;
|
||||
try {
|
||||
shellProcess.exitValue();
|
||||
isValid = false;
|
||||
return; // The process is dead, return
|
||||
} catch (IllegalThreadStateException ignored) {
|
||||
// This should be the expected result
|
||||
}
|
||||
synchronized (shellProcess) {
|
||||
StreamGobbler out = new StreamGobbler(STDOUT, output);
|
||||
out.start();
|
||||
sh_raw(true, commands);
|
||||
sh_raw(true, "echo \'-shell-done-\'");
|
||||
try { out.join(); } catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> su(String... commands) {
|
||||
public static List<String> su(String... commands) {
|
||||
if (!rootAccess()) return sh();
|
||||
return sh(commands);
|
||||
}
|
||||
|
||||
public void su_raw(String... commands) {
|
||||
if (!rootAccess()) return;
|
||||
sh_raw(commands);
|
||||
}
|
||||
|
||||
public void su(Collection<String> output, String... commands) {
|
||||
public static void su(Collection<String> output, String... commands) {
|
||||
if (!rootAccess()) return;
|
||||
sh(output, commands);
|
||||
}
|
||||
|
||||
public static void su_raw(String... commands) {
|
||||
if (!rootAccess()) return;
|
||||
sh_raw(commands);
|
||||
}
|
||||
|
||||
public static abstract class AbstractList<E> extends java.util.AbstractList<E> {
|
||||
|
||||
@Override
|
||||
|
@ -62,31 +62,31 @@ public class Utils {
|
||||
private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1;
|
||||
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
|
||||
|
||||
public static boolean itemExist(Shell shell, String path) {
|
||||
public static boolean itemExist(String path) {
|
||||
String command = "[ -e " + path + " ] && echo true || echo false";
|
||||
List<String> ret = shell.su(command);
|
||||
List<String> ret = Shell.su(command);
|
||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||
}
|
||||
|
||||
public static void createFile(Shell shell, String path) {
|
||||
public static void createFile(String path) {
|
||||
String folder = path.substring(0, path.lastIndexOf('/'));
|
||||
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null;";
|
||||
shell.su_raw(command);
|
||||
Shell.su_raw(command);
|
||||
}
|
||||
|
||||
public static void removeItem(Shell shell, String path) {
|
||||
public static void removeItem(String path) {
|
||||
String command = "rm -rf " + path + " 2>/dev/null";
|
||||
shell.su_raw(command);
|
||||
Shell.su_raw(command);
|
||||
}
|
||||
|
||||
public static List<String> getModList(Shell shell, String path) {
|
||||
public static List<String> getModList(String path) {
|
||||
String command = "ls -d " + path + "/* | grep -v lost+found";
|
||||
return shell.su(command);
|
||||
return Shell.su(command);
|
||||
}
|
||||
|
||||
public static List<String> readFile(Shell shell, String path) {
|
||||
public static List<String> readFile(String path) {
|
||||
String command = "cat " + path + " | sed '$a\\ ' | sed '$d'";
|
||||
return shell.su(command);
|
||||
return Shell.su(command);
|
||||
}
|
||||
|
||||
public static void dlAndReceive(Context context, DownloadReceiver receiver, String link, String filename) {
|
||||
@ -225,24 +225,24 @@ public class Utils {
|
||||
notificationManager.notify(APK_UPDATE_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
public static void enableMagiskHide(Shell shell) {
|
||||
shell.su_raw("magiskhide --enable");
|
||||
public static void enableMagiskHide() {
|
||||
Shell.su_raw("magiskhide --enable");
|
||||
}
|
||||
|
||||
public static void disableMagiskHide(Shell shell) {
|
||||
shell.su_raw("magiskhide --disable");
|
||||
public static void disableMagiskHide() {
|
||||
Shell.su_raw("magiskhide --disable");
|
||||
}
|
||||
|
||||
public static List<String> listMagiskHide(Shell shell) {
|
||||
return shell.su("magiskhide --ls");
|
||||
public static List<String> listMagiskHide() {
|
||||
return Shell.su("magiskhide --ls");
|
||||
}
|
||||
|
||||
public static void addMagiskHide(Shell shell, String pkg) {
|
||||
shell.su_raw("magiskhide --add " + pkg);
|
||||
public static void addMagiskHide(String pkg) {
|
||||
Shell.su_raw("magiskhide --add " + pkg);
|
||||
}
|
||||
|
||||
public static void rmMagiskHide(Shell shell, String pkg) {
|
||||
shell.su_raw("magiskhide --rm " + pkg);
|
||||
public static void rmMagiskHide(String pkg) {
|
||||
Shell.su_raw("magiskhide --rm " + pkg);
|
||||
}
|
||||
|
||||
public static String getLocaleString(Context context, Locale locale, @StringRes int id) {
|
||||
@ -331,7 +331,7 @@ public class Utils {
|
||||
if (Shell.rootAccess()) {
|
||||
options.add(mm.getString(R.string.direct_install));
|
||||
}
|
||||
List<String> res = Shell.getShell(mm).su("echo $SLOT");
|
||||
List<String> res = Shell.su("echo $SLOT");
|
||||
if (isValidShellResponse(res)) {
|
||||
options.add(mm.getString(R.string.install_second_slot));
|
||||
}
|
||||
@ -409,14 +409,14 @@ public class Utils {
|
||||
if (slot[1] == 'a') slot[1] = 'b';
|
||||
else slot[1] = 'a';
|
||||
// Then find the boot image again
|
||||
List<String> ret = Shell.getShell(mm).su(
|
||||
List<String> ret = Shell.su(
|
||||
"BOOTIMAGE=",
|
||||
"SLOT=" + String.valueOf(slot),
|
||||
"find_boot_image",
|
||||
"echo \"$BOOTIMAGE\""
|
||||
);
|
||||
boot = isValidShellResponse(ret) ? ret.get(ret.size() - 1) : null;
|
||||
Shell.getShell(mm).su_raw("mount_partitions");
|
||||
Shell.su_raw("mount_partitions");
|
||||
if (boot == null)
|
||||
return;
|
||||
receiver = new DownloadReceiver() {
|
||||
@ -497,12 +497,12 @@ public class Utils {
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
Shell.getShell(mm).su(
|
||||
Shell.su(
|
||||
"cat " + uninstaller + " > /cache/" + UNINSTALLER,
|
||||
"cat " + utils + " > /data/magisk/" + UTIL_FUNCTIONS
|
||||
);
|
||||
mm.toast(R.string.uninstall_toast, Toast.LENGTH_LONG);
|
||||
Shell.getShell(mm).su_raw(
|
||||
Shell.su_raw(
|
||||
"sleep 5",
|
||||
"pm uninstall " + mm.getApplicationInfo().packageName
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user