Rewrite RootUtils in Kotlin
This commit is contained in:
parent
a2a3c7f438
commit
d3f5f5ee59
@ -89,7 +89,7 @@ public class DownloadApp {
|
||||
// Make it world readable
|
||||
apk.setReadable(true, false);
|
||||
if (Shell.su("pm install " + apk).exec().isSuccess())
|
||||
RootUtils.rmAndLaunch(app.getPackageName(),
|
||||
RootUtils.Companion.rmAndLaunch(app.getPackageName(),
|
||||
new ComponentName(BuildConfig.APPLICATION_ID,
|
||||
ClassMap.get(SplashActivity.class).getName()));
|
||||
progress.dismiss();
|
||||
|
@ -3,6 +3,8 @@ package com.topjohnwu.magisk.utils;
|
||||
import android.content.ComponentName;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.topjohnwu.magisk.App;
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.ClassMap;
|
||||
@ -27,8 +29,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
public class PatchAPK {
|
||||
|
||||
public static final String LOWERALPHA = "abcdefghijklmnopqrstuvwxyz";
|
||||
@ -112,7 +112,7 @@ public class PatchAPK {
|
||||
|
||||
Config.set(Config.Key.SU_MANAGER, pkg);
|
||||
Config.export();
|
||||
RootUtils.rmAndLaunch(BuildConfig.APPLICATION_ID,
|
||||
RootUtils.Companion.rmAndLaunch(BuildConfig.APPLICATION_ID,
|
||||
new ComponentName(pkg, ClassMap.get(SplashActivity.class).getName()));
|
||||
|
||||
return true;
|
||||
|
@ -1,149 +0,0 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.topjohnwu.magisk.Config;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RootUtils extends Shell.Initializer {
|
||||
|
||||
public static void rmAndLaunch(String rm, ComponentName component) {
|
||||
Shell.su(Utils.fmt("(rm_launch %s %s)&", rm, component.flattenToString())).exec();
|
||||
}
|
||||
|
||||
public static void reboot() {
|
||||
Shell.su("/system/bin/reboot" + (Config.recovery ? " recovery" : "")).submit();
|
||||
}
|
||||
|
||||
public static void startActivity(Intent intent) {
|
||||
if (intent.getComponent() == null)
|
||||
return;
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("am");
|
||||
args.add("start");
|
||||
intentToCommand(intent, args);
|
||||
Shell.su(Utils.argsToCommand(args)).exec();
|
||||
}
|
||||
|
||||
public static void intentToCommand(Intent intent, List<String> args) {
|
||||
if (intent.getAction() != null) {
|
||||
args.add("-a");
|
||||
args.add(intent.getAction());
|
||||
}
|
||||
if (intent.getComponent() != null) {
|
||||
args.add("-n");
|
||||
args.add(intent.getComponent().flattenToString());
|
||||
}
|
||||
if (intent.getData() != null) {
|
||||
args.add("-d");
|
||||
args.add(intent.getDataString());
|
||||
}
|
||||
if (intent.getCategories() != null) {
|
||||
for (String cat : intent.getCategories()) {
|
||||
args.add("-c");
|
||||
args.add(cat);
|
||||
}
|
||||
}
|
||||
if (intent.getType() != null) {
|
||||
args.add("-t");
|
||||
args.add(intent.getType());
|
||||
}
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras != null) {
|
||||
for (String key : extras.keySet()) {
|
||||
Object val = extras.get(key);
|
||||
if (val == null)
|
||||
continue;
|
||||
Object value = val;
|
||||
String arg;
|
||||
if (val instanceof String) arg = "--es";
|
||||
else if (val instanceof Boolean) arg = "--ez";
|
||||
else if (val instanceof Integer) arg = "--ei";
|
||||
else if (val instanceof Long) arg = "--el";
|
||||
else if (val instanceof Float) arg = "--ef";
|
||||
else if (val instanceof Uri) arg = "--eu";
|
||||
else if (val instanceof ComponentName) {
|
||||
arg = "--ecn";
|
||||
value = ((ComponentName) val).flattenToString();
|
||||
} else if (val instanceof ArrayList) {
|
||||
ArrayList arr = (ArrayList) val;
|
||||
if (arr.size() <= 0)
|
||||
/* Impossible to know the type due to type erasure */
|
||||
continue;
|
||||
|
||||
if (arr.get(0) instanceof Integer) arg = "--eial";
|
||||
else if (arr.get(0) instanceof Long) arg = "--elal";
|
||||
else if (arr.get(0) instanceof Float) arg = "--efal";
|
||||
else if (arr.get(0) instanceof String) arg = "--esal";
|
||||
else continue; /* Unsupported */
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object o : arr) {
|
||||
sb.append(o.toString().replace(",", "\\,"));
|
||||
sb.append(',');
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
value = sb;
|
||||
} else if (val.getClass().isArray()) {
|
||||
if (val instanceof int[]) arg = "--eia";
|
||||
else if (val instanceof long[]) arg = "--ela";
|
||||
else if (val instanceof float[]) arg = "--efa";
|
||||
else if (val instanceof String[]) arg = "--esa";
|
||||
else continue; /* Unsupported */
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len = Array.getLength(val);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
sb.append(Array.get(val, i).toString().replace(",", "\\,"));
|
||||
sb.append(',');
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
value = sb;
|
||||
}
|
||||
else continue; /* Unsupported */
|
||||
|
||||
args.add(arg);
|
||||
args.add(key);
|
||||
args.add(value.toString());
|
||||
}
|
||||
}
|
||||
args.add("-f");
|
||||
args.add(String.valueOf(intent.getFlags()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInit(Context context, @NonNull Shell shell) {
|
||||
Shell.Job job = shell.newJob();
|
||||
if (shell.isRoot()) {
|
||||
job.add(context.getResources().openRawResource(R.raw.util_functions))
|
||||
.add(context.getResources().openRawResource(R.raw.utils));
|
||||
Const.MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk");
|
||||
Config.loadMagiskInfo();
|
||||
} else {
|
||||
InputStream nonroot = context.getResources().openRawResource(R.raw.nonroot_utils);
|
||||
job.add(nonroot);
|
||||
}
|
||||
|
||||
job.add("mount_partitions", "get_flags", "run_migrations", "export BOOTMODE=true").exec();
|
||||
|
||||
Config.keepVerity = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPVERITY"));
|
||||
Config.keepEnc = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPFORCEENCRYPT"));
|
||||
Config.recovery = Boolean.parseBoolean(ShellUtils.fastCmd("echo $RECOVERYMODE"));
|
||||
return true;
|
||||
}
|
||||
}
|
164
app/src/main/java/com/topjohnwu/magisk/utils/RootUtils.kt
Normal file
164
app/src/main/java/com/topjohnwu/magisk/utils/RootUtils.kt
Normal file
@ -0,0 +1,164 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import java.util.*
|
||||
import java.lang.reflect.Array as RArray
|
||||
|
||||
fun Intent.toCommand(args: MutableList<String>) {
|
||||
if (action != null) {
|
||||
args.add("-a")
|
||||
args.add(action!!)
|
||||
}
|
||||
if (component != null) {
|
||||
args.add("-n")
|
||||
args.add(component!!.flattenToString())
|
||||
}
|
||||
if (data != null) {
|
||||
args.add("-d")
|
||||
args.add(dataString!!)
|
||||
}
|
||||
if (categories != null) {
|
||||
for (cat in categories) {
|
||||
args.add("-c")
|
||||
args.add(cat)
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
args.add("-t")
|
||||
args.add(type!!)
|
||||
}
|
||||
val extras = extras
|
||||
if (extras != null) {
|
||||
for (key in extras.keySet()) {
|
||||
val v = extras.get(key) ?: continue
|
||||
var value: Any = v
|
||||
val arg: String
|
||||
if (v is String)
|
||||
arg = "--es"
|
||||
else if (v is Boolean)
|
||||
arg = "--ez"
|
||||
else if (v is Int)
|
||||
arg = "--ei"
|
||||
else if (v is Long)
|
||||
arg = "--el"
|
||||
else if (v is Float)
|
||||
arg = "--ef"
|
||||
else if (v is Uri)
|
||||
arg = "--eu"
|
||||
else if (v is ComponentName) {
|
||||
arg = "--ecn"
|
||||
value = v.flattenToString()
|
||||
} else if (v is ArrayList<*>) {
|
||||
if (v.size <= 0)
|
||||
/* Impossible to know the type due to type erasure */
|
||||
continue
|
||||
|
||||
arg = if (v[0] is Int)
|
||||
"--eial"
|
||||
else if (v[0] is Long)
|
||||
"--elal"
|
||||
else if (v[0] is Float)
|
||||
"--efal"
|
||||
else if (v[0] is String)
|
||||
"--esal"
|
||||
else
|
||||
continue /* Unsupported */
|
||||
|
||||
val sb = StringBuilder()
|
||||
for (o in v) {
|
||||
sb.append(o.toString().replace(",", "\\,"))
|
||||
sb.append(',')
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
value = sb
|
||||
} else if (v.javaClass.isArray) {
|
||||
arg = if (v is IntArray)
|
||||
"--eia"
|
||||
else if (v is LongArray)
|
||||
"--ela"
|
||||
else if (v is FloatArray)
|
||||
"--efa"
|
||||
else if (v is Array<*> && v.isArrayOf<String>())
|
||||
"--esa"
|
||||
else
|
||||
continue /* Unsupported */
|
||||
|
||||
val sb = StringBuilder()
|
||||
val len = RArray.getLength(v)
|
||||
for (i in 0 until len) {
|
||||
sb.append(RArray.get(v, i)!!.toString().replace(",", "\\,"))
|
||||
sb.append(',')
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
value = sb
|
||||
} else
|
||||
continue /* Unsupported */
|
||||
|
||||
args.add(arg)
|
||||
args.add(key)
|
||||
args.add(value.toString())
|
||||
}
|
||||
}
|
||||
args.add("-f")
|
||||
args.add(flags.toString())
|
||||
}
|
||||
|
||||
fun startActivity(intent: Intent) {
|
||||
if (intent.component == null)
|
||||
return
|
||||
val args = ArrayList<String>()
|
||||
args.add("am")
|
||||
args.add("start")
|
||||
intent.toCommand(args)
|
||||
Shell.su(args.toShellCmd()).exec()
|
||||
}
|
||||
|
||||
class RootUtils : Shell.Initializer() {
|
||||
|
||||
override fun onInit(context: Context?, shell: Shell): Boolean {
|
||||
context ?: return false
|
||||
|
||||
val job = shell.newJob()
|
||||
if (shell.isRoot) {
|
||||
job.add(context.rawResource(R.raw.util_functions))
|
||||
.add(context.rawResource(R.raw.utils))
|
||||
Const.MAGISK_DISABLE_FILE = SuFile("/cache/.disable_magisk")
|
||||
Config.loadMagiskInfo()
|
||||
} else {
|
||||
job.add(context.rawResource(R.raw.nonroot_utils))
|
||||
}
|
||||
|
||||
job.add("mount_partitions",
|
||||
"get_flags",
|
||||
"run_migrations",
|
||||
"export BOOTMODE=true")
|
||||
.exec()
|
||||
|
||||
Config.keepVerity = ShellUtils.fastCmd("echo \$KEEPVERITY").toBoolean()
|
||||
Config.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean()
|
||||
Config.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean()
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun rmAndLaunch(rm: String, component: ComponentName) {
|
||||
Shell.su("(rm_launch $rm ${component.flattenToString()})").exec()
|
||||
}
|
||||
|
||||
fun reboot() {
|
||||
Shell.su("/system/bin/reboot ${if (Config.recovery) "recovery" else ""}").submit()
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,12 @@ import android.net.Uri;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.work.Constraints;
|
||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
||||
import androidx.work.NetworkType;
|
||||
import androidx.work.PeriodicWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
import com.topjohnwu.magisk.App;
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.ClassMap;
|
||||
@ -25,17 +31,10 @@ import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.internal.UiThreadHandler;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import androidx.work.Constraints;
|
||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
||||
import androidx.work.NetworkType;
|
||||
import androidx.work.PeriodicWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static void toast(CharSequence msg, int duration) {
|
||||
@ -166,18 +165,4 @@ public class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String argsToCommand(List<String> args) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : args) {
|
||||
if (s.contains(" ")) {
|
||||
sb.append('"').append(s).append('"');
|
||||
} else {
|
||||
sb.append(s);
|
||||
}
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.ComponentInfo
|
||||
import android.content.pm.PackageInfo
|
||||
@ -47,4 +48,6 @@ fun PackageManager.receivers(packageName: String) =
|
||||
getPackageInfo(packageName, GET_RECEIVERS).receivers
|
||||
|
||||
fun PackageManager.providers(packageName: String) =
|
||||
getPackageInfo(packageName, GET_PROVIDERS).providers
|
||||
getPackageInfo(packageName, GET_PROVIDERS).providers
|
||||
|
||||
fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
||||
|
@ -10,6 +10,20 @@ fun <T> MutableList<T>.update(newList: List<T>) {
|
||||
addAll(newList)
|
||||
}
|
||||
|
||||
fun List<String>.toShellCmd() : String {
|
||||
val sb = StringBuilder()
|
||||
for (s in this) {
|
||||
if (s.contains(" ")) {
|
||||
sb.append('"').append(s).append('"')
|
||||
} else {
|
||||
sb.append(s)
|
||||
}
|
||||
sb.append(' ')
|
||||
}
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
fun <T1, T2> ObservableList<T1>.sendUpdatesTo(
|
||||
target: DiffObservableList<T2>,
|
||||
mapper: (List<T1>) -> List<T2>
|
||||
|
@ -4,6 +4,8 @@ import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.tasks.MagiskInstaller;
|
||||
import com.topjohnwu.magisk.utils.RootUtils;
|
||||
@ -12,8 +14,6 @@ import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.internal.UiThreadHandler;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class EnvFixDialog extends CustomAlertDialog {
|
||||
|
||||
public EnvFixDialog(@NonNull Activity activity) {
|
||||
@ -38,7 +38,7 @@ public class EnvFixDialog extends CustomAlertDialog {
|
||||
pd.dismiss();
|
||||
Utils.toast(success ? R.string.reboot_delay_toast : R.string.setup_fail, Toast.LENGTH_LONG);
|
||||
if (success)
|
||||
UiThreadHandler.handler.postDelayed(RootUtils::reboot, 5000);
|
||||
UiThreadHandler.handler.postDelayed(RootUtils.Companion::reboot, 5000);
|
||||
}
|
||||
}.exec();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user