Update semantics of Bluetooth setting.

The setting now enables/disables the plugin, not just contact
connections. The key agreement UI will need to be updated to change the
setting if the user agrees to use Bluetooth.
This commit is contained in:
akwizgran
2020-01-16 15:50:44 +00:00
parent 7ae86d70af
commit fc86c46456
2 changed files with 64 additions and 36 deletions

View File

@@ -10,4 +10,7 @@ public interface BluetoothConstants {
String PROP_UUID = "uuid";
String PREF_BT_ENABLE = "enable";
int REASON_USER = 1;
int REASON_NO_BT_ADAPTER = 2;
}

View File

@@ -10,6 +10,7 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementListeningEvent;
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStoppedListeningEvent;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
@@ -49,6 +50,7 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
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;
@@ -78,7 +80,6 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
protected final PluginState state = new PluginState();
private volatile boolean contactConnections = false;
private volatile String contactConnectionsUuid = null;
abstract void initialiseAdapter() throws IOException;
@@ -131,16 +132,18 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
LOG.info("Bluetooth enabled");
// We may not have been able to get the local address before
ioExecutor.execute(this::updateProperties);
if (shouldAllowContactConnections()) bind();
callback.pluginStateChanged(getState());
if (getState() == INACTIVE) bind();
}
void onAdapterDisabled() {
LOG.info("Bluetooth disabled");
connectionLimiter.allConnectionsClosed();
// The server socket may not have been closed automatically
tryToClose(state.clearServerSocket());
callback.pluginStateChanged(getState());
SS ss = state.clearServerSocket();
if (ss != null) {
LOG.info("Closing server socket");
tryToClose(ss);
}
}
@Override
@@ -164,29 +167,22 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
try {
initialiseAdapter();
} catch (IOException e) {
state.setNoAdapter();
throw new PluginException(e);
}
updateProperties();
state.setStarted();
loadSettings(callback.getSettings());
if (shouldAllowContactConnections()) {
Settings settings = callback.getSettings();
boolean enabledByUser = settings.getBoolean(PREF_BT_ENABLE, false);
state.setStarted(enabledByUser);
if (enabledByUser) {
if (isAdapterEnabled()) bind();
else enableAdapter();
}
}
private void loadSettings(Settings settings) {
contactConnections = settings.getBoolean(PREF_BT_ENABLE, false);
}
private boolean shouldAllowContactConnections() {
return contactConnections;
}
private void bind() {
ioExecutor.execute(() -> {
if (!shouldAllowContactConnections() || getState() != ACTIVE)
return;
if (getState() != INACTIVE) return;
// Bind a server socket to accept connections from contacts
SS ss;
try {
@@ -195,8 +191,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
logException(LOG, WARNING, e);
return;
}
if (!shouldAllowContactConnections() ||
!state.setServerSocket(ss)) {
if (!state.setServerSocket(ss)) {
LOG.info("Closing redundant server socket");
tryToClose(ss);
return;
@@ -263,7 +258,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
@Override
public int getReasonDisabled() {
return getState() == DISABLED ? REASON_STARTING_STOPPING : -1;
return state.getReasonDisabled();
}
@Override
@@ -279,7 +274,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
@Override
public void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties) {
if (!shouldAllowContactConnections() || getState() != ACTIVE) return;
if (getState() != ACTIVE) return;
backoff.increment();
for (Pair<TransportProperties, ConnectionHandler> p : properties) {
connect(p.getFirst(), p.getSecond());
@@ -333,8 +328,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
@Override
public DuplexTransportConnection createConnection(TransportProperties p) {
if (!shouldAllowContactConnections() || getState() != ACTIVE)
return null;
if (getState() != ACTIVE) return null;
if (!connectionLimiter.canOpenContactConnection()) return null;
String address = p.get(PROP_ADDRESS);
if (isNullOrEmpty(address)) return null;
@@ -438,16 +432,18 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
}
}
@IoExecutor
private void onSettingsUpdated(Settings settings) {
boolean wasAllowed = shouldAllowContactConnections();
loadSettings(settings);
boolean isAllowed = shouldAllowContactConnections();
if (wasAllowed && !isAllowed) {
LOG.info("Contact connections disabled");
tryToClose(state.clearServerSocket());
boolean enabledByUser = settings.getBoolean(PREF_BT_ENABLE, false);
SS ss = state.setEnabledByUser(enabledByUser);
State s = getState();
callback.pluginStateChanged(s);
if (ss != null) {
LOG.info("Disabled by user, closing server socket");
tryToClose(ss);
disableAdapterIfEnabledByUs();
} else if (!wasAllowed && isAllowed) {
LOG.info("Contact connections enabled");
} else if (s == INACTIVE) {
LOG.info("Enabled by user, opening server socket");
if (isAdapterEnabled()) bind();
else enableAdapter();
}
@@ -481,13 +477,18 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
protected class PluginState {
@GuardedBy("this")
private boolean started = false, stopped = false;
private boolean started = false,
stopped = false,
noAdapter = false,
enabledByUser = false;
@GuardedBy("this")
@Nullable
private SS serverSocket = null;
synchronized void setStarted() {
synchronized void setStarted(boolean enabledByUser) {
started = true;
this.enabledByUser = enabledByUser;
callback.pluginStateChanged(getState());
}
@@ -500,6 +501,23 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
return ss;
}
synchronized void setNoAdapter() {
noAdapter = true;
callback.pluginStateChanged(getState());
}
@Nullable
synchronized SS setEnabledByUser(boolean enabledByUser) {
this.enabledByUser = enabledByUser;
SS ss = null;
if (!enabledByUser) {
ss = serverSocket;
serverSocket = null;
}
callback.pluginStateChanged(getState());
return ss;
}
synchronized boolean setServerSocket(SS ss) {
if (stopped || serverSocket != null) return false;
serverSocket = ss;
@@ -511,12 +529,19 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
synchronized SS clearServerSocket() {
SS ss = serverSocket;
serverSocket = null;
callback.pluginStateChanged(getState());
return ss;
}
synchronized State getState() {
if (!started || stopped) return DISABLED;
return isAdapterEnabled() ? ACTIVE : INACTIVE;
if (!started || stopped || !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;
}
}
}