From 292df1217580fdda3592f59ed356bdb289564392 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 27 May 2018 18:57:52 +0200 Subject: [PATCH] Support always-on-vpn Signed-off-by: Jason A. Donenfeld --- app/src/main/AndroidManifest.xml | 3 -- .../android/BootShutdownReceiver.java | 6 +++- .../android/activity/SettingsActivity.java | 7 +++-- .../wireguard/android/backend/GoBackend.java | 18 +++++++++++ .../android/model/TunnelManager.java | 30 +++++++++++++++++-- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f99c02ee..e83f8841 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,9 +62,6 @@ - tunnels = new ObservableSortedKeyedArrayList<>(COMPARATOR); private Tunnel lastUsedTunnel; + private boolean haveLoaded; + private ArrayList> delayedLoadRestoreTunnels = new ArrayList<>(); @Inject public TunnelManager(final AsyncWorker asyncWorker, final Backend backend, @@ -140,12 +143,27 @@ public final class TunnelManager extends BaseObservable { .whenComplete(ExceptionLoggers.E); } + @SuppressWarnings("unchecked") private void onTunnelsLoaded(final Iterable present, final Collection running) { for (final String name : present) addToList(name, null, running.contains(name) ? State.UP : State.DOWN); final String lastUsedName = preferences.getString(KEY_LAST_USED_TUNNEL, null); if (lastUsedName != null) setLastUsedTunnel(tunnels.get(lastUsedName)); + CompletableFuture toComplete[]; + synchronized (delayedLoadRestoreTunnels) { + haveLoaded = true; + toComplete = delayedLoadRestoreTunnels.toArray(new CompletableFuture[delayedLoadRestoreTunnels.size()]); + delayedLoadRestoreTunnels.clear(); + } + restoreState(true).whenComplete((v, t) -> { + for (final CompletableFuture f : toComplete) { + if (t == null) + f.complete(v); + else + f.completeExceptionally(t); + } + }); } public void refreshTunnelStates() { @@ -157,9 +175,16 @@ public final class TunnelManager extends BaseObservable { .whenComplete(ExceptionLoggers.E); } - public CompletionStage restoreState() { - if (!preferences.getBoolean(KEY_RESTORE_ON_BOOT, false)) + public CompletionStage restoreState(boolean force) { + if (!force && !preferences.getBoolean(KEY_RESTORE_ON_BOOT, false)) return CompletableFuture.completedFuture(null); + synchronized (delayedLoadRestoreTunnels) { + if (!haveLoaded) { + CompletableFuture f = new CompletableFuture<>(); + delayedLoadRestoreTunnels.add(f); + return f; + } + } final Set previouslyRunning = preferences.getStringSet(KEY_RUNNING_TUNNELS, null); if (previouslyRunning == null) return CompletableFuture.completedFuture(null); @@ -236,6 +261,7 @@ public final class TunnelManager extends BaseObservable { tunnel.onStateChanged(e == null ? newState : tunnel.getState()); if (e == null && newState == State.UP) setLastUsedTunnel(tunnel); + saveState(); }); } }