diff --git a/app/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.java b/app/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.java
index 437d05e3..4d9e0fa8 100644
--- a/app/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.java
+++ b/app/src/main/java/com/wireguard/android/preference/ToolsInstallerPreference.java
@@ -26,7 +26,7 @@ import com.wireguard.android.util.ToolsInstaller;
public class ToolsInstallerPreference extends Preference {
private final AsyncWorker asyncWorker;
private final ToolsInstaller toolsInstaller;
- private State state = State.INITIAL;
+ private State state;
@SuppressWarnings({"SameParameterValue", "WeakerAccess"})
public ToolsInstallerPreference(final Context context, final AttributeSet attrs) {
@@ -34,6 +34,7 @@ public class ToolsInstallerPreference extends Preference {
final ApplicationComponent applicationComponent = Application.getComponent();
asyncWorker = applicationComponent.getAsyncWorker();
toolsInstaller = applicationComponent.getToolsInstaller();
+ state = initialState();
}
@Override
@@ -54,12 +55,12 @@ public class ToolsInstallerPreference extends Preference {
private void onCheckResult(final Integer result, final Throwable throwable) {
setState(throwable == null && result == OsConstants.EALREADY ?
- State.ALREADY : State.INITIAL);
+ State.ALREADY : initialState());
}
@Override
protected void onClick() {
- setState(State.WORKING);
+ setState(workingState());
asyncWorker.supplyAsync(toolsInstaller::install).whenComplete(this::onInstallResult);
}
@@ -68,7 +69,7 @@ public class ToolsInstallerPreference extends Preference {
if (throwable != null)
nextState = State.FAILURE;
else if (result == OsConstants.EXIT_SUCCESS)
- nextState = State.SUCCESS;
+ nextState = successState();
else if (result == OsConstants.EALREADY)
nextState = State.ALREADY;
else
@@ -85,12 +86,25 @@ public class ToolsInstallerPreference extends Preference {
notifyChanged();
}
+ private State initialState() {
+ return toolsInstaller.willInstallAsMagiskModule() ? State.INITIAL_MAGISK : State.INITIAL_SYSTEM;
+ }
+ private State workingState() {
+ return toolsInstaller.willInstallAsMagiskModule() ? State.WORKING_MAGISK : State.WORKING_SYSTEM;
+ }
+ private State successState() {
+ return toolsInstaller.willInstallAsMagiskModule() ? State.SUCCESS_MAGISK : State.SUCCESS_SYSTEM;
+ }
+
private enum State {
ALREADY(R.string.tools_installer_already, false),
FAILURE(R.string.tools_installer_failure, true),
- INITIAL(R.string.tools_installer_initial, true),
- SUCCESS(R.string.tools_installer_success, false),
- WORKING(R.string.tools_installer_working, false);
+ INITIAL_SYSTEM(R.string.tools_installer_initial_system, true),
+ SUCCESS_SYSTEM(R.string.tools_installer_success_system, false),
+ WORKING_SYSTEM(R.string.tools_installer_working_system, false),
+ INITIAL_MAGISK(R.string.tools_installer_initial_magisk, true),
+ SUCCESS_MAGISK(R.string.tools_installer_success_magisk, false),
+ WORKING_MAGISK(R.string.tools_installer_working_magisk, false);
private final int messageResourceId;
private final boolean shouldEnableView;
diff --git a/app/src/main/java/com/wireguard/android/util/ToolsInstaller.java b/app/src/main/java/com/wireguard/android/util/ToolsInstaller.java
index de82e69c..0ce089fd 100644
--- a/app/src/main/java/com/wireguard/android/util/ToolsInstaller.java
+++ b/app/src/main/java/com/wireguard/android/util/ToolsInstaller.java
@@ -13,6 +13,7 @@ import android.util.Log;
import com.wireguard.android.Application;
import com.wireguard.android.Application.ApplicationContext;
import com.wireguard.android.Application.ApplicationScope;
+import com.wireguard.android.BuildConfig;
import com.wireguard.android.util.RootShell.NoRootException;
import java.io.File;
@@ -48,6 +49,7 @@ public final class ToolsInstaller {
private final File nativeLibraryDir;
private final RootShell rootShell;
private Boolean areToolsAvailable;
+ private Boolean installAsMagiskModule;
@Inject
public ToolsInstaller(@ApplicationContext final Context context, final RootShell rootShell) {
@@ -114,7 +116,20 @@ public final class ToolsInstaller {
}
}
- public int install() throws NoRootException {
+ public boolean willInstallAsMagiskModule() {
+ synchronized (lock) {
+ if (installAsMagiskModule == null) {
+ try {
+ installAsMagiskModule = rootShell.run(null, "[ -d /sbin/.core/mirror -a -d /sbin/.core/img -a ! -f /cache/.disable_magisk ]") == OsConstants.EXIT_SUCCESS;
+ } catch (final Exception ignored) {
+ installAsMagiskModule = false;
+ }
+ }
+ return installAsMagiskModule;
+ }
+ }
+
+ private int installSystem() throws NoRootException {
if (INSTALL_DIR == null)
return OsConstants.ENOENT;
final StringBuilder script = new StringBuilder("set -ex; ");
@@ -131,6 +146,31 @@ public final class ToolsInstaller {
}
}
+ private int installMagisk() throws NoRootException {
+ final StringBuilder script = new StringBuilder("set -ex; ");
+
+ script.append("trap 'rm -rf /sbin/.core/img/wireguard' INT TERM EXIT; ");
+ script.append(String.format("rm -rf /sbin/.core/img/wireguard/; mkdir -p /sbin/.core/img/wireguard%s; ", INSTALL_DIR));
+ script.append(String.format("printf 'name=WireGuard Command Line Tools\nversion=%s\nversionCode=%s\nauthor=zx2c4\ndescription=Command line tools for WireGuard\nminMagisk=1500\n' > /sbin/.core/img/wireguard/module.prop; ", BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
+ script.append("touch /sbin/.core/img/wireguard/auto_mount; ");
+ for (final String[] names : EXECUTABLES) {
+ final File destination = new File("/sbin/.core/img/wireguard" + INSTALL_DIR, names[1]);
+ script.append(String.format("cp '%s' '%s'; chmod 755 '%s'; restorecon '%s' || true; ",
+ new File(nativeLibraryDir, names[0]), destination, destination, destination));
+ }
+ script.append("trap - INT TERM EXIT;");
+
+ try {
+ return rootShell.run(null, script.toString());
+ } catch (final IOException ignored) {
+ return OsConstants.EXIT_FAILURE;
+ }
+ }
+
+ public int install() throws NoRootException {
+ return willInstallAsMagiskModule() ? installMagisk() : installSystem();
+ }
+
public int symlink() throws NoRootException {
final StringBuilder script = new StringBuilder("set -x; ");
for (final String[] names : EXECUTABLES) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 893f9a16..47c1e9a0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -69,10 +69,13 @@
Error toggling WireGuard tunnel: %s
wg and wg-quick are already installed
Unable to install command-line tools (no root?)
- Install optional tools for scripting into the system partition
- wg and wg-quick installed into the system partition
+ Install optional tools for scripting into the system partition
+ Install optional tools for scripting as Magisk module
+ wg and wg-quick installed into the system partition
+ wg and wg-quick installed as a Magisk module (reboot required)
Install command line tools
- Installing wg and wg-quick into the system partition
+ Installing wg and wg-quick into the system partition
+ Installing wg and wg-quick as a Magisk module
Unable to create tunnel: %s
Successfully created tunnel ā%sā
Unable to rename tunnel: %s