diff --git a/app/src/main/java/com/wireguard/android/Application.java b/app/src/main/java/com/wireguard/android/Application.java index 2a07df1..2ebeb69 100644 --- a/app/src/main/java/com/wireguard/android/Application.java +++ b/app/src/main/java/com/wireguard/android/Application.java @@ -5,7 +5,6 @@ package com.wireguard.android; -import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -20,7 +19,6 @@ import androidx.preference.PreferenceManager; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatDelegate; -import com.wireguard.android.activity.MainActivity; import com.wireguard.android.backend.Backend; import com.wireguard.android.backend.GoBackend; import com.wireguard.android.backend.WgQuickBackend; @@ -88,7 +86,7 @@ public class Application extends android.app.Application { try { if (!didStartRootShell) app.rootShell.start(); - backend = new WgQuickBackend(app.getApplicationContext()); + backend = new WgQuickBackend(app.getApplicationContext(), app.rootShell, app.toolsInstaller); } catch (final Exception ignored) { } } @@ -119,6 +117,7 @@ public class Application extends android.app.Application { public static ToolsInstaller getToolsInstaller() { return get().toolsInstaller; } + public static ModuleLoader getModuleLoader() { return get().moduleLoader; } @@ -152,8 +151,8 @@ public class Application extends android.app.Application { asyncWorker = new AsyncWorker(AsyncTask.SERIAL_EXECUTOR, new Handler(Looper.getMainLooper())); rootShell = new RootShell(getApplicationContext()); - toolsInstaller = new ToolsInstaller(getApplicationContext()); - moduleLoader = new ModuleLoader(getApplicationContext()); + toolsInstaller = new ToolsInstaller(getApplicationContext(), rootShell); + moduleLoader = new ModuleLoader(getApplicationContext(), rootShell, USER_AGENT); sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { diff --git a/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java b/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java index 5769da6..75032f2 100644 --- a/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java +++ b/app/src/main/java/com/wireguard/android/backend/WgQuickBackend.java @@ -10,9 +10,10 @@ import androidx.annotation.Nullable; import android.content.Context; import android.util.Log; -import com.wireguard.android.Application; import com.wireguard.android.backend.BackendException.Reason; import com.wireguard.android.backend.Tunnel.State; +import com.wireguard.android.util.RootShell; +import com.wireguard.android.util.ToolsInstaller; import com.wireguard.config.Config; import com.wireguard.crypto.Key; @@ -40,12 +41,16 @@ import java9.util.stream.Stream; public final class WgQuickBackend implements Backend { private static final String TAG = "WireGuard/" + WgQuickBackend.class.getSimpleName(); + private final RootShell rootShell; + private final ToolsInstaller toolsInstaller; private final File localTemporaryDir; private final Map runningConfigs = new HashMap<>(); private final Set notifiers = new HashSet<>(); - public WgQuickBackend(final Context context) { + public WgQuickBackend(final Context context, final RootShell rootShell, final ToolsInstaller toolsInstaller) { localTemporaryDir = new File(context.getCacheDir(), "tmp"); + this.rootShell = rootShell; + this.toolsInstaller = toolsInstaller; } @Override @@ -53,8 +58,8 @@ public final class WgQuickBackend implements Backend { final List output = new ArrayList<>(); // Don't throw an exception here or nothing will show up in the UI. try { - Application.getToolsInstaller().ensureToolsAvailable(); - if (Application.getRootShell().run(output, "wg show interfaces") != 0 || output.isEmpty()) + toolsInstaller.ensureToolsAvailable(); + if (rootShell.run(output, "wg show interfaces") != 0 || output.isEmpty()) return Collections.emptySet(); } catch (final Exception e) { Log.w(TAG, "Unable to enumerate running tunnels", e); @@ -74,7 +79,7 @@ public final class WgQuickBackend implements Backend { final Statistics stats = new Statistics(); final Collection output = new ArrayList<>(); try { - if (Application.getRootShell().run(output, String.format("wg show '%s' transfer", tunnel.getName())) != 0) + if (rootShell.run(output, String.format("wg show '%s' transfer", tunnel.getName())) != 0) return stats; } catch (final Exception ignored) { return stats; @@ -94,8 +99,7 @@ public final class WgQuickBackend implements Backend { @Override public String getVersion() throws Exception { final List output = new ArrayList<>(); - if (Application.getRootShell() - .run(output, "cat /sys/module/wireguard/version") != 0 || output.isEmpty()) + if (rootShell.run(output, "cat /sys/module/wireguard/version") != 0 || output.isEmpty()) throw new BackendException(Reason.UNKNOWN_KERNEL_MODULE_NAME); return output.get(0); } @@ -111,7 +115,7 @@ public final class WgQuickBackend implements Backend { (state == State.DOWN && originalState == State.DOWN)) return originalState; if (state == State.UP) { - Application.getToolsInstaller().ensureToolsAvailable(); + toolsInstaller.ensureToolsAvailable(); if (originalState == State.UP) setStateInternal(tunnel, originalConfig == null ? config : originalConfig, State.DOWN); try { @@ -140,7 +144,7 @@ public final class WgQuickBackend implements Backend { state.toString().toLowerCase(Locale.ENGLISH), tempFile.getAbsolutePath()); if (state == State.UP) command = "cat /sys/module/wireguard/version && " + command; - final int result = Application.getRootShell().run(null, command); + final int result = rootShell.run(null, command); // noinspection ResultOfMethodCallIgnored tempFile.delete(); if (result != 0) diff --git a/app/src/main/java/com/wireguard/android/util/ModuleLoader.java b/app/src/main/java/com/wireguard/android/util/ModuleLoader.java index 7c943d2..bf094a5 100644 --- a/app/src/main/java/com/wireguard/android/util/ModuleLoader.java +++ b/app/src/main/java/com/wireguard/android/util/ModuleLoader.java @@ -9,7 +9,6 @@ import android.content.Context; import android.system.OsConstants; import android.util.Base64; -import com.wireguard.android.Application; import com.wireguard.android.util.RootShell.RootShellException; import net.i2p.crypto.eddsa.EdDSAEngine; @@ -43,12 +42,16 @@ public class ModuleLoader { private static final String MODULE_URL = "https://download.wireguard.com/android-module/%s"; private static final String MODULE_NAME = "wireguard-%s.ko"; + private final RootShell rootShell; + private final String userAgent; private final File moduleDir; private final File tmpDir; - public ModuleLoader(final Context context) { + public ModuleLoader(final Context context, final RootShell rootShell, final String userAgent) { moduleDir = new File(context.getCacheDir(), "kmod"); tmpDir = new File(context.getCacheDir(), "tmp"); + this.rootShell = rootShell; + this.userAgent = userAgent; } public boolean moduleMightExist() { @@ -56,7 +59,7 @@ public class ModuleLoader { } public void loadModule() throws IOException, RootShellException { - Application.getRootShell().run(null, String.format("insmod \"%s/wireguard-$(sha256sum /proc/version|cut -d ' ' -f 1).ko\"", moduleDir.getAbsolutePath())); + rootShell.run(null, String.format("insmod \"%s/wireguard-$(sha256sum /proc/version|cut -d ' ' -f 1).ko\"", moduleDir.getAbsolutePath())); } public static boolean isModuleLoaded() { @@ -124,12 +127,12 @@ public class ModuleLoader { public Integer download() throws IOException, RootShellException, NoSuchAlgorithmException { final List output = new ArrayList<>(); - Application.getRootShell().run(output, "sha256sum /proc/version|cut -d ' ' -f 1"); + rootShell.run(output, "sha256sum /proc/version|cut -d ' ' -f 1"); if (output.size() != 1 || output.get(0).length() != 64) throw new InvalidParameterException("Invalid sha256 of /proc/version"); final String moduleName = String.format(MODULE_NAME, output.get(0)); HttpURLConnection connection = (HttpURLConnection)new URL(MODULE_LIST_URL).openConnection(); - connection.setRequestProperty("User-Agent", Application.USER_AGENT); + connection.setRequestProperty("User-Agent", userAgent); connection.connect(); if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) throw new IOException("Hash list could not be found"); @@ -146,7 +149,7 @@ public class ModuleLoader { if (!modules.containsKey(moduleName)) return OsConstants.ENOENT; connection = (HttpURLConnection)new URL(String.format(MODULE_URL, moduleName)).openConnection(); - connection.setRequestProperty("User-Agent", Application.USER_AGENT); + connection.setRequestProperty("User-Agent", userAgent); connection.connect(); if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) throw new IOException("Module file could not be found, despite being on hash list"); 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 f2fdedd..5a75c15 100644 --- a/app/src/main/java/com/wireguard/android/util/ToolsInstaller.java +++ b/app/src/main/java/com/wireguard/android/util/ToolsInstaller.java @@ -10,7 +10,6 @@ import androidx.annotation.Nullable; import android.system.OsConstants; import android.util.Log; -import com.wireguard.android.Application; import com.wireguard.android.BuildConfig; import com.wireguard.android.util.RootShell.RootShellException; @@ -39,14 +38,16 @@ public final class ToolsInstaller { private static final String TAG = "WireGuard/" + ToolsInstaller.class.getSimpleName(); private final Context context; + private final RootShell rootShell; private final File localBinaryDir; private final Object lock = new Object(); @Nullable private Boolean areToolsAvailable; @Nullable private Boolean installAsMagiskModule; - public ToolsInstaller(final Context context) { + public ToolsInstaller(final Context context, final RootShell rootShell) { localBinaryDir = new File(context.getCodeCacheDir(), "bin"); this.context = context; + this.rootShell = rootShell; } @Nullable @@ -73,7 +74,7 @@ public final class ToolsInstaller { } script.append("exit ").append(OsConstants.EALREADY).append(';'); try { - final int ret = Application.getRootShell().run(null, script.toString()); + final int ret = rootShell.run(null, script.toString()); if (ret == OsConstants.EALREADY) return willInstallAsMagiskModule() ? YES | MAGISK : YES | SYSTEM; else @@ -124,7 +125,7 @@ public final class ToolsInstaller { script.append("trap - INT TERM EXIT;"); try { - return Application.getRootShell().run(null, script.toString()) == 0 ? YES | MAGISK : ERROR; + return rootShell.run(null, script.toString()) == 0 ? YES | MAGISK : ERROR; } catch (final IOException ignored) { return ERROR; } catch (final RootShellException e) { @@ -146,7 +147,7 @@ public final class ToolsInstaller { new File(localBinaryDir, name), destination, destination, destination)); } try { - return Application.getRootShell().run(null, script.toString()) == 0 ? YES | SYSTEM : ERROR; + return rootShell.run(null, script.toString()) == 0 ? YES | SYSTEM : ERROR; } catch (final IOException ignored) { return ERROR; } catch (final RootShellException e) { @@ -183,7 +184,7 @@ public final class ToolsInstaller { synchronized (lock) { if (installAsMagiskModule == null) { try { - installAsMagiskModule = Application.getRootShell().run(null, "[ -d /sbin/.magisk/mirror -a -d /sbin/.magisk/img -a ! -f /cache/.disable_magisk ]") == OsConstants.EXIT_SUCCESS; + installAsMagiskModule = rootShell.run(null, "[ -d /sbin/.magisk/mirror -a -d /sbin/.magisk/img -a ! -f /cache/.disable_magisk ]") == OsConstants.EXIT_SUCCESS; } catch (final Exception ignored) { installAsMagiskModule = false; }