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