com/tailscale/ipn,cmd/tailscale: handle quick tile clicks while signed out

Specifically, start the main activity to prompt the user to sign in or
be notified of a pending machine auth.

Fixes tailscale/tailscale#1225

Signed-off-by: Elias Naur <mail@eliasnaur.com>
pull/7/head
Elias Naur 4 years ago
parent 71a9bd537c
commit 07b2373e6b

@ -98,11 +98,18 @@ public class App extends Application {
); );
} }
void setTileStatus(boolean wantRunning) { void setTileReady(boolean ready) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return; return;
} }
QuickToggleService.setStatus(this, wantRunning); QuickToggleService.setReady(this, ready);
}
void setTileStatus(boolean status) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return;
}
QuickToggleService.setStatus(this, status);
} }
String getHostname() { String getHostname() {

@ -6,6 +6,7 @@ package com.tailscale.ipn;
import android.content.Context; import android.content.Context;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent;
import android.service.quicksettings.Tile; import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService; import android.service.quicksettings.TileService;
@ -13,33 +14,68 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class QuickToggleService extends TileService { public class QuickToggleService extends TileService {
private static AtomicBoolean active = new AtomicBoolean(); // lock protects the static fields below it.
private static AtomicReference<Tile> currentTile = new AtomicReference<Tile>(); private static Object lock = new Object();
// Active tracks whether the VPN is active.
private static boolean active;
// Ready tracks whether the tailscale backend is
// ready to switch on/off.
private static boolean ready;
// currentTile tracks getQsTile while service is listening.
private static Tile currentTile;
@Override public void onStartListening() { @Override public void onStartListening() {
currentTile.set(getQsTile()); synchronized (lock) {
currentTile = getQsTile();
}
updateTile(); updateTile();
} }
@Override public void onStopListening() { @Override public void onStopListening() {
currentTile.set(null); synchronized (lock) {
currentTile = null;
}
} }
@Override public void onClick() { @Override public void onClick() {
onTileClick(); boolean r;
synchronized (lock) {
r = ready;
}
if (r) {
onTileClick();
} else {
// Start main activity.
Intent i = getPackageManager().getLaunchIntentForPackage(getPackageName());
startActivityAndCollapse(i);
}
} }
private static void updateTile() { private static void updateTile() {
Tile t = currentTile.get(); Tile t;
boolean act;
synchronized (lock) {
t = currentTile;
act = active && ready;
}
if (t == null) { if (t == null) {
return; return;
} }
t.setState(active.get() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE); t.setState(act ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
t.updateTile(); t.updateTile();
} }
static void setStatus(Context ctx, boolean wantRunning) { static void setReady(Context ctx, boolean rdy) {
active.set(wantRunning); synchronized (lock) {
ready = rdy;
}
updateTile();
}
static void setStatus(Context ctx, boolean act) {
synchronized (lock) {
active = act;
}
updateTile(); updateTile();
} }

@ -468,6 +468,13 @@ func (a *App) notify(state BackendState) {
case a.updates <- struct{}{}: case a.updates <- struct{}{}:
default: default:
} }
ready := jni.False
if state.State >= ipn.Stopped {
ready = jni.True
}
if err := a.callVoidMethod(a.appCtx, "setTileReady", "(Z)V", jni.Value(ready)); err != nil {
fatalErr(err)
}
} }
func (a *App) setPrefs(prefs *ipn.Prefs) { func (a *App) setPrefs(prefs *ipn.Prefs) {

Loading…
Cancel
Save