diff --git a/cmd/tailscale/callbacks.go b/cmd/tailscale/callbacks.go index a8df122..42fc244 100644 --- a/cmd/tailscale/callbacks.go +++ b/cmd/tailscale/callbacks.go @@ -7,7 +7,6 @@ package main // JNI implementations of Java native callback methods. import ( - "sync/atomic" "unsafe" "github.com/tailscale/tailscale-android/jni" @@ -33,20 +32,12 @@ var ( onDisconnect = make(chan jni.Object) // onConnectivityChange is notified every time the network // conditions change. - onConnectivityChange = make(chan struct{}, 1) + onConnectivityChange = make(chan bool, 1) // onGoogleToken receives google ID tokens. onGoogleToken = make(chan string) ) -var ( - connected atomic.Value -) - -func init() { - connected.Store(true) -} - const ( // Request codes for Android callbacks. // requestSignin is for Google Sign-In. @@ -98,12 +89,12 @@ func Java_com_tailscale_ipn_IPNService_disconnect(env *C.JNIEnv, this C.jobject) } //export Java_com_tailscale_ipn_App_onConnectivityChanged -func Java_com_tailscale_ipn_App_onConnectivityChanged(env *C.JNIEnv, cls C.jclass, newConnected C.jboolean) { - connected.Store(newConnected == C.JNI_TRUE) +func Java_com_tailscale_ipn_App_onConnectivityChanged(env *C.JNIEnv, cls C.jclass, connected C.jboolean) { select { - case onConnectivityChange <- struct{}{}: + case <-onConnectivityChange: default: } + onConnectivityChange <- connected == C.JNI_TRUE } //export Java_com_tailscale_ipn_QuickToggleService_onTileClick diff --git a/cmd/tailscale/main.go b/cmd/tailscale/main.go index f10ad84..3934eb1 100644 --- a/cmd/tailscale/main.go +++ b/cmd/tailscale/main.go @@ -10,7 +10,6 @@ import ( "log" "sort" "strings" - "sync" "time" "unsafe" @@ -36,22 +35,16 @@ type App struct { store *stateStore - // updates is notifies whenever netState or browseURL changes. - updates chan struct{} + // netStates receives the most recent network state. + netStates chan BackendState + // prefs receives new preferences from the backend. + prefs chan *ipn.Prefs + // browseURLs receives URLs when the backend wants to browse. + browseURLs chan string // backend is the channel for events from the frontend to the // backend. backendEvents chan UIEvent - - // mu protects the following fields. - mu sync.Mutex - // netState is the most recent network state. - netState BackendState - // browseURL is set whenever the backend wants to - // browse. - browseURL *string - // prefs is set when new preferences arrive. - prefs *ipn.Prefs } var ( @@ -117,9 +110,11 @@ var backendEvents = make(chan UIEvent) func main() { a := &App{ - jvm: (*jni.JVM)(unsafe.Pointer(app.JavaVM())), - appCtx: jni.Object(app.AppContext()), - updates: make(chan struct{}, 1), + jvm: (*jni.JVM)(unsafe.Pointer(app.JavaVM())), + appCtx: jni.Object(app.AppContext()), + netStates: make(chan BackendState, 1), + browseURLs: make(chan string, 1), + prefs: make(chan *ipn.Prefs, 1), } err := jni.Do(a.jvm, func(env *jni.Env) error { loader := jni.ClassLoaderFor(env, a.appCtx) @@ -304,8 +299,8 @@ func (a *App) runBackend() error { notifyVPNClosed() } } - case <-onConnectivityChange: - state.LostInternet = !connected.Load().(bool) + case connected := <-onConnectivityChange: + state.LostInternet = !connected if b != nil { go b.LinkChange() } @@ -461,13 +456,11 @@ func (a *App) notifyExpiry(service jni.Object, expiry time.Time) *time.Timer { } func (a *App) notify(state BackendState) { - a.mu.Lock() - a.netState = state - a.mu.Unlock() select { - case a.updates <- struct{}{}: + case <-a.netStates: default: } + a.netStates <- state ready := jni.Bool(state.State >= ipn.Stopped) if err := a.callVoidMethod(a.appCtx, "setTileReady", "(Z)V", jni.Value(ready)); err != nil { fatalErr(err) @@ -475,27 +468,23 @@ func (a *App) notify(state BackendState) { } func (a *App) setPrefs(prefs *ipn.Prefs) { - a.mu.Lock() - a.prefs = prefs wantRunning := jni.Bool(prefs.WantRunning) - a.mu.Unlock() if err := a.callVoidMethod(a.appCtx, "setTileStatus", "(Z)V", jni.Value(wantRunning)); err != nil { fatalErr(err) } select { - case a.updates <- struct{}{}: + case <-a.prefs: default: } + a.prefs <- prefs } func (a *App) setURL(url string) { - a.mu.Lock() - a.browseURL = &url - a.mu.Unlock() select { - case a.updates <- struct{}{}: + case <-a.browseURLs: default: } + a.browseURLs <- url } func (a *App) runUI() error { @@ -542,20 +531,16 @@ func (a *App) runUI() error { w.Invalidate() } } - case <-a.updates: - a.mu.Lock() + case p := <-a.prefs: + ui.enabled.Value = p.WantRunning + w.Invalidate() + case state.browseURL = <-a.browseURLs: + ui.signinType = noSignin + w.Invalidate() + a.updateState(activity, state) + case newState := <-a.netStates: oldState := state.backend.State - state.backend = a.netState - if a.browseURL != nil { - state.browseURL = *a.browseURL - a.browseURL = nil - ui.signinType = noSignin - } - if a.prefs != nil { - ui.enabled.Value = a.prefs.WantRunning - a.prefs = nil - } - a.mu.Unlock() + state.backend = newState a.updateState(activity, state) w.Invalidate() if activity != 0 {