Don't try to make multiple Bluetooth connections on Motorola devices.

This commit is contained in:
akwizgran
2020-10-30 17:00:58 +00:00
parent 01a146ba71
commit 027329ddd6
9 changed files with 78 additions and 13 deletions

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.Executor;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static android.os.Build.BRAND;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
@Immutable
@@ -81,8 +82,12 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
@Override
public DuplexPlugin createPlugin(PluginCallback callback) {
// On Motorola devices, don't try to open multiple connections - the
// Bluetooth stack can't handle it
// TODO: Narrow this down to specific models/versions if possible
boolean singleConnection = "motorola".equalsIgnoreCase(BRAND);
BluetoothConnectionLimiter connectionLimiter =
new BluetoothConnectionLimiterImpl(eventBus);
new BluetoothConnectionLimiterImpl(eventBus, singleConnection);
BluetoothConnectionFactory<BluetoothSocket> connectionFactory =
new AndroidBluetoothConnectionFactory(connectionLimiter,
wakeLockManager, timeoutMonitor);

View File

@@ -22,6 +22,8 @@ public abstract class AbstractDuplexTransportConnection
private final Writer writer;
private final AtomicBoolean halfClosed, closed;
private volatile boolean markedForClose = false;
protected AbstractDuplexTransportConnection(Plugin plugin) {
this.plugin = plugin;
reader = new Reader();
@@ -52,6 +54,16 @@ public abstract class AbstractDuplexTransportConnection
return remote;
}
@Override
public boolean isMarkedForClose() {
return markedForClose;
}
@Override
public void markForClose() {
markedForClose = true;
}
private class Reader implements TransportConnectionReader {
@Override

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.properties.TransportProperties;
@@ -30,4 +31,17 @@ public interface DuplexTransportConnection {
* the remote peer.
*/
TransportProperties getRemoteProperties();
/**
* Returns true if the connection should be closed immediately without
* sending anything.
*/
boolean isMarkedForClose();
/**
* Call this method before the connection is passed to its
* {@link ConnectionHandler} if the connection should be closed immediately
* without sending anything.
*/
void markForClose();
}

View File

@@ -33,6 +33,7 @@ abstract class DuplexSyncConnection extends SyncConnection
final Executor ioExecutor;
final TransportId transportId;
final DuplexTransportConnection connection;
final TransportConnectionReader reader;
final TransportConnectionWriter writer;
final TransportProperties remote;
@@ -80,6 +81,7 @@ abstract class DuplexSyncConnection extends SyncConnection
transportPropertyManager);
this.ioExecutor = ioExecutor;
this.transportId = transportId;
this.connection = connection;
reader = connection.getReader();
writer = connection.getWriter();
remote = connection.getRemoteProperties();
@@ -96,6 +98,13 @@ abstract class DuplexSyncConnection extends SyncConnection
disposeOnError(writer);
}
void closeOutgoingStream(StreamContext ctx, TransportConnectionWriter w)
throws IOException {
StreamWriter streamWriter = streamWriterFactory.createStreamWriter(
w.getOutputStream(), ctx);
streamWriter.sendEndOfStream();
}
SyncSession createDuplexOutgoingSession(StreamContext ctx,
TransportConnectionWriter w, @Nullable Priority priority)
throws IOException {

View File

@@ -93,10 +93,16 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection
return;
}
try {
// Create and run the outgoing session
SyncSession out = createDuplexOutgoingSession(ctx, writer, null);
setOutgoingSession(out);
out.run();
if (connection.isMarkedForClose()) {
// Close the outgoing stream without sending anything
closeOutgoingStream(ctx, writer);
} else {
// Create and run the outgoing session
SyncSession out =
createDuplexOutgoingSession(ctx, writer, null);
setOutgoingSession(out);
out.run();
}
writer.dispose(false);
} catch (IOException e) {
logException(LOG, WARNING, e);

View File

@@ -65,11 +65,16 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
Priority priority = generatePriority();
ioExecutor.execute(() -> runIncomingSession(priority));
try {
// Create and run the outgoing session
SyncSession out =
createDuplexOutgoingSession(ctx, writer, priority);
setOutgoingSession(out);
out.run();
if (connection.isMarkedForClose()) {
// Close the outgoing stream without sending anything
closeOutgoingStream(ctx, writer);
} else {
// Create and run the outgoing session
SyncSession out =
createDuplexOutgoingSession(ctx, writer, priority);
setOutgoingSession(out);
out.run();
}
writer.dispose(false);
} catch (IOException e) {
logException(LOG, WARNING, e);

View File

@@ -23,7 +23,9 @@ interface BluetoothConnectionLimiter {
boolean canOpenContactConnection();
/**
* Informs the limiter that the given connection has been opened.
* Informs the limiter that the given connection has been opened. If the
* connection is above the limit it will be
* {@link DuplexTransportConnection#markForClose() marked for close}.
*/
void connectionOpened(DuplexTransportConnection conn);

View File

@@ -24,6 +24,7 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
getLogger(BluetoothConnectionLimiterImpl.class.getName());
private final EventBus eventBus;
private final boolean singleConnection;
private final Object lock = new Object();
@GuardedBy("lock")
@@ -32,8 +33,10 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
@GuardedBy("lock")
private boolean keyAgreementInProgress = false;
BluetoothConnectionLimiterImpl(EventBus eventBus) {
BluetoothConnectionLimiterImpl(EventBus eventBus,
boolean singleConnection) {
this.eventBus = eventBus;
this.singleConnection = singleConnection;
}
@Override
@@ -59,6 +62,9 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
if (keyAgreementInProgress) {
LOG.info("Can't open contact connection during key agreement");
return false;
} else if (singleConnection && !connections.isEmpty()) {
LOG.info("Can't open contact connection due to limit");
return false;
} else {
LOG.info("Can open contact connection");
return true;
@@ -68,12 +74,18 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
@Override
public void connectionOpened(DuplexTransportConnection conn) {
boolean shouldClose = false;
synchronized (lock) {
connections.add(conn);
if (LOG.isLoggable(INFO)) {
LOG.info("Connection opened, " + connections.size() + " open");
}
if (singleConnection && connections.size() > 1) {
LOG.info("Marking connection for close");
shouldClose = true;
}
}
if (shouldClose) conn.markForClose();
}
@Override

View File

@@ -65,7 +65,7 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory {
@Override
public DuplexPlugin createPlugin(PluginCallback callback) {
BluetoothConnectionLimiter connectionLimiter =
new BluetoothConnectionLimiterImpl(eventBus);
new BluetoothConnectionLimiterImpl(eventBus, false);
BluetoothConnectionFactory<StreamConnection> connectionFactory =
new JavaBluetoothConnectionFactory(connectionLimiter,
timeoutMonitor);