diff --git a/app/src/main/java/com/topjohnwu/magisk/FlashActivity.java b/app/src/main/java/com/topjohnwu/magisk/FlashActivity.java index 589e8abef..27c24f986 100644 --- a/app/src/main/java/com/topjohnwu/magisk/FlashActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/FlashActivity.java @@ -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" diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java index b70289c9c..a03c99240 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java @@ -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; diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java index 436cf0cc4..6612cc34a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskLogFragment.java @@ -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; diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java b/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java index 0831f7765..670cada36 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskManager.java @@ -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 res = shell.su("echo \"$BOOTIMAGE\""); + List 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 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; diff --git a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java index ca29a80a7..7121032e7 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SettingsActivity.java @@ -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]); diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java index 6ea4ec9e9..f72257394 100644 --- a/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/ApplicationAdapter.java @@ -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 { 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 a.loadLabel(pm).toString().toLowerCase() .compareTo(b.loadLabel(pm).toString().toLowerCase())); - mHideList = Utils.listMagiskHide(shell); + mHideList = Utils.listMagiskHide(); return null; } diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/ModulesAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/ModulesAdapter.java index 5029664fc..ac4a605fc 100644 --- a/app/src/main/java/com/topjohnwu/magisk/adapters/ModulesAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/ModulesAdapter.java @@ -38,7 +38,6 @@ public class ModulesAdapter extends RecyclerView.Adapter { 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 { 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(); diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java index 5856a1d63..a8e041b22 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/DownloadBusybox.java @@ -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 { @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 { e.printStackTrace(); } if (busybox.exists()) { - getShell().su( + Shell.su( "rm -rf " + MagiskManager.BUSYBOXPATH, "mkdir -p " + MagiskManager.BUSYBOXPATH, "cp " + busybox + " " + MagiskManager.BUSYBOXPATH, diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java index b21becd69..31ce9570a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/FlashZip.java @@ -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 { private boolean unzipAndCheck() throws Exception { ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", true); - List ret = Utils.readFile(getShell(), new File(mCachedFile.getParentFile(), "updater-script").getPath()); + List 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 { } 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 { 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 ); diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java index 7957a7d37..db02ae15f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/HideManager.java @@ -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 { } // Install the application - List ret = getShell().su("pm install " + unhideAPK + ">/dev/null && echo true || echo false"); + List 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 { } // Hide myself! - getShell().su_raw("pm hide " + mm.getPackageName()); + Shell.su_raw("pm hide " + mm.getPackageName()); return true; } diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java index ce3d81bef..94e1604ef 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java @@ -76,7 +76,7 @@ public class InstallMagisk extends ParallelTask { 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 abis = Arrays.asList(Build.SUPPORTED_ABIS); String arch; @@ -157,13 +157,16 @@ public class InstallMagisk extends ParallelTask { 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 { 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 { 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", diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/LoadModules.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/LoadModules.java index 1815ef0eb..c59772702 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/LoadModules.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/LoadModules.java @@ -19,8 +19,8 @@ public class LoadModules extends ParallelTask { 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); } diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/ParallelTask.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/ParallelTask.java index bef4375ae..723d89b1d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/ParallelTask.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/ParallelTask.java @@ -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 extends AsyncTask

exec(Params... params) { executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java index 267157680..c67f4c75e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java @@ -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 { @Override protected Boolean doInBackground(Void... voids) { - List ret = getShell().su("cat /init.magisk.rc | grep STOCKSHA1"); + List 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; } diff --git a/app/src/main/java/com/topjohnwu/magisk/components/Activity.java b/app/src/main/java/com/topjohnwu/magisk/components/Activity.java index fd348dfd8..31b8d12f7 100644 --- a/app/src/main/java/com/topjohnwu/magisk/components/Activity.java +++ b/app/src/main/java/com/topjohnwu/magisk/components/Activity.java @@ -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) { diff --git a/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java b/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java index 7c2ef198d..5fc9d3861 100644 --- a/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java @@ -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(); diff --git a/app/src/main/java/com/topjohnwu/magisk/container/Module.java b/app/src/main/java/com/topjohnwu/magisk/container/Module.java index b171964cb..c364f8461 100644 --- a/app/src/main/java/com/topjohnwu/magisk/container/Module.java +++ b/app/src/main/java/com/topjohnwu/magisk/container/Module.java @@ -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() { diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java b/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java index e8afee71e..366a8620c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Shell.java @@ -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 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 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 sh(String... commands) { + public static List sh(String... commands) { List 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 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 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 su(String... commands) { + public static List 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 output, String... commands) { + public static void su(Collection 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 extends java.util.AbstractList { @Override diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index b049f988b..b63e7b54a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -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 ret = shell.su(command); + List 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 getModList(Shell shell, String path) { + public static List getModList(String path) { String command = "ls -d " + path + "/* | grep -v lost+found"; - return shell.su(command); + return Shell.su(command); } - public static List readFile(Shell shell, String path) { + public static List 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 listMagiskHide(Shell shell) { - return shell.su("magiskhide --ls"); + public static List 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 res = Shell.getShell(mm).su("echo $SLOT"); + List 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 ret = Shell.getShell(mm).su( + List 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 );