ObservableTunnel: port to kotlin

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2020-03-26 22:26:53 -06:00
parent c8ac970d11
commit 4d6837ea53
7 changed files with 121 additions and 150 deletions

View File

@ -54,7 +54,7 @@ class QuickTileService : TileService() {
tile.icon = if (tile.icon == iconOn) iconOff else iconOn tile.icon = if (tile.icon == iconOn) iconOff else iconOn
tile.updateTile() tile.updateTile()
} }
tunnel!!.setState(Tunnel.State.TOGGLE).whenComplete { _, t -> tunnel!!.setStateAsync(Tunnel.State.TOGGLE).whenComplete { _, t ->
if (t == null) { if (t == null) {
updateTile() updateTile()
} else { } else {

View File

@ -23,7 +23,7 @@ class TunnelToggleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val tunnel = Application.getTunnelManager().lastUsedTunnel ?: return val tunnel = Application.getTunnelManager().lastUsedTunnel ?: return
tunnel.setState(Tunnel.State.TOGGLE).whenComplete { _, t -> tunnel.setStateAsync(Tunnel.State.TOGGLE).whenComplete { _, t ->
TileService.requestListeningState(this, ComponentName(this, QuickTileService::class.java)) TileService.requestListeningState(this, ComponentName(this, QuickTileService::class.java))
onToggleFinished(t) onToggleFinished(t)
finishAffinity() finishAffinity()

View File

@ -85,7 +85,7 @@ abstract class BaseFragment : Fragment(), OnSelectedTunnelChangedListener {
} }
private fun setTunnelStateWithPermissionsResult(tunnel: ObservableTunnel, checked: Boolean) { private fun setTunnelStateWithPermissionsResult(tunnel: ObservableTunnel, checked: Boolean) {
tunnel.setState(Tunnel.State.of(checked)).whenComplete { _, throwable -> tunnel.setStateAsync(Tunnel.State.of(checked)).whenComplete { _, throwable ->
if (throwable == null) return@whenComplete if (throwable == null) return@whenComplete
val error = ErrorMessages.get(throwable) val error = ErrorMessages.get(throwable)
val messageResId = if (checked) R.string.error_up else R.string.error_down val messageResId = if (checked) R.string.error_up else R.string.error_down

View File

@ -130,12 +130,12 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
} }
tunnel!!.name != binding!!.name -> { tunnel!!.name != binding!!.name -> {
Log.d(TAG, "Attempting to rename tunnel to " + binding!!.name) Log.d(TAG, "Attempting to rename tunnel to " + binding!!.name)
tunnel!!.setName(binding!!.name!!) tunnel!!.setNameAsync(binding!!.name!!)
.whenComplete { _, t -> onTunnelRenamed(tunnel!!, newConfig, t) } .whenComplete { _, t -> onTunnelRenamed(tunnel!!, newConfig, t) }
} }
else -> { else -> {
Log.d(TAG, "Attempting to save config of " + tunnel!!.name) Log.d(TAG, "Attempting to save config of " + tunnel!!.name)
tunnel!!.setConfig(newConfig) tunnel!!.setConfigAsync(newConfig)
.whenComplete { _, t -> onConfigSaved(tunnel!!, t) } .whenComplete { _, t -> onConfigSaved(tunnel!!, t) }
} }
} }
@ -198,7 +198,7 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
Log.d(TAG, message) Log.d(TAG, message)
// Now save the rest of configuration changes. // Now save the rest of configuration changes.
Log.d(TAG, "Attempting to save config of renamed tunnel " + tunnel!!.name) Log.d(TAG, "Attempting to save config of renamed tunnel " + tunnel!!.name)
renamedTunnel.setConfig(newConfig).whenComplete { _, t -> onConfigSaved(renamedTunnel, t) } renamedTunnel.setConfigAsync(newConfig).whenComplete { _, t -> onConfigSaved(renamedTunnel, t) }
} else { } else {
val error = ErrorMessages.get(throwable) val error = ErrorMessages.get(throwable)
message = getString(R.string.tunnel_rename_error, error) message = getString(R.string.tunnel_rename_error, error)

View File

@ -1,143 +0,0 @@
/*
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.model;
import com.wireguard.android.BR;
import com.wireguard.android.backend.Statistics;
import com.wireguard.android.backend.Tunnel;
import com.wireguard.android.util.ExceptionLoggers;
import com.wireguard.config.Config;
import com.wireguard.util.Keyed;
import com.wireguard.util.NonNullForAll;
import androidx.annotation.Nullable;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import java9.util.concurrent.CompletableFuture;
import java9.util.concurrent.CompletionStage;
/**
* Encapsulates the volatile and nonvolatile state of a WireGuard tunnel.
*/
@NonNullForAll
public class ObservableTunnel extends BaseObservable implements Keyed<String>, Tunnel {
private final TunnelManager manager;
@Nullable private Config config;
private String name;
private State state;
@Nullable private Statistics statistics;
ObservableTunnel(final TunnelManager manager, final String name,
@Nullable final Config config, final State state) {
this.name = name;
this.manager = manager;
this.config = config;
this.state = state;
}
public CompletionStage<Void> delete() {
return manager.delete(this);
}
@Bindable
@Nullable
public Config getConfig() {
if (config == null)
manager.getTunnelConfig(this).whenComplete(ExceptionLoggers.E);
return config;
}
public CompletionStage<Config> getConfigAsync() {
if (config == null)
return manager.getTunnelConfig(this);
return CompletableFuture.completedFuture(config);
}
@Override
public String getKey() {
return name;
}
@Override
@Bindable
public String getName() {
return name;
}
@Bindable
public State getState() {
return state;
}
public CompletionStage<State> getStateAsync() {
return TunnelManager.getTunnelState(this);
}
@Bindable
@Nullable
public Statistics getStatistics() {
if (statistics == null || statistics.isStale())
TunnelManager.getTunnelStatistics(this).whenComplete(ExceptionLoggers.E);
return statistics;
}
public CompletionStage<Statistics> getStatisticsAsync() {
if (statistics == null || statistics.isStale())
return TunnelManager.getTunnelStatistics(this);
return CompletableFuture.completedFuture(statistics);
}
Config onConfigChanged(final Config config) {
this.config = config;
notifyPropertyChanged(BR.config);
return config;
}
String onNameChanged(final String name) {
this.name = name;
notifyPropertyChanged(BR.name);
return name;
}
@Override
public void onStateChange(final State newState) {
onStateChanged(newState);
}
State onStateChanged(final State state) {
if (state != State.UP)
onStatisticsChanged(null);
this.state = state;
notifyPropertyChanged(BR.state);
return state;
}
@Nullable
Statistics onStatisticsChanged(@Nullable final Statistics statistics) {
this.statistics = statistics;
notifyPropertyChanged(BR.statistics);
return statistics;
}
public CompletionStage<Config> setConfig(final Config config) {
if (!config.equals(this.config))
return manager.setTunnelConfig(this, config);
return CompletableFuture.completedFuture(this.config);
}
public CompletionStage<String> setName(final String name) {
if (!name.equals(this.name))
return manager.setTunnelName(this, name);
return CompletableFuture.completedFuture(this.name);
}
public CompletionStage<State> setState(final State state) {
if (state != this.state)
return manager.setTunnelState(this, state);
return CompletableFuture.completedFuture(this.state);
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package com.wireguard.android.model
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import com.wireguard.android.BR
import com.wireguard.android.backend.Statistics
import com.wireguard.android.backend.Tunnel
import com.wireguard.android.util.ExceptionLoggers
import com.wireguard.config.Config
import com.wireguard.util.Keyed
import java9.util.concurrent.CompletableFuture
import java9.util.concurrent.CompletionStage
/**
* Encapsulates the volatile and nonvolatile state of a WireGuard tunnel.
*/
class ObservableTunnel internal constructor(
private val manager: TunnelManager,
private var name: String,
config: Config?,
state: Tunnel.State
) : BaseObservable(), Keyed<String>, Tunnel {
override fun getKey() = name
@Bindable
override fun getName() = name
fun setNameAsync(name: String): CompletionStage<String> = if (name != this.name)
manager.setTunnelName(this, name)
else
CompletableFuture.completedFuture(this.name)
fun onNameChanged(name: String): String {
this.name = name
notifyPropertyChanged(BR.name)
return name
}
@get:Bindable
var state = state
private set
override fun onStateChange(newState: Tunnel.State) {
onStateChanged(newState)
}
fun onStateChanged(state: Tunnel.State): Tunnel.State {
if (state != Tunnel.State.UP) onStatisticsChanged(null)
this.state = state
notifyPropertyChanged(BR.state)
return state
}
fun setStateAsync(state: Tunnel.State): CompletionStage<Tunnel.State> = if (state != this.state)
manager.setTunnelState(this, state)
else
CompletableFuture.completedFuture(this.state)
@get:Bindable
var config = config
get() {
if (config == null)
manager.getTunnelConfig(this).whenComplete(ExceptionLoggers.E)
return config
}
private set
val configAsync: CompletionStage<Config> = if (config == null)
manager.getTunnelConfig(this)
else
CompletableFuture.completedFuture(config)
fun setConfigAsync(config: Config): CompletionStage<Config?> = if (config != this.config)
manager.setTunnelConfig(this, config)
else
CompletableFuture.completedFuture(this.config)
fun onConfigChanged(config: Config?): Config? {
this.config = config
notifyPropertyChanged(BR.config)
return config
}
@get:Bindable
var statistics: Statistics? = null
get() {
if (field == null || field!!.isStale)
TunnelManager.getTunnelStatistics(this).whenComplete(ExceptionLoggers.E)
return field
}
private set
val statisticsAsync: CompletionStage<Statistics> = if (statistics == null || statistics!!.isStale)
TunnelManager.getTunnelStatistics(this)
else
CompletableFuture.completedFuture(statistics)
fun onStatisticsChanged(statistics: Statistics?): Statistics? {
this.statistics = statistics
notifyPropertyChanged(BR.statistics)
return statistics
}
fun delete(): CompletionStage<Void> = manager.delete(this)
}

View File

@ -35,7 +35,7 @@ class KernelModuleDisablerPreference(context: Context, attrs: AttributeSet?) : P
} }
Application.getAsyncWorker().runAsync { Application.getAsyncWorker().runAsync {
Application.getTunnelManager().tunnels.thenApply { observableTunnels -> Application.getTunnelManager().tunnels.thenApply { observableTunnels ->
val downings = observableTunnels.values().map { it.setState(Tunnel.State.DOWN).toCompletableFuture() }.toTypedArray() val downings = observableTunnels.values().map { it.setStateAsync(Tunnel.State.DOWN).toCompletableFuture() }.toTypedArray()
CompletableFuture.allOf(*downings).thenRun { CompletableFuture.allOf(*downings).thenRun {
val restartIntent = Intent(context, SettingsActivity::class.java) val restartIntent = Intent(context, SettingsActivity::class.java)
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)