summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-05-29 05:07:50 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-05-29 05:09:37 +0200
commitded0191aae5bfe14409f343c0e3ce3b5db47261a (patch)
tree126cc6f78fc65970f9359ba1015d99e7a098efbc
parent9245e9536ac0e20f03049f074a6a3934447b3d35 (diff)
SharedLibraryLoader: introduce to work around Samsung PackageManager bugs
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--app/src/main/java/com/wireguard/android/backend/GoBackend.java6
-rw-r--r--app/src/main/java/com/wireguard/android/util/SharedLibraryLoader.java74
2 files changed, 76 insertions, 4 deletions
diff --git a/app/src/main/java/com/wireguard/android/backend/GoBackend.java b/app/src/main/java/com/wireguard/android/backend/GoBackend.java
index ffd05eae..4963f759 100644
--- a/app/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/app/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -19,6 +19,7 @@ import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.Tunnel.State;
import com.wireguard.android.model.Tunnel.Statistics;
import com.wireguard.android.util.ExceptionLoggers;
+import com.wireguard.android.util.SharedLibraryLoader;
import com.wireguard.config.Config;
import com.wireguard.config.IPCidr;
import com.wireguard.config.Interface;
@@ -38,15 +39,12 @@ public final class GoBackend implements Backend {
private static final String TAG = "WireGuard/" + GoBackend.class.getSimpleName();
private static CompletableFuture<VpnService> vpnService = new CompletableFuture<>();
- static {
- System.loadLibrary("wg-go");
- }
-
private final Context context;
private Tunnel currentTunnel;
private int currentTunnelHandle = -1;
public GoBackend(final Context context) {
+ SharedLibraryLoader.loadSharedLibrary(context, "wg-go");
this.context = context;
}
diff --git a/app/src/main/java/com/wireguard/android/util/SharedLibraryLoader.java b/app/src/main/java/com/wireguard/android/util/SharedLibraryLoader.java
new file mode 100644
index 00000000..90ed8fcf
--- /dev/null
+++ b/app/src/main/java/com/wireguard/android/util/SharedLibraryLoader.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+package com.wireguard.android.util;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipEntry;
+
+public final class SharedLibraryLoader {
+ private static final String TAG = "WireGuard/" + SharedLibraryLoader.class.getSimpleName();
+
+ private SharedLibraryLoader() {
+ }
+
+ public static final void loadSharedLibrary(final Context context, final String libName) {
+ Throwable noAbiException;
+ try {
+ System.loadLibrary(libName);
+ return;
+ } catch (UnsatisfiedLinkError e) {
+ Log.d(TAG, "Failed to load library normally, so attempting to extract from apk", e);
+ noAbiException = e;
+ }
+
+ final ZipFile zipFile;
+ try {
+ zipFile = new ZipFile(new File(context.getApplicationInfo().sourceDir), ZipFile.OPEN_READ);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ final String mappedLibName = System.mapLibraryName(libName);
+ byte buffer[] = new byte[1024 * 32];
+ for (final String abi : Build.SUPPORTED_ABIS) {
+ final String libZipPath = "lib" + File.separatorChar + abi + File.separatorChar + mappedLibName;
+ final ZipEntry zipEntry = zipFile.getEntry(libZipPath);
+ if (zipEntry == null)
+ continue;
+ File f = null;
+ try {
+ f = File.createTempFile("lib", ".so", context.getCacheDir());
+ Log.d(TAG, "Extracting apk:/" + libZipPath + " to " + f.getAbsolutePath() + " and loading");
+ FileOutputStream out = new FileOutputStream(f);
+ InputStream in = zipFile.getInputStream(zipEntry);
+ int len;
+ while ((len = in.read(buffer)) != -1) {
+ out.write(buffer, 0, len);
+ }
+ out.close();
+ System.load(f.getAbsolutePath());
+ return;
+ } catch (Exception e) {
+ Log.d(TAG, "Failed to load library apk:/" + libZipPath, e);
+ noAbiException = e;
+ } finally {
+ if (f != null)
+ f.delete();
+ }
+ }
+ if (noAbiException instanceof RuntimeException)
+ throw (RuntimeException) noAbiException;
+ throw new RuntimeException(noAbiException);
+ }
+}