diff --git a/app/build.gradle b/app/build.gradle
index 0b3403ffa7fa9d8855d74667d8085979dfca9cbd..979bf40f700cbde46884094cc9ae787f354f6a58 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,8 +4,7 @@ import java.util.regex.Pattern
 apply plugin: 'com.android.application'
 
 android {
-  compileSdkVersion 28
-  buildToolsVersion '28.0.3'
+  compileSdkVersion 30
 
   compileOptions {
     targetCompatibility 1.8
@@ -17,7 +16,7 @@ android {
     versionCode 149
     versionName "1.0.5"
     minSdkVersion 16
-    targetSdkVersion 28
+    targetSdkVersion 30
     vectorDrawables.useSupportLibrary = true
     buildConfigField 'boolean', 'openvpn3', 'false'
 
@@ -361,31 +360,29 @@ dependencies {
   //TODO: remove that library
   androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.6.3'
   testImplementation 'junit:junit:4.12'
-  testImplementation 'org.json:json:20170516'
+  testImplementation 'org.json:json:20180813'
   debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.2'
   releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
   betaImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.2'
-  annotationProcessor 'com.jakewharton:butterknife:6.1.0'
+  annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
   annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2'
-  implementation 'com.jakewharton:butterknife:6.1.0'
+  implementation 'com.jakewharton:butterknife:10.2.1'
   //TODO: replace that library
   compileOnly 'com.squareup.dagger:dagger-compiler:1.2.2'
   implementation 'com.github.pedrovgs:renderers:1.5'
-  implementation 'com.intellij:annotations:12.0'
-  implementation 'com.google.code.gson:gson:2.8.2'
-  implementation 'com.squareup.okhttp3:okhttp:3.9.0'
+  implementation 'com.google.code.gson:gson:2.8.6'
+  implementation 'com.squareup.okhttp3:okhttp:3.12.12'
   implementation 'androidx.legacy:legacy-support-core-utils:1.0.0'
-  implementation 'androidx.annotation:annotation:1.0.0'
+  implementation 'androidx.annotation:annotation:1.1.0'
   implementation 'androidx.legacy:legacy-support-v4:1.0.0'
-  implementation 'androidx.appcompat:appcompat:1.0.0'
-  implementation 'com.google.android.material:material:1.0.0'
-  implementation 'androidx.fragment:fragment:1.0.0'
-  implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
-  implementation 'androidx.multidex:multidex:2.0.0'
+  implementation 'androidx.appcompat:appcompat:1.2.0'
+  implementation 'com.google.android.material:material:1.2.1'
+  implementation 'androidx.fragment:fragment:1.2.5'
+  implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+  implementation 'androidx.multidex:multidex:2.0.1'
   implementation 'androidx.cardview:cardview:1.0.0'
   implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
   implementation 'de.hdodenhof:circleimageview:3.1.0'
-  //implementation project(path: ':shapeshifter')
   fatwebImplementation project(path: ':bitmask-web-core')
   fatImplementation project(path: ':bitmask-core')
   x86Implementation project(path: ':bitmask-core')
@@ -449,20 +446,13 @@ configurations.all { config ->
       }
     }
   }
-  resolutionStrategy.force "com.android.support:support-annotations:28.0.0"
-  resolutionStrategy.force "com.android.support:support-v4:28.0.0"
-  resolutionStrategy.force "com.android.support:support-core-utils:28.0.0"
-  resolutionStrategy.force "com.android.support:appcompat-v7:28.0.0"
-  resolutionStrategy.force "com.android.support:design:28.0.0"
-  resolutionStrategy.force "com.android.support:support-fragment:28.0.0"
 }
 
 subprojects {
   afterEvaluate {project ->
     if (project.hasProperty("android")) {
       android {
-        compileSdkVersion 28
-        buildToolsVersion "28.0.3"
+        compileSdkVersion 30
       }
     }
   }
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java
index c3a4c890b4bb25239eabe4d83ac10012b454bc78..5591454b1dda527c41f66298082733a59c3cf20c 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadBroadcastReceiver.java
@@ -22,13 +22,11 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.widget.Toast;
 
-import se.leap.bitmaskclient.Constants;
 import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.base.models.Constants;
 import se.leap.bitmaskclient.base.utils.PreferenceHelper;
 
 import static android.app.Activity.RESULT_CANCELED;
-import static se.leap.bitmaskclient.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT;
-import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_PROGRESS;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.NO_NEW_VERISON;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.PROGRESS_VALUE;
@@ -38,6 +36,8 @@ import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_FOUND;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_NOT_FOUND;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.VERIFICATION_ERROR;
 import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.DOWNLOAD_UPDATE;
+import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT;
+import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE;
 
 public class DownloadBroadcastReceiver extends BroadcastReceiver {
 
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java
index bc9adfc1d6211289e1dd042feddd64f5fcecd5cf..46c0457b1df018402b678b0b3bcdd2e440a955ba 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadService.java
@@ -23,7 +23,8 @@ import androidx.annotation.NonNull;
 import androidx.core.app.JobIntentService;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 
-import se.leap.bitmaskclient.OkHttpClientGenerator;
+import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator;
+
 
 public class DownloadService extends JobIntentService implements UpdateDownloadManager.DownloadServiceCallback {
 
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadServiceCommand.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadServiceCommand.java
index c4e809f2ddc4eb2078f35fa0e7ba924cb4a7f33d..4e0d90794a5d8fbd251de9b25da4ebcea1ebe06f 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadServiceCommand.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/DownloadServiceCommand.java
@@ -20,10 +20,10 @@ import android.content.Context;
 import android.content.Intent;
 import android.os.ResultReceiver;
 
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
-import se.leap.bitmaskclient.ProviderAPI;
+import se.leap.bitmaskclient.providersetup.ProviderAPI;
 
 public class DownloadServiceCommand {
 
@@ -35,11 +35,11 @@ public class DownloadServiceCommand {
     private String action;
     private ResultReceiver resultReceiver;
 
-    private DownloadServiceCommand(@NotNull Context context, @NotNull String action) {
+    private DownloadServiceCommand(@NonNull Context context, @NonNull String action) {
         this(context.getApplicationContext(), action, null);
     }
 
-    private DownloadServiceCommand(@NotNull Context context, @NotNull String action, @Nullable ResultReceiver resultReceiver) {
+    private DownloadServiceCommand(@NonNull Context context, @NonNull String action, @Nullable ResultReceiver resultReceiver) {
         super();
         this.context = context;
         this.action = action;
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
index 37a5f01e9560b29ccce5a44a5f4417f9947aea18..69c6feb3087b3cc5954dc2fd917470fa8cee8743 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/InstallActivity.java
@@ -31,9 +31,9 @@ import java.io.File;
 import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.base.utils.PreferenceHelper;
 
-import static se.leap.bitmaskclient.Constants.REQUEST_CODE_REQUEST_UPDATE;
 import static se.leap.bitmaskclient.appUpdate.DownloadConnector.APP_TYPE;
 import static se.leap.bitmaskclient.appUpdate.FileProviderUtil.getUriFor;
+import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_REQUEST_UPDATE;
 
 public class InstallActivity extends Activity {
 
diff --git a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java
index 0db53297add8a6521d65273b7b357159bcd774b2..b50c587cb39ae7095bb0ae9e50aa9e410331e420 100644
--- a/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java
+++ b/app/src/fatweb/java/se.leap.bitmaskclient/appUpdate/UpdateDownloadManager.java
@@ -28,14 +28,10 @@ import okhttp3.OkHttpClient;
 import pgpverify.Logger;
 import pgpverify.PgpVerifier;
 import se.leap.bitmaskclient.BuildConfig;
-import se.leap.bitmaskclient.OkHttpClientGenerator;
 import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator;
 
 import static android.text.TextUtils.isEmpty;
-import static se.leap.bitmaskclient.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT;
-import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_CODE;
-import static se.leap.bitmaskclient.Constants.BROADCAST_RESULT_KEY;
-import static se.leap.bitmaskclient.ProviderAPI.RECEIVER_KEY;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_FAILED;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.DOWNLOAD_PROGRESS;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.NO_NEW_VERISON;
@@ -48,7 +44,11 @@ import static se.leap.bitmaskclient.appUpdate.DownloadService.UPDATE_NOT_FOUND;
 import static se.leap.bitmaskclient.appUpdate.DownloadService.VERIFICATION_ERROR;
 import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.CHECK_VERSION_FILE;
 import static se.leap.bitmaskclient.appUpdate.DownloadServiceCommand.DOWNLOAD_UPDATE;
+import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_DOWNLOAD_SERVICE_EVENT;
+import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE;
+import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY;
 import static se.leap.bitmaskclient.base.utils.FileHelper.readPublicKey;
+import static se.leap.bitmaskclient.providersetup.ProviderAPI.RECEIVER_KEY;
 
 public class UpdateDownloadManager implements Logger, DownloadConnector.DownloadProgress {
 
diff --git a/app/src/insecure/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java b/app/src/insecure/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java
index a566f37add01af1d0aa385e96499e48e8d18198a..6d23c48d566d677ef0165735148943e76ce54367 100644
--- a/app/src/insecure/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java
+++ b/app/src/insecure/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java
@@ -7,8 +7,9 @@ import android.widget.CheckBox;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 
-import butterknife.InjectView;
-import butterknife.Optional;
+import androidx.annotation.Nullable;
+
+import butterknife.BindView;
 import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.providersetup.activities.AddProviderBaseActivity;
 
@@ -20,14 +21,14 @@ public class AddProviderActivity extends AddProviderBaseActivity {
 
     final public static String TAG = "AddProviderActivity";
 
-    @InjectView(R.id.danger_checkbox)
+    @BindView(R.id.danger_checkbox)
     CheckBox checkboxDanger;
 
-    @InjectView(R.id.button_save)
+    @BindView(R.id.button_save)
     Button saveButton;
 
-    @Optional
-    @InjectView(R.id.button_container)
+    @Nullable
+    @BindView(R.id.button_container)
     LinearLayout buttonContainer;
 
     @Override
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7e964211e7911b12c74375889abeea34432e6c13..75b166d905773e9f219713087ecb75d421ba6f09 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -27,12 +27,16 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 		     android:maxSdkVersion="18"/>
+    <!-- Used to show all apps in the allowed Apps selection -->
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 
     <application
         android:name=".base.BitmaskApp"
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
+        android:extractNativeLibs="true"
+        android:appCategory="productivity"
         android:logo="@mipmap/ic_launcher"
         android:theme="@style/BitmaskTheme">
         <service
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 5df1d56b1b8636a7c9c571610e165e349abfc686..3792d092fead212a5d295993cf810981f115eb3f 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -165,6 +165,7 @@ public class VpnProfile implements Serializable, Cloneable {
     public boolean mRemoteRandom = false;
     public HashSet<String> mAllowedAppsVpn = new HashSet<>();
     public boolean mAllowedAppsVpnAreDisallowed = true;
+    public boolean mAllowAppVpnBypass = false;
     public String mCrlFilename;
     public String mProfileCreator;
     public String mExternalAuthenticator;
@@ -186,6 +187,7 @@ public class VpnProfile implements Serializable, Cloneable {
     // set members to default values
     private UUID mUuid;
     private int mProfileVersion;
+    public boolean mBlockUnusedAddressFamilies = true;
     public String mGatewayIp;
     public boolean mUsePluggableTransports;
 
@@ -509,15 +511,18 @@ public class VpnProfile implements Serializable, Cloneable {
 
         if (mUseTLSAuth) {
             boolean useTlsCrypt = mTLSAuthDirection.equals("tls-crypt");
+            boolean useTlsCrypt2 = mTLSAuthDirection.equals("tls-crypt-v2");
 
             if (mAuthenticationType == TYPE_STATICKEYS)
                 cfg.append(insertFileData("secret", mTLSAuthFilename));
             else if (useTlsCrypt)
                 cfg.append(insertFileData("tls-crypt", mTLSAuthFilename));
+            else if (useTlsCrypt2)
+                cfg.append(insertFileData("tls-crypt-v2", mTLSAuthFilename));
             else
                 cfg.append(insertFileData("tls-auth", mTLSAuthFilename));
 
-            if (!TextUtils.isEmpty(mTLSAuthDirection) && !useTlsCrypt) {
+            if (!TextUtils.isEmpty(mTLSAuthDirection) && !useTlsCrypt && !useTlsCrypt2) {
                 cfg.append("key-direction ");
                 cfg.append(mTLSAuthDirection);
                 cfg.append("\n");
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index 7dfacd91368ddf36b88585bc056b0d7144f7f2c9..0d4a80377436d6e4e4c46cac9b445a144b3dd543 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -199,6 +199,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
 
     private boolean runningOnAndroidTV() {
         UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE);
+        if (uiModeManager == null)
+            return false;
         return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
     }
 
@@ -393,6 +395,13 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
             return;
         }
         String nativeLibraryDirectory = getApplicationInfo().nativeLibraryDir;
+        String tmpDir;
+        try {
+            tmpDir = getApplication().getCacheDir().getCanonicalPath();
+        } catch (IOException e) {
+            e.printStackTrace();
+            tmpDir = "/tmp";
+        }
 
         // Write OpenVPN binary
         String[] argv = VPNLaunchHelper.buildOpenvpnArgv(this);
@@ -439,7 +448,7 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
             processThread = (Runnable) mOpenVPN3;
             mManagement = mOpenVPN3;
         } else {
-            processThread = new OpenVPNThread(this, argv, nativeLibraryDirectory);
+            processThread = new OpenVPNThread(this, argv, nativeLibraryDirectory, tmpDir);
             mOpenVPNThread = processThread;
         }
 
@@ -570,7 +579,8 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
 
         VpnStatus.logInfo(R.string.last_openvpn_tun_config);
 
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mProfile.mAllowLocalLAN) {
+        boolean allowUnsetAF = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !mProfile.mBlockUnusedAddressFamilies;
+        if (allowUnsetAF) {
             allowAllAFFamilies(builder);
         }
 
@@ -673,15 +683,34 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
             builder.addSearchDomain(mDomain);
 
         String ipv4info;
+        String ipv6info;
+        if (allowUnsetAF) {
+            ipv4info = "(not set, allowed)";
+            ipv6info = "(not set, allowed)";
+        } else {
+            ipv4info = "(not set)";
+            ipv6info = "(not set)";
+        }
+
         int ipv4len;
         if (mLocalIP!=null) {
             ipv4len=mLocalIP.len;
             ipv4info=mLocalIP.mIp;
         } else {
             ipv4len = -1;
-            ipv4info="(not set)";
         }
-        VpnStatus.logInfo(R.string.local_ip_info, ipv4info, ipv4len, mLocalIPv6, mMtu);
+
+        if (mLocalIPv6!=null)
+        {
+            ipv6info = mLocalIPv6;
+        }
+
+        if ((!mRoutes.getNetworks(false).isEmpty() || !mRoutesv6.getNetworks(false).isEmpty()) && isLockdownEnabledCompat())
+        {
+            VpnStatus.logInfo("VPN lockdown enabled (do not allow apps to bypass VPN) enabled. Route exclusion will not allow apps to bypass VPN (e.g. bypass VPN for local networks)");
+        }
+
+        VpnStatus.logInfo(R.string.local_ip_info, ipv4info, ipv4len, ipv6info, mMtu);
         VpnStatus.logInfo(R.string.dns_server_info, TextUtils.join(", ", mDnslist), mDomain);
         VpnStatus.logInfo(R.string.routes_info_incl, TextUtils.join(", ", mRoutes.getNetworks(true)), TextUtils.join(", ", mRoutesv6.getNetworks(true)));
         VpnStatus.logInfo(R.string.routes_info_excl, TextUtils.join(", ", mRoutes.getNetworks(false)), TextUtils.join(", ", mRoutesv6.getNetworks(false)));
@@ -694,6 +723,12 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
             builder.setUnderlyingNetworks(null);
         }
 
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+            // Setting this false, will cause the VPN to inherit the underlying network metered
+            // value
+            builder.setMetered(false);
+        }
+
 
         String session = mProfile.mName;
         if (mLocalIP != null && mLocalIPv6 != null)
@@ -736,6 +771,15 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
 
     }
 
+    private boolean isLockdownEnabledCompat() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+            return isLockdownEnabled();
+        } else {
+            /* We cannot determine this, return false */
+            return false;
+        }
+    }
+
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     private void allowAllAFFamilies(Builder builder) {
         builder.allowFamily(OsConstants.AF_INET);
@@ -822,6 +866,11 @@ public class OpenVPNService extends VpnService implements StateListener, Callbac
         } else {
             VpnStatus.logDebug(R.string.allowed_vpn_apps_info, TextUtils.join(", ", mProfile.mAllowedAppsVpn));
         }
+
+        if (mProfile.mAllowAppVpnBypass) {
+            builder.allowBypass();
+            VpnStatus.logDebug("Apps may bypass VPN");
+        }
     }
 
     public void addDNS(String dns) {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
index b902f5d7edf68115bb1f4a79cb6a4cf947b7e053..fc77d9a524c9cd901fa41f0f90b865a631f941b8 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNThread.java
@@ -37,15 +37,17 @@ public class OpenVPNThread implements Runnable {
     private String[] mArgv;
     private Process mProcess;
     private String mNativeDir;
+    private String mTmpDir;
     private OpenVPNService mService;
     private String mDumpPath;
     private boolean mBrokenPie = false;
     private boolean mNoProcessExitStatus = false;
 
-    public OpenVPNThread(OpenVPNService service, String[] argv, String nativelibdir) {
+    public OpenVPNThread(OpenVPNService service, String[] argv, String nativelibdir, String tmpdir) {
         mArgv = argv;
         mNativeDir = nativelibdir;
         mService = service;
+        mTmpDir = tmpdir;
     }
 
     public void stopProcess() {
@@ -128,6 +130,7 @@ public class OpenVPNThread implements Runnable {
         String lbpath = genLibraryPath(argv, pb);
 
         pb.environment().put("LD_LIBRARY_PATH", lbpath);
+        pb.environment().put("TMPDIR", mTmpDir);
 
         pb.redirectErrorStream(true);
         try {
diff --git a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
index 810974df6ca5231f12da68cf3b0a396a972563e8..7c742746a522d95a0f947b8ad92b54a0427e027e 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/VPNLaunchHelper.java
@@ -27,6 +27,10 @@ public class VPNLaunchHelper {
 
 
     private static String writeMiniVPN(Context context) {
+        String nativeAPI = NativeUtils.getNativeAPI();
+        /* Q does not allow executing binaries written in temp directory anymore */
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
+            return new File(context.getApplicationInfo().nativeLibraryDir, "libovpnexec.so").getPath();
         String[] abis;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
             abis = getSupportedABIsLollipop();
@@ -34,7 +38,6 @@ public class VPNLaunchHelper {
             //noinspection deprecation
             abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2};
 
-        String nativeAPI = NativeUtils.getNativeAPI();
         if (!nativeAPI.equals(abis[0])) {
             VpnStatus.logWarning(R.string.abi_mismatch, Arrays.toString(abis), nativeAPI);
             abis = new String[]{nativeAPI};
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java
index d901ba68b82d10f96c45cb47b7727329ae50d9f7..c269c8728d9208bfcd24d26ec673dccff1c21c93 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/AboutFragment.java
@@ -3,14 +3,16 @@ package se.leap.bitmaskclient.base.fragments;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
-import androidx.fragment.app.Fragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
+import androidx.fragment.app.Fragment;
+
+import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.InjectView;
+import butterknife.Unbinder;
 import se.leap.bitmaskclient.BuildConfig;
 import se.leap.bitmaskclient.R;
 
@@ -20,17 +22,18 @@ public class AboutFragment extends Fragment {
 
     final public static String TAG = AboutFragment.class.getSimpleName();
     final public static int VIEWED = 0;
+    private Unbinder unbinder;
 
-    @InjectView(R.id.version)
+    @BindView(R.id.version)
     TextView versionTextView;
 
-    @InjectView(R.id.terms_of_service)
+    @BindView(R.id.terms_of_service)
     TextView termsOfService;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         View view = inflater.inflate(R.layout.f_about, container, false);
-        ButterKnife.inject(this, view);
+        unbinder = ButterKnife.bind(this, view);
         return view;
     }
 
@@ -56,6 +59,12 @@ public class AboutFragment extends Fragment {
         }
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        unbinder.unbind();
+    }
+
     private boolean hasTermsOfServiceResource() {
         return getTermsOfServiceResource() != 0;
     }
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/AlwaysOnDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/AlwaysOnDialog.java
index a8034e1a14d4fea5f0e89b48e0b08cc8c0b97f86..7d457406b1522707ec490736f4c4f562c40dcec3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/AlwaysOnDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/AlwaysOnDialog.java
@@ -4,17 +4,19 @@ import android.app.Dialog;
 import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AlertDialog;
 import androidx.appcompat.app.AppCompatDialogFragment;
 import androidx.appcompat.widget.AppCompatTextView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.CheckBox;
 
+import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.InjectView;
+import butterknife.Unbinder;
 import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.base.views.IconTextView;
 
@@ -31,15 +33,17 @@ public class AlwaysOnDialog extends AppCompatDialogFragment {
 
     public final static String TAG = AlwaysOnDialog.class.getName();
 
-    @InjectView(R.id.do_not_show_again)
+    @BindView(R.id.do_not_show_again)
     CheckBox doNotShowAgainCheckBox;
 
-    @InjectView(R.id.user_message)
+    @BindView(R.id.user_message)
     IconTextView userMessage;
 
-    @InjectView(R.id.block_vpn_user_message)
+    @BindView(R.id.block_vpn_user_message)
     AppCompatTextView blockVpnUserMessage;
 
+    private Unbinder unbinder;
+
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -52,7 +56,7 @@ public class AlwaysOnDialog extends AppCompatDialogFragment {
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         LayoutInflater inflater = getActivity().getLayoutInflater();
         View view = inflater.inflate(R.layout.d_checkbox_confirm, null);
-        ButterKnife.inject(this, view);
+        unbinder = ButterKnife.bind(this, view);
 
         userMessage.setIcon(R.drawable.ic_settings);
         userMessage.setText(getString(R.string.always_on_vpn_user_message));
@@ -73,4 +77,10 @@ public class AlwaysOnDialog extends AppCompatDialogFragment {
                 .setNegativeButton(R.string.cancel, (dialog, id) -> dialog.cancel());
         return builder.create();
     }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        unbinder.unbind();
+    }
 }
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/DonationReminderDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/DonationReminderDialog.java
index 0277933c65d15f3090f779d4f5e710bbdfd90445..c39386fc950baf4b13c546e870abb31d22dddad7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/DonationReminderDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/DonationReminderDialog.java
@@ -6,19 +6,21 @@ import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatDialogFragment;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.Button;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatDialogFragment;
+
 import java.text.ParseException;
 
+import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.InjectView;
+import butterknife.Unbinder;
 import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.base.utils.DateHelper;
 import se.leap.bitmaskclient.base.utils.PreferenceHelper;
@@ -35,12 +37,14 @@ public class DonationReminderDialog extends AppCompatDialogFragment {
     public final static String TAG = DonationReminderDialog.class.getName();
     private static boolean isShown = false;
 
-    @InjectView(R.id.btnDonate)
+    @BindView(R.id.btnDonate)
     Button btnDonate;
 
-    @InjectView(R.id.btnLater)
+    @BindView(R.id.btnLater)
     Button btnLater;
 
+    private Unbinder unbinder;
+
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -52,7 +56,7 @@ public class DonationReminderDialog extends AppCompatDialogFragment {
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         LayoutInflater inflater = getActivity().getLayoutInflater();
         View view = inflater.inflate(R.layout.donation_reminder_dialog, null);
-        ButterKnife.inject(this, view);
+        unbinder = ButterKnife.bind(this, view);
         isShown = true;
 
         builder.setView(view);
@@ -76,6 +80,12 @@ public class DonationReminderDialog extends AppCompatDialogFragment {
         return builder.create();
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        unbinder.unbind();
+    }
+
     public static boolean isCallable(Context context) {
         if (isShown) {
             return false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java
index 9544fb1e2bfad2a890d2ddf165422ebae8b20c81..d8501a9204aa1733c5f90ac7ca828a249a456453 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java
@@ -48,9 +48,10 @@ import androidx.fragment.app.FragmentTransaction;
 import java.util.Observable;
 import java.util.Observer;
 
+import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.InjectView;
 import butterknife.OnClick;
+import butterknife.Unbinder;
 import de.blinkt.openvpn.core.IOpenVPNServiceInternal;
 import de.blinkt.openvpn.core.OpenVPNService;
 import de.blinkt.openvpn.core.VpnStatus;
@@ -97,23 +98,22 @@ public class EipFragment extends Fragment implements Observer {
     private SharedPreferences preferences;
     private Provider provider;
 
-    @InjectView(R.id.background)
+    @BindView(R.id.background)
     AppCompatImageView background;
 
-    @InjectView(R.id.vpn_state_image)
+    @BindView(R.id.vpn_state_image)
     VpnStateImage vpnStateImage;
 
-    @InjectView(R.id.vpn_main_button)
+    @BindView(R.id.vpn_main_button)
     AppCompatButton mainButton;
 
-    @InjectView(R.id.routed_text)
+    @BindView(R.id.routed_text)
     AppCompatTextView routedText;
 
-    @InjectView(R.id.vpn_route)
+    @BindView(R.id.vpn_route)
     AppCompatTextView vpnRoute;
 
-
-
+    private Unbinder unbinder;
     private EipStatus eipStatus;
 
     //---saved Instance -------
@@ -157,8 +157,6 @@ public class EipFragment extends Fragment implements Observer {
 
     }
 
-
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -176,7 +174,7 @@ public class EipFragment extends Fragment implements Observer {
     public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         eipStatus.addObserver(this);
         View view = inflater.inflate(R.layout.f_eip, container, false);
-        ButterKnife.inject(this, view);
+        unbinder = ButterKnife.bind(this, view);
 
         Bundle arguments = getArguments();
         if (arguments != null && arguments.containsKey(ASK_TO_CANCEL_VPN) && arguments.getBoolean(ASK_TO_CANCEL_VPN)) {
@@ -241,6 +239,7 @@ public class EipFragment extends Fragment implements Observer {
     public void onDestroyView() {
         super.onDestroyView();
         eipStatus.deleteObserver(this);
+        unbinder.unbind();
     }
 
     private void saveStatus(boolean restartOnBoot) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
index 8593e25c0825f1c64819878c93461cd2ad4847b6..675f1a61f7f5477918dd4bd69950fb404333edd2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
@@ -7,12 +7,6 @@ import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.provider.Settings;
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatDialogFragment;
-import androidx.appcompat.widget.AppCompatTextView;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.method.LinkMovementMethod;
@@ -22,19 +16,27 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatDialogFragment;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
 import java.util.Observable;
 import java.util.Observer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.InjectView;
+import butterknife.Unbinder;
 import de.blinkt.openvpn.core.VpnStatus;
 import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.firewall.FirewallManager;
-import se.leap.bitmaskclient.tethering.TetheringObservable;
 import se.leap.bitmaskclient.base.utils.PreferenceHelper;
 import se.leap.bitmaskclient.base.views.IconCheckboxEntry;
+import se.leap.bitmaskclient.firewall.FirewallManager;
+import se.leap.bitmaskclient.tethering.TetheringObservable;
 
 /**
  * Copyright (c) 2020 LEAP Encryption Access Project and contributers
@@ -57,16 +59,17 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
 
     public final static String TAG = TetheringDialog.class.getName();
 
-    @InjectView(R.id.tvTitle)
+    @BindView(R.id.tvTitle)
     AppCompatTextView title;
 
-    @InjectView(R.id.user_message)
+    @BindView(R.id.user_message)
     AppCompatTextView userMessage;
 
-    @InjectView(R.id.selection_list_view)
+    @BindView(R.id.selection_list_view)
     RecyclerView selectionListView;
     DialogListAdapter adapter;
     private DialogListAdapter.ViewModel[] dataset;
+    private Unbinder unbinder;
 
     public static class DialogListAdapter extends RecyclerView.Adapter<DialogListAdapter.ViewHolder> {
 
@@ -137,7 +140,7 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         LayoutInflater inflater = getActivity().getLayoutInflater();
         View view = inflater.inflate(R.layout.d_list_selection, null);
-        ButterKnife.inject(this, view);
+        unbinder = ButterKnife.bind(this, view);
 
         title.setText(R.string.tethering);
         userMessage.setMovementMethod(LinkMovementMethod.getInstance());
@@ -187,6 +190,12 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
         TetheringObservable.getInstance().deleteObserver(this);
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        unbinder.unbind();
+    }
+
     public void onItemClick(DialogListAdapter.ViewModel item) {
 
     }
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java b/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java
index fdbd7dbd8632d5234a3cc9844683913254c68ed7..977056f7528b626d76f5a3716178ec7e32168f6a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/views/IconCheckboxEntry.java
@@ -3,31 +3,32 @@ package se.leap.bitmaskclient.base.views;
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
-import androidx.appcompat.widget.AppCompatImageView;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
+
+import butterknife.BindView;
 import butterknife.ButterKnife;
-import butterknife.InjectView;
 import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.base.fragments.TetheringDialog;
 
 
 public class IconCheckboxEntry extends LinearLayout {
 
-    @InjectView(android.R.id.text1)
+    @BindView(android.R.id.text1)
     TextView textView;
 
-    @InjectView(R.id.material_icon)
+    @BindView(R.id.material_icon)
     AppCompatImageView iconView;
 
-    @InjectView(R.id.checked_icon)
+    @BindView(R.id.checked_icon)
     AppCompatImageView checkedIcon;
 
     public IconCheckboxEntry(Context context) {
@@ -55,10 +56,7 @@ public class IconCheckboxEntry extends LinearLayout {
         LayoutInflater inflater = (LayoutInflater) context
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View rootview = inflater.inflate(R.layout.v_icon_select_text_list_item, this, true);
-        ButterKnife.inject(this, rootview);
-
-
-
+        ButterKnife.bind(this, rootview);
     }
 
     public void bind(TetheringDialog.DialogListAdapter.ViewModel model) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java
index 39d4e33e74f43188fee6422cbc28a831dbdda666..0650e8cd48ad2d446b9434e0feb53f3af35c6aad 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipCommand.java
@@ -6,11 +6,9 @@ import android.content.Intent;
 import android.os.ResultReceiver;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
 import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CHECK_CERT_VALIDITY;
 import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_CONFIGURE_TETHERING;
 import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START;
@@ -26,7 +24,7 @@ import static se.leap.bitmaskclient.base.models.Constants.EIP_RECEIVER;
 
 public class EipCommand {
 
-    private static void execute(@NotNull Context context, @NotNull String action) {
+    private static void execute(@NonNull Context context, @NonNull String action) {
         execute(context.getApplicationContext(), action, null, null);
     }
 
@@ -37,7 +35,7 @@ public class EipCommand {
      *               filter for the EIP class
      * @param resultReceiver The resultreceiver to reply to
      */
-    private static void execute(@NotNull Context context, @NotNull String action, @Nullable ResultReceiver resultReceiver, @Nullable Intent vpnIntent) {
+    private static void execute(@NonNull Context context, @NonNull String action, @Nullable ResultReceiver resultReceiver, @Nullable Intent vpnIntent) {
         if (vpnIntent == null) {
             vpnIntent = new Intent();
         }
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPICommand.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPICommand.java
index 79a107d108023818c3e4526136fb292cd91df730..1408dce8cdcfbf04cc13430c1e3fe198104fa3e7 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPICommand.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPICommand.java
@@ -5,8 +5,8 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.os.ResultReceiver;
 
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import se.leap.bitmaskclient.base.models.Constants;
 import se.leap.bitmaskclient.base.models.Provider;
@@ -20,18 +20,18 @@ public class ProviderAPICommand {
     private ResultReceiver resultReceiver;
     private Provider provider;
 
-    private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Provider provider, ResultReceiver resultReceiver) {
+    private ProviderAPICommand(@NonNull Context context, @NonNull String action, @NonNull Provider provider, ResultReceiver resultReceiver) {
         this(context.getApplicationContext(), action, Bundle.EMPTY, provider, resultReceiver);
     }
-    private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Provider provider) {
+    private ProviderAPICommand(@NonNull Context context, @NonNull String action, @NonNull Provider provider) {
         this(context.getApplicationContext(), action, Bundle.EMPTY, provider);
     }
 
-    private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Bundle parameters, @NotNull Provider provider) {
+    private ProviderAPICommand(@NonNull Context context, @NonNull String action, @NonNull Bundle parameters, @NonNull Provider provider) {
         this(context.getApplicationContext(), action, parameters, provider, null);
     }
 
-    private ProviderAPICommand(@NotNull Context context, @NotNull String action, @NotNull Bundle parameters, @NotNull Provider provider, @Nullable ResultReceiver resultReceiver) {
+    private ProviderAPICommand(@NonNull Context context, @NonNull String action, @NonNull Bundle parameters, @NonNull Provider provider, @Nullable ResultReceiver resultReceiver) {
         super();
         this.context = context;
         this.action = action;
@@ -64,22 +64,22 @@ public class ProviderAPICommand {
         return command;
     }
 
-    public static void execute(Context context, String action, @NotNull Provider provider) {
+    public static void execute(Context context, String action, @NonNull Provider provider) {
         ProviderAPICommand command = new ProviderAPICommand(context, action, provider);
         command.execute();
     }
 
-    public static void execute(Context context, String action, Bundle parameters, @NotNull Provider provider) {
+    public static void execute(Context context, String action, Bundle parameters, @NonNull Provider provider) {
         ProviderAPICommand command = new ProviderAPICommand(context, action, parameters, provider);
         command.execute();
     }
 
-    public static void execute(Context context, String action, Bundle parameters, @NotNull Provider provider, ResultReceiver resultReceiver) {
+    public static void execute(Context context, String action, Bundle parameters, @NonNull Provider provider, ResultReceiver resultReceiver) {
         ProviderAPICommand command = new ProviderAPICommand(context, action, parameters, provider, resultReceiver);
         command.execute();
     }
 
-    public static void execute(Context context, String action, @NotNull Provider provider, ResultReceiver resultReceiver) {
+    public static void execute(Context context, String action, @NonNull Provider provider, ResultReceiver resultReceiver) {
         ProviderAPICommand command = new ProviderAPICommand(context, action, provider, resultReceiver);
         command.execute();
     }
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderRenderer.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderRenderer.java
index 52ee46560615eaae1ee5c18bf75d33fe488840c9..339199e0922e467f9bdef412dc2553b4f1ec1660 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderRenderer.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderRenderer.java
@@ -1,14 +1,17 @@
 package se.leap.bitmaskclient.providersetup;
 
-import android.content.*;
-import android.view.*;
-import android.widget.*;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
 
-import com.pedrogomez.renderers.*;
+import com.pedrogomez.renderers.Renderer;
 
-import butterknife.*;
-import se.leap.bitmaskclient.base.models.Provider;
+import butterknife.BindView;
+import butterknife.ButterKnife;
 import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.base.models.Provider;
 
 /**
  * Created by parmegv on 4/12/14.
@@ -16,9 +19,9 @@ import se.leap.bitmaskclient.R;
 public class ProviderRenderer extends Renderer<Provider> {
     private final Context context;
 
-    @InjectView(R.id.provider_name)
+    @BindView(R.id.provider_name)
     TextView name;
-    @InjectView(R.id.provider_domain)
+    @BindView(R.id.provider_domain)
     TextView domain;
 
     public ProviderRenderer(Context context) {
@@ -28,7 +31,7 @@ public class ProviderRenderer extends Renderer<Provider> {
     @Override
     protected View inflate(LayoutInflater inflater, ViewGroup parent) {
         View view = inflater.inflate(R.layout.v_provider_list_item, parent, false);
-        ButterKnife.inject(this, view);
+        ButterKnife.bind(this, view);
         return view;
     }
 
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AbstractProviderDetailActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AbstractProviderDetailActivity.java
index b7325e03bd9322f53616edad6d6e218f4cbbe3ac..ba84ed9a195b7a8ffeeb8f01654259bf3aa3883a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AbstractProviderDetailActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AbstractProviderDetailActivity.java
@@ -11,7 +11,8 @@ import android.widget.TextView;
 
 import java.util.ArrayList;
 
-import butterknife.InjectView;
+
+import butterknife.BindView;
 import se.leap.bitmaskclient.base.models.Provider;
 import se.leap.bitmaskclient.R;
 
@@ -22,10 +23,10 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct
 
     final public static String TAG = "providerDetailActivity";
 
-    @InjectView(R.id.provider_detail_description)
+    @BindView(R.id.provider_detail_description)
     AppCompatTextView description;
 
-    @InjectView(R.id.provider_detail_options)
+    @BindView(R.id.provider_detail_options)
     ListView options;
 
     @Override
@@ -39,7 +40,6 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct
             return;
         }
 
-
         setProviderHeaderText(provider.getName());
         description.setText(provider.getDescription());
 
@@ -55,7 +55,6 @@ public abstract class AbstractProviderDetailActivity extends ConfigWizardBaseAct
             onAnonymouslySelected();
         }
 
-
         options.setAdapter(new ArrayAdapter<>(
                 this,
                 R.layout.v_single_list_item,
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AddProviderBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AddProviderBaseActivity.java
index 0031f48ddea2827f730800ce29e3a39122055d69..193c1d59a2e686e0b02b52fe5387036cfdaa1480 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AddProviderBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/AddProviderBaseActivity.java
@@ -2,14 +2,15 @@ package se.leap.bitmaskclient.providersetup.activities;
 
 import android.content.Intent;
 import android.os.Bundle;
-import com.google.android.material.textfield.TextInputEditText;
-import com.google.android.material.textfield.TextInputLayout;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.View;
 import android.widget.Button;
 
-import butterknife.InjectView;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.android.material.textfield.TextInputLayout;
+
+import butterknife.BindView;
 import se.leap.bitmaskclient.R;
 
 import static se.leap.bitmaskclient.providersetup.activities.ProviderListBaseActivity.EXTRAS_KEY_INVALID_URL;
@@ -22,16 +23,16 @@ public abstract class AddProviderBaseActivity extends ConfigWizardBaseActivity {
 
     final public static String EXTRAS_KEY_NEW_URL = "NEW_URL";
 
-    @InjectView(R.id.text_uri_error)
+    @BindView(R.id.text_uri_error)
     TextInputLayout urlError;
 
-    @InjectView(R.id.text_uri)
+    @BindView(R.id.text_uri)
     TextInputEditText editUrl;
 
-    @InjectView(R.id.button_cancel)
+    @BindView(R.id.button_cancel)
     Button cancelButton;
 
-    @InjectView(R.id.button_save)
+    @BindView(R.id.button_save)
     Button saveButton;
 
 
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ButterKnifeActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ButterKnifeActivity.java
index 22edd9eedb88ea90299fb33b6b2ece1291eac7d7..c695cc46bd074e9b0778ab2b0ebbba7247cac0dc 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ButterKnifeActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ButterKnifeActivity.java
@@ -16,9 +16,10 @@
  */
 package se.leap.bitmaskclient.providersetup.activities;
 
-import androidx.appcompat.app.AppCompatActivity;
 import android.view.View;
 
+import androidx.appcompat.app.AppCompatActivity;
+
 import butterknife.ButterKnife;
 
 /**
@@ -30,13 +31,13 @@ public abstract class ButterKnifeActivity extends AppCompatActivity {
     @Override
     public void setContentView(View view) {
         super.setContentView(view);
-        ButterKnife.inject(this);
+        ButterKnife.bind(this);
     }
 
     @Override
     public void setContentView(int layoutResID) {
         super.setContentView(layoutResID);
-        ButterKnife.inject(this);
+        ButterKnife.bind(this);
     }
 
     @Override
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java
index 3712c5443e257f82ac5a437ebc139bc56e3bec42..b2f13e0792fa0a3c216e3108c97dc2854915d19d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ConfigWizardBaseActivity.java
@@ -5,23 +5,24 @@ import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
+import androidx.appcompat.widget.AppCompatTextView;
 import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.constraintlayout.widget.Guideline;
 import androidx.core.content.ContextCompat;
-import androidx.appcompat.widget.AppCompatTextView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
 
-import butterknife.InjectView;
+import butterknife.BindView;
 import butterknife.Optional;
-import se.leap.bitmaskclient.base.models.Provider;
 import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.base.models.Provider;
 import se.leap.bitmaskclient.base.views.ProviderHeaderView;
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -42,32 +43,32 @@ public abstract class ConfigWizardBaseActivity extends ButterKnifeActivity {
     public static final float GUIDE_LINE_COMPACT_DELTA = 0.1f;
     protected SharedPreferences preferences;
 
-    @InjectView(R.id.header)
+    @BindView(R.id.header)
     ProviderHeaderView providerHeaderView;
 
     //Add provider screen has no loading screen
-    @Optional
-    @InjectView(R.id.loading_screen)
+    @Nullable
+    @BindView(R.id.loading_screen)
     protected LinearLayout loadingScreen;
 
-    @Optional
-    @InjectView(R.id.progressbar)
+    @Nullable
+    @BindView(R.id.progressbar)
     protected ProgressBar progressBar;
 
-    @Optional
-    @InjectView(R.id.progressbar_description)
+    @Nullable
+    @BindView(R.id.progressbar_description)
     protected AppCompatTextView progressbarText;
 
     //Only tablet layouts have guidelines as they are based on a ConstraintLayout
-    @Optional
-    @InjectView(R.id.guideline_top)
+    @Nullable
+    @BindView(R.id.guideline_top)
     protected Guideline guideline_top;
 
-    @Optional
-    @InjectView(R.id.guideline_bottom)
+    @Nullable
+    @BindView(R.id.guideline_bottom)
     protected Guideline guideline_bottom;
 
-    @InjectView(R.id.content)
+    @BindView(R.id.content)
     protected LinearLayout content;
 
     protected Provider provider;
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderCredentialsBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderCredentialsBaseActivity.java
index 91d0de566f8a653f99cf7e2f7de5f01e78e68258..e186ce5dfe7f1bd822b5efbd8efe0c11ca415c4d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderCredentialsBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderCredentialsBaseActivity.java
@@ -43,7 +43,7 @@ import android.widget.TextView;
 import org.json.JSONArray;
 import org.json.JSONException;
 
-import butterknife.InjectView;
+import butterknife.BindView;
 import butterknife.OnClick;
 import se.leap.bitmaskclient.base.models.Constants.CREDENTIAL_ERRORS;
 import se.leap.bitmaskclient.base.models.Provider;
@@ -87,28 +87,28 @@ public abstract class ProviderCredentialsBaseActivity extends ConfigWizardBaseAc
     protected Intent mConfigState = new Intent(SHOWING_FORM);
     protected ProviderAPIBroadcastReceiver providerAPIBroadcastReceiver;
 
-    @InjectView(R.id.provider_credentials_user_message)
+    @BindView(R.id.provider_credentials_user_message)
     AppCompatTextView userMessage;
 
-    @InjectView(R.id.provider_credentials_username)
+    @BindView(R.id.provider_credentials_username)
     TextInputEditText usernameField;
 
-    @InjectView(R.id.provider_credentials_password)
+    @BindView(R.id.provider_credentials_password)
     TextInputEditText passwordField;
 
-    @InjectView(R.id.provider_credentials_password_verification)
+    @BindView(R.id.provider_credentials_password_verification)
     TextInputEditText passwordVerificationField;
 
-    @InjectView(R.id.provider_credentials_username_error)
+    @BindView(R.id.provider_credentials_username_error)
     TextInputLayout usernameError;
 
-    @InjectView(R.id.provider_credentials_password_error)
+    @BindView(R.id.provider_credentials_password_error)
     TextInputLayout passwordError;
 
-    @InjectView(R.id.provider_credentials_password_verification_error)
+    @BindView(R.id.provider_credentials_password_verification_error)
     TextInputLayout passwordVerificationError;
 
-    @InjectView(R.id.button)
+    @BindView(R.id.button)
     AppCompatButton button;
 
     private boolean isUsernameError = false;
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java
index 46a40d118ab94e0364142a3555c439e2bd96279f..002335dbc7a4a57079b68019414cc1604bb577ce 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderListBaseActivity.java
@@ -30,15 +30,15 @@ import java.util.List;
 
 import javax.inject.Inject;
 
-import butterknife.InjectView;
+import butterknife.BindView;
 import butterknife.OnItemClick;
-import se.leap.bitmaskclient.providersetup.AddProviderActivity;
+import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.base.models.Provider;
+import se.leap.bitmaskclient.providersetup.AddProviderActivity;
 import se.leap.bitmaskclient.providersetup.ProviderListActivity;
+import se.leap.bitmaskclient.providersetup.ProviderListAdapter;
 import se.leap.bitmaskclient.providersetup.ProviderRenderer;
 import se.leap.bitmaskclient.providersetup.ProviderRendererBuilder;
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.providersetup.ProviderListAdapter;
 
 import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_ADD_PROVIDER;
 import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_CONFIGURE_LEAP;
@@ -58,7 +58,7 @@ import static se.leap.bitmaskclient.providersetup.ProviderSetupInterface.Provide
 
 public abstract class ProviderListBaseActivity extends ProviderSetupBaseActivity {
 
-    @InjectView(R.id.provider_list)
+    @BindView(R.id.provider_list)
     protected ListView providerListView;
     @Inject
     protected ProviderListAdapter adapter;
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderSetupBaseActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderSetupBaseActivity.java
index e54fb048a4f0850599d8ce48fdbf21a66f08bda4..40efd8114be7938c8258ab416d7852991f60b3c9 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderSetupBaseActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/ProviderSetupBaseActivity.java
@@ -21,12 +21,12 @@ import android.content.IntentFilter;
 import android.os.Bundle;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.FragmentTransaction;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 
-import org.jetbrains.annotations.NotNull;
 import org.json.JSONException;
 import org.json.JSONObject;
 
@@ -107,7 +107,7 @@ public abstract class ProviderSetupBaseActivity extends ConfigWizardBaseActivity
 
 
     @Override
-    public void onSaveInstanceState(@NotNull Bundle outState) {
+    public void onSaveInstanceState(@NonNull Bundle outState) {
         outState.putString(ACTIVITY_STATE, providerConfigState.toString());
         outState.putString(REASON_TO_FAIL, reasonToFail);
 
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/connectivity/DnsResolver.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/connectivity/DnsResolver.java
index 44de1e6d9d44f1c2dcc2478b3e56094666ff68f7..c5100a6781a2140412a0812b1602e67603a1b86a 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/connectivity/DnsResolver.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/connectivity/DnsResolver.java
@@ -1,6 +1,6 @@
 package se.leap.bitmaskclient.providersetup.connectivity;
 
-import org.jetbrains.annotations.NotNull;
+import androidx.annotation.NonNull;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
@@ -15,7 +15,7 @@ import se.leap.bitmaskclient.base.utils.IPAddress;
 class DnsResolver implements Dns {
 
     @Override
-    public List<InetAddress> lookup(@NotNull String hostname) throws UnknownHostException {
+    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
         try {
             return Dns.SYSTEM.lookup(hostname);
         } catch (UnknownHostException e) {
diff --git a/app/src/production/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java b/app/src/production/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java
index d05c76f08bd2f174cb1b62c3cfe5b33a0b8dc04c..7ca707db0a75e2d54d65a2d76fd4928dc3eea25d 100644
--- a/app/src/production/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java
+++ b/app/src/production/java/se/leap/bitmaskclient/providersetup/AddProviderActivity.java
@@ -4,7 +4,7 @@ import android.os.Bundle;
 import android.view.View;
 import android.widget.Button;
 
-import butterknife.InjectView;
+import butterknife.BindView;
 import se.leap.bitmaskclient.R;
 import se.leap.bitmaskclient.providersetup.activities.AddProviderBaseActivity;
 
@@ -12,7 +12,7 @@ public class AddProviderActivity extends AddProviderBaseActivity {
 
     final public static String TAG = "AddProviderActivity";
 
-    @InjectView(R.id.button_save)
+    @BindView(R.id.button_save)
     Button saveButton;
 
     @Override
diff --git a/bitmask-core/bitmask-core.aar b/bitmask-core/bitmask-core.aar
index 37e25808d0ef12cf9647928105a8680f2b888a8c..bceec02d79b217ecc4ea237a0e8d505aa3c266d4 100644
Binary files a/bitmask-core/bitmask-core.aar and b/bitmask-core/bitmask-core.aar differ
diff --git a/bitmask-web-core/bitmask-web-core-sources.jar b/bitmask-web-core/bitmask-web-core-sources.jar
index 6788dc007bca3732d3b2c814ce8e0b703c9fd6a3..64edeb9bd37d7ae229b7128f790b5009228981a5 100644
Binary files a/bitmask-web-core/bitmask-web-core-sources.jar and b/bitmask-web-core/bitmask-web-core-sources.jar differ
diff --git a/bitmask-web-core/bitmask-web-core.aar b/bitmask-web-core/bitmask-web-core.aar
index 6f580439cba3b91c95651282ae6ed85b1093ef1e..0e5108c0f0f7dc4eaf813731b622fa732c53b9a1 100644
Binary files a/bitmask-web-core/bitmask-web-core.aar and b/bitmask-web-core/bitmask-web-core.aar differ
diff --git a/go/lib/README b/go/lib/README
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/ics-openvpn b/ics-openvpn
index 446814e65e2f7ad8ba544d020a5ddce9d2e37230..f2ca3dc135452ffb733711ba735056bb61a7a67f 160000
--- a/ics-openvpn
+++ b/ics-openvpn
@@ -1 +1 @@
-Subproject commit 446814e65e2f7ad8ba544d020a5ddce9d2e37230
+Subproject commit f2ca3dc135452ffb733711ba735056bb61a7a67f