From cb936d95c5fcd55c62059f84c17ae25151f10004 Mon Sep 17 00:00:00 2001 From: akwizgran Date: Thu, 30 Jan 2020 14:49:22 +0000 Subject: [PATCH] Add STARTING_STOPPING state, use flags for reasons disabled. --- .../api/plugin/BluetoothConstants.java | 3 - .../bramble/api/plugin/Plugin.java | 29 +++-- .../bramble/api/plugin/TorConstants.java | 16 ++- .../bramble/plugin/PluginManagerImpl.java | 4 +- .../plugin/bluetooth/BluetoothPlugin.java | 34 +++--- .../bramble/plugin/tcp/TcpPlugin.java | 13 ++- .../bramble/plugin/tor/TorPlugin.java | 106 +++++++++--------- .../bramble/plugin/modem/ModemPlugin.java | 8 +- .../keyagreement/KeyAgreementActivity.java | 9 +- .../android/navdrawer/NavDrawerViewModel.java | 4 +- .../navdrawer/PluginViewController.java | 16 ++- 11 files changed, 127 insertions(+), 115 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java index 1752ba10f..c2e506851 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/BluetoothConstants.java @@ -8,7 +8,4 @@ public interface BluetoothConstants { String PROP_ADDRESS = "address"; String PROP_UUID = "uuid"; - - // Reason code returned by Plugin#getReasonDisabled() - int REASON_NO_BT_ADAPTER = 2; } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java index 4ecd851e2..9d2d50600 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/Plugin.java @@ -13,8 +13,13 @@ public interface Plugin { enum State { /** - * The plugin has not been started, has been stopped, or is disabled by - * settings. + * The plugin has not finished starting or has been stopped. + */ + STARTING_STOPPING, + + /** + * The plugin is disabled by settings. Use {@link #getReasonsDisabled()} + * to find out which settings are responsible. */ DISABLED, @@ -42,14 +47,7 @@ public interface Plugin { String PREF_PLUGIN_ENABLE = "enable"; /** - * Reason code returned by {@link #getReasonDisabled()} to indicate that - * the plugin is disabled because it has not been started or has been - * stopped. - */ - int REASON_STARTING_STOPPING = 0; - - /** - * Reason code returned by {@link #getReasonDisabled()} to indicate that + * Reason flag returned by {@link #getReasonsDisabled()} to indicate that * the plugin has been disabled by the user. */ int REASON_USER = 1; @@ -85,14 +83,13 @@ public interface Plugin { State getState(); /** - * Returns an integer code indicating why the plugin is - * {@link State#DISABLED disabled}, or -1 if the plugin is not disabled. + * Returns a set of flags indicating why the plugin is + * {@link State#DISABLED disabled}, or 0 if the plugin is not disabled. *

- * The codes used are plugin-specific, except the generic codes - * {@link #REASON_STARTING_STOPPING} and {@link #REASON_USER}, which may - * be used by any plugin. + * The flags used are plugin-specific, except the generic flag + * {@link #REASON_USER}, which may be used by any plugin. */ - int getReasonDisabled(); + int getReasonsDisabled(); /** * Returns true if the plugin should be polled periodically to attempt to diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java index 3a4432d8c..e22d6da4a 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java @@ -24,8 +24,18 @@ public interface TorConstants { // TODO: Remove when settings migration code is removed int PREF_TOR_NETWORK_NEVER = 3; - // Reason codes returned by Plugin#getReasonDisabled() + /** + * Reason flag returned by {@link Plugin#getReasonsDisabled()}. + */ int REASON_BATTERY = 2; - int REASON_MOBILE_DATA = 3; - int REASON_COUNTRY_BLOCKED = 4; + + /** + * Reason flag returned by {@link Plugin#getReasonsDisabled()}. + */ + int REASON_MOBILE_DATA = 4; + + /** + * Reason flag returned by {@link Plugin#getReasonsDisabled()}. + */ + int REASON_COUNTRY_BLOCKED = 8; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java index 9c91abeff..e44631894 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/PluginManagerImpl.java @@ -50,7 +50,7 @@ import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.plugin.Plugin.PREF_PLUGIN_ENABLE; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; -import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.now; @@ -277,7 +277,7 @@ class PluginManagerImpl implements PluginManager, Service { private final TransportId id; private final AtomicReference state = - new AtomicReference<>(DISABLED); + new AtomicReference<>(STARTING_STOPPING); private Callback(TransportId id) { this.id = id; diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java index b807e8956..e42294f2b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/bluetooth/BluetoothPlugin.java @@ -48,11 +48,11 @@ import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TR import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID; import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS; import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID; -import static org.briarproject.bramble.api.plugin.BluetoothConstants.REASON_NO_BT_ADAPTER; import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; @@ -159,16 +159,15 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { @Override public void start() throws PluginException { if (used.getAndSet(true)) throw new IllegalStateException(); - try { - initialiseAdapter(); - } catch (IOException e) { - state.setNoAdapter(); - throw new PluginException(e); - } - updateProperties(); Settings settings = callback.getSettings(); boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE, false); state.setStarted(enabledByUser); + try { + initialiseAdapter(); + } catch (IOException e) { + throw new PluginException(e); + } + updateProperties(); if (enabledByUser) { if (isAdapterEnabled()) bind(); else enableAdapter(); @@ -252,8 +251,8 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { } @Override - public int getReasonDisabled() { - return state.getReasonDisabled(); + public int getReasonsDisabled() { + return state.getReasonsDisabled(); } @Override @@ -477,7 +476,6 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { @GuardedBy("this") private boolean started = false, stopped = false, - noAdapter = false, enabledByUser = false; @GuardedBy("this") @@ -499,11 +497,6 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { return ss; } - synchronized void setNoAdapter() { - noAdapter = true; - callback.pluginStateChanged(getState()); - } - @Nullable synchronized SS setEnabledByUser(boolean enabledByUser) { this.enabledByUser = enabledByUser; @@ -532,14 +525,13 @@ abstract class BluetoothPlugin implements DuplexPlugin, EventListener { } synchronized State getState() { - if (!started || stopped || !enabledByUser) return DISABLED; + if (!started || stopped) return STARTING_STOPPING; + if (!enabledByUser) return DISABLED; return serverSocket == null ? INACTIVE : ACTIVE; } - synchronized int getReasonDisabled() { - if (noAdapter && !stopped) return REASON_NO_BT_ADAPTER; - if (!started || stopped) return REASON_STARTING_STOPPING; - return enabledByUser ? -1 : REASON_USER; + synchronized int getReasonsDisabled() { + return getState() == DISABLED ? REASON_USER : 0; } } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java index 69b860088..4a8ea8753 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/TcpPlugin.java @@ -51,6 +51,7 @@ import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress; @@ -205,8 +206,8 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener { } @Override - public int getReasonDisabled() { - return state.getReasonDisabled(); + public int getReasonsDisabled() { + return state.getReasonsDisabled(); } @Override @@ -455,13 +456,13 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener { } synchronized State getState() { - if (!started || stopped || !enabledByUser) return DISABLED; + if (!started || stopped) return STARTING_STOPPING; + if (!enabledByUser) return DISABLED; return serverSocket == null ? INACTIVE : ACTIVE; } - synchronized int getReasonDisabled() { - if (!started || stopped) return REASON_STARTING_STOPPING; - return enabledByUser ? -1 : REASON_USER; + synchronized int getReasonsDisabled() { + return getState() == DISABLED ? REASON_USER : 0; } } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java index e2292d063..66a869d0c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java @@ -73,6 +73,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT; import static org.briarproject.bramble.api.plugin.TorConstants.ID; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE; @@ -533,8 +534,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } @Override - public int getReasonDisabled() { - return state.getReasonDisabled(); + public int getReasonsDisabled() { + return state.getReasonsDisabled(); } @Override @@ -773,7 +774,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { String country = locationUtils.getCurrentCountry(); boolean blocked = circumventionProvider.isTorProbablyBlocked(country); - boolean enabledByUser = settings.getBoolean(PREF_PLUGIN_ENABLE, true); + boolean enabledByUser = + settings.getBoolean(PREF_PLUGIN_ENABLE, true); int network = settings.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_AUTOMATIC); boolean useMobile = settings.getBoolean(PREF_TOR_MOBILE, true); @@ -789,54 +791,58 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { LOG.info("Charging: " + charging); } + int reasonsDisabled = 0; boolean enableNetwork = false, enableBridges = false; boolean useMeek = false, enableConnectionPadding = false; - boolean disabledBySettings = false; - int reasonDisabled = REASON_STARTING_STOPPING; if (!online) { LOG.info("Disabling network, device is offline"); - } else if (!enabledByUser) { - LOG.info("Disabling network, user has disabled Tor"); - disabledBySettings = true; - reasonDisabled = REASON_USER; - } else if (!charging && onlyWhenCharging) { - LOG.info("Disabling network, device is on battery"); - disabledBySettings = true; - reasonDisabled = REASON_BATTERY; - } else if (!useMobile && !wifi) { - LOG.info("Disabling network, device is using mobile data"); - disabledBySettings = true; - reasonDisabled = REASON_MOBILE_DATA; - } else if (automatic && blocked && !bridgesWork) { - LOG.info("Disabling network, country is blocked"); - disabledBySettings = true; - reasonDisabled = REASON_COUNTRY_BLOCKED; } else { - LOG.info("Enabling network"); - enableNetwork = true; - if (network == PREF_TOR_NETWORK_WITH_BRIDGES || - (automatic && bridgesWork)) { - if (circumventionProvider.needsMeek(country)) { - LOG.info("Using meek bridges"); - enableBridges = true; - useMeek = true; - } else { - LOG.info("Using obfs4 bridges"); - enableBridges = true; - } - } else { - LOG.info("Not using bridges"); + if (!enabledByUser) { + LOG.info("User has disabled Tor"); + reasonsDisabled |= REASON_USER; } - if (wifi && charging) { - LOG.info("Enabling connection padding"); - enableConnectionPadding = true; + if (!charging && onlyWhenCharging) { + LOG.info("Configured not to use battery"); + reasonsDisabled |= REASON_BATTERY; + } + if (!useMobile && !wifi) { + LOG.info("Configured not to use mobile data"); + reasonsDisabled |= REASON_MOBILE_DATA; + } + if (automatic && blocked && !bridgesWork) { + LOG.info("Country is blocked"); + reasonsDisabled |= REASON_COUNTRY_BLOCKED; + } + + if (reasonsDisabled != 0) { + LOG.info("Disabling network due to settings"); } else { - LOG.info("Disabling connection padding"); + LOG.info("Enabling network"); + enableNetwork = true; + if (network == PREF_TOR_NETWORK_WITH_BRIDGES || + (automatic && bridgesWork)) { + if (circumventionProvider.needsMeek(country)) { + LOG.info("Using meek bridges"); + enableBridges = true; + useMeek = true; + } else { + LOG.info("Using obfs4 bridges"); + enableBridges = true; + } + } else { + LOG.info("Not using bridges"); + } + if (wifi && charging) { + LOG.info("Enabling connection padding"); + enableConnectionPadding = true; + } else { + LOG.info("Disabling connection padding"); + } } } - state.setDisabledBySettings(disabledBySettings, reasonDisabled); + state.setReasonsDisabled(reasonsDisabled); try { if (enableNetwork) { @@ -865,11 +871,10 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { networkEnabled = false, bootstrapped = false, circuitBuilt = false, - settingsChecked = false, - disabledBySettings = false; + settingsChecked = false; @GuardedBy("this") - private int reasonDisabled = REASON_STARTING_STOPPING; + private int reasonsDisabled = 0; @GuardedBy("this") @Nullable @@ -912,11 +917,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { callback.pluginStateChanged(getState()); } - synchronized void setDisabledBySettings(boolean disabledBySettings, - int reasonDisabled) { + synchronized void setReasonsDisabled(int reasonsDisabled) { settingsChecked = true; - this.disabledBySettings = disabledBySettings; - this.reasonDisabled = reasonDisabled; + this.reasonsDisabled = reasonsDisabled; callback.pluginStateChanged(getState()); } @@ -933,16 +936,17 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { } synchronized State getState() { - if (!started || stopped || !settingsChecked || disabledBySettings) { - return DISABLED; + if (!started || stopped || !settingsChecked) { + return STARTING_STOPPING; } + if (reasonsDisabled != 0) return DISABLED; if (!networkInitialised) return ENABLING; if (!networkEnabled) return INACTIVE; return bootstrapped && circuitBuilt ? ACTIVE : ENABLING; } - synchronized int getReasonDisabled() { - return getState() == DISABLED ? reasonDisabled : -1; + synchronized int getReasonsDisabled() { + return getState() == DISABLED ? reasonsDisabled : 0; } } } diff --git a/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java b/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java index e2eb69ca8..53a668f20 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/plugin/modem/ModemPlugin.java @@ -31,9 +31,9 @@ import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; -import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; @@ -121,8 +121,8 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { } @Override - public int getReasonDisabled() { - return getState() == DISABLED ? REASON_STARTING_STOPPING : -1; + public int getReasonsDisabled() { + return 0; } @Override @@ -280,7 +280,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { } private State getState() { - if (!started || stopped) return DISABLED; + if (!started || stopped) return STARTING_STOPPING; if (failed) return INACTIVE; return initialised ? ACTIVE : ENABLING; } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java index 72e7b69c8..f55d89a49 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/keyagreement/KeyAgreementActivity.java @@ -53,6 +53,7 @@ import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION; @@ -258,7 +259,9 @@ public abstract class KeyAgreementActivity extends BriarActivity implements private boolean shouldEnableWifi() { if (hasEnabledWifi) return false; Plugin p = pluginManager.getPlugin(LanTcpConstants.ID); - return p != null && p.getState() == DISABLED; + if (p == null) return false; + State state = p.getState(); + return state == STARTING_STOPPING || state == DISABLED; } private void requestBluetoothDiscoverable() { @@ -284,7 +287,9 @@ public abstract class KeyAgreementActivity extends BriarActivity implements if (bluetoothDecision != BluetoothDecision.ACCEPTED) return false; if (hasEnabledBluetooth) return false; Plugin p = pluginManager.getPlugin(BluetoothConstants.ID); - return p != null && p.getState() == DISABLED; + if (p == null) return false; + State state = p.getState(); + return state == STARTING_STOPPING || state == DISABLED; } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerViewModel.java index 89cf1e751..da95ef228 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerViewModel.java @@ -34,7 +34,7 @@ import static java.util.concurrent.TimeUnit.DAYS; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; -import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; @@ -194,7 +194,7 @@ public class NavDrawerViewModel extends AndroidViewModel private State getTransportState(TransportId id) { Plugin plugin = pluginManager.getPlugin(id); - return plugin == null ? DISABLED : plugin.getState(); + return plugin == null ? STARTING_STOPPING : plugin.getState(); } @Nullable diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/PluginViewController.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/PluginViewController.java index 52995b23e..075125959 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/PluginViewController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/PluginViewController.java @@ -17,6 +17,7 @@ import static androidx.core.content.ContextCompat.getColor; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING; +import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.briar.android.navdrawer.NavDrawerViewModel.TRANSPORT_IDS; class PluginViewController { @@ -38,10 +39,13 @@ class PluginViewController { for (TransportId t : TRANSPORT_IDS) { // a OnCheckedChangeListener would get triggered on programmatic updates SwitchCompat switchCompat = getSwitch(t); - switchCompat.setOnClickListener(buttonView -> - // TODO check reason first and change settings if needed - viewModel.setPluginEnabled(t, switchCompat.isChecked()) - ); + switchCompat.setOnClickListener(buttonView -> { + // TODO check reason first and change settings if needed + viewModel.setPluginEnabled(t, switchCompat.isChecked()); + // Revert the switch to its previous state until the plugin + // changes its state + switchCompat.toggle(); + }); viewModel.getPluginState(t) .observe(owner, state -> stateUpdate(t, state)); } @@ -60,7 +64,9 @@ class PluginViewController { } private void updateSwitch(SwitchCompat switchCompat, State state) { - switchCompat.setChecked(state != DISABLED); + boolean checked = state != STARTING_STOPPING && state != DISABLED; + switchCompat.setChecked(checked); + switchCompat.setEnabled(state != STARTING_STOPPING); } private ImageView getIcon(TransportId id) {