global: Add nullity annotations
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
This commit is contained in:
parent
fbaa4d9ab1
commit
67ea8b2936
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ build/
|
|||||||
*.iml
|
*.iml
|
||||||
*.jks
|
*.jks
|
||||||
keystore.properties
|
keystore.properties
|
||||||
|
package-info.java
|
||||||
|
@ -94,6 +94,8 @@
|
|||||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||||
</XML>
|
</XML>
|
||||||
<codeStyleSettings language="JAVA">
|
<codeStyleSettings language="JAVA">
|
||||||
|
<option name="METHOD_ANNOTATION_WRAP" value="0" />
|
||||||
|
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||||
<arrangement>
|
<arrangement>
|
||||||
<groups />
|
<groups />
|
||||||
<rules>
|
<rules>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
apply from: 'nonnull.gradle'
|
||||||
|
|
||||||
// Create a variable called keystorePropertiesFile, and initialize it to your
|
// Create a variable called keystorePropertiesFile, and initialize it to your
|
||||||
// keystore.properties file, in the rootProject folder.
|
// keystore.properties file, in the rootProject folder.
|
||||||
@ -56,6 +57,7 @@ ext {
|
|||||||
databindingVersion = '3.1.3'
|
databindingVersion = '3.1.3'
|
||||||
supportLibsVersion = '27.1.1'
|
supportLibsVersion = '27.1.1'
|
||||||
streamsupportVersion = '1.6.0'
|
streamsupportVersion = '1.6.0'
|
||||||
|
jsr305Version = '3.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -67,6 +69,7 @@ dependencies {
|
|||||||
implementation "com.android.support:support-annotations:$supportLibsVersion"
|
implementation "com.android.support:support-annotations:$supportLibsVersion"
|
||||||
implementation "net.sourceforge.streamsupport:android-retrofuture:$streamsupportVersion"
|
implementation "net.sourceforge.streamsupport:android-retrofuture:$streamsupportVersion"
|
||||||
implementation "net.sourceforge.streamsupport:android-retrostreams:$streamsupportVersion"
|
implementation "net.sourceforge.streamsupport:android-retrostreams:$streamsupportVersion"
|
||||||
|
implementation "com.google.code.findbugs:jsr305:$jsr305Version"
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
|
87
app/nonnull.gradle
Normal file
87
app/nonnull.gradle
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2018 Eric Kuck <eric@bluelinelabs.com>.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
task generateNonNullJavaFiles(dependsOn: "assembleDebug", type: Copy) {
|
||||||
|
group = "Copying"
|
||||||
|
description = "Generate package-info.java classes"
|
||||||
|
|
||||||
|
def basePackage = "com" + File.separatorChar + "wireguard"
|
||||||
|
def mainSrcPhrase = "src" + File.separatorChar + "main" + File.separatorChar +
|
||||||
|
"java" + File.separatorChar
|
||||||
|
def mainTestSrcPhrase = "src" + File.separatorChar + "test" + File.separatorChar +
|
||||||
|
"java" + File.separatorChar
|
||||||
|
def mainAndroidTestSrcPhrase = "src" + File.separatorChar + "androidTest" + File.separatorChar +
|
||||||
|
"java" + File.separatorChar
|
||||||
|
|
||||||
|
def sourceDir = file( "${projectDir}" + File.separatorChar + "src" + File.separatorChar +
|
||||||
|
"main" + File.separatorChar + "java" + File.separatorChar +
|
||||||
|
basePackage )
|
||||||
|
def testSourceDir = file( "${projectDir}" + File.separatorChar + "src" + File.separatorChar +
|
||||||
|
"test" + File.separatorChar + "java" + File.separatorChar +
|
||||||
|
basePackage)
|
||||||
|
def androidTestSourceDir = file( "${projectDir}" + File.separatorChar + "src" + File
|
||||||
|
.separatorChar +
|
||||||
|
"androidTest" + File.separatorChar + "java" + File.separatorChar +
|
||||||
|
basePackage )
|
||||||
|
|
||||||
|
generateInfoFiles(sourceDir, mainSrcPhrase);
|
||||||
|
sourceDir.eachDirRecurse { dir ->
|
||||||
|
generateInfoFiles(dir, mainSrcPhrase)
|
||||||
|
}
|
||||||
|
if (file(testSourceDir).exists()) {
|
||||||
|
generateInfoFiles(testSourceDir, mainTestSrcPhrase);
|
||||||
|
testSourceDir.eachDirRecurse { dir ->
|
||||||
|
generateInfoFiles(dir, mainTestSrcPhrase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file(androidTestSourceDir).exists()) {
|
||||||
|
generateInfoFiles(androidTestSourceDir, mainAndroidTestSrcPhrase);
|
||||||
|
androidTestSourceDir.eachDirRecurse { dir ->
|
||||||
|
generateInfoFiles(dir, mainAndroidTestSrcPhrase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println "[SUCCESS] NonNull generator: package-info.java files checked"
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateInfoFiles(File dir, String mainSrcPhrase) {
|
||||||
|
def infoFileContentHeader = getFileContentHeader();
|
||||||
|
def infoFileContentFooter = getFileContentFooter();
|
||||||
|
def infoFilePath = dir.getAbsolutePath() + File.separatorChar + "package-info.java"
|
||||||
|
|
||||||
|
//file(infoFilePath).delete(); //do not use in production code
|
||||||
|
if (!file(infoFilePath).exists()) {
|
||||||
|
def infoFileContentPackage = getFileContentPackage(dir.getAbsolutePath(), mainSrcPhrase);
|
||||||
|
new File(infoFilePath).write(infoFileContentHeader +
|
||||||
|
infoFileContentPackage + infoFileContentFooter)
|
||||||
|
println "[dir] " + infoFilePath + " created";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def getFileContentPackage(String path, String mainSrcPhrase) {
|
||||||
|
def mainSrcPhraseIndex = path.indexOf(mainSrcPhrase)
|
||||||
|
def output = path.substring(mainSrcPhraseIndex)
|
||||||
|
|
||||||
|
// Win hotfix
|
||||||
|
if (System.properties['os.name'].toLowerCase().contains('windows')) {
|
||||||
|
output = output.replace("\\", "/")
|
||||||
|
mainSrcPhrase = mainSrcPhrase.replace("\\", "/")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "package " + output.replaceAll(mainSrcPhrase, "").replaceAll(
|
||||||
|
"/", ".") + ";\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
def getFileContentHeader() {
|
||||||
|
return "/**\n" +
|
||||||
|
" * Make all method parameters @NonNull by default.\n" +
|
||||||
|
" */\n" +
|
||||||
|
"@NonNullForAll\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
def getFileContentFooter() {
|
||||||
|
return "\n" +
|
||||||
|
"import com.wireguard.util.NonNullForAll;\n"
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ import android.os.AsyncTask;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.AppCompatDelegate;
|
import android.support.v7.app.AppCompatDelegate;
|
||||||
|
|
||||||
import com.wireguard.android.backend.Backend;
|
import com.wireguard.android.backend.Backend;
|
||||||
@ -26,18 +27,19 @@ import java.io.File;
|
|||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
public class Application extends android.app.Application {
|
public class Application extends android.app.Application {
|
||||||
private static WeakReference<Application> weakSelf;
|
@SuppressWarnings("NullableProblems") private static WeakReference<Application> weakSelf;
|
||||||
private AsyncWorker asyncWorker;
|
@SuppressWarnings("NullableProblems") private AsyncWorker asyncWorker;
|
||||||
private Backend backend;
|
@SuppressWarnings("NullableProblems") private RootShell rootShell;
|
||||||
private RootShell rootShell;
|
@SuppressWarnings("NullableProblems") private SharedPreferences sharedPreferences;
|
||||||
private SharedPreferences sharedPreferences;
|
@SuppressWarnings("NullableProblems") private ToolsInstaller toolsInstaller;
|
||||||
private ToolsInstaller toolsInstaller;
|
@SuppressWarnings("NullableProblems") private TunnelManager tunnelManager;
|
||||||
private TunnelManager tunnelManager;
|
@SuppressWarnings("NullableProblems") private Handler handler;
|
||||||
private Handler handler;
|
@Nullable private Backend backend;
|
||||||
private Collection<BackendCallback> haveBackendCallbacks = new ArrayList<>();
|
@Nullable private Collection<BackendCallback> haveBackendCallbacks = new ArrayList<>();
|
||||||
private final Object haveBackendCallbacksLock = new Object();
|
private final Object haveBackendCallbacksLock = new Object();
|
||||||
|
|
||||||
public Application() {
|
public Application() {
|
||||||
@ -65,9 +67,11 @@ public class Application extends android.app.Application {
|
|||||||
if (app.backend == null)
|
if (app.backend == null)
|
||||||
app.backend = new GoBackend(app.getApplicationContext());
|
app.backend = new GoBackend(app.getApplicationContext());
|
||||||
synchronized (app.haveBackendCallbacksLock) {
|
synchronized (app.haveBackendCallbacksLock) {
|
||||||
for (final BackendCallback callback : app.haveBackendCallbacks)
|
if (app.haveBackendCallbacks != null) {
|
||||||
app.handler.post(() -> callback.callback(app.backend));
|
for (final BackendCallback callback : app.haveBackendCallbacks)
|
||||||
app.haveBackendCallbacks = null;
|
app.handler.post(() -> callback.callback(app.backend));
|
||||||
|
app.haveBackendCallbacks = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return app.backend;
|
return app.backend;
|
||||||
@ -82,10 +86,12 @@ public class Application extends android.app.Application {
|
|||||||
public static void onHaveBackend(final BackendCallback callback) {
|
public static void onHaveBackend(final BackendCallback callback) {
|
||||||
final Application app = get();
|
final Application app = get();
|
||||||
synchronized (app.haveBackendCallbacksLock) {
|
synchronized (app.haveBackendCallbacksLock) {
|
||||||
if (app.haveBackendCallbacks == null)
|
if (app.haveBackendCallbacks == null) {
|
||||||
|
Objects.requireNonNull(app.backend, "Backend still null in onHaveBackend call");
|
||||||
callback.callback(app.backend);
|
callback.callback(app.backend);
|
||||||
else
|
} else {
|
||||||
app.haveBackendCallbacks.add(callback);
|
app.haveBackendCallbacks.add(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,11 @@ import android.databinding.Observable;
|
|||||||
import android.databinding.Observable.OnPropertyChangedCallback;
|
import android.databinding.Observable.OnPropertyChangedCallback;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.service.quicksettings.Tile;
|
import android.service.quicksettings.Tile;
|
||||||
import android.service.quicksettings.TileService;
|
import android.service.quicksettings.TileService;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@ -41,9 +40,9 @@ public class QuickTileService extends TileService {
|
|||||||
|
|
||||||
private final OnStateChangedCallback onStateChangedCallback = new OnStateChangedCallback();
|
private final OnStateChangedCallback onStateChangedCallback = new OnStateChangedCallback();
|
||||||
private final OnTunnelChangedCallback onTunnelChangedCallback = new OnTunnelChangedCallback();
|
private final OnTunnelChangedCallback onTunnelChangedCallback = new OnTunnelChangedCallback();
|
||||||
private Tunnel tunnel;
|
@Nullable private Tunnel tunnel;
|
||||||
private Icon iconOn;
|
@Nullable private Icon iconOn;
|
||||||
private Icon iconOff;
|
@Nullable private Icon iconOff;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
@ -91,7 +90,7 @@ public class QuickTileService extends TileService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onToggleFinished(@SuppressWarnings("unused") final State state,
|
private void onToggleFinished(@SuppressWarnings("unused") final State state,
|
||||||
final Throwable throwable) {
|
@Nullable final Throwable throwable) {
|
||||||
if (throwable == null)
|
if (throwable == null)
|
||||||
return;
|
return;
|
||||||
final String error = ExceptionLoggers.unwrapMessage(throwable);
|
final String error = ExceptionLoggers.unwrapMessage(throwable);
|
||||||
|
@ -9,6 +9,7 @@ package com.wireguard.android.activity;
|
|||||||
import android.databinding.CallbackRegistry;
|
import android.databinding.CallbackRegistry;
|
||||||
import android.databinding.CallbackRegistry.NotifierCallback;
|
import android.databinding.CallbackRegistry.NotifierCallback;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.android.Application;
|
import com.wireguard.android.Application;
|
||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
@ -24,19 +25,19 @@ public abstract class BaseActivity extends ThemeChangeAwareActivity {
|
|||||||
private static final String KEY_SELECTED_TUNNEL = "selected_tunnel";
|
private static final String KEY_SELECTED_TUNNEL = "selected_tunnel";
|
||||||
|
|
||||||
private final SelectionChangeRegistry selectionChangeRegistry = new SelectionChangeRegistry();
|
private final SelectionChangeRegistry selectionChangeRegistry = new SelectionChangeRegistry();
|
||||||
private Tunnel selectedTunnel;
|
@Nullable private Tunnel selectedTunnel;
|
||||||
|
|
||||||
public void addOnSelectedTunnelChangedListener(
|
public void addOnSelectedTunnelChangedListener(final OnSelectedTunnelChangedListener listener) {
|
||||||
final OnSelectedTunnelChangedListener listener) {
|
|
||||||
selectionChangeRegistry.add(listener);
|
selectionChangeRegistry.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public Tunnel getSelectedTunnel() {
|
public Tunnel getSelectedTunnel() {
|
||||||
return selectedTunnel;
|
return selectedTunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
// Restore the saved tunnel if there is one; otherwise grab it from the arguments.
|
// Restore the saved tunnel if there is one; otherwise grab it from the arguments.
|
||||||
String savedTunnelName = null;
|
String savedTunnelName = null;
|
||||||
if (savedInstanceState != null)
|
if (savedInstanceState != null)
|
||||||
@ -59,14 +60,14 @@ public abstract class BaseActivity extends ThemeChangeAwareActivity {
|
|||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void onSelectedTunnelChanged(Tunnel oldTunnel, Tunnel newTunnel);
|
protected abstract void onSelectedTunnelChanged(@Nullable Tunnel oldTunnel, @Nullable Tunnel newTunnel);
|
||||||
|
|
||||||
public void removeOnSelectedTunnelChangedListener(
|
public void removeOnSelectedTunnelChangedListener(
|
||||||
final OnSelectedTunnelChangedListener listener) {
|
final OnSelectedTunnelChangedListener listener) {
|
||||||
selectionChangeRegistry.remove(listener);
|
selectionChangeRegistry.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedTunnel(final Tunnel tunnel) {
|
public void setSelectedTunnel(@Nullable final Tunnel tunnel) {
|
||||||
final Tunnel oldTunnel = selectedTunnel;
|
final Tunnel oldTunnel = selectedTunnel;
|
||||||
if (Objects.equals(oldTunnel, tunnel))
|
if (Objects.equals(oldTunnel, tunnel))
|
||||||
return;
|
return;
|
||||||
@ -76,7 +77,7 @@ public abstract class BaseActivity extends ThemeChangeAwareActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface OnSelectedTunnelChangedListener {
|
public interface OnSelectedTunnelChangedListener {
|
||||||
void onSelectedTunnelChanged(Tunnel oldTunnel, Tunnel newTunnel);
|
void onSelectedTunnelChanged(@Nullable Tunnel oldTunnel, @Nullable Tunnel newTunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class SelectionChangeNotifier
|
private static final class SelectionChangeNotifier
|
||||||
|
@ -9,6 +9,7 @@ package com.wireguard.android.activity;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
@ -22,6 +23,8 @@ import com.wireguard.android.fragment.TunnelEditorFragment;
|
|||||||
import com.wireguard.android.fragment.TunnelListFragment;
|
import com.wireguard.android.fragment.TunnelListFragment;
|
||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import java9.util.stream.Stream;
|
import java9.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,6 +36,7 @@ import java9.util.stream.Stream;
|
|||||||
public class MainActivity extends BaseActivity {
|
public class MainActivity extends BaseActivity {
|
||||||
private static final String KEY_STATE = "fragment_state";
|
private static final String KEY_STATE = "fragment_state";
|
||||||
private static final String TAG = "WireGuard/" + MainActivity.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + MainActivity.class.getSimpleName();
|
||||||
|
|
||||||
private State state = State.EMPTY;
|
private State state = State.EMPTY;
|
||||||
|
|
||||||
private boolean moveToState(final State nextState) {
|
private boolean moveToState(final State nextState) {
|
||||||
@ -70,13 +74,19 @@ public class MainActivity extends BaseActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
TunnelListFragment fragment = null;
|
final List<Fragment> fragments = getSupportFragmentManager().getFragments();
|
||||||
try {
|
|
||||||
fragment = ((TunnelListFragment) getSupportFragmentManager().getFragments().get(0));
|
boolean handled = false;
|
||||||
} catch (final ClassCastException ignored) { }
|
if (!fragments.isEmpty() && fragments.get(0) instanceof TunnelListFragment) {
|
||||||
if (fragment == null || !fragment.collapseActionMenu()) {
|
handled = ((TunnelListFragment) fragments.get(0)).collapseActionMenu();
|
||||||
if (!moveToState(State.ofLayer(state.layer - 1)))
|
}
|
||||||
super.onBackPressed();
|
|
||||||
|
if (!handled) {
|
||||||
|
handled = moveToState(State.ofLayer(state.layer - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +94,7 @@ public class MainActivity extends BaseActivity {
|
|||||||
// calling View#performClick defeats the purpose of it.
|
// calling View#performClick defeats the purpose of it.
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.main_activity);
|
setContentView(R.layout.main_activity);
|
||||||
if (savedInstanceState != null && savedInstanceState.getString(KEY_STATE) != null)
|
if (savedInstanceState != null && savedInstanceState.getString(KEY_STATE) != null)
|
||||||
@ -99,9 +109,10 @@ public class MainActivity extends BaseActivity {
|
|||||||
final int actionBarId = getResources().getIdentifier("action_bar", "id", getPackageName());
|
final int actionBarId = getResources().getIdentifier("action_bar", "id", getPackageName());
|
||||||
if (actionBarId != 0 && findViewById(actionBarId) != null) {
|
if (actionBarId != 0 && findViewById(actionBarId) != null) {
|
||||||
findViewById(actionBarId).setOnTouchListener((v, e) -> {
|
findViewById(actionBarId).setOnTouchListener((v, e) -> {
|
||||||
try {
|
final List<Fragment> fragments = getSupportFragmentManager().getFragments();
|
||||||
((TunnelListFragment) getSupportFragmentManager().getFragments().get(0)).collapseActionMenu();
|
if (!fragments.isEmpty() && fragments.get(0) instanceof TunnelListFragment) {
|
||||||
} catch (final ClassCastException ignored) { }
|
((TunnelListFragment) fragments.get(0)).collapseActionMenu();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -142,7 +153,7 @@ public class MainActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
|
protected void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) {
|
||||||
moveToState(newTunnel != null ? State.DETAIL : State.LIST);
|
moveToState(newTunnel != null ? State.DETAIL : State.LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,10 +168,10 @@ public class MainActivity extends BaseActivity {
|
|||||||
DETAIL(TunnelDetailFragment.class, 2),
|
DETAIL(TunnelDetailFragment.class, 2),
|
||||||
EDITOR(TunnelEditorFragment.class, 3);
|
EDITOR(TunnelEditorFragment.class, 3);
|
||||||
|
|
||||||
private final String fragment;
|
@Nullable private final String fragment;
|
||||||
private final int layer;
|
private final int layer;
|
||||||
|
|
||||||
State(final Class<? extends Fragment> fragment, final int layer) {
|
State(@Nullable final Class<? extends Fragment> fragment, final int layer) {
|
||||||
this.fragment = fragment != null ? fragment.getName() : null;
|
this.fragment = fragment != null ? fragment.getName() : null;
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,13 @@ package com.wireguard.android.activity;
|
|||||||
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import com.wireguard.android.Application;
|
import com.wireguard.android.Application;
|
||||||
@ -22,16 +23,14 @@ import com.wireguard.android.backend.WgQuickBackend;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for changing application-global persistent settings.
|
* Interface for changing application-global persistent settings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SettingsActivity extends ThemeChangeAwareActivity {
|
public class SettingsActivity extends ThemeChangeAwareActivity {
|
||||||
private final Map<Integer, PermissionRequestCallback> permissionRequestCallbacks = new HashMap<>();
|
private final SparseArray<PermissionRequestCallback> permissionRequestCallbacks = new SparseArray<>();
|
||||||
private int permissionRequestCounter;
|
private int permissionRequestCounter;
|
||||||
|
|
||||||
public void ensurePermissions(final String[] permissions, final PermissionRequestCallback cb) {
|
public void ensurePermissions(final String[] permissions, final PermissionRequestCallback cb) {
|
||||||
@ -54,7 +53,7 @@ public class SettingsActivity extends ThemeChangeAwareActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
|
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
@ -76,8 +75,8 @@ public class SettingsActivity extends ThemeChangeAwareActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(final int requestCode,
|
public void onRequestPermissionsResult(final int requestCode,
|
||||||
@NonNull final String[] permissions,
|
final String[] permissions,
|
||||||
@NonNull final int[] grantResults) {
|
final int[] grantResults) {
|
||||||
final PermissionRequestCallback f = permissionRequestCallbacks.get(requestCode);
|
final PermissionRequestCallback f = permissionRequestCallbacks.get(requestCode);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
permissionRequestCallbacks.remove(requestCode);
|
permissionRequestCallbacks.remove(requestCode);
|
||||||
|
@ -8,6 +8,7 @@ package com.wireguard.android.activity;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.app.AppCompatDelegate;
|
import android.support.v7.app.AppCompatDelegate;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -19,7 +20,7 @@ import java.lang.reflect.Field;
|
|||||||
public abstract class ThemeChangeAwareActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
public abstract class ThemeChangeAwareActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private static final String TAG = "WireGuard/" + ThemeChangeAwareActivity.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + ThemeChangeAwareActivity.class.getSimpleName();
|
||||||
|
|
||||||
private static Resources lastResources;
|
@Nullable private static Resources lastResources;
|
||||||
private static boolean lastDarkMode;
|
private static boolean lastDarkMode;
|
||||||
private static synchronized void invalidateDrawableCache(final Resources resources, final boolean darkMode) {
|
private static synchronized void invalidateDrawableCache(final Resources resources, final boolean darkMode) {
|
||||||
if (resources == lastResources && darkMode == lastDarkMode)
|
if (resources == lastResources && darkMode == lastDarkMode)
|
||||||
@ -51,7 +52,7 @@ public abstract class ThemeChangeAwareActivity extends AppCompatActivity impleme
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
Application.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
Application.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package com.wireguard.android.activity;
|
package com.wireguard.android.activity;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.android.fragment.TunnelEditorFragment;
|
import com.wireguard.android.fragment.TunnelEditorFragment;
|
||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
@ -18,7 +19,7 @@ import com.wireguard.android.model.Tunnel;
|
|||||||
public class TunnelCreatorActivity extends BaseActivity {
|
public class TunnelCreatorActivity extends BaseActivity {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("UnnecessaryFullyQualifiedName")
|
@SuppressWarnings("UnnecessaryFullyQualifiedName")
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
|
if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
|
||||||
getSupportFragmentManager().beginTransaction()
|
getSupportFragmentManager().beginTransaction()
|
||||||
@ -28,7 +29,7 @@ public class TunnelCreatorActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
|
protected void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.ArraySet;
|
import android.support.v4.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ import com.wireguard.crypto.KeyEncoding;
|
|||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
@ -40,7 +42,7 @@ public final class GoBackend implements Backend {
|
|||||||
private static CompletableFuture<VpnService> vpnService = new CompletableFuture<>();
|
private static CompletableFuture<VpnService> vpnService = new CompletableFuture<>();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private Tunnel currentTunnel;
|
@Nullable private Tunnel currentTunnel;
|
||||||
private int currentTunnelHandle = -1;
|
private int currentTunnelHandle = -1;
|
||||||
|
|
||||||
public GoBackend(final Context context) {
|
public GoBackend(final Context context) {
|
||||||
@ -114,12 +116,14 @@ public final class GoBackend implements Backend {
|
|||||||
return getState(tunnel);
|
return getState(tunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStateInternal(final Tunnel tunnel, final Config config, final State state)
|
private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (state == State.UP) {
|
if (state == State.UP) {
|
||||||
Log.i(TAG, "Bringing tunnel up");
|
Log.i(TAG, "Bringing tunnel up");
|
||||||
|
|
||||||
|
Objects.requireNonNull(config, "Trying to bring up a tunnel with no config");
|
||||||
|
|
||||||
if (VpnService.prepare(context) != null)
|
if (VpnService.prepare(context) != null)
|
||||||
throw new Exception("VPN service not authorized by user");
|
throw new Exception("VPN service not authorized by user");
|
||||||
|
|
||||||
@ -245,7 +249,7 @@ public final class GoBackend implements Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
public int onStartCommand(@Nullable final Intent intent, final int flags, final int startId) {
|
||||||
vpnService.complete(this);
|
vpnService.complete(this);
|
||||||
if (intent == null || intent.getComponent() == null || !intent.getComponent().getPackageName().equals(getPackageName())) {
|
if (intent == null || intent.getComponent() == null || !intent.getComponent().getPackageName().equals(getPackageName())) {
|
||||||
Log.d(TAG, "Service started by Always-on VPN feature");
|
Log.d(TAG, "Service started by Always-on VPN feature");
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package com.wireguard.android.backend;
|
package com.wireguard.android.backend;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.wireguard.android.Application;
|
import com.wireguard.android.Application;
|
||||||
@ -21,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import java9.util.stream.Collectors;
|
import java9.util.stream.Collectors;
|
||||||
@ -106,8 +108,9 @@ public final class WgQuickBackend implements Backend {
|
|||||||
return getState(tunnel);
|
return getState(tunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStateInternal(final Tunnel tunnel, final Config config, final State state)
|
private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state) throws Exception {
|
||||||
throws Exception {
|
Objects.requireNonNull(config, "Trying to set state with a null config");
|
||||||
|
|
||||||
final File tempFile = new File(localTemporaryDir, tunnel.getName() + ".conf");
|
final File tempFile = new File(localTemporaryDir, tunnel.getName() + ".conf");
|
||||||
try (final FileOutputStream stream = new FileOutputStream(tempFile, false)) {
|
try (final FileOutputStream stream = new FileOutputStream(tempFile, false)) {
|
||||||
stream.write(config.toString().getBytes(StandardCharsets.UTF_8));
|
stream.write(config.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
@ -9,6 +9,7 @@ package com.wireguard.android.databinding;
|
|||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.databinding.ObservableList;
|
import android.databinding.ObservableList;
|
||||||
import android.databinding.ViewDataBinding;
|
import android.databinding.ViewDataBinding;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -16,6 +17,7 @@ import android.view.ViewGroup;
|
|||||||
import com.wireguard.android.BR;
|
import com.wireguard.android.BR;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for binding an ObservableList to the children of a ViewGroup.
|
* Helper class for binding an ObservableList to the children of a ViewGroup.
|
||||||
@ -26,7 +28,7 @@ class ItemChangeListener<T> {
|
|||||||
private final ViewGroup container;
|
private final ViewGroup container;
|
||||||
private final int layoutId;
|
private final int layoutId;
|
||||||
private final LayoutInflater layoutInflater;
|
private final LayoutInflater layoutInflater;
|
||||||
private ObservableList<T> list;
|
@Nullable private ObservableList<T> list;
|
||||||
|
|
||||||
ItemChangeListener(final ViewGroup container, final int layoutId) {
|
ItemChangeListener(final ViewGroup container, final int layoutId) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
@ -34,17 +36,21 @@ class ItemChangeListener<T> {
|
|||||||
layoutInflater = LayoutInflater.from(container.getContext());
|
layoutInflater = LayoutInflater.from(container.getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private View getView(final int position, final View convertView) {
|
private View getView(final int position, @Nullable final View convertView) {
|
||||||
ViewDataBinding binding = DataBindingUtil.getBinding(convertView);
|
ViewDataBinding binding = convertView != null ? DataBindingUtil.getBinding(convertView) : null;
|
||||||
if (binding == null)
|
if (binding == null) {
|
||||||
binding = DataBindingUtil.inflate(layoutInflater, layoutId, container, false);
|
binding = DataBindingUtil.inflate(layoutInflater, layoutId, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Objects.requireNonNull(list, "Trying to get a view while list is still null");
|
||||||
|
|
||||||
binding.setVariable(BR.collection, list);
|
binding.setVariable(BR.collection, list);
|
||||||
binding.setVariable(BR.item, list.get(position));
|
binding.setVariable(BR.item, list.get(position));
|
||||||
binding.executePendingBindings();
|
binding.executePendingBindings();
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setList(final ObservableList<T> newList) {
|
void setList(@Nullable final ObservableList<T> newList) {
|
||||||
if (list != null)
|
if (list != null)
|
||||||
list.removeOnListChangedCallback(callback);
|
list.removeOnListChangedCallback(callback);
|
||||||
list = newList;
|
list = newList;
|
||||||
|
@ -10,7 +10,7 @@ import android.content.Context;
|
|||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.databinding.ObservableList;
|
import android.databinding.ObservableList;
|
||||||
import android.databinding.ViewDataBinding;
|
import android.databinding.ViewDataBinding;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.support.v7.widget.RecyclerView.Adapter;
|
import android.support.v7.widget.RecyclerView.Adapter;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -31,8 +31,8 @@ public class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>>
|
|||||||
private final OnListChangedCallback<E> callback = new OnListChangedCallback<>(this);
|
private final OnListChangedCallback<E> callback = new OnListChangedCallback<>(this);
|
||||||
private final int layoutId;
|
private final int layoutId;
|
||||||
private final LayoutInflater layoutInflater;
|
private final LayoutInflater layoutInflater;
|
||||||
private ObservableKeyedList<K, E> list;
|
@Nullable private ObservableKeyedList<K, E> list;
|
||||||
private RowConfigurationHandler rowConfigurationHandler;
|
@Nullable private RowConfigurationHandler rowConfigurationHandler;
|
||||||
|
|
||||||
ObservableKeyedRecyclerViewAdapter(final Context context, final int layoutId,
|
ObservableKeyedRecyclerViewAdapter(final Context context, final int layoutId,
|
||||||
final ObservableKeyedList<K, E> list) {
|
final ObservableKeyedList<K, E> list) {
|
||||||
@ -46,6 +46,7 @@ public class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>>
|
|||||||
return list != null ? list.size() : 0;
|
return list != null ? list.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private E getItem(final int position) {
|
private E getItem(final int position) {
|
||||||
if (list == null || position < 0 || position >= list.size())
|
if (list == null || position < 0 || position >= list.size())
|
||||||
return null;
|
return null;
|
||||||
@ -58,30 +59,34 @@ public class ObservableKeyedRecyclerViewAdapter<K, E extends Keyed<? extends K>>
|
|||||||
return key != null ? key.hashCode() : -1;
|
return key != null ? key.hashCode() : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private K getKey(final int position) {
|
private K getKey(final int position) {
|
||||||
final E item = getItem(position);
|
final E item = getItem(position);
|
||||||
return item != null ? item.getKey() : null;
|
return item != null ? item.getKey() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull @Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
|
public ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
|
||||||
return new ViewHolder(DataBindingUtil.inflate(layoutInflater, layoutId, parent, false));
|
return new ViewHolder(DataBindingUtil.inflate(layoutInflater, layoutId, parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
|
public void onBindViewHolder(final ViewHolder holder, final int position) {
|
||||||
holder.binding.setVariable(BR.collection, list);
|
holder.binding.setVariable(BR.collection, list);
|
||||||
holder.binding.setVariable(BR.key, getKey(position));
|
holder.binding.setVariable(BR.key, getKey(position));
|
||||||
holder.binding.setVariable(BR.item, getItem(position));
|
holder.binding.setVariable(BR.item, getItem(position));
|
||||||
holder.binding.executePendingBindings();
|
holder.binding.executePendingBindings();
|
||||||
|
|
||||||
if (rowConfigurationHandler != null) {
|
if (rowConfigurationHandler != null) {
|
||||||
rowConfigurationHandler.onConfigureRow(holder.binding, getItem(position), position);
|
E item = getItem(position);
|
||||||
|
if (item != null) {
|
||||||
|
rowConfigurationHandler.onConfigureRow(holder.binding, item, position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setList(final ObservableKeyedList<K, E> newList) {
|
void setList(@Nullable final ObservableKeyedList<K, E> newList) {
|
||||||
if (list != null)
|
if (list != null)
|
||||||
list.removeOnListChangedCallback(callback);
|
list.removeOnListChangedCallback(callback);
|
||||||
list = newList;
|
list = newList;
|
||||||
|
@ -39,7 +39,7 @@ public class AppListDialogFragment extends DialogFragment {
|
|||||||
|
|
||||||
private static final String KEY_EXCLUDED_APPS = "excludedApps";
|
private static final String KEY_EXCLUDED_APPS = "excludedApps";
|
||||||
|
|
||||||
private List<String> currentlyExcludedApps;
|
private final List<String> currentlyExcludedApps = Arrays.asList(getArguments().getStringArray(KEY_EXCLUDED_APPS));
|
||||||
private final ObservableKeyedList<String, ApplicationData> appData = new ObservableKeyedArrayList<>();
|
private final ObservableKeyedList<String, ApplicationData> appData = new ObservableKeyedArrayList<>();
|
||||||
|
|
||||||
public static <T extends Fragment & AppExclusionListener> AppListDialogFragment newInstance(final String[] excludedApps, final T target) {
|
public static <T extends Fragment & AppExclusionListener> AppListDialogFragment newInstance(final String[] excludedApps, final T target) {
|
||||||
@ -51,24 +51,12 @@ public class AppListDialogFragment extends DialogFragment {
|
|||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
currentlyExcludedApps = Arrays.asList(getArguments().getStringArray(KEY_EXCLUDED_APPS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(final Context context) {
|
|
||||||
super.onAttach(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||||
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
|
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
|
||||||
alertDialogBuilder.setTitle(R.string.excluded_applications);
|
alertDialogBuilder.setTitle(R.string.excluded_applications);
|
||||||
|
|
||||||
AppListDialogFragmentBinding binding = AppListDialogFragmentBinding.inflate(getActivity().getLayoutInflater(), null, false);
|
final AppListDialogFragmentBinding binding = AppListDialogFragmentBinding.inflate(getActivity().getLayoutInflater(), null, false);
|
||||||
binding.executePendingBindings();
|
binding.executePendingBindings();
|
||||||
alertDialogBuilder.setView(binding.getRoot());
|
alertDialogBuilder.setView(binding.getRoot());
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
import android.databinding.ViewDataBinding;
|
import android.databinding.ViewDataBinding;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -37,10 +37,11 @@ public abstract class BaseFragment extends Fragment implements OnSelectedTunnelC
|
|||||||
private static final String TAG = "WireGuard/" + BaseFragment.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + BaseFragment.class.getSimpleName();
|
||||||
private static final int REQUEST_CODE_VPN_PERMISSION = 23491;
|
private static final int REQUEST_CODE_VPN_PERMISSION = 23491;
|
||||||
|
|
||||||
private BaseActivity activity;
|
@Nullable private BaseActivity activity;
|
||||||
private Tunnel pendingTunnel;
|
@Nullable private Tunnel pendingTunnel;
|
||||||
private Boolean pendingTunnelUp;
|
@Nullable private Boolean pendingTunnelUp;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
protected Tunnel getSelectedTunnel() {
|
protected Tunnel getSelectedTunnel() {
|
||||||
return activity != null ? activity.getSelectedTunnel() : null;
|
return activity != null ? activity.getSelectedTunnel() : null;
|
||||||
}
|
}
|
||||||
@ -65,7 +66,7 @@ public abstract class BaseFragment extends Fragment implements OnSelectedTunnelC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
if (requestCode == REQUEST_CODE_VPN_PERMISSION) {
|
if (requestCode == REQUEST_CODE_VPN_PERMISSION) {
|
||||||
@ -76,7 +77,7 @@ public abstract class BaseFragment extends Fragment implements OnSelectedTunnelC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setSelectedTunnel(final Tunnel tunnel) {
|
protected void setSelectedTunnel(@Nullable final Tunnel tunnel) {
|
||||||
if (activity != null)
|
if (activity != null)
|
||||||
activity.setSelectedTunnel(tunnel);
|
activity.setSelectedTunnel(tunnel);
|
||||||
}
|
}
|
||||||
@ -106,7 +107,7 @@ public abstract class BaseFragment extends Fragment implements OnSelectedTunnelC
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTunnelStateWithPermissionsResult(@NonNull final Tunnel tunnel, final boolean checked) {
|
private void setTunnelStateWithPermissionsResult(final Tunnel tunnel, final boolean checked) {
|
||||||
tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> {
|
tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> {
|
||||||
if (throwable == null)
|
if (throwable == null)
|
||||||
return;
|
return;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
package com.wireguard.android.fragment;
|
package com.wireguard.android.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -24,14 +24,16 @@ import com.wireguard.config.Config;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class TunnelDetailFragment extends BaseFragment {
|
public class TunnelDetailFragment extends BaseFragment {
|
||||||
private TunnelDetailFragmentBinding binding;
|
@Nullable private TunnelDetailFragmentBinding binding;
|
||||||
|
|
||||||
private void onConfigLoaded(final String name, final Config config) {
|
private void onConfigLoaded(final String name, final Config config) {
|
||||||
binding.setConfig(new Config.Observable(config, name));
|
if (binding != null) {
|
||||||
|
binding.setConfig(new Config.Observable(config, name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
@ -42,8 +44,8 @@ public class TunnelDetailFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreateView(inflater, container, savedInstanceState);
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
binding = TunnelDetailFragmentBinding.inflate(inflater, container, false);
|
binding = TunnelDetailFragmentBinding.inflate(inflater, container, false);
|
||||||
binding.executePendingBindings();
|
binding.executePendingBindings();
|
||||||
@ -57,7 +59,7 @@ public class TunnelDetailFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
|
public void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) {
|
||||||
if (binding == null)
|
if (binding == null)
|
||||||
return;
|
return;
|
||||||
binding.setTunnel(newTunnel);
|
binding.setTunnel(newTunnel);
|
||||||
@ -68,7 +70,11 @@ public class TunnelDetailFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewStateRestored(final Bundle savedInstanceState) {
|
public void onViewStateRestored(@Nullable final Bundle savedInstanceState) {
|
||||||
|
if (binding == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
binding.setFragment(this);
|
binding.setFragment(this);
|
||||||
onSelectedTunnelChanged(null, getSelectedTunnel());
|
onSelectedTunnelChanged(null, getSelectedTunnel());
|
||||||
super.onViewStateRestored(savedInstanceState);
|
super.onViewStateRestored(savedInstanceState);
|
||||||
|
@ -11,7 +11,7 @@ import android.content.Context;
|
|||||||
import android.databinding.Observable;
|
import android.databinding.Observable;
|
||||||
import android.databinding.ObservableList;
|
import android.databinding.ObservableList;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -37,6 +37,7 @@ import com.wireguard.config.Config;
|
|||||||
import com.wireguard.config.Peer;
|
import com.wireguard.config.Peer;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment for editing a WireGuard configuration.
|
* Fragment for editing a WireGuard configuration.
|
||||||
@ -47,15 +48,17 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
private static final String KEY_ORIGINAL_NAME = "original_name";
|
private static final String KEY_ORIGINAL_NAME = "original_name";
|
||||||
private static final String TAG = "WireGuard/" + TunnelEditorFragment.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + TunnelEditorFragment.class.getSimpleName();
|
||||||
|
|
||||||
private TunnelEditorFragmentBinding binding;
|
@Nullable private TunnelEditorFragmentBinding binding;
|
||||||
private Tunnel tunnel;
|
@Nullable private Tunnel tunnel;
|
||||||
|
|
||||||
private void onConfigLoaded(final String name, final Config config) {
|
private void onConfigLoaded(final String name, final Config config) {
|
||||||
binding.setConfig(new Config.Observable(config, name));
|
if (binding != null) {
|
||||||
|
binding.setConfig(new Config.Observable(config, name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onConfigSaved(final Tunnel savedTunnel,
|
private void onConfigSaved(final Tunnel savedTunnel,
|
||||||
final Throwable throwable) {
|
@Nullable final Throwable throwable) {
|
||||||
final String message;
|
final String message;
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
message = getString(R.string.config_save_success, savedTunnel.getName());
|
message = getString(R.string.config_save_success, savedTunnel.getName());
|
||||||
@ -73,7 +76,7 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
@ -124,8 +127,8 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreateView(inflater, container, savedInstanceState);
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
binding = TunnelEditorFragmentBinding.inflate(inflater, container, false);
|
binding = TunnelEditorFragmentBinding.inflate(inflater, container, false);
|
||||||
binding.addOnPropertyChangedCallback(breakObjectOrientedLayeringHandler);
|
binding.addOnPropertyChangedCallback(breakObjectOrientedLayeringHandler);
|
||||||
@ -197,14 +200,14 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(@NonNull final Bundle outState) {
|
public void onSaveInstanceState(final Bundle outState) {
|
||||||
outState.putParcelable(KEY_LOCAL_CONFIG, binding.getConfig());
|
outState.putParcelable(KEY_LOCAL_CONFIG, binding.getConfig());
|
||||||
outState.putString(KEY_ORIGINAL_NAME, tunnel == null ? null : tunnel.getName());
|
outState.putString(KEY_ORIGINAL_NAME, tunnel == null ? null : tunnel.getName());
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
|
public void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) {
|
||||||
tunnel = newTunnel;
|
tunnel = newTunnel;
|
||||||
if (binding == null)
|
if (binding == null)
|
||||||
return;
|
return;
|
||||||
@ -213,7 +216,7 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
tunnel.getConfigAsync().thenAccept(a -> onConfigLoaded(tunnel.getName(), a));
|
tunnel.getConfigAsync().thenAccept(a -> onConfigLoaded(tunnel.getName(), a));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onTunnelCreated(final Tunnel newTunnel, final Throwable throwable) {
|
private void onTunnelCreated(final Tunnel newTunnel, @Nullable final Throwable throwable) {
|
||||||
final String message;
|
final String message;
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
tunnel = newTunnel;
|
tunnel = newTunnel;
|
||||||
@ -232,7 +235,7 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onTunnelRenamed(final Tunnel renamedTunnel, final Config newConfig,
|
private void onTunnelRenamed(final Tunnel renamedTunnel, final Config newConfig,
|
||||||
final Throwable throwable) {
|
@Nullable final Throwable throwable) {
|
||||||
final String message;
|
final String message;
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
message = getString(R.string.tunnel_rename_success, renamedTunnel.getName());
|
message = getString(R.string.tunnel_rename_success, renamedTunnel.getName());
|
||||||
@ -251,7 +254,11 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewStateRestored(final Bundle savedInstanceState) {
|
public void onViewStateRestored(@Nullable final Bundle savedInstanceState) {
|
||||||
|
if (binding == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
binding.setFragment(this);
|
binding.setFragment(this);
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
@ -271,15 +278,16 @@ public class TunnelEditorFragment extends BaseFragment implements AppExclusionLi
|
|||||||
|
|
||||||
public void onRequestSetExcludedApplications(@SuppressWarnings("unused") final View view) {
|
public void onRequestSetExcludedApplications(@SuppressWarnings("unused") final View view) {
|
||||||
final FragmentManager fragmentManager = getFragmentManager();
|
final FragmentManager fragmentManager = getFragmentManager();
|
||||||
if (fragmentManager != null) {
|
if (fragmentManager != null && binding != null) {
|
||||||
final String[] excludedApps = Attribute.stringToList(binding.getConfig().getInterfaceSection().getExcludedApplications());
|
final String[] excludedApps = Attribute.stringToList(binding.getConfig().getInterfaceSection().getExcludedApplications());
|
||||||
final AppListDialogFragment fragment = AppListDialogFragment.newInstance(excludedApps, this);
|
final AppListDialogFragment fragment = AppListDialogFragment.newInstance(excludedApps, this);
|
||||||
fragment.show(getFragmentManager(), null);
|
fragment.show(fragmentManager, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onExcludedAppsSelected(final List<String> excludedApps) {
|
public void onExcludedAppsSelected(final List<String> excludedApps) {
|
||||||
|
Objects.requireNonNull(binding, "Tried to set excluded apps while no view was loaded");
|
||||||
binding.getConfig().getInterfaceSection().setExcludedApplications(Attribute.iterableToString(excludedApps));
|
binding.getConfig().getInterfaceSection().setExcludedApplications(Attribute.iterableToString(excludedApps));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import android.database.Cursor;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
@ -60,20 +59,20 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
private static final String TAG = "WireGuard/" + TunnelListFragment.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + TunnelListFragment.class.getSimpleName();
|
||||||
|
|
||||||
private final ActionModeListener actionModeListener = new ActionModeListener();
|
private final ActionModeListener actionModeListener = new ActionModeListener();
|
||||||
private ActionMode actionMode;
|
@Nullable private ActionMode actionMode;
|
||||||
private TunnelListFragmentBinding binding;
|
@Nullable private TunnelListFragmentBinding binding;
|
||||||
|
|
||||||
public boolean collapseActionMenu() {
|
public boolean collapseActionMenu() {
|
||||||
if (binding.createMenu.isExpanded()) {
|
if (binding != null && binding.createMenu.isExpanded()) {
|
||||||
binding.createMenu.collapse();
|
binding.createMenu.collapse();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void importTunnel(final Uri uri) {
|
private void importTunnel(@Nullable final Uri uri) {
|
||||||
final Activity activity = getActivity();
|
final Activity activity = getActivity();
|
||||||
if (activity == null)
|
if (activity == null || uri == null)
|
||||||
return;
|
return;
|
||||||
final ContentResolver contentResolver = activity.getContentResolver();
|
final ContentResolver contentResolver = activity.getContentResolver();
|
||||||
|
|
||||||
@ -165,10 +164,10 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_IMPORT:
|
case REQUEST_IMPORT:
|
||||||
if (resultCode == Activity.RESULT_OK)
|
if (resultCode == Activity.RESULT_OK && data != null)
|
||||||
importTunnel(data.getData());
|
importTunnel(data.getData());
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
@ -178,8 +177,8 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||||
final Bundle savedInstanceState) {
|
@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreateView(inflater, container, savedInstanceState);
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
binding = TunnelListFragmentBinding.inflate(inflater, container, false);
|
binding = TunnelListFragmentBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
@ -216,16 +215,18 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
binding.createMenu.collapse();
|
if (binding != null) {
|
||||||
|
binding.createMenu.collapse();
|
||||||
|
}
|
||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
|
public void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onTunnelDeletionFinished(final Integer count, final Throwable throwable) {
|
private void onTunnelDeletionFinished(final Integer count, @Nullable final Throwable throwable) {
|
||||||
final String message;
|
final String message;
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
message = getResources().getQuantityString(R.plurals.delete_success, count, count);
|
message = getResources().getQuantityString(R.plurals.delete_success, count, count);
|
||||||
@ -265,8 +266,13 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewStateRestored(final Bundle savedInstanceState) {
|
public void onViewStateRestored(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onViewStateRestored(savedInstanceState);
|
super.onViewStateRestored(savedInstanceState);
|
||||||
|
|
||||||
|
if (binding == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
binding.setFragment(this);
|
binding.setFragment(this);
|
||||||
binding.setTunnels(Application.getTunnelManager().getTunnels());
|
binding.setTunnels(Application.getTunnelManager().getTunnels());
|
||||||
binding.setRowConfigurationHandler((ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler<TunnelListItemBinding, Tunnel>) (binding, tunnel, position) -> {
|
binding.setRowConfigurationHandler((ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler<TunnelListItemBinding, Tunnel>) (binding, tunnel, position) -> {
|
||||||
@ -290,7 +296,7 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
private final class ActionModeListener implements ActionMode.Callback {
|
private final class ActionModeListener implements ActionMode.Callback {
|
||||||
private final Collection<Integer> checkedItems = new HashSet<>();
|
private final Collection<Integer> checkedItems = new HashSet<>();
|
||||||
|
|
||||||
private Resources resources;
|
@Nullable private Resources resources;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||||
@ -357,7 +363,9 @@ public class TunnelListFragment extends BaseFragment {
|
|||||||
actionMode.finish();
|
actionMode.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.tunnelList.getAdapter().notifyItemChanged(position);
|
if (binding != null) {
|
||||||
|
binding.tunnelList.getAdapter().notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
|
||||||
updateTitle(actionMode);
|
updateTitle(actionMode);
|
||||||
}
|
}
|
||||||
|
@ -9,36 +9,32 @@ package com.wireguard.android.model;
|
|||||||
import android.databinding.BaseObservable;
|
import android.databinding.BaseObservable;
|
||||||
import android.databinding.Bindable;
|
import android.databinding.Bindable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.wireguard.android.BR;
|
import com.wireguard.android.BR;
|
||||||
import com.wireguard.util.Keyed;
|
import com.wireguard.util.Keyed;
|
||||||
|
|
||||||
public class ApplicationData extends BaseObservable implements Keyed<String> {
|
public class ApplicationData extends BaseObservable implements Keyed<String> {
|
||||||
|
|
||||||
@NonNull private final Drawable icon;
|
private final Drawable icon;
|
||||||
@NonNull private final String name;
|
private final String name;
|
||||||
@NonNull private final String packageName;
|
private final String packageName;
|
||||||
private boolean excludedFromTunnel;
|
private boolean excludedFromTunnel;
|
||||||
|
|
||||||
public ApplicationData(@NonNull final Drawable icon, @NonNull final String name, @NonNull final String packageName, final boolean excludedFromTunnel) {
|
public ApplicationData(final Drawable icon, final String name, final String packageName, final boolean excludedFromTunnel) {
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.excludedFromTunnel = excludedFromTunnel;
|
this.excludedFromTunnel = excludedFromTunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Drawable getIcon() {
|
public Drawable getIcon() {
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
return packageName;
|
return packageName;
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,12 @@ package com.wireguard.android.model;
|
|||||||
|
|
||||||
import android.databinding.BaseObservable;
|
import android.databinding.BaseObservable;
|
||||||
import android.databinding.Bindable;
|
import android.databinding.Bindable;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.android.BR;
|
import com.wireguard.android.BR;
|
||||||
import com.wireguard.android.util.ExceptionLoggers;
|
import com.wireguard.android.util.ExceptionLoggers;
|
||||||
import com.wireguard.util.Keyed;
|
|
||||||
import com.wireguard.config.Config;
|
import com.wireguard.config.Config;
|
||||||
|
import com.wireguard.util.Keyed;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -30,20 +29,20 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
private static final Pattern NAME_PATTERN = Pattern.compile("[a-zA-Z0-9_=+.-]{1,15}");
|
private static final Pattern NAME_PATTERN = Pattern.compile("[a-zA-Z0-9_=+.-]{1,15}");
|
||||||
|
|
||||||
private final TunnelManager manager;
|
private final TunnelManager manager;
|
||||||
private Config config;
|
@Nullable private Config config;
|
||||||
private String name;
|
private String name;
|
||||||
private State state;
|
private State state;
|
||||||
private Statistics statistics;
|
@Nullable private Statistics statistics;
|
||||||
|
|
||||||
Tunnel(@NonNull final TunnelManager manager, @NonNull final String name,
|
Tunnel(final TunnelManager manager, final String name,
|
||||||
@Nullable final Config config, @NonNull final State state) {
|
@Nullable final Config config, final State state) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNameInvalid(@NonNull final CharSequence name) {
|
public static boolean isNameInvalid(final CharSequence name) {
|
||||||
return !NAME_PATTERN.matcher(name).matches();
|
return !NAME_PATTERN.matcher(name).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
return manager.delete(this);
|
return manager.delete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public Config getConfig() {
|
public Config getConfig() {
|
||||||
if (config == null)
|
if (config == null)
|
||||||
manager.getTunnelConfig(this).whenComplete(ExceptionLoggers.E);
|
manager.getTunnelConfig(this).whenComplete(ExceptionLoggers.E);
|
||||||
@ -83,7 +82,7 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
return TunnelManager.getTunnelState(this);
|
return TunnelManager.getTunnelState(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public Statistics getStatistics() {
|
public Statistics getStatistics() {
|
||||||
// FIXME: Check age of statistics.
|
// FIXME: Check age of statistics.
|
||||||
if (statistics == null)
|
if (statistics == null)
|
||||||
@ -118,25 +117,26 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
Statistics onStatisticsChanged(final Statistics statistics) {
|
@Nullable
|
||||||
|
Statistics onStatisticsChanged(@Nullable final Statistics statistics) {
|
||||||
this.statistics = statistics;
|
this.statistics = statistics;
|
||||||
notifyPropertyChanged(BR.statistics);
|
notifyPropertyChanged(BR.statistics);
|
||||||
return statistics;
|
return statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletionStage<Config> setConfig(@NonNull final Config config) {
|
public CompletionStage<Config> setConfig(final Config config) {
|
||||||
if (!config.equals(this.config))
|
if (!config.equals(this.config))
|
||||||
return manager.setTunnelConfig(this, config);
|
return manager.setTunnelConfig(this, config);
|
||||||
return CompletableFuture.completedFuture(this.config);
|
return CompletableFuture.completedFuture(this.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletionStage<String> setName(@NonNull final String name) {
|
public CompletionStage<String> setName(final String name) {
|
||||||
if (!name.equals(this.name))
|
if (!name.equals(this.name))
|
||||||
return manager.setTunnelName(this, name);
|
return manager.setTunnelName(this, name);
|
||||||
return CompletableFuture.completedFuture(this.name);
|
return CompletableFuture.completedFuture(this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletionStage<State> setState(@NonNull final State state) {
|
public CompletionStage<State> setState(final State state) {
|
||||||
if (state != this.state)
|
if (state != this.state)
|
||||||
return manager.setTunnelState(this, state);
|
return manager.setTunnelState(this, state);
|
||||||
return CompletableFuture.completedFuture(this.state);
|
return CompletableFuture.completedFuture(this.state);
|
||||||
@ -152,6 +152,5 @@ public class Tunnel extends BaseObservable implements Keyed<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Statistics extends BaseObservable {
|
public static class Statistics extends BaseObservable { }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.databinding.BaseObservable;
|
import android.databinding.BaseObservable;
|
||||||
import android.databinding.Bindable;
|
import android.databinding.Bindable;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.android.Application;
|
import com.wireguard.android.Application;
|
||||||
import com.wireguard.android.BR;
|
import com.wireguard.android.BR;
|
||||||
@ -47,9 +47,8 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
private static final String KEY_RUNNING_TUNNELS = "enabled_configs";
|
private static final String KEY_RUNNING_TUNNELS = "enabled_configs";
|
||||||
|
|
||||||
private final ConfigStore configStore;
|
private final ConfigStore configStore;
|
||||||
private final ObservableSortedKeyedList<String, Tunnel> tunnels =
|
private final ObservableSortedKeyedList<String, Tunnel> tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR);
|
||||||
new ObservableSortedKeyedArrayList<>(COMPARATOR);
|
@Nullable private Tunnel lastUsedTunnel;
|
||||||
private Tunnel lastUsedTunnel;
|
|
||||||
private boolean haveLoaded;
|
private boolean haveLoaded;
|
||||||
private final ArrayList<CompletableFuture<Void>> delayedLoadRestoreTunnels = new ArrayList<>();
|
private final ArrayList<CompletableFuture<Void>> delayedLoadRestoreTunnels = new ArrayList<>();
|
||||||
|
|
||||||
@ -57,13 +56,13 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
this.configStore = configStore;
|
this.configStore = configStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tunnel addToList(final String name, final Config config, final State state) {
|
private Tunnel addToList(final String name, @Nullable final Config config, final State state) {
|
||||||
final Tunnel tunnel = new Tunnel(this, name, config, state);
|
final Tunnel tunnel = new Tunnel(this, name, config, state);
|
||||||
tunnels.add(tunnel);
|
tunnels.add(tunnel);
|
||||||
return tunnel;
|
return tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletionStage<Tunnel> create(@NonNull final String name, final Config config) {
|
public CompletionStage<Tunnel> create(final String name, @Nullable final Config config) {
|
||||||
if (Tunnel.isNameInvalid(name))
|
if (Tunnel.isNameInvalid(name))
|
||||||
return CompletableFuture.failedFuture(new IllegalArgumentException("Invalid name"));
|
return CompletableFuture.failedFuture(new IllegalArgumentException("Invalid name"));
|
||||||
if (tunnels.containsKey(name)) {
|
if (tunnels.containsKey(name)) {
|
||||||
@ -102,7 +101,7 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public Tunnel getLastUsedTunnel() {
|
public Tunnel getLastUsedTunnel() {
|
||||||
return lastUsedTunnel;
|
return lastUsedTunnel;
|
||||||
}
|
}
|
||||||
@ -191,7 +190,7 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
Application.getSharedPreferences().edit().putStringSet(KEY_RUNNING_TUNNELS, runningTunnels).apply();
|
Application.getSharedPreferences().edit().putStringSet(KEY_RUNNING_TUNNELS, runningTunnels).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLastUsedTunnel(final Tunnel tunnel) {
|
private void setLastUsedTunnel(@Nullable final Tunnel tunnel) {
|
||||||
if (tunnel == lastUsedTunnel)
|
if (tunnel == lastUsedTunnel)
|
||||||
return;
|
return;
|
||||||
lastUsedTunnel = tunnel;
|
lastUsedTunnel = tunnel;
|
||||||
@ -256,7 +255,7 @@ public final class TunnelManager extends BaseObservable {
|
|||||||
|
|
||||||
public static final class IntentReceiver extends BroadcastReceiver {
|
public static final class IntentReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, @Nullable final Intent intent) {
|
||||||
final TunnelManager manager = Application.getTunnelManager();
|
final TunnelManager manager = Application.getTunnelManager();
|
||||||
if (intent == null)
|
if (intent == null)
|
||||||
return;
|
return;
|
||||||
|
@ -10,6 +10,7 @@ import android.Manifest;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@ -33,7 +34,7 @@ import java.io.InputStreamReader;
|
|||||||
public class LogExporterPreference extends Preference {
|
public class LogExporterPreference extends Preference {
|
||||||
private static final String TAG = "WireGuard/" + LogExporterPreference.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + LogExporterPreference.class.getSimpleName();
|
||||||
|
|
||||||
private String exportedFilePath;
|
@Nullable private String exportedFilePath;
|
||||||
|
|
||||||
public LogExporterPreference(final Context context, final AttributeSet attrs) {
|
public LogExporterPreference(final Context context, final AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@ -73,7 +74,7 @@ public class LogExporterPreference extends Preference {
|
|||||||
}).whenComplete(this::exportLogComplete);
|
}).whenComplete(this::exportLogComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exportLogComplete(final String filePath, final Throwable throwable) {
|
private void exportLogComplete(final String filePath, @Nullable final Throwable throwable) {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
final String error = ExceptionLoggers.unwrapMessage(throwable);
|
final String error = ExceptionLoggers.unwrapMessage(throwable);
|
||||||
final String message = getContext().getString(R.string.log_export_error, error);
|
final String message = getContext().getString(R.string.log_export_error, error);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
package com.wireguard.android.preference;
|
package com.wireguard.android.preference;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ public class ToolsInstallerPreference extends Preference {
|
|||||||
Application.getAsyncWorker().supplyAsync(Application.getToolsInstaller()::areInstalled).whenComplete(this::onCheckResult);
|
Application.getAsyncWorker().supplyAsync(Application.getToolsInstaller()::areInstalled).whenComplete(this::onCheckResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCheckResult(final int state, final Throwable throwable) {
|
private void onCheckResult(final int state, @Nullable final Throwable throwable) {
|
||||||
if (throwable != null || state == ToolsInstaller.ERROR)
|
if (throwable != null || state == ToolsInstaller.ERROR)
|
||||||
setState(State.INITIAL);
|
setState(State.INITIAL);
|
||||||
else if ((state & ToolsInstaller.YES) == ToolsInstaller.YES)
|
else if ((state & ToolsInstaller.YES) == ToolsInstaller.YES)
|
||||||
@ -62,7 +62,7 @@ public class ToolsInstallerPreference extends Preference {
|
|||||||
Application.getAsyncWorker().supplyAsync(Application.getToolsInstaller()::install).whenComplete(this::onInstallResult);
|
Application.getAsyncWorker().supplyAsync(Application.getToolsInstaller()::install).whenComplete(this::onInstallResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onInstallResult(final Integer result, final Throwable throwable) {
|
private void onInstallResult(final Integer result, @Nullable final Throwable throwable) {
|
||||||
if (throwable != null)
|
if (throwable != null)
|
||||||
setState(State.FAILURE);
|
setState(State.FAILURE);
|
||||||
else if ((result & (ToolsInstaller.YES | ToolsInstaller.MAGISK)) == (ToolsInstaller.YES | ToolsInstaller.MAGISK))
|
else if ((result & (ToolsInstaller.YES | ToolsInstaller.MAGISK)) == (ToolsInstaller.YES | ToolsInstaller.MAGISK))
|
||||||
@ -73,7 +73,7 @@ public class ToolsInstallerPreference extends Preference {
|
|||||||
setState(State.FAILURE);
|
setState(State.FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setState(@NonNull final State state) {
|
private void setState(final State state) {
|
||||||
if (this.state == state)
|
if (this.state == state)
|
||||||
return;
|
return;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
@ -9,6 +9,7 @@ import android.content.ActivityNotFoundException;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ import com.wireguard.android.BuildConfig;
|
|||||||
import com.wireguard.android.R;
|
import com.wireguard.android.R;
|
||||||
|
|
||||||
public class VersionPreference extends Preference {
|
public class VersionPreference extends Preference {
|
||||||
private String versionSummary;
|
@Nullable private String versionSummary;
|
||||||
|
|
||||||
public VersionPreference(final Context context, final AttributeSet attrs) {
|
public VersionPreference(final Context context, final AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@ -33,7 +34,7 @@ public class VersionPreference extends Preference {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public CharSequence getSummary() {
|
public CharSequence getSummary() {
|
||||||
return versionSummary;
|
return versionSummary;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import android.Manifest;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@ -40,7 +41,7 @@ import java9.util.concurrent.CompletableFuture;
|
|||||||
public class ZipExporterPreference extends Preference {
|
public class ZipExporterPreference extends Preference {
|
||||||
private static final String TAG = "WireGuard/" + ZipExporterPreference.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + ZipExporterPreference.class.getSimpleName();
|
||||||
|
|
||||||
private String exportedFilePath;
|
@Nullable private String exportedFilePath;
|
||||||
|
|
||||||
public ZipExporterPreference(final Context context, final AttributeSet attrs) {
|
public ZipExporterPreference(final Context context, final AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@ -79,7 +80,7 @@ public class ZipExporterPreference extends Preference {
|
|||||||
}).whenComplete(this::exportZipComplete));
|
}).whenComplete(this::exportZipComplete));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void exportZipComplete(final String filePath, final Throwable throwable) {
|
private void exportZipComplete(@Nullable final String filePath, @Nullable final Throwable throwable) {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
final String error = ExceptionLoggers.unwrapMessage(throwable);
|
final String error = ExceptionLoggers.unwrapMessage(throwable);
|
||||||
final String message = getContext().getString(R.string.zip_export_error, error);
|
final String message = getContext().getString(R.string.zip_export_error, error);
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
package com.wireguard.android.util;
|
package com.wireguard.android.util;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java9.util.concurrent.CompletionException;
|
import java9.util.concurrent.CompletionException;
|
||||||
import java9.util.function.BiConsumer;
|
import java9.util.function.BiConsumer;
|
||||||
|
|
||||||
@ -34,7 +35,6 @@ public enum ExceptionLoggers implements BiConsumer<Object, Throwable> {
|
|||||||
return throwable;
|
return throwable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static String unwrapMessage(Throwable throwable) {
|
public static String unwrapMessage(Throwable throwable) {
|
||||||
throwable = unwrap(throwable);
|
throwable = unwrap(throwable);
|
||||||
final String message = throwable.getMessage();
|
final String message = throwable.getMessage();
|
||||||
@ -44,7 +44,7 @@ public enum ExceptionLoggers implements BiConsumer<Object, Throwable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(final Object result, final Throwable throwable) {
|
public void accept(final Object result, @Nullable final Throwable throwable) {
|
||||||
if (throwable != null)
|
if (throwable != null)
|
||||||
Log.println(Log.ERROR, TAG, Log.getStackTraceString(throwable));
|
Log.println(Log.ERROR, TAG, Log.getStackTraceString(throwable));
|
||||||
else if (priority <= Log.DEBUG)
|
else if (priority <= Log.DEBUG)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
package com.wireguard.android.util;
|
package com.wireguard.android.util;
|
||||||
|
|
||||||
import android.databinding.ObservableArrayList;
|
import android.databinding.ObservableArrayList;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.util.Keyed;
|
import com.wireguard.util.Keyed;
|
||||||
|
|
||||||
@ -25,28 +25,28 @@ import java.util.Objects;
|
|||||||
public class ObservableKeyedArrayList<K, E extends Keyed<? extends K>>
|
public class ObservableKeyedArrayList<K, E extends Keyed<? extends K>>
|
||||||
extends ObservableArrayList<E> implements ObservableKeyedList<K, E> {
|
extends ObservableArrayList<E> implements ObservableKeyedList<K, E> {
|
||||||
@Override
|
@Override
|
||||||
public boolean add(final E e) {
|
public boolean add(@Nullable final E e) {
|
||||||
if (e == null)
|
if (e == null)
|
||||||
throw new NullPointerException("Trying to add a null element");
|
throw new NullPointerException("Trying to add a null element");
|
||||||
return super.add(e);
|
return super.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(final int index, final E e) {
|
public void add(final int index, @Nullable final E e) {
|
||||||
if (e == null)
|
if (e == null)
|
||||||
throw new NullPointerException("Trying to add a null element");
|
throw new NullPointerException("Trying to add a null element");
|
||||||
super.add(index, e);
|
super.add(index, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(@NonNull final Collection<? extends E> c) {
|
public boolean addAll(final Collection<? extends E> c) {
|
||||||
if (c.contains(null))
|
if (c.contains(null))
|
||||||
throw new NullPointerException("Trying to add a collection with null element(s)");
|
throw new NullPointerException("Trying to add a collection with null element(s)");
|
||||||
return super.addAll(c);
|
return super.addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(final int index, @NonNull final Collection<? extends E> c) {
|
public boolean addAll(final int index, final Collection<? extends E> c) {
|
||||||
if (c.contains(null))
|
if (c.contains(null))
|
||||||
throw new NullPointerException("Trying to add a collection with null element(s)");
|
throw new NullPointerException("Trying to add a collection with null element(s)");
|
||||||
return super.addAll(index, c);
|
return super.addAll(index, c);
|
||||||
@ -65,13 +65,13 @@ public class ObservableKeyedArrayList<K, E extends Keyed<? extends K>>
|
|||||||
return indexOfKey(key) >= 0;
|
return indexOfKey(key) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public E get(final K key) {
|
public E get(final K key) {
|
||||||
final int index = indexOfKey(key);
|
final int index = indexOfKey(key);
|
||||||
return index >= 0 ? get(index) : null;
|
return index >= 0 ? get(index) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public E getLast(final K key) {
|
public E getLast(final K key) {
|
||||||
final int index = lastIndexOfKey(key);
|
final int index = lastIndexOfKey(key);
|
||||||
return index >= 0 ? get(index) : null;
|
return index >= 0 ? get(index) : null;
|
||||||
@ -100,7 +100,7 @@ public class ObservableKeyedArrayList<K, E extends Keyed<? extends K>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public E set(final int index, final E e) {
|
public E set(final int index, @Nullable final E e) {
|
||||||
if (e == null)
|
if (e == null)
|
||||||
throw new NullPointerException("Trying to set a null key");
|
throw new NullPointerException("Trying to set a null key");
|
||||||
return super.set(index, e);
|
return super.set(index, e);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
package com.wireguard.android.util;
|
package com.wireguard.android.util;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.util.Keyed;
|
import com.wireguard.util.Keyed;
|
||||||
import com.wireguard.util.SortedKeyedList;
|
import com.wireguard.util.SortedKeyedList;
|
||||||
@ -29,6 +29,7 @@ import java.util.Spliterator;
|
|||||||
|
|
||||||
public class ObservableSortedKeyedArrayList<K, E extends Keyed<? extends K>>
|
public class ObservableSortedKeyedArrayList<K, E extends Keyed<? extends K>>
|
||||||
extends ObservableKeyedArrayList<K, E> implements ObservableSortedKeyedList<K, E> {
|
extends ObservableKeyedArrayList<K, E> implements ObservableSortedKeyedList<K, E> {
|
||||||
|
@Nullable
|
||||||
private final Comparator<? super K> comparator;
|
private final Comparator<? super K> comparator;
|
||||||
private final transient KeyList<K, E> keyList = new KeyList<>(this);
|
private final transient KeyList<K, E> keyList = new KeyList<>(this);
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ public class ObservableSortedKeyedArrayList<K, E extends Keyed<? extends K>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(@NonNull final Collection<? extends E> c) {
|
public boolean addAll(final Collection<? extends E> c) {
|
||||||
boolean didChange = false;
|
boolean didChange = false;
|
||||||
for (final E e : c)
|
for (final E e : c)
|
||||||
if (add(e))
|
if (add(e))
|
||||||
@ -84,12 +85,13 @@ public class ObservableSortedKeyedArrayList<K, E extends Keyed<? extends K>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAll(int index, @NonNull final Collection<? extends E> c) {
|
public boolean addAll(int index, final Collection<? extends E> c) {
|
||||||
for (final E e : c)
|
for (final E e : c)
|
||||||
add(index++, e);
|
add(index++, e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Comparator<? super K> comparator() {
|
public Comparator<? super K> comparator() {
|
||||||
return comparator;
|
return comparator;
|
||||||
@ -128,7 +130,6 @@ public class ObservableSortedKeyedArrayList<K, E extends Keyed<? extends K>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
|
||||||
public Set<K> keySet() {
|
public Set<K> keySet() {
|
||||||
return keyList;
|
return keyList;
|
||||||
}
|
}
|
||||||
@ -168,7 +169,6 @@ public class ObservableSortedKeyedArrayList<K, E extends Keyed<? extends K>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
|
||||||
public Collection<E> values() {
|
public Collection<E> values() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package com.wireguard.android.util;
|
package com.wireguard.android.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.wireguard.android.R;
|
import com.wireguard.android.R;
|
||||||
@ -34,10 +35,10 @@ public class RootShell {
|
|||||||
private final File localTemporaryDir;
|
private final File localTemporaryDir;
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
private final String preamble;
|
private final String preamble;
|
||||||
private Process process;
|
@Nullable private Process process;
|
||||||
private BufferedReader stderr;
|
@Nullable private BufferedReader stderr;
|
||||||
private OutputStreamWriter stdin;
|
@Nullable private OutputStreamWriter stdin;
|
||||||
private BufferedReader stdout;
|
@Nullable private BufferedReader stdout;
|
||||||
|
|
||||||
public RootShell(final Context context) {
|
public RootShell(final Context context) {
|
||||||
deviceNotRootedMessage = context.getString(R.string.error_root);
|
deviceNotRootedMessage = context.getString(R.string.error_root);
|
||||||
@ -80,7 +81,7 @@ public class RootShell {
|
|||||||
* @param command Command to run as root.
|
* @param command Command to run as root.
|
||||||
* @return The exit value of the command.
|
* @return The exit value of the command.
|
||||||
*/
|
*/
|
||||||
public int run(final Collection<String> output, final String command)
|
public int run(@Nullable final Collection<String> output, final String command)
|
||||||
throws IOException, NoRootException {
|
throws IOException, NoRootException {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
/* Start inside synchronized block to prevent a concurrent call to stop(). */
|
/* Start inside synchronized block to prevent a concurrent call to stop(). */
|
||||||
|
@ -19,8 +19,7 @@ import java.util.zip.ZipFile;
|
|||||||
public final class SharedLibraryLoader {
|
public final class SharedLibraryLoader {
|
||||||
private static final String TAG = "WireGuard/" + SharedLibraryLoader.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + SharedLibraryLoader.class.getSimpleName();
|
||||||
|
|
||||||
private SharedLibraryLoader() {
|
private SharedLibraryLoader() { }
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadSharedLibrary(final Context context, final String libName) {
|
public static void loadSharedLibrary(final Context context, final String libName) {
|
||||||
Throwable noAbiException;
|
Throwable noAbiException;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package com.wireguard.android.util;
|
package com.wireguard.android.util;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -39,20 +40,21 @@ public final class ToolsInstaller {
|
|||||||
new File("/system/xbin"),
|
new File("/system/xbin"),
|
||||||
new File("/system/bin"),
|
new File("/system/bin"),
|
||||||
};
|
};
|
||||||
private static final File INSTALL_DIR = getInstallDir();
|
@Nullable private static final File INSTALL_DIR = getInstallDir();
|
||||||
private static final String TAG = "WireGuard/" + ToolsInstaller.class.getSimpleName();
|
private static final String TAG = "WireGuard/" + ToolsInstaller.class.getSimpleName();
|
||||||
|
|
||||||
private final File localBinaryDir;
|
private final File localBinaryDir;
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
private final File nativeLibraryDir;
|
private final File nativeLibraryDir;
|
||||||
private Boolean areToolsAvailable;
|
@Nullable private Boolean areToolsAvailable;
|
||||||
private Boolean installAsMagiskModule;
|
@Nullable private Boolean installAsMagiskModule;
|
||||||
|
|
||||||
public ToolsInstaller(final Context context) {
|
public ToolsInstaller(final Context context) {
|
||||||
localBinaryDir = new File(context.getCacheDir(), "bin");
|
localBinaryDir = new File(context.getCacheDir(), "bin");
|
||||||
nativeLibraryDir = new File(context.getApplicationInfo().nativeLibraryDir);
|
nativeLibraryDir = new File(context.getApplicationInfo().nativeLibraryDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static File getInstallDir() {
|
private static File getInstallDir() {
|
||||||
final String path = System.getenv("PATH");
|
final String path = System.getenv("PATH");
|
||||||
if (path == null)
|
if (path == null)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package com.wireguard.android.widget;
|
package com.wireguard.android.widget;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.InputFilter;
|
import android.text.InputFilter;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
@ -25,7 +26,7 @@ public class KeyInputFilter implements InputFilter {
|
|||||||
return new KeyInputFilter();
|
return new KeyInputFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public CharSequence filter(final CharSequence source,
|
public CharSequence filter(final CharSequence source,
|
||||||
final int sStart, final int sEnd,
|
final int sStart, final int sEnd,
|
||||||
final Spanned dest,
|
final Spanned dest,
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package com.wireguard.android.widget;
|
package com.wireguard.android.widget;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.InputFilter;
|
import android.text.InputFilter;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
@ -25,7 +26,7 @@ public class NameInputFilter implements InputFilter {
|
|||||||
return new NameInputFilter();
|
return new NameInputFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override @Nullable
|
||||||
public CharSequence filter(final CharSequence source,
|
public CharSequence filter(final CharSequence source,
|
||||||
final int sStart, final int sEnd,
|
final int sStart, final int sEnd,
|
||||||
final Spanned dest,
|
final Spanned dest,
|
||||||
|
@ -25,11 +25,9 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.IntRange;
|
import android.support.annotation.IntRange;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.FloatProperty;
|
import android.util.FloatProperty;
|
||||||
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.N)
|
@TargetApi(Build.VERSION_CODES.N)
|
||||||
public class SlashDrawable extends Drawable {
|
public class SlashDrawable extends Drawable {
|
||||||
|
|
||||||
@ -53,26 +51,24 @@ public class SlashDrawable extends Drawable {
|
|||||||
// Draw the slash washington-monument style; rotate to no-u-turn style
|
// Draw the slash washington-monument style; rotate to no-u-turn style
|
||||||
private static final float DEFAULT_ROTATION = -45f;
|
private static final float DEFAULT_ROTATION = -45f;
|
||||||
|
|
||||||
private Drawable mDrawable;
|
private final Drawable mDrawable;
|
||||||
private final RectF mSlashRect = new RectF(0, 0, 0, 0);
|
private final RectF mSlashRect = new RectF(0, 0, 0, 0);
|
||||||
private float mRotation;
|
private float mRotation;
|
||||||
private boolean mSlashed;
|
private boolean mSlashed;
|
||||||
private Mode mTintMode;
|
|
||||||
private ColorStateList mTintList;
|
|
||||||
private boolean mAnimationEnabled = true;
|
private boolean mAnimationEnabled = true;
|
||||||
|
|
||||||
public SlashDrawable(final Drawable d) {
|
public SlashDrawable(final Drawable d) {
|
||||||
setDrawable(d);
|
mDrawable = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIntrinsicHeight() {
|
public int getIntrinsicHeight() {
|
||||||
return mDrawable != null ? mDrawable.getIntrinsicHeight(): 0;
|
return mDrawable.getIntrinsicHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getIntrinsicWidth() {
|
public int getIntrinsicWidth() {
|
||||||
return mDrawable != null ? mDrawable.getIntrinsicWidth(): 0;
|
return mDrawable.getIntrinsicWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -81,17 +77,6 @@ public class SlashDrawable extends Drawable {
|
|||||||
mDrawable.setBounds(bounds);
|
mDrawable.setBounds(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawable(final Drawable d) {
|
|
||||||
mDrawable = d;
|
|
||||||
mDrawable.setCallback(getCallback());
|
|
||||||
mDrawable.setBounds(getBounds());
|
|
||||||
if (mTintMode != null)
|
|
||||||
mDrawable.setTintMode(mTintMode);
|
|
||||||
if (mTintList != null)
|
|
||||||
mDrawable.setTintList(mTintList);
|
|
||||||
invalidateSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRotation(final float rotation) {
|
public void setRotation(final float rotation) {
|
||||||
if (mRotation == rotation)
|
if (mRotation == rotation)
|
||||||
return;
|
return;
|
||||||
@ -139,7 +124,7 @@ public class SlashDrawable extends Drawable {
|
|||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void draw(@NonNull final Canvas canvas) {
|
public void draw(final Canvas canvas) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
final Matrix m = new Matrix();
|
final Matrix m = new Matrix();
|
||||||
final int width = getBounds().width();
|
final int width = getBounds().width();
|
||||||
@ -201,7 +186,6 @@ public class SlashDrawable extends Drawable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTintList(@Nullable final ColorStateList tint) {
|
public void setTintList(@Nullable final ColorStateList tint) {
|
||||||
mTintList = tint;
|
|
||||||
super.setTintList(tint);
|
super.setTintList(tint);
|
||||||
setDrawableTintList(tint);
|
setDrawableTintList(tint);
|
||||||
mPaint.setColor(tint == null ? 0 : tint.getDefaultColor());
|
mPaint.setColor(tint == null ? 0 : tint.getDefaultColor());
|
||||||
@ -213,8 +197,7 @@ public class SlashDrawable extends Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTintMode(@NonNull final Mode tintMode) {
|
public void setTintMode(final Mode tintMode) {
|
||||||
mTintMode = tintMode;
|
|
||||||
super.setTintMode(tintMode);
|
super.setTintMode(tintMode);
|
||||||
mDrawable.setTintMode(tintMode);
|
mDrawable.setTintMode(tintMode);
|
||||||
}
|
}
|
||||||
|
@ -7,22 +7,23 @@ package com.wireguard.android.widget;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
|
|
||||||
public class ToggleSwitch extends Switch {
|
public class ToggleSwitch extends Switch {
|
||||||
private boolean isRestoringState;
|
private boolean isRestoringState;
|
||||||
private OnBeforeCheckedChangeListener listener;
|
@Nullable private OnBeforeCheckedChangeListener listener;
|
||||||
|
|
||||||
@SuppressWarnings({"SameParameterValue", "WeakerAccess"})
|
|
||||||
public ToggleSwitch(final Context context, final AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ToggleSwitch(final Context context) {
|
public ToggleSwitch(final Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"SameParameterValue", "WeakerAccess"})
|
||||||
|
public ToggleSwitch(final Context context, @Nullable final AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestoreInstanceState(final Parcelable state) {
|
public void onRestoreInstanceState(final Parcelable state) {
|
||||||
isRestoringState = true;
|
isRestoringState = true;
|
||||||
|
@ -20,7 +20,7 @@ import android.graphics.drawable.LayerDrawable;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.Keep;
|
import android.support.annotation.Keep;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.v4.content.res.ResourcesCompat;
|
import android.support.v4.content.res.ResourcesCompat;
|
||||||
import android.support.v7.widget.AppCompatTextView;
|
import android.support.v7.widget.AppCompatTextView;
|
||||||
@ -57,32 +57,32 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
private boolean mExpanded;
|
private boolean mExpanded;
|
||||||
private final AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
private final AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
||||||
private final AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
private final AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
||||||
private FloatingActionButton mAddButton;
|
@Nullable private FloatingActionButton mAddButton;
|
||||||
private RotatingDrawable mRotatingDrawable;
|
@Nullable private RotatingDrawable mRotatingDrawable;
|
||||||
private int mMaxButtonWidth;
|
private int mMaxButtonWidth;
|
||||||
private int mMaxButtonHeight;
|
private int mMaxButtonHeight;
|
||||||
private int mLabelsStyle;
|
private int mLabelsStyle;
|
||||||
private int mLabelsPosition;
|
private int mLabelsPosition;
|
||||||
private int mButtonsCount;
|
private int mButtonsCount;
|
||||||
private TouchDelegateGroup mTouchDelegateGroup;
|
@Nullable private TouchDelegateGroup mTouchDelegateGroup;
|
||||||
private OnFloatingActionsMenuUpdateListener mListener;
|
@Nullable private OnFloatingActionsMenuUpdateListener mListener;
|
||||||
private final Rect touchArea = new Rect(0, 0, 0, 0);
|
private final Rect touchArea = new Rect(0, 0, 0, 0);
|
||||||
|
|
||||||
public FloatingActionsMenu(final Context context) {
|
public FloatingActionsMenu(final Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FloatingActionsMenu(final Context context, final AttributeSet attrs) {
|
public FloatingActionsMenu(final Context context, @Nullable final AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
init(context, attrs);
|
init(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FloatingActionsMenu(final Context context, final AttributeSet attrs, final int defStyle) {
|
public FloatingActionsMenu(final Context context, @Nullable final AttributeSet attrs, final int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
init(context, attrs);
|
init(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init(final Context context, final AttributeSet attributeSet) {
|
private void init(final Context context, @Nullable final AttributeSet attributeSet) {
|
||||||
mButtonSpacing = (int) (getResources().getDimension(R.dimen.fab_actions_spacing));
|
mButtonSpacing = (int) (getResources().getDimension(R.dimen.fab_actions_spacing));
|
||||||
mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin);
|
mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin);
|
||||||
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
|
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
|
||||||
@ -530,7 +530,7 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(@NonNull final Parcel out, final int flags) {
|
public void writeToParcel(final Parcel out, final int flags) {
|
||||||
super.writeToParcel(out, flags);
|
super.writeToParcel(out, flags);
|
||||||
out.writeInt(mExpanded ? 1 : 0);
|
out.writeInt(mExpanded ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ package com.wireguard.android.widget.fab;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -16,17 +17,17 @@ import com.wireguard.android.R;
|
|||||||
|
|
||||||
public class LabeledFloatingActionButton extends FloatingActionButton {
|
public class LabeledFloatingActionButton extends FloatingActionButton {
|
||||||
|
|
||||||
private final String title;
|
@Nullable private final String title;
|
||||||
|
|
||||||
public LabeledFloatingActionButton(final Context context) {
|
public LabeledFloatingActionButton(final Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LabeledFloatingActionButton(final Context context, final AttributeSet attrs) {
|
public LabeledFloatingActionButton(final Context context, @Nullable final AttributeSet attrs) {
|
||||||
this(context, attrs, 0);
|
this(context, attrs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LabeledFloatingActionButton(final Context context, final AttributeSet attrs, final int defStyle) {
|
public LabeledFloatingActionButton(final Context context, @Nullable final AttributeSet attrs, final int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
final TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.LabeledFloatingActionButton, 0, 0);
|
final TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.LabeledFloatingActionButton, 0, 0);
|
||||||
@ -34,10 +35,12 @@ public class LabeledFloatingActionButton extends FloatingActionButton {
|
|||||||
attr.recycle();
|
attr.recycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
TextView getLabelView() {
|
TextView getLabelView() {
|
||||||
return (TextView) getTag(R.id.fab_label);
|
return (TextView) getTag(R.id.fab_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
package com.wireguard.android.widget.fab;
|
package com.wireguard.android.widget.fab;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.Nullable;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.TouchDelegate;
|
import android.view.TouchDelegate;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -18,14 +18,14 @@ import java.util.Collection;
|
|||||||
public class TouchDelegateGroup extends TouchDelegate {
|
public class TouchDelegateGroup extends TouchDelegate {
|
||||||
private static final Rect USELESS_HACKY_RECT = new Rect();
|
private static final Rect USELESS_HACKY_RECT = new Rect();
|
||||||
private final Collection<TouchDelegate> mTouchDelegates = new ArrayList<>();
|
private final Collection<TouchDelegate> mTouchDelegates = new ArrayList<>();
|
||||||
private TouchDelegate mCurrentTouchDelegate;
|
@Nullable private TouchDelegate mCurrentTouchDelegate;
|
||||||
private boolean mEnabled;
|
private boolean mEnabled;
|
||||||
|
|
||||||
public TouchDelegateGroup(final View uselessHackyView) {
|
public TouchDelegateGroup(final View uselessHackyView) {
|
||||||
super(USELESS_HACKY_RECT, uselessHackyView);
|
super(USELESS_HACKY_RECT, uselessHackyView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTouchDelegate(@NonNull final TouchDelegate touchDelegate) {
|
public void addTouchDelegate(final TouchDelegate touchDelegate) {
|
||||||
mTouchDelegates.add(touchDelegate);
|
mTouchDelegates.add(touchDelegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ public class TouchDelegateGroup extends TouchDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(@NonNull final MotionEvent event) {
|
public boolean onTouchEvent(final MotionEvent event) {
|
||||||
if (!mEnabled)
|
if (!mEnabled)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package com.wireguard.config;
|
package com.wireguard.config;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -59,13 +60,13 @@ public enum Attribute {
|
|||||||
return KEY_MAP.get(SEPARATOR_PATTERN.split(line)[0].toLowerCase());
|
return KEY_MAP.get(SEPARATOR_PATTERN.split(line)[0].toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[] stringToList(final String string) {
|
public static String[] stringToList(@Nullable final String string) {
|
||||||
if (TextUtils.isEmpty(string))
|
if (TextUtils.isEmpty(string))
|
||||||
return EMPTY_LIST;
|
return EMPTY_LIST;
|
||||||
return LIST_SEPARATOR_PATTERN.split(string.trim());
|
return LIST_SEPARATOR_PATTERN.split(string.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String composeWith(final Object value) {
|
public String composeWith(@Nullable final Object value) {
|
||||||
return String.format("%s = %s%n", token, value);
|
return String.format("%s = %s%n", token, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,11 +78,13 @@ public enum Attribute {
|
|||||||
return String.format("%s = %s%n", token, iterableToString(value));
|
return String.format("%s = %s%n", token, iterableToString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String parse(final CharSequence line) {
|
public String parse(final CharSequence line) {
|
||||||
final Matcher matcher = pattern.matcher(line);
|
final Matcher matcher = pattern.matcher(line);
|
||||||
return matcher.matches() ? matcher.group(1) : null;
|
return matcher.matches() ? matcher.group(1) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String[] parseList(final CharSequence line) {
|
public String[] parseList(final CharSequence line) {
|
||||||
final Matcher matcher = pattern.matcher(line);
|
final Matcher matcher = pattern.matcher(line);
|
||||||
return matcher.matches() ? stringToList(matcher.group(1)) : null;
|
return matcher.matches() ? stringToList(matcher.group(1)) : null;
|
||||||
|
@ -12,6 +12,7 @@ import android.databinding.ObservableArrayList;
|
|||||||
import android.databinding.ObservableList;
|
import android.databinding.ObservableList;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.databinding.library.baseAdapters.BR;
|
import com.android.databinding.library.baseAdapters.BR;
|
||||||
|
|
||||||
@ -96,13 +97,19 @@ public class Config {
|
|||||||
return new Observable[size];
|
return new Observable[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private String name;
|
@Nullable private String name;
|
||||||
private Interface.Observable observableInterface;
|
private final Interface.Observable observableInterface;
|
||||||
private ObservableList<Peer.Observable> observablePeers;
|
private final ObservableList<Peer.Observable> observablePeers;
|
||||||
|
|
||||||
public Observable(final Config parent, final String name) {
|
public Observable(@Nullable final Config parent, @Nullable final String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
loadData(parent);
|
|
||||||
|
observableInterface = new Interface.Observable(parent == null ? null : parent.interfaceSection);
|
||||||
|
observablePeers = new ObservableArrayList<>();
|
||||||
|
if (parent != null) {
|
||||||
|
for (final Peer peer : parent.getPeers())
|
||||||
|
observablePeers.add(new Peer.Observable(peer));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Observable(final Parcel in) {
|
private Observable(final Parcel in) {
|
||||||
@ -144,15 +151,6 @@ public class Config {
|
|||||||
return observablePeers;
|
return observablePeers;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadData(final Config parent) {
|
|
||||||
observableInterface = new Interface.Observable(parent == null ? null : parent.interfaceSection);
|
|
||||||
observablePeers = new ObservableArrayList<>();
|
|
||||||
if (parent != null) {
|
|
||||||
for (final Peer peer : parent.getPeers())
|
|
||||||
observablePeers.add(new Peer.Observable(peer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(final String name) {
|
public void setName(final String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
notifyPropertyChanged(BR.name);
|
notifyPropertyChanged(BR.name);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
package com.wireguard.config;
|
package com.wireguard.config;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -29,7 +28,6 @@ public final class InetAddresses {
|
|||||||
// Prevent instantiation.
|
// Prevent instantiation.
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public static InetAddress parse(@Nullable final String address) {
|
public static InetAddress parse(@Nullable final String address) {
|
||||||
if (address == null || address.isEmpty())
|
if (address == null || address.isEmpty())
|
||||||
throw new IllegalArgumentException("Empty address");
|
throw new IllegalArgumentException("Empty address");
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
package com.wireguard.config;
|
package com.wireguard.config;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -16,7 +14,7 @@ public class InetNetwork {
|
|||||||
private final InetAddress address;
|
private final InetAddress address;
|
||||||
private final int mask;
|
private final int mask;
|
||||||
|
|
||||||
public InetNetwork(@NonNull final String input) {
|
public InetNetwork(final String input) {
|
||||||
final int slash = input.lastIndexOf('/');
|
final int slash = input.lastIndexOf('/');
|
||||||
final int rawMask;
|
final int rawMask;
|
||||||
final String rawAddress;
|
final String rawAddress;
|
||||||
@ -40,7 +38,6 @@ public class InetNetwork {
|
|||||||
return Objects.equals(address, other.address) && mask == other.mask;
|
return Objects.equals(address, other.address) && mask == other.mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public InetAddress getAddress() {
|
public InetAddress getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import android.databinding.BaseObservable;
|
|||||||
import android.databinding.Bindable;
|
import android.databinding.Bindable;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.wireguard.android.BR;
|
import com.wireguard.android.BR;
|
||||||
import com.wireguard.crypto.Keypair;
|
import com.wireguard.crypto.Keypair;
|
||||||
@ -27,7 +28,7 @@ public class Interface {
|
|||||||
private final List<InetNetwork> addressList;
|
private final List<InetNetwork> addressList;
|
||||||
private final List<InetAddress> dnsList;
|
private final List<InetAddress> dnsList;
|
||||||
private final List<String> excludedApplications;
|
private final List<String> excludedApplications;
|
||||||
private Keypair keypair;
|
@Nullable private Keypair keypair;
|
||||||
private int listenPort;
|
private int listenPort;
|
||||||
private int mtu;
|
private int mtu;
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ public class Interface {
|
|||||||
excludedApplications = new ArrayList<>();
|
excludedApplications = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAddresses(final String[] addresses) {
|
private void addAddresses(@Nullable final String[] addresses) {
|
||||||
if (addresses != null && addresses.length > 0) {
|
if (addresses != null && addresses.length > 0) {
|
||||||
for (final String addr : addresses) {
|
for (final String addr : addresses) {
|
||||||
if (addr.isEmpty())
|
if (addr.isEmpty())
|
||||||
@ -47,7 +48,7 @@ public class Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDnses(final String[] dnses) {
|
private void addDnses(@Nullable final String[] dnses) {
|
||||||
if (dnses != null && dnses.length > 0) {
|
if (dnses != null && dnses.length > 0) {
|
||||||
for (final String dns : dnses) {
|
for (final String dns : dnses) {
|
||||||
dnsList.add(InetAddresses.parse(dns));
|
dnsList.add(InetAddresses.parse(dns));
|
||||||
@ -55,12 +56,13 @@ public class Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addExcludedApplications(final String[] applications) {
|
private void addExcludedApplications(@Nullable final String[] applications) {
|
||||||
if (applications != null && applications.length > 0) {
|
if (applications != null && applications.length > 0) {
|
||||||
excludedApplications.addAll(Arrays.asList(applications));
|
excludedApplications.addAll(Arrays.asList(applications));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getAddressString() {
|
private String getAddressString() {
|
||||||
if (addressList.isEmpty())
|
if (addressList.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
@ -71,6 +73,7 @@ public class Interface {
|
|||||||
return addressList.toArray(new InetNetwork[addressList.size()]);
|
return addressList.toArray(new InetNetwork[addressList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getDnsString() {
|
private String getDnsString() {
|
||||||
if (dnsList.isEmpty())
|
if (dnsList.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
@ -88,6 +91,7 @@ public class Interface {
|
|||||||
return dnsList.toArray(new InetAddress[dnsList.size()]);
|
return dnsList.toArray(new InetAddress[dnsList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getExcludedApplicationsString() {
|
private String getExcludedApplicationsString() {
|
||||||
if (excludedApplications.isEmpty())
|
if (excludedApplications.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
@ -102,6 +106,7 @@ public class Interface {
|
|||||||
return listenPort;
|
return listenPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getListenPortString() {
|
private String getListenPortString() {
|
||||||
if (listenPort == 0)
|
if (listenPort == 0)
|
||||||
return null;
|
return null;
|
||||||
@ -112,18 +117,21 @@ public class Interface {
|
|||||||
return mtu;
|
return mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getMtuString() {
|
private String getMtuString() {
|
||||||
if (mtu == 0)
|
if (mtu == 0)
|
||||||
return null;
|
return null;
|
||||||
return Integer.toString(mtu);
|
return Integer.toString(mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getPrivateKey() {
|
public String getPrivateKey() {
|
||||||
if (keypair == null)
|
if (keypair == null)
|
||||||
return null;
|
return null;
|
||||||
return keypair.getPrivateKey();
|
return keypair.getPrivateKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getPublicKey() {
|
public String getPublicKey() {
|
||||||
if (keypair == null)
|
if (keypair == null)
|
||||||
return null;
|
return null;
|
||||||
@ -156,17 +164,17 @@ public class Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAddressString(final String addressString) {
|
private void setAddressString(@Nullable final String addressString) {
|
||||||
addressList.clear();
|
addressList.clear();
|
||||||
addAddresses(Attribute.stringToList(addressString));
|
addAddresses(Attribute.stringToList(addressString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDnsString(final String dnsString) {
|
private void setDnsString(@Nullable final String dnsString) {
|
||||||
dnsList.clear();
|
dnsList.clear();
|
||||||
addDnses(Attribute.stringToList(dnsString));
|
addDnses(Attribute.stringToList(dnsString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setExcludedApplicationsString(final String applicationsString) {
|
private void setExcludedApplicationsString(@Nullable final String applicationsString) {
|
||||||
excludedApplications.clear();
|
excludedApplications.clear();
|
||||||
addExcludedApplications(Attribute.stringToList(applicationsString));
|
addExcludedApplications(Attribute.stringToList(applicationsString));
|
||||||
}
|
}
|
||||||
@ -175,7 +183,7 @@ public class Interface {
|
|||||||
this.listenPort = listenPort;
|
this.listenPort = listenPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setListenPortString(final String port) {
|
private void setListenPortString(@Nullable final String port) {
|
||||||
if (port != null && !port.isEmpty())
|
if (port != null && !port.isEmpty())
|
||||||
setListenPort(Integer.parseInt(port, 10));
|
setListenPort(Integer.parseInt(port, 10));
|
||||||
else
|
else
|
||||||
@ -186,14 +194,14 @@ public class Interface {
|
|||||||
this.mtu = mtu;
|
this.mtu = mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMtuString(final String mtu) {
|
private void setMtuString(@Nullable final String mtu) {
|
||||||
if (mtu != null && !mtu.isEmpty())
|
if (mtu != null && !mtu.isEmpty())
|
||||||
setMtu(Integer.parseInt(mtu, 10));
|
setMtu(Integer.parseInt(mtu, 10));
|
||||||
else
|
else
|
||||||
setMtu(0);
|
setMtu(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPrivateKey(String privateKey) {
|
private void setPrivateKey(@Nullable String privateKey) {
|
||||||
if (privateKey != null && privateKey.isEmpty())
|
if (privateKey != null && privateKey.isEmpty())
|
||||||
privateKey = null;
|
privateKey = null;
|
||||||
keypair = privateKey == null ? null : new Keypair(privateKey);
|
keypair = privateKey == null ? null : new Keypair(privateKey);
|
||||||
@ -229,15 +237,15 @@ public class Interface {
|
|||||||
return new Observable[size];
|
return new Observable[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private String addresses;
|
@Nullable private String addresses;
|
||||||
private String dnses;
|
@Nullable private String dnses;
|
||||||
private String excludedApplications;
|
@Nullable private String excludedApplications;
|
||||||
private String listenPort;
|
@Nullable private String listenPort;
|
||||||
private String mtu;
|
@Nullable private String mtu;
|
||||||
private String privateKey;
|
@Nullable private String privateKey;
|
||||||
private String publicKey;
|
@Nullable private String publicKey;
|
||||||
|
|
||||||
public Observable(final Interface parent) {
|
public Observable(@Nullable final Interface parent) {
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
loadData(parent);
|
loadData(parent);
|
||||||
}
|
}
|
||||||
@ -276,16 +284,19 @@ public class Interface {
|
|||||||
notifyPropertyChanged(BR.publicKey);
|
notifyPropertyChanged(BR.publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getAddresses() {
|
public String getAddresses() {
|
||||||
return addresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getDnses() {
|
public String getDnses() {
|
||||||
return dnses;
|
return dnses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getExcludedApplications() {
|
public String getExcludedApplications() {
|
||||||
return excludedApplications;
|
return excludedApplications;
|
||||||
@ -296,21 +307,25 @@ public class Interface {
|
|||||||
return Attribute.stringToList(excludedApplications).length;
|
return Attribute.stringToList(excludedApplications).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getListenPort() {
|
public String getListenPort() {
|
||||||
return listenPort;
|
return listenPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getMtu() {
|
public String getMtu() {
|
||||||
return mtu;
|
return mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getPrivateKey() {
|
public String getPrivateKey() {
|
||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Bindable
|
@Bindable
|
||||||
public String getPublicKey() {
|
public String getPublicKey() {
|
||||||
return publicKey;
|
return publicKey;
|
||||||
|
@ -10,6 +10,7 @@ import android.databinding.BaseObservable;
|
|||||||
import android.databinding.Bindable;
|
import android.databinding.Bindable;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.databinding.library.baseAdapters.BR;
|
import com.android.databinding.library.baseAdapters.BR;
|
||||||
import com.wireguard.crypto.KeyEncoding;
|
import com.wireguard.crypto.KeyEncoding;
|
||||||
@ -34,16 +35,16 @@ import java9.lang.Iterables;
|
|||||||
|
|
||||||
public class Peer {
|
public class Peer {
|
||||||
private final List<InetNetwork> allowedIPsList;
|
private final List<InetNetwork> allowedIPsList;
|
||||||
private InetSocketAddress endpoint;
|
@Nullable private InetSocketAddress endpoint;
|
||||||
private int persistentKeepalive;
|
private int persistentKeepalive;
|
||||||
private String preSharedKey;
|
@Nullable private String preSharedKey;
|
||||||
private String publicKey;
|
@Nullable private String publicKey;
|
||||||
|
|
||||||
public Peer() {
|
public Peer() {
|
||||||
allowedIPsList = new ArrayList<>();
|
allowedIPsList = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAllowedIPs(final String[] allowedIPs) {
|
private void addAllowedIPs(@Nullable final String[] allowedIPs) {
|
||||||
if (allowedIPs != null && allowedIPs.length > 0) {
|
if (allowedIPs != null && allowedIPs.length > 0) {
|
||||||
for (final String allowedIP : allowedIPs) {
|
for (final String allowedIP : allowedIPs) {
|
||||||
allowedIPsList.add(new InetNetwork(allowedIP));
|
allowedIPsList.add(new InetNetwork(allowedIP));
|
||||||
@ -55,16 +56,19 @@ public class Peer {
|
|||||||
return allowedIPsList.toArray(new InetNetwork[allowedIPsList.size()]);
|
return allowedIPsList.toArray(new InetNetwork[allowedIPsList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getAllowedIPsString() {
|
private String getAllowedIPsString() {
|
||||||
if (allowedIPsList.isEmpty())
|
if (allowedIPsList.isEmpty())
|
||||||
return null;
|
return null;
|
||||||
return Attribute.iterableToString(allowedIPsList);
|
return Attribute.iterableToString(allowedIPsList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public InetSocketAddress getEndpoint() {
|
public InetSocketAddress getEndpoint() {
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getEndpointString() {
|
private String getEndpointString() {
|
||||||
if (endpoint == null)
|
if (endpoint == null)
|
||||||
return null;
|
return null;
|
||||||
@ -75,16 +79,19 @@ public class Peer {
|
|||||||
return persistentKeepalive;
|
return persistentKeepalive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private String getPersistentKeepaliveString() {
|
private String getPersistentKeepaliveString() {
|
||||||
if (persistentKeepalive == 0)
|
if (persistentKeepalive == 0)
|
||||||
return null;
|
return null;
|
||||||
return Integer.valueOf(persistentKeepalive).toString();
|
return Integer.valueOf(persistentKeepalive).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getPreSharedKey() {
|
public String getPreSharedKey() {
|
||||||
return preSharedKey;
|
return preSharedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public String getPublicKey() {
|
public String getPublicKey() {
|
||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
@ -130,16 +137,16 @@ public class Peer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAllowedIPsString(final String allowedIPsString) {
|
private void setAllowedIPsString(@Nullable final String allowedIPsString) {
|
||||||
allowedIPsList.clear();
|
allowedIPsList.clear();
|
||||||
addAllowedIPs(Attribute.stringToList(allowedIPsString));
|
addAllowedIPs(Attribute.stringToList(allowedIPsString));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEndpoint(final InetSocketAddress endpoint) {
|
private void setEndpoint(@Nullable final InetSocketAddress endpoint) {
|
||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEndpointString(final String endpoint) {
|
private void setEndpointString(@Nullable final String endpoint) {
|
||||||
if (endpoint != null && !endpoint.isEmpty()) {
|
if (endpoint != null && !endpoint.isEmpty()) {
|
||||||
final InetSocketAddress constructedEndpoint;
|
final InetSocketAddress constructedEndpoint;
|
||||||
if (endpoint.indexOf('/') != -1 || endpoint.indexOf('?') != -1 || endpoint.indexOf('#') != -1)
|
if (endpoint.indexOf('/') != -1 || endpoint.indexOf('?') != -1 || endpoint.indexOf('#') != -1)
|
||||||
@ -160,14 +167,14 @@ public class Peer {
|
|||||||
this.persistentKeepalive = persistentKeepalive;
|
this.persistentKeepalive = persistentKeepalive;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPersistentKeepaliveString(final String persistentKeepalive) {
|
private void setPersistentKeepaliveString(@Nullable final String persistentKeepalive) {
|
||||||
if (persistentKeepalive != null && !persistentKeepalive.isEmpty())
|
if (persistentKeepalive != null && !persistentKeepalive.isEmpty())
|
||||||
setPersistentKeepalive(Integer.parseInt(persistentKeepalive, 10));
|
setPersistentKeepalive(Integer.parseInt(persistentKeepalive, 10));
|
||||||
else
|
else
|
||||||
setPersistentKeepalive(0);
|
setPersistentKeepalive(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPreSharedKey(String preSharedKey) {
|
private void setPreSharedKey(@Nullable String preSharedKey) {
|
||||||
if (preSharedKey != null && preSharedKey.isEmpty())
|
if (preSharedKey != null && preSharedKey.isEmpty())
|
||||||
preSharedKey = null;
|
preSharedKey = null;
|
||||||
if (preSharedKey != null)
|
if (preSharedKey != null)
|
||||||
@ -175,7 +182,7 @@ public class Peer {
|
|||||||
this.preSharedKey = preSharedKey;
|
this.preSharedKey = preSharedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPublicKey(String publicKey) {
|
private void setPublicKey(@Nullable String publicKey) {
|
||||||
if (publicKey != null && publicKey.isEmpty())
|
if (publicKey != null && publicKey.isEmpty())
|
||||||
publicKey = null;
|
publicKey = null;
|
||||||
if (publicKey != null)
|
if (publicKey != null)
|
||||||
@ -211,12 +218,12 @@ public class Peer {
|
|||||||
return new Observable[size];
|
return new Observable[size];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private String allowedIPs;
|
@Nullable private String allowedIPs;
|
||||||
private String endpoint;
|
@Nullable private String endpoint;
|
||||||
private String persistentKeepalive;
|
@Nullable private String persistentKeepalive;
|
||||||
private String preSharedKey;
|
@Nullable private String preSharedKey;
|
||||||
private String publicKey;
|
@Nullable private String publicKey;
|
||||||
private List<String> interfaceDNSRoutes;
|
private final List<String> interfaceDNSRoutes = new ArrayList<>();
|
||||||
private int numSiblings;
|
private int numSiblings;
|
||||||
|
|
||||||
public Observable(final Peer parent) {
|
public Observable(final Peer parent) {
|
||||||
@ -230,7 +237,6 @@ public class Peer {
|
|||||||
preSharedKey = in.readString();
|
preSharedKey = in.readString();
|
||||||
publicKey = in.readString();
|
publicKey = in.readString();
|
||||||
numSiblings = in.readInt();
|
numSiblings = in.readInt();
|
||||||
interfaceDNSRoutes = new ArrayList<>();
|
|
||||||
in.readStringList(interfaceDNSRoutes);
|
in.readStringList(interfaceDNSRoutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,27 +290,27 @@ public class Peer {
|
|||||||
return numSiblings == 0 && Arrays.asList(Attribute.stringToList(allowedIPs)).containsAll(DEFAULT_ROUTE_MOD_RFC1918_V4);
|
return numSiblings == 0 && Arrays.asList(Attribute.stringToList(allowedIPs)).containsAll(DEFAULT_ROUTE_MOD_RFC1918_V4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public String getAllowedIPs() {
|
public String getAllowedIPs() {
|
||||||
return allowedIPs;
|
return allowedIPs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public String getEndpoint() {
|
public String getEndpoint() {
|
||||||
return endpoint;
|
return endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public String getPersistentKeepalive() {
|
public String getPersistentKeepalive() {
|
||||||
return persistentKeepalive;
|
return persistentKeepalive;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public String getPreSharedKey() {
|
public String getPreSharedKey() {
|
||||||
return preSharedKey;
|
return preSharedKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bindable
|
@Bindable @Nullable
|
||||||
public String getPublicKey() {
|
public String getPublicKey() {
|
||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
@ -315,7 +321,6 @@ public class Peer {
|
|||||||
persistentKeepalive = parent.getPersistentKeepaliveString();
|
persistentKeepalive = parent.getPersistentKeepaliveString();
|
||||||
preSharedKey = parent.getPreSharedKey();
|
preSharedKey = parent.getPreSharedKey();
|
||||||
publicKey = parent.getPublicKey();
|
publicKey = parent.getPublicKey();
|
||||||
interfaceDNSRoutes = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllowedIPs(final String allowedIPs) {
|
public void setAllowedIPs(final String allowedIPs) {
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package com.wireguard.crypto;
|
package com.wireguard.crypto;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +95,7 @@ public final class Curve25519 {
|
|||||||
* if the base point of the curve should be used.
|
* if the base point of the curve should be used.
|
||||||
*/
|
*/
|
||||||
public static void eval(final byte[] result, final int offset,
|
public static void eval(final byte[] result, final int offset,
|
||||||
final byte[] privateKey, final byte[] publicKey) {
|
final byte[] privateKey, @Nullable final byte[] publicKey) {
|
||||||
final Curve25519 state = new Curve25519();
|
final Curve25519 state = new Curve25519();
|
||||||
try {
|
try {
|
||||||
// Unpack the public key value. If null, use 9 as the base point.
|
// Unpack the public key value. If null, use 9 as the base point.
|
||||||
|
25
app/src/main/java/com/wireguard/util/NonNullForAll.java
Normal file
25
app/src/main/java/com/wireguard/util/NonNullForAll.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2018 Eric Kuck <eric@bluelinelabs.com>.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.wireguard.util;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.meta.TypeQualifierDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation can be applied to a package, class or method to indicate that all
|
||||||
|
* class fields and method parameters and return values in that element are nonnull
|
||||||
|
* by default unless overridden.
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Nonnull
|
||||||
|
@TypeQualifierDefault({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface NonNullForAll { }
|
Loading…
Reference in New Issue
Block a user