mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-24 10:35:26 +00:00
Merge shells
This commit is contained in:
parent
2ea046cd80
commit
6933bcf7bb
@ -35,7 +35,7 @@ public class FlashActivity extends Activity {
|
||||
|
||||
@OnClick(R.id.reboot)
|
||||
public void reboot() {
|
||||
Shell.getRootShell(this).su_raw("reboot");
|
||||
Shell.getShell(this).su_raw("reboot");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,7 +26,6 @@ import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
@ -105,25 +104,18 @@ public class MagiskFragment extends Fragment
|
||||
collapse();
|
||||
}
|
||||
|
||||
@OnClick(R.id.detect_bootimage)
|
||||
public void toAutoDetect() {
|
||||
if (magiskManager.bootBlock != null) {
|
||||
spinner.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.install_button)
|
||||
public void install() {
|
||||
String bootImage = null;
|
||||
if (magiskManager.blockList != null) {
|
||||
int idx = spinner.getSelectedItemPosition();
|
||||
if (Shell.rootAccess()) {
|
||||
if (magiskManager.bootBlock != null) {
|
||||
bootImage = magiskManager.bootBlock;
|
||||
} else {
|
||||
int idx = spinner.getSelectedItemPosition();
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
} else {
|
||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG);
|
||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -135,27 +127,32 @@ public class MagiskFragment extends Fragment
|
||||
.setMessage(getString(R.string.repo_install_msg, filename))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(Shell.rootAccess() ? R.string.install : R.string.download,
|
||||
(dialogInterface, i) -> Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = finalBootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
(d, i) ->
|
||||
Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = finalBootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri, Context context) {
|
||||
if (Shell.rootAccess()) {
|
||||
new SetInstallFlags(boot, enc, verity)
|
||||
.setCallBack(() -> startActivity(new Intent(context, FlashActivity.class).setData(uri)))
|
||||
.exec(context);
|
||||
} else {
|
||||
Utils.showUriSnack(getActivity(), uri);
|
||||
}
|
||||
}
|
||||
},
|
||||
magiskManager.magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri, Context context) {
|
||||
if (Shell.rootAccess()) {
|
||||
magiskManager.shell.su_raw(
|
||||
"rm -f /dev/.magisk",
|
||||
"echo \"BOOTIMAGE=" + boot + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk"
|
||||
);
|
||||
startActivity(new Intent(context, FlashActivity.class).setData(uri));
|
||||
} else {
|
||||
Utils.showUriSnack(getActivity(), uri);
|
||||
}
|
||||
}
|
||||
},
|
||||
magiskManager.magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (d, i) -> {
|
||||
if (magiskManager.releaseNoteLink != null) {
|
||||
Intent openReleaseNoteLink = new Intent(Intent.ACTION_VIEW, Uri.parse(magiskManager.releaseNoteLink));
|
||||
openReleaseNoteLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@ -166,28 +163,6 @@ public class MagiskFragment extends Fragment
|
||||
.show();
|
||||
}
|
||||
|
||||
private static class SetInstallFlags extends ParallelTask<Context, Void, Void> {
|
||||
|
||||
private String boot;
|
||||
private boolean enc, verity;
|
||||
|
||||
SetInstallFlags(String boot, boolean enc, boolean verity) {
|
||||
this.boot = boot;
|
||||
this.enc = enc;
|
||||
this.verity = verity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Context... contexts) {
|
||||
Shell.getRootShell(contexts[0]).su_raw("rm -f /dev/.magisk",
|
||||
(boot != null) ? "echo \"BOOTIMAGE=" + boot + "\" >> /dev/.magisk" : "",
|
||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.uninstall_button)
|
||||
public void uninstall() {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
@ -225,7 +200,7 @@ public class MagiskFragment extends Fragment
|
||||
@Override
|
||||
public void onFinish() {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||
magiskManager.rootShell.su_raw(
|
||||
magiskManager.shell.su_raw(
|
||||
"mv -f " + uninstaller + " /cache/" + MagiskManager.UNINSTALLER,
|
||||
"mv -f " + utils + " /data/magisk/" + MagiskManager.UTIL_FUNCTIONS,
|
||||
"reboot"
|
||||
@ -314,8 +289,6 @@ public class MagiskFragment extends Fragment
|
||||
updateCheckUI();
|
||||
} else if (event == magiskManager.safetyNetDone) {
|
||||
updateSafetyNetUI();
|
||||
} else if (event == magiskManager.blockDetectionDone) {
|
||||
updateInstallUI();
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,11 +300,8 @@ public class MagiskFragment extends Fragment
|
||||
updateCheckUI();
|
||||
if (magiskManager.safetyNetDone.isTriggered)
|
||||
updateSafetyNetUI();
|
||||
if (magiskManager.blockDetectionDone.isTriggered || !Shell.rootAccess())
|
||||
updateInstallUI();
|
||||
magiskManager.updateCheckDone.register(this);
|
||||
magiskManager.safetyNetDone.register(this);
|
||||
magiskManager.blockDetectionDone.register(this);
|
||||
getActivity().setTitle(R.string.magisk);
|
||||
}
|
||||
|
||||
@ -339,7 +309,6 @@ public class MagiskFragment extends Fragment
|
||||
public void onStop() {
|
||||
magiskManager.updateCheckDone.unRegister(this);
|
||||
magiskManager.safetyNetDone.unRegister(this);
|
||||
magiskManager.blockDetectionDone.unRegister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@ -351,6 +320,8 @@ public class MagiskFragment extends Fragment
|
||||
|
||||
private void updateUI() {
|
||||
((MainActivity) getActivity()).checkHideSection();
|
||||
magiskManager.updateMagiskInfo();
|
||||
|
||||
final int ROOT = 0x1, NETWORK = 0x2, UPTODATE = 0x4;
|
||||
int status = 0;
|
||||
status |= Shell.rootAccess() ? ROOT : 0;
|
||||
@ -362,14 +333,9 @@ public class MagiskFragment extends Fragment
|
||||
installOptionCard.setVisibility(Utils.checkBits(status, NETWORK, ROOT) ? View.VISIBLE : View.GONE);
|
||||
installButton.setVisibility(Utils.checkBits(status, NETWORK) ? View.VISIBLE : View.GONE);
|
||||
uninstallButton.setVisibility(Utils.checkBits(status, UPTODATE, ROOT) ? View.VISIBLE : View.GONE);
|
||||
updateVersionUI();
|
||||
}
|
||||
|
||||
private void updateVersionUI() {
|
||||
int image, color;
|
||||
|
||||
magiskManager.updateMagiskInfo();
|
||||
|
||||
if (magiskManager.magiskVersionCode < 0) {
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
@ -405,6 +371,25 @@ public class MagiskFragment extends Fragment
|
||||
|
||||
rootStatusIcon.setImageResource(image);
|
||||
rootStatusIcon.setColorFilter(color);
|
||||
|
||||
if (!Shell.rootAccess()) {
|
||||
installText.setText(R.string.download);
|
||||
} else {
|
||||
installText.setText(R.string.download_install);
|
||||
|
||||
List<String> items = new ArrayList<>();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
|
||||
spinner.setEnabled(false);
|
||||
} else {
|
||||
items.add(getString(R.string.cannot_auto_detect));
|
||||
items.addAll(magiskManager.blockList);
|
||||
}
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCheckUI() {
|
||||
@ -428,28 +413,6 @@ public class MagiskFragment extends Fragment
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
private void updateInstallUI() {
|
||||
if (!Shell.rootAccess()) {
|
||||
installText.setText(R.string.download);
|
||||
} else {
|
||||
installText.setText(R.string.download_install);
|
||||
|
||||
List<String> items = new ArrayList<>();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
|
||||
spinner.setEnabled(false);
|
||||
} else {
|
||||
items.add(getString(R.string.cannot_auto_detect));
|
||||
items.addAll(magiskManager.blockList);
|
||||
}
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
toAutoDetect();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSafetyNetUI() {
|
||||
int image, color;
|
||||
safetyNetProgress.setVisibility(View.GONE);
|
||||
|
@ -142,7 +142,7 @@ public class MagiskLogFragment extends Fragment {
|
||||
mode = (int) params[0];
|
||||
switch (mode) {
|
||||
case 0:
|
||||
List<String> logList = Utils.readFile(magiskManager.rootShell, MAGISK_LOG);
|
||||
List<String> logList = Utils.readFile(magiskManager.shell, MAGISK_LOG);
|
||||
|
||||
if (Utils.isValidShellResponse(logList)) {
|
||||
StringBuilder llog = new StringBuilder(15 * 10 * 1024);
|
||||
@ -154,7 +154,7 @@ public class MagiskLogFragment extends Fragment {
|
||||
return "";
|
||||
|
||||
case 1:
|
||||
magiskManager.rootShell.su_raw("echo > " + MAGISK_LOG);
|
||||
magiskManager.shell.su_raw("echo > " + MAGISK_LOG);
|
||||
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
||||
return "";
|
||||
|
||||
@ -184,7 +184,7 @@ public class MagiskLogFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> in = Utils.readFile(magiskManager.rootShell, MAGISK_LOG);
|
||||
List<String> in = Utils.readFile(magiskManager.shell, MAGISK_LOG);
|
||||
|
||||
if (Utils.isValidShellResponse(in)) {
|
||||
try (FileWriter out = new FileWriter(targetFile)) {
|
||||
|
@ -38,7 +38,6 @@ public class MagiskManager extends Application {
|
||||
public static final String NOTIFICATION_CHANNEL = "magisk_update_notice";
|
||||
|
||||
// Events
|
||||
public final CallbackEvent<Void> blockDetectionDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> magiskHideDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> reloadMainActivity = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> moduleLoadDone = new CallbackEvent<>();
|
||||
@ -88,7 +87,7 @@ public class MagiskManager extends Application {
|
||||
// Global resources
|
||||
public SharedPreferences prefs;
|
||||
public SuDatabaseHelper suDB;
|
||||
public Shell rootShell;
|
||||
public Shell shell;
|
||||
|
||||
private static Handler mHandler = new Handler();
|
||||
|
||||
@ -97,7 +96,7 @@ public class MagiskManager extends Application {
|
||||
super.onCreate();
|
||||
new File(getApplicationInfo().dataDir).mkdirs(); /* Create the app data directory */
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
rootShell = Shell.getRootShell();
|
||||
shell = Shell.getShell();
|
||||
}
|
||||
|
||||
public void toast(String msg, int duration) {
|
||||
@ -121,11 +120,12 @@ public class MagiskManager extends Application {
|
||||
updateNotification = prefs.getBoolean("notification", true);
|
||||
initSU();
|
||||
updateMagiskInfo();
|
||||
updateBlockInfo();
|
||||
// Initialize busybox
|
||||
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
|
||||
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
|
||||
busybox.getParentFile().mkdirs();
|
||||
rootShell.su_raw(
|
||||
shell.su_raw(
|
||||
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
|
||||
"chmod -R 755 " + busybox.getParent(),
|
||||
busybox + " --install -s " + busybox.getParent()
|
||||
@ -137,7 +137,7 @@ public class MagiskManager extends Application {
|
||||
.putBoolean("magiskhide", magiskHide)
|
||||
.putBoolean("notification", updateNotification)
|
||||
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
|
||||
.putBoolean("disable", Utils.itemExist(rootShell, MAGISK_DISABLE_FILE))
|
||||
.putBoolean("disable", Utils.itemExist(shell, MAGISK_DISABLE_FILE))
|
||||
.putBoolean("su_reauth", suReauth)
|
||||
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
|
||||
.putString("su_auto_response", String.valueOf(suResponseType))
|
||||
@ -148,7 +148,7 @@ public class MagiskManager extends Application {
|
||||
.putString("busybox_version", BUSYBOX_VERSION)
|
||||
.apply();
|
||||
// Add busybox to PATH
|
||||
rootShell.su_raw("PATH=$PATH:" + busybox.getParent());
|
||||
shell.su_raw("PATH=$PATH:" + busybox.getParent());
|
||||
|
||||
// Create notification channel on Android O
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
@ -170,7 +170,7 @@ public class MagiskManager extends Application {
|
||||
public void initSU() {
|
||||
initSUConfig();
|
||||
|
||||
List<String> ret = Shell.sh("su -v");
|
||||
List<String> ret = shell.sh("su -v");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suVersion = ret.get(0);
|
||||
isSuClient = suVersion.toUpperCase().contains("MAGISK");
|
||||
@ -184,9 +184,9 @@ public class MagiskManager extends Application {
|
||||
|
||||
public void updateMagiskInfo() {
|
||||
List<String> ret;
|
||||
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);
|
||||
@ -195,24 +195,39 @@ 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;
|
||||
}
|
||||
ret = Shell.sh("getprop " + MAGISKHIDE_PROP);
|
||||
ret = shell.sh("getprop " + MAGISKHIDE_PROP);
|
||||
try {
|
||||
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
magiskHide = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateBlockInfo() {
|
||||
List<String> res = shell.su(
|
||||
"for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do",
|
||||
"BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null",
|
||||
"[ ! -z \"$BOOTIMAGE\" ] && break",
|
||||
"done",
|
||||
"[ ! -z \"$BOOTIMAGE\" -a -L \"$BOOTIMAGE\" ] && BOOTIMAGE=`readlink $BOOTIMAGE`",
|
||||
"echo \"$BOOTIMAGE\""
|
||||
);
|
||||
if (Utils.isValidShellResponse(res)) {
|
||||
bootBlock = res.get(0);
|
||||
} else {
|
||||
blockList = shell.su("ls -d /dev/block/mmc* /dev/block/sd* 2>/dev/null");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -149,9 +149,9 @@ public class SettingsActivity extends Activity {
|
||||
case "disable":
|
||||
enabled = prefs.getBoolean("disable", false);
|
||||
if (enabled) {
|
||||
Utils.createFile(magiskManager.rootShell, MagiskManager.MAGISK_DISABLE_FILE);
|
||||
Utils.createFile(magiskManager.shell, MagiskManager.MAGISK_DISABLE_FILE);
|
||||
} else {
|
||||
Utils.removeItem(magiskManager.rootShell, MagiskManager.MAGISK_DISABLE_FILE);
|
||||
Utils.removeItem(magiskManager.shell, MagiskManager.MAGISK_DISABLE_FILE);
|
||||
}
|
||||
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
@ -175,11 +175,11 @@ public class SettingsActivity extends Activity {
|
||||
case "hosts":
|
||||
enabled = prefs.getBoolean("hosts", false);
|
||||
if (enabled) {
|
||||
magiskManager.rootShell.su_raw(
|
||||
magiskManager.shell.su_raw(
|
||||
"cp -af /system/etc/hosts /magisk/.core/hosts",
|
||||
"mount -o bind /magisk/.core/hosts /system/etc/hosts");
|
||||
} else {
|
||||
magiskManager.rootShell.su_raw(
|
||||
magiskManager.shell.su_raw(
|
||||
"umount -l /system/etc/hosts",
|
||||
"rm -f /magisk/.core/hosts");
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.GetBootBlocks;
|
||||
import com.topjohnwu.magisk.asyncs.LoadApps;
|
||||
import com.topjohnwu.magisk.asyncs.LoadModules;
|
||||
import com.topjohnwu.magisk.asyncs.LoadRepos;
|
||||
@ -25,12 +24,13 @@ public class SplashActivity extends Activity{
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Init the info and configs and root shell
|
||||
// Init the info and configs and root sh
|
||||
getApplicationContext().init();
|
||||
|
||||
// Now fire all async tasks
|
||||
new GetBootBlocks(this).exec();
|
||||
new LoadModules(this).setCallBack(() -> new LoadRepos(this).exec()).exec();
|
||||
new LoadModules(this)
|
||||
.setCallBack(() -> new LoadRepos(this).exec())
|
||||
.exec();
|
||||
new LoadApps(this).exec();
|
||||
|
||||
if (Utils.checkNetworkStatus(this)) {
|
||||
|
@ -38,7 +38,7 @@ 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.getRootShell(context);
|
||||
Shell rootShell = Shell.getShell(context);
|
||||
final Module module = mList.get(position);
|
||||
|
||||
String version = module.getVersion();
|
||||
|
@ -63,7 +63,7 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
||||
|
||||
private boolean unzipAndCheck() throws Exception {
|
||||
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
|
||||
List<String> ret = Utils.readFile(magiskManager.rootShell, mCheckFile.getPath());
|
||||
List<String> ret = Utils.readFile(magiskManager.shell, mCheckFile.getPath());
|
||||
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
||||
copyToCache();
|
||||
if (!unzipAndCheck()) return 0;
|
||||
mList.add(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
|
||||
magiskManager.rootShell.su(mList,
|
||||
magiskManager.shell.su(mList,
|
||||
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile +
|
||||
" && echo 'Success!' || echo 'Failed!'"
|
||||
);
|
||||
@ -99,7 +99,7 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
||||
// -1 = error, manual install; 0 = invalid zip; 1 = success
|
||||
@Override
|
||||
protected void onPostExecute(Integer result) {
|
||||
magiskManager.rootShell.su_raw(
|
||||
magiskManager.shell.su_raw(
|
||||
"rm -rf " + mCachedFile.getParent() + "/*",
|
||||
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
|
||||
);
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class GetBootBlocks extends ParallelTask<Void, Void, Void> {
|
||||
|
||||
public GetBootBlocks(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
magiskManager.blockList = magiskManager.rootShell.su(
|
||||
"find /dev/block -type b -maxdepth 1 | grep -v -E \"loop|ram|dm-0\""
|
||||
);
|
||||
if (magiskManager.bootBlock == null) {
|
||||
magiskManager.bootBlock = Utils.detectBootImage(magiskManager.rootShell);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
magiskManager.blockDetectionDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
@ -21,10 +21,10 @@ public class LoadModules extends ParallelTask<Void, Void, Void> {
|
||||
|
||||
magiskManager.moduleMap = new ValueSortedMap<>();
|
||||
|
||||
for (String path : Utils.getModList(magiskManager.rootShell, MagiskManager.MAGISK_PATH)) {
|
||||
for (String path : Utils.getModList(magiskManager.shell, MagiskManager.MAGISK_PATH)) {
|
||||
Logger.dev("LoadModules: Adding modules from " + path);
|
||||
try {
|
||||
Module module = new Module(magiskManager.rootShell, path);
|
||||
Module module = new Module(magiskManager.shell, path);
|
||||
magiskManager.moduleMap.put(module.getId(), module);
|
||||
} catch (BaseModule.CacheModException ignored) {}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public class MagiskHide extends ParallelTask<Object, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(Object... params) {
|
||||
String command = (String) params[0];
|
||||
List<String> ret = magiskManager.rootShell.su("magiskhide --" + command);
|
||||
List<String> ret = magiskManager.shell.su("magiskhide --" + command);
|
||||
if (isList) {
|
||||
magiskManager.magiskHideList = ret;
|
||||
}
|
||||
|
@ -37,13 +37,13 @@ public class Logger {
|
||||
dev(String.format(Locale.US, fmt, args));
|
||||
}
|
||||
|
||||
public static void shell(boolean root, String line) {
|
||||
public static void shell(String line) {
|
||||
if (MagiskManager.shellLogging) {
|
||||
Log.d(DEBUG_TAG, (root ? "MANAGERSU: " : "MANAGERSH: ") + line);
|
||||
Log.d(DEBUG_TAG, "SHELL: " + line);
|
||||
}
|
||||
}
|
||||
|
||||
public static void shell(boolean root, String fmt, Object... args) {
|
||||
shell(root, String.format(Locale.US, fmt, args));
|
||||
public static void shell(String fmt, Object... args) {
|
||||
shell(String.format(Locale.US, fmt, args));
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -18,145 +19,133 @@ public class Shell {
|
||||
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
|
||||
public static int rootStatus;
|
||||
|
||||
private final Process rootShell;
|
||||
private final DataOutputStream rootSTDIN;
|
||||
private final DataInputStream rootSTDOUT;
|
||||
private final Process shellProcess;
|
||||
private final DataOutputStream STDIN;
|
||||
private final DataInputStream STDOUT;
|
||||
|
||||
private boolean isValid;
|
||||
|
||||
private Shell() {
|
||||
Process process;
|
||||
rootStatus = 1;
|
||||
Process process = null;
|
||||
DataOutputStream in = null;
|
||||
DataInputStream out = null;
|
||||
|
||||
try {
|
||||
process = Runtime.getRuntime().exec("su");
|
||||
in = new DataOutputStream(process.getOutputStream());
|
||||
out = new DataInputStream(process.getInputStream());
|
||||
} catch (IOException e) {
|
||||
// No root
|
||||
rootStatus = 0;
|
||||
rootShell = null;
|
||||
rootSTDIN = null;
|
||||
rootSTDOUT = null;
|
||||
isValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
rootStatus = 1;
|
||||
isValid = true;
|
||||
rootShell = process;
|
||||
rootSTDIN = new DataOutputStream(rootShell.getOutputStream());
|
||||
rootSTDOUT = new DataInputStream(rootShell.getInputStream());
|
||||
|
||||
su_raw("umask 022");
|
||||
List<String> ret = su("echo -BOC-", "id");
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
// Something wrong with root, not allowed?
|
||||
rootStatus = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (String line : ret) {
|
||||
if (line.contains("uid=")) {
|
||||
// id command is working, let's see if we are actually root
|
||||
rootStatus = line.contains("uid=0") ? 1 : -1;
|
||||
return;
|
||||
} else if (!line.contains("-BOC-")) {
|
||||
rootStatus = -1;
|
||||
return;
|
||||
while (true) {
|
||||
if (rootAccess()) {
|
||||
try {
|
||||
in.write(("id\n").getBytes("UTF-8"));
|
||||
in.flush();
|
||||
String s = new BufferedReader(new InputStreamReader(out)).readLine();
|
||||
if (s.isEmpty() || !s.contains("uid=0")) {
|
||||
in.close();
|
||||
out.close();
|
||||
process.destroy();
|
||||
throw new IOException();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
rootStatus = -1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isValid = true;
|
||||
shellProcess = process;
|
||||
STDIN = in;
|
||||
STDOUT = out;
|
||||
sh_raw("umask 022");
|
||||
}
|
||||
|
||||
public static Shell getRootShell() {
|
||||
public static Shell getShell() {
|
||||
return new Shell();
|
||||
}
|
||||
|
||||
public static Shell getRootShell(Context context) {
|
||||
return Utils.getMagiskManager(context).rootShell;
|
||||
public static Shell getShell(Context context) {
|
||||
return Utils.getMagiskManager(context).shell;
|
||||
}
|
||||
|
||||
public static boolean rootAccess() {
|
||||
return rootStatus > 0;
|
||||
}
|
||||
|
||||
public static List<String> sh(String... commands) {
|
||||
List<String> res = Collections.synchronizedList(new ArrayList<String>());
|
||||
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec("sh");
|
||||
DataOutputStream STDIN = new DataOutputStream(process.getOutputStream());
|
||||
StreamGobbler STDOUT = new StreamGobbler(process.getInputStream(), res);
|
||||
|
||||
STDOUT.start();
|
||||
|
||||
try {
|
||||
for (String write : commands) {
|
||||
STDIN.write((write + "\n").getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
Logger.shell(false, write);
|
||||
}
|
||||
STDIN.write("exit\n".getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().contains("EPIPE")) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
process.waitFor();
|
||||
|
||||
try {
|
||||
STDIN.close();
|
||||
} catch (IOException e) {
|
||||
// might be closed already
|
||||
}
|
||||
STDOUT.join();
|
||||
process.destroy();
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
// shell probably not found
|
||||
res = null;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<String> su(String... commands) {
|
||||
if (!isValid) return null;
|
||||
public List<String> sh(String... commands) {
|
||||
List<String> res = new ArrayList<>();
|
||||
su(res, commands);
|
||||
if (!isValid) return res;
|
||||
sh(res, commands);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void su_raw(String... commands) {
|
||||
public void sh_raw(String... commands) {
|
||||
if (!isValid) return;
|
||||
synchronized (rootShell) {
|
||||
synchronized (shellProcess) {
|
||||
try {
|
||||
for (String command : commands) {
|
||||
rootSTDIN.write((command + "\n").getBytes("UTF-8"));
|
||||
rootSTDIN.flush();
|
||||
STDIN.write((command + "\n").getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
rootShell.destroy();
|
||||
shellProcess.destroy();
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void su(List<String> output, String... commands) {
|
||||
public void sh(List<String> output, String... commands) {
|
||||
if (!isValid) return;
|
||||
try {
|
||||
rootShell.exitValue();
|
||||
shellProcess.exitValue();
|
||||
isValid = false;
|
||||
return; // The process is dead, return
|
||||
} catch (IllegalThreadStateException ignored) {
|
||||
// This should be the expected result
|
||||
}
|
||||
synchronized (rootShell) {
|
||||
StreamGobbler STDOUT = new StreamGobbler(rootSTDOUT, output, true);
|
||||
STDOUT.start();
|
||||
su_raw(commands);
|
||||
su_raw("echo \'-root-done-\'");
|
||||
try { STDOUT.join(); } catch (InterruptedException ignored) {}
|
||||
synchronized (shellProcess) {
|
||||
StreamGobbler out = new StreamGobbler(this.STDOUT, output);
|
||||
out.start();
|
||||
sh_raw(commands);
|
||||
sh_raw("echo \'-shell-done-\'");
|
||||
try { out.join(); } catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
public 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(List<String> output, String... commands) {
|
||||
if (!rootAccess()) return;
|
||||
sh(output, commands);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class StreamGobbler extends Thread {
|
||||
/**
|
||||
* <p>StreamGobbler constructor</p>
|
||||
*
|
||||
* <p>We use this class because shell STDOUT and STDERR should be read as quickly as
|
||||
* <p>We use this class because sh STDOUT and STDERR should be read as quickly as
|
||||
* possible to prevent a deadlock from occurring, or Process.waitFor() never
|
||||
* returning (as the buffer is full, pausing the native process)</p>
|
||||
*
|
||||
@ -38,21 +38,16 @@ public class StreamGobbler extends Thread {
|
||||
writer = outputList;
|
||||
}
|
||||
|
||||
public StreamGobbler(InputStream inputStream, List<String> outputList, boolean root) {
|
||||
this(inputStream, outputList);
|
||||
isRoot = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// keep reading the InputStream until it ends (or an error occurs)
|
||||
try {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (TextUtils.equals(line, "-root-done-"))
|
||||
if (TextUtils.equals(line, "-shell-done-"))
|
||||
return;
|
||||
writer.add(line);
|
||||
Logger.shell(isRoot, line);
|
||||
Logger.shell(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// reader probably closed, expected exit condition
|
||||
|
Loading…
Reference in New Issue
Block a user