aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorHarsh Shandilya <msfjarvis@gmail.com>2019-12-15 00:35:28 +0530
committerJason A. Donenfeld <Jason@zx2c4.com>2019-12-20 11:26:33 +0100
commit90e2b66df719784a6c8f9e8673a14bb2861081fb (patch)
treec7d7edc17812a7d6b55663ef683ab2af774c0fd4
parentUse RequiresApi instead of TargetApi (diff)
downloadwireguard-android-90e2b66df719784a6c8f9e8673a14bb2861081fb.tar.xz
wireguard-android-90e2b66df719784a6c8f9e8673a14bb2861081fb.zip
Introduce TunnelToggleActivity
On Android 10, apps cannot start services when they're in the background. This means that starting VpnService from within QuickTileService when the app is not active ends badly. To mitigate this situation, we introduce a proxy activity of sorts that will handle starting VpnService for us. The activity is completely transparent and invisible, and does only four things: - Toggle the tunnel state - Request the Tile bound by QuickTileService to refresh its state - Handle any error that might have been thrown during toggle - Call finishAffinity() and go away Signed-off-by: Harsh Shandilya <msfjarvis@gmail.com>
-rw-r--r--app/src/main/AndroidManifest.xml3
-rw-r--r--app/src/main/java/com/wireguard/android/QuickTileService.java23
-rw-r--r--app/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.java51
-rw-r--r--app/src/main/res/values/styles.xml13
4 files changed, 75 insertions, 15 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 67653221..21fc6eb3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,11 +26,10 @@
android:theme="@style/AppTheme"
tools:ignore="UnusedAttribute">
+ <activity android:name=".activity.TunnelToggleActivity" android:theme="@style/NoBackgroundTheme"/>
<activity android:name=".activity.MainActivity">
-
<intent-filter>
<action android:name="android.intent.action.MAIN" />
-
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
diff --git a/app/src/main/java/com/wireguard/android/QuickTileService.java b/app/src/main/java/com/wireguard/android/QuickTileService.java
index d296a88c..8909beec 100644
--- a/app/src/main/java/com/wireguard/android/QuickTileService.java
+++ b/app/src/main/java/com/wireguard/android/QuickTileService.java
@@ -18,12 +18,11 @@ import android.service.quicksettings.TileService;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.util.Log;
-import android.widget.Toast;
import com.wireguard.android.activity.MainActivity;
+import com.wireguard.android.activity.TunnelToggleActivity;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.Tunnel.State;
-import com.wireguard.android.util.ErrorMessages;
import com.wireguard.android.widget.SlashDrawable;
import java.util.Objects;
@@ -66,7 +65,15 @@ public class QuickTileService extends TileService {
tile.setIcon(tile.getIcon() == iconOn ? iconOff : iconOn);
tile.updateTile();
}
- tunnel.setState(State.TOGGLE).whenComplete(this::onToggleFinished);
+ tunnel.setState(State.TOGGLE).whenComplete((v, t) -> {
+ if (t == null) {
+ updateTile();
+ } else {
+ final Intent toggleIntent = new Intent(this, TunnelToggleActivity.class);
+ toggleIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(toggleIntent);
+ }
+ });
});
} else {
final Intent intent = new Intent(this, MainActivity.class);
@@ -112,16 +119,6 @@ public class QuickTileService extends TileService {
Application.getTunnelManager().removeOnPropertyChangedCallback(onTunnelChangedCallback);
}
- private void onToggleFinished(@SuppressWarnings("unused") final State state,
- @Nullable final Throwable throwable) {
- if (throwable == null)
- return;
- final String error = ErrorMessages.get(throwable);
- final String message = getString(R.string.toggle_error, error);
- Log.e(TAG, message, throwable);
- Toast.makeText(this, message, Toast.LENGTH_LONG).show();
- }
-
private void updateTile() {
// Update the tunnel.
final Tunnel newTunnel = Application.getTunnelManager().getLastUsedTunnel();
diff --git a/app/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.java b/app/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.java
new file mode 100644
index 00000000..69c995fe
--- /dev/null
+++ b/app/src/main/java/com/wireguard/android/activity/TunnelToggleActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.wireguard.android.activity;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Build;
+import android.service.quicksettings.TileService;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.wireguard.android.Application;
+import com.wireguard.android.QuickTileService;
+import com.wireguard.android.R;
+import com.wireguard.android.model.Tunnel;
+import com.wireguard.android.model.Tunnel.State;
+import com.wireguard.android.util.ErrorMessages;
+
+@RequiresApi(Build.VERSION_CODES.N)
+public class TunnelToggleActivity extends AppCompatActivity {
+ private static final String TAG = "WireGuard/" + TunnelToggleActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Tunnel tunnel = Application.getTunnelManager().getLastUsedTunnel();
+ if (tunnel == null)
+ return;
+ tunnel.setState(State.TOGGLE).whenComplete((v, t) -> {
+ TileService.requestListeningState(this, new ComponentName(this, QuickTileService.class));
+ onToggleFinished(t);
+ finishAffinity();
+ });
+ }
+
+ private void onToggleFinished(@Nullable final Throwable throwable) {
+ if (throwable == null)
+ return;
+ final String error = ErrorMessages.get(throwable);
+ final String message = getString(R.string.toggle_error, error);
+ Log.e(TAG, message, throwable);
+ Toast.makeText(this, message, Toast.LENGTH_LONG).show();
+ }
+}
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 2605691d..7da1aa9c 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -5,6 +5,19 @@
<item name="colorAccent">@color/accent</item>
</style>
+ <style name="NoBackgroundTheme" parent="AppTheme">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:background">@android:color/transparent</item>
+ <item name="colorPrimaryDark">@android:color/transparent</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
+ <item name="android:windowExitAnimation">@android:anim/fade_out</item>
+ </style>
+
<style name="fab_label" parent="TextAppearance.AppCompat.Inverse">
<item name="android:background">@drawable/fab_label_background</item>
<item name="android:textColor">@color/fab_label_text_color</item>