diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/AbstractBTBRDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/AbstractBTBRDeviceSupport.java
new file mode 100644
index 000000000..053fb8a3b
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/AbstractBTBRDeviceSupport.java
@@ -0,0 +1,155 @@
+/* Copyright (C) 2022 Damien Gaignon
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+import org.slf4j.Logger;
+
+import android.location.Location;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.UUID;
+
+import nodomain.freeyourgadget.gadgetbridge.Logging;
+import nodomain.freeyourgadget.gadgetbridge.model.Reminder;
+import nodomain.freeyourgadget.gadgetbridge.model.WorldClock;
+import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
+import nodomain.freeyourgadget.gadgetbridge.service.btbr.actions.CheckInitializedAction;
+
+/**
+ * Abstract base class for devices connected through a serial protocol, like RFCOMM BT or TCP socket.
+ *
+ * The connection to the device and all communication is made with a generic {@link BtClassicIo}.
+ * Messages to the device are encoded
+ * sent via {@link BtClassicIo}.
+ *
+ * @see BtClassicIo
+ */
+public abstract class AbstractBTBRDeviceSupport extends AbstractDeviceSupport implements SocketCallback {
+ private BtBRQueue mQueue;
+ private UUID mSupportedService = null;
+ private Logger logger;
+
+ public AbstractBTBRDeviceSupport(Logger logger) {
+ this.logger = logger;
+ if (logger == null) {
+ throw new IllegalArgumentException("logger must not be null");
+ }
+ }
+
+ @Override
+ public boolean connect() {
+ if (mQueue == null) {
+ mQueue = new BtBRQueue(getBluetoothAdapter(), getDevice(), getContext(), this, getSupportedService());
+ }
+ return mQueue.connect();
+ }
+
+ /**
+ * Subclasses should populate the given builder to initialize the device (if necessary).
+ *
+ * @return the same builder as passed as the argument
+ */
+ protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
+ return builder;
+ }
+
+ @Override
+ public void dispose() {
+ if (mQueue != null) {
+ mQueue.dispose();
+ mQueue = null;
+ }
+ }
+
+ public TransactionBuilder createTransactionBuilder(String taskName) {
+ return new TransactionBuilder(taskName);
+ }
+
+ /**
+ * Ensures that the device is connected and (only then) performs the actions of the given
+ * transaction builder.
+ *
+ * In contrast to {@link #performInitialized(String)}, no initialization sequence is performed
+ * with the device, only the actions of the given builder are executed.
+ * @param transaction
+ * @throws IOException
+ * @see {@link #performInitialized(String)}
+ */
+ public void performConnected(Transaction transaction) throws IOException {
+ if (!isConnected()) {
+ if (!connect()) {
+ throw new IOException("2: Unable to connect to device: " + getDevice());
+ }
+ }
+ getQueue().add(transaction);
+ }
+
+ public BtBRQueue getQueue() {
+ return mQueue;
+ }
+
+ /**
+ * Subclasses should call this method to add services they support.
+ * Only supported services will be queried for characteristics.
+ *
+ * @param aSupportedService
+ */
+ protected void addSupportedService(UUID aSupportedService) {
+ mSupportedService = aSupportedService;
+ }
+
+ protected UUID getSupportedService() {
+ return mSupportedService;
+ }
+
+ /**
+ * Utility method that may be used to log incoming messages when we don't know how to deal with them yet.
+ *
+ * @param value
+ */
+ public void logMessageContent(byte[] value) {
+ logger.info("RECEIVED DATA WITH LENGTH: " + ((value != null) ? value.length : "(null)"));
+ Logging.logBytes(logger, value);
+ }
+
+ public void onConnectionEstablished() {
+ initializeDevice(createTransactionBuilder("Initializing device")).queue(getQueue());
+ }
+
+ @Override
+ public void onSetFmFrequency(float frequency) {}
+
+ @Override
+ public void onSetLedColor(int color) {}
+
+ @Override
+ public void onSetGpsLocation(Location location) {}
+
+ @Override
+ public void onSetWorldClocks(ArrayList extends WorldClock> clocks) {}
+
+ @Override
+ public void onPowerOff() {}
+
+ @Override
+ public void onSetPhoneVolume(final float volume) {}
+
+ @Override
+ public void onSetReminders(ArrayList extends Reminder> reminders) {}
+
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/AbstractTransaction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/AbstractTransaction.java
new file mode 100644
index 000000000..f042f859e
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/AbstractTransaction.java
@@ -0,0 +1,47 @@
+/* Copyright (C) 2015-2021 Andreas Böhler, Andreas Shimokawa, Carsten
+ Pfeiffer, Daniele Gobbetti
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public abstract class AbstractTransaction {
+ private final String mName;
+ private final long creationTimestamp = System.currentTimeMillis();
+
+ public AbstractTransaction(String taskName) {
+ this.mName = taskName;
+ }
+
+ public String getTaskName() {
+ return mName;
+ }
+
+ protected String getCreationTime() {
+ return DateFormat.getTimeInstance(DateFormat.MEDIUM).format(new Date(creationTimestamp));
+ }
+
+ public abstract int getActionCount();
+
+ @Override
+ public String toString() {
+ return String.format(Locale.US, "%s: Transaction task: %s with %d actions", getCreationTime(), getTaskName(), getActionCount());
+ }
+
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/BtBRAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/BtBRAction.java
new file mode 100644
index 000000000..6a9b48a7d
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/BtBRAction.java
@@ -0,0 +1,64 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer, Uwe Hermann
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+import android.bluetooth.BluetoothSocket;
+
+import java.util.Date;
+
+import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
+
+/**
+ * This allows performing one socket request at a time.
+ * As they are asynchronous anyway, we encapsulate every socket request (only write)
+ * inside a runnable action.
+ *
+ * These actions are then executed one after another, ensuring that every action's result
+ * has been posted before invoking the next action.
+ *
+ * As there is only write action, this class will be needed for later usage.
+ */
+public abstract class BtBRAction {
+ private final long creationTimestamp;
+
+ public BtBRAction() {
+ creationTimestamp = System.currentTimeMillis();
+ }
+
+ /**
+ * Returns true if this action expects an (async) result which must
+ * be waited for, before continuing with other actions.
+ *
+ */
+ public abstract boolean expectsResult();
+
+ /**
+ * Executes this action, e.g. reads or write a Socket characteristic.
+ *
+ * @param socket the characteristic to manipulate, or null if none.
+ * @return true if the action was successful, false otherwise
+ */
+ public abstract boolean run(BluetoothSocket socket);
+
+ protected String getCreationTime() {
+ return DateTimeUtils.formatDateTime(new Date(creationTimestamp));
+ }
+
+ public String toString() {
+ return getCreationTime() + ": " + getClass().getSimpleName();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/BtBRQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/BtBRQueue.java
new file mode 100644
index 000000000..5eeb57c9b
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/BtBRQueue.java
@@ -0,0 +1,250 @@
+/* Copyright (C) 2022 Damien Gaignon
+*
+* This file is part of Gadgetbridge.
+*
+* Gadgetbridge is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License as published
+* by the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* Gadgetbridge is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see .
+*/
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+import android.content.Context;
+import android.os.ParcelUuid;
+
+import androidx.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
+
+public final class BtBRQueue {
+ private static final Logger LOG = LoggerFactory.getLogger(BtBRQueue.class);
+
+ private BluetoothAdapter mBtAdapter = null;
+ private BluetoothSocket mBtSocket = null;
+ private GBDevice mGbDevice;
+ private SocketCallback mCallback;
+ private UUID mService;
+
+ private final BlockingQueue mTransactions = new LinkedBlockingQueue<>();
+ private volatile boolean mDisposed;
+ private volatile boolean mCrashed;
+
+ private Context mContext;
+ private CountDownLatch mConnectionLatch;
+ private CountDownLatch mAvailableData;
+
+ private Thread writeThread = new Thread("Gadgetbridge IO writeThread") {
+ @Override
+ public void run() {
+ LOG.debug("Socket Write Thread started.");
+
+ while (!mDisposed && !mCrashed) {
+ try {
+ AbstractTransaction qTransaction = mTransactions.take();
+ if (!isConnected()) {
+ LOG.debug("Not connected, waiting for connection...");
+ setDeviceConnectionState(GBDevice.State.NOT_CONNECTED);
+ // wait until the connection succeeds before running the actions
+ // Note that no automatic connection is performed. This has to be triggered
+ // on the outside typically by the DeviceSupport. The reason is that
+ // devices have different kinds of initializations and this class has no
+ // idea about them.
+ mConnectionLatch = new CountDownLatch(1);
+ mConnectionLatch.await();
+ mConnectionLatch = null;
+ }
+ LOG.info("Ready for a new message exchange.");
+ Transaction transaction = (Transaction)qTransaction;
+ for (BtBRAction action : transaction.getActions()) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("About to run action: " + action);
+ }
+ if (action.run(mBtSocket)) {
+ LOG.debug("Action ok: " + action);
+ } else {
+ LOG.error("Action returned false: " + action);
+ break;
+ }
+ }
+ } catch (InterruptedException ignored) {
+ mConnectionLatch = null;
+ LOG.debug("Thread interrupted");
+ } catch (Throwable ex) {
+ LOG.error("IO Write Thread died: " + ex.getMessage(), ex);
+ mCrashed = true;
+ mConnectionLatch = null;
+ }
+ }
+ }
+ };
+
+ private Thread readThread = new Thread("Gadgetbridge IO readThread") {
+ @Override
+ public void run() {
+ LOG.debug("Queue Read Thread started.");
+ while (!mDisposed && !mCrashed) {
+ try {
+ if (!isConnected()) {
+ LOG.debug("not connected, waiting for connection...");
+ // wait until the connection succeeds before running the actions
+ // Note that no automatic connection is performed. This has to be triggered
+ // on the outside typically by the DeviceSupport. The reason is that
+ // devices have different kinds of initializations and this class has no
+ // idea about them.
+ mConnectionLatch = new CountDownLatch(1);
+ mConnectionLatch.await();
+ mConnectionLatch = null;
+ }
+ if (mAvailableData != null) {
+ if (mBtSocket.getInputStream().available() == 0) {
+ mAvailableData.countDown();
+ }
+ }
+ byte[] data = new byte[1024];
+ int len = mBtSocket.getInputStream().read(data);
+ LOG.debug("Received data: " + StringUtils.bytesToHex(data));
+ mCallback.onSocketRead(Arrays.copyOf(data, len));
+ } catch (InterruptedException ignored) {
+ mConnectionLatch = null;
+ LOG.debug("Thread interrupted");
+ } catch (Throwable ex) {
+ LOG.error("IO Read Thread died: " + ex.getMessage(), ex);
+ mCrashed = true;
+ mConnectionLatch = null;
+ }
+ }
+ }
+ };
+
+ public BtBRQueue(BluetoothAdapter btAdapter, GBDevice gbDevice, Context context, SocketCallback socketCallback, UUID supportedService) {
+ mBtAdapter = btAdapter;
+ mGbDevice = gbDevice;
+ mContext = context;
+ mCallback = socketCallback;
+ mService = supportedService;
+
+ writeThread.start();
+ readThread.start();
+ }
+
+ /**
+ * Connects to the given remote device. Note that this does not perform any device
+ * specific initialization. This should be done in the specific {@link DeviceSupport}
+ * class.
+ *
+ * @return true
whether the connection attempt was successfully triggered and false
if that failed or if there is already a connection
+ */
+
+ protected boolean connect() {
+ if (isConnected()) {
+ LOG.warn("Ignoring connect() because already connected.");
+ return false;
+ }
+
+ LOG.info("Attemping to connect to " + mGbDevice.getName());
+ GBDevice.State originalState = mGbDevice.getState();
+ setDeviceConnectionState(GBDevice.State.CONNECTING);
+
+ try {
+ BluetoothDevice btDevice = mBtAdapter.getRemoteDevice(mGbDevice.getAddress());
+ // UUID should be in a BluetoothSocket class and not in BluetoothSocketCharacteristic
+ mBtSocket = btDevice.createRfcommSocketToServiceRecord(mService);
+ mBtSocket.connect();
+ if (mBtSocket.isConnected()) {
+ setDeviceConnectionState(GBDevice.State.CONNECTED);
+ } else {
+ LOG.debug("Connection not established");
+ }
+ if (mConnectionLatch != null) {
+ mConnectionLatch.countDown();
+ }
+ } catch (IOException e) {
+ LOG.error("Server socket cannot be started.", e);
+ setDeviceConnectionState(originalState);
+ mBtSocket = null;
+ return false;
+ }
+
+ onConnectionEstablished();
+
+ return true;
+ }
+
+ protected void onConnectionEstablished() {
+ mCallback.onConnectionEstablished();
+ }
+
+ public void disconnect() {
+ if (mBtSocket != null) {
+ try {
+ mAvailableData = new CountDownLatch(1);
+ mAvailableData.await();
+ mAvailableData = null;
+ mBtSocket.close();
+ } catch (IOException e) {
+ LOG.error(e.getMessage());
+ } catch (InterruptedException e) {
+ LOG.error(e.getMessage());
+ }
+ }
+ }
+
+ protected boolean isConnected() {
+ return mGbDevice.isConnected();
+ }
+
+ /**
+ * Adds a transaction to the end of the queue.
+ *
+ * @param transaction
+ */
+ public void add(Transaction transaction) {
+ LOG.debug("about to add: " + transaction);
+ if (!transaction.isEmpty()) {
+ mTransactions.add(transaction);
+ }
+ }
+
+ protected void setDeviceConnectionState(GBDevice.State newState) {
+ LOG.debug("New device connection state: " + newState);
+ mGbDevice.setState(newState);
+ mGbDevice.sendDeviceUpdateIntent(mContext, GBDevice.DeviceUpdateSubject.DEVICE_STATE);
+ }
+
+ public void dispose() {
+ if (mDisposed) {
+ return;
+ }
+ mDisposed = true;
+ disconnect();
+ writeThread.interrupt();
+ writeThread = null;
+ readThread.interrupt();
+ readThread = null;
+ }
+
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/SocketCallback.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/SocketCallback.java
new file mode 100644
index 000000000..f31effc68
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/SocketCallback.java
@@ -0,0 +1,35 @@
+/** Copyright (C) 2022 Damien Gaignon
+ *
+ * This file is part of Gadgetbridge.
+ *
+ * Gadgetbridge is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gadgetbridge is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+/**
+ * Callback interface handling io events of a BluetoothSocket.
+ * It is the counterpart of GattCallback interface designed for GB.
+*/
+public interface SocketCallback {
+
+ void onConnectionEstablished();
+
+ /**
+ * Read data from InputStream of BluetoothSocket
+ *
+ * @param data
+ */
+ void onSocketRead(byte[] data);
+
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/Transaction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/Transaction.java
new file mode 100644
index 000000000..46dd4c0a8
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/Transaction.java
@@ -0,0 +1,71 @@
+/* Copyright (C) 2015-2021 Andreas Böhler, Andreas Shimokawa, Carsten
+ Pfeiffer, Daniele Gobbetti
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import androidx.annotation.Nullable;
+
+/**
+ * Groups a bunch of {@link BtBRAction actions} together, making sure
+ * that upon failure of one action, all subsequent actions are discarded.
+ *
+ * @author TREND
+ */
+public class Transaction extends AbstractTransaction {
+ private final List mActions = new ArrayList<>(4);
+ private
+ @Nullable
+ SocketCallback socketCallback;
+
+ public Transaction(String taskName) {
+ super(taskName);
+ }
+
+ public void add(BtBRAction action) {
+ mActions.add(action);
+ }
+
+ public List getActions() {
+ return Collections.unmodifiableList(mActions);
+ }
+
+ public boolean isEmpty() {
+ return mActions.isEmpty();
+ }
+
+ public void setCallback(@Nullable SocketCallback callback) {
+ socketCallback = callback;
+ }
+
+ /**
+ * Returns the GattCallback for this transaction, or null if none.
+ */
+ public
+ @Nullable
+ SocketCallback getSocketCallback() {
+ return socketCallback;
+ }
+
+ @Override
+ public int getActionCount() {
+ return mActions.size();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/TransactionBuilder.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/TransactionBuilder.java
new file mode 100644
index 000000000..2066d1d0e
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/TransactionBuilder.java
@@ -0,0 +1,89 @@
+/* Copyright (C) 2022 Damien Gaignon
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr;
+
+import android.os.Build;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import nodomain.freeyourgadget.gadgetbridge.service.btbr.actions.WaitAction;
+import nodomain.freeyourgadget.gadgetbridge.service.btbr.actions.WriteAction;
+
+public class TransactionBuilder {
+ private static final Logger LOG = LoggerFactory.getLogger(TransactionBuilder.class);
+
+ private final Transaction mTransaction;
+ private boolean mQueued;
+
+ public TransactionBuilder(String taskName) {
+ mTransaction = new Transaction(taskName);
+ }
+
+ public TransactionBuilder write(byte[] data) {
+ WriteAction action = new WriteAction(data);
+ return add(action);
+ }
+
+
+ /**
+ * Causes the queue to sleep for the specified time.
+ * Note that this is usually a bad idea, since it will not be able to process messages
+ * during that time. It is also likely to cause race conditions.
+ * @param millis the number of milliseconds to sleep
+ */
+ public TransactionBuilder wait(int millis) {
+ WaitAction action = new WaitAction(millis);
+ return add(action);
+ }
+
+ public TransactionBuilder add(BtBRAction action) {
+ mTransaction.add(action);
+ return this;
+ }
+
+ /**
+ * Sets a SocketCallback instance that will be called when the transaction is executed,
+ * resulting in SocketCallback events.
+ *
+ * @param callback the callback to set, may be null
+ */
+ public void setCallback(@Nullable SocketCallback callback) {
+ mTransaction.setCallback(callback);
+ }
+
+ /**
+ * To be used as the final step to execute the transaction by the given queue.
+ *
+ * @param queue
+ */
+ public void queue(BtBRQueue queue) {
+ if (mQueued) {
+ throw new IllegalStateException("This builder had already been queued. You must not reuse it.");
+ }
+ mQueued = true;
+ queue.add(mTransaction);
+ }
+
+ public Transaction getTransaction() {
+ return mTransaction;
+ }
+
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/AbortTransactionAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/AbortTransactionAction.java
new file mode 100644
index 000000000..c7eed31da
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/AbortTransactionAction.java
@@ -0,0 +1,49 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import android.bluetooth.BluetoothSocket;
+
+/**
+ * A special action that checks for an abort-condition, and if met, the currently
+ * executing transaction will be aborted by returning false.
+ */
+public abstract class AbortTransactionAction extends PlainAction {
+ private static final Logger LOG = LoggerFactory.getLogger(AbortTransactionAction.class);
+
+ public AbortTransactionAction() {
+ }
+
+ @Override
+ public boolean run(BluetoothSocket socket) {
+ if (shouldAbort()) {
+ LOG.info("Aborting transaction because abort criteria met.");
+ return false;
+ }
+ return true;
+ }
+
+ protected abstract boolean shouldAbort();
+
+ @Override
+ public String toString() {
+ return getCreationTime() + ": " + getClass().getSimpleName() + ": aborting? " + shouldAbort();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/CheckInitializedAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/CheckInitializedAction.java
new file mode 100644
index 000000000..ff967c6a1
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/CheckInitializedAction.java
@@ -0,0 +1,46 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+/**
+ * A special action that is executed at the very front of the initialization
+ * sequence (transaction). It will abort the entire initialization sequence
+ * by returning false, when the device is already initialized.
+ */
+public class CheckInitializedAction extends AbortTransactionAction {
+ private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
+
+ private final GBDevice device;
+
+ public CheckInitializedAction(GBDevice gbDevice) {
+ device = gbDevice;
+ }
+
+ @Override
+ protected boolean shouldAbort() {
+ boolean abort = device.isInitialized();
+ if (abort) {
+ LOG.info("Aborting device initialization, because already initialized: " + device);
+ }
+ return abort;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/PlainAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/PlainAction.java
new file mode 100644
index 000000000..34341b8df
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/PlainAction.java
@@ -0,0 +1,39 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import nodomain.freeyourgadget.gadgetbridge.service.btbr.BtBRAction;
+
+/**
+ * An abstract non-BTBR action. It performs no bluetooth operation,
+ * does not have a BluetoothSocketCharacteristic instance and expects no result.
+ */
+public abstract class PlainAction extends BtBRAction {
+
+ public PlainAction() {
+ }
+
+ @Override
+ public boolean expectsResult() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return getCreationTime() + ": " + getClass().getSimpleName();
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/SetDeviceBusyAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/SetDeviceBusyAction.java
new file mode 100644
index 000000000..2c7990bd6
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/SetDeviceBusyAction.java
@@ -0,0 +1,53 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import android.bluetooth.BluetoothSocket;
+import android.content.Context;
+
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class SetDeviceBusyAction extends PlainAction {
+ private final GBDevice device;
+ private final Context context;
+ private final String busyTask;
+
+ /**
+ * When run, will mark the device as busy (or not busy).
+ *
+ * @param device the device to mark
+ * @param busyTask the task name to set as busy task, or null to mark as not busy
+ * @param context
+ */
+ public SetDeviceBusyAction(GBDevice device, String busyTask, Context context) {
+ this.device = device;
+ this.busyTask = busyTask;
+ this.context = context;
+ }
+
+ @Override
+ public boolean run(BluetoothSocket socket) {
+ device.setBusyTask(busyTask);
+ device.sendDeviceUpdateIntent(context);
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return getCreationTime() + ": " + getClass().getName() + ": " + busyTask;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/SetDeviceStateAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/SetDeviceStateAction.java
new file mode 100644
index 000000000..63a53c3f0
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/SetDeviceStateAction.java
@@ -0,0 +1,53 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import android.bluetooth.BluetoothSocket;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
+
+public class SetDeviceStateAction extends PlainAction {
+ private final GBDevice device;
+ private final GBDevice.State deviceState;
+ private final Context context;
+
+ public SetDeviceStateAction(GBDevice device, GBDevice.State deviceState, Context context) {
+ this.device = device;
+ this.deviceState = deviceState;
+ this.context = context;
+ }
+
+ @Override
+ public boolean run(BluetoothSocket socket) {
+ device.setState(deviceState);
+ device.sendDeviceUpdateIntent(getContext(), GBDevice.DeviceUpdateSubject.DEVICE_STATE);
+ return true;
+ }
+
+ public Context getContext() {
+ return context;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return super.toString() + " to " + deviceState;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/WaitAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/WaitAction.java
new file mode 100644
index 000000000..48c8ab705
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/WaitAction.java
@@ -0,0 +1,43 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import android.bluetooth.BluetoothSocket;
+
+/**
+ * An action that will cause the queue to sleep for the specified time.
+ * Note that this is usually a bad idea, since it will not be able to process messages
+ * during that time. It is also likely to cause race conditions.
+ */
+public class WaitAction extends PlainAction {
+
+ private final int mMillis;
+
+ public WaitAction(int millis) {
+ mMillis = millis;
+ }
+
+ @Override
+ public boolean run(BluetoothSocket socket) {
+ try {
+ Thread.sleep(mMillis);
+ return true;
+ } catch (InterruptedException e) {
+ return false;
+ }
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/WriteAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/WriteAction.java
new file mode 100644
index 000000000..69c5e1099
--- /dev/null
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btbr/actions/WriteAction.java
@@ -0,0 +1,83 @@
+/* Copyright (C) 2015-2021 Andreas Shimokawa, Carsten Pfeiffer, Daniele
+ Gobbetti, Uwe Hermann
+
+ This file is part of Gadgetbridge.
+
+ Gadgetbridge is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Gadgetbridge is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see . */
+package nodomain.freeyourgadget.gadgetbridge.service.btbr.actions;
+
+import android.bluetooth.BluetoothSocket;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import nodomain.freeyourgadget.gadgetbridge.Logging;
+import nodomain.freeyourgadget.gadgetbridge.service.btbr.BtBRAction;
+
+/**
+ * Invokes a write operation on a given socket.
+ * The result status will be made available asynchronously through the
+ * {@link SocketCallback}
+ */
+public class WriteAction extends BtBRAction {
+ private static final Logger LOG = LoggerFactory.getLogger(WriteAction.class);
+
+ private final byte[] value;
+ private OutputStream mOutputStream = null;
+
+ public WriteAction(byte[] value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean run(BluetoothSocket socket) {
+ try {
+ mOutputStream = socket.getOutputStream();
+ if (mOutputStream == null) {
+ LOG.error("mOutStream is null");
+ return false;
+ }
+ return writeValue(value);
+ } catch (IOException e) {
+ LOG.error("Can not get the output stream");
+ }
+ return false;
+ }
+
+ protected boolean writeValue(byte[] value) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("writing to socket: " + Logging.formatBytes(value));
+ }
+ try {
+ mOutputStream.write(value);
+ mOutputStream.flush();
+ return true;
+ } catch (IOException e) {
+ LOG.error("Error writing to socket: ", e);
+ }
+ return false;
+ }
+
+ protected final byte[] getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean expectsResult() {
+ return true;
+ }
+}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java
index e8d18d6cf..55dd62231 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java
@@ -105,13 +105,13 @@ public abstract class AbstractBTLEOperation
*/
public TransactionBuilder performInitialized(String taskName) throws IOException {
TransactionBuilder builder = mSupport.performInitialized(taskName);
- builder.setGattCallback(this);
+ builder.setCallback(this);
return builder;
}
public TransactionBuilder createTransactionBuilder(String taskName) {
TransactionBuilder builder = getSupport().createTransactionBuilder(taskName);
- builder.setGattCallback(this);
+ builder.setCallback(this);
return builder;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransaction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransaction.java
index 54a1dec19..e9682a933 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransaction.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransaction.java
@@ -57,7 +57,7 @@ public class ServerTransaction extends AbstractTransaction {
return String.format(Locale.US, "%s: Transaction task: %s with %d actions", getCreationTime(), getTaskName(), mActions.size());
}
- public void setGattCallback(@Nullable GattServerCallback callback) {
+ public void setCallback(@Nullable GattServerCallback callback) {
gattCallback = callback;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransactionBuilder.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransactionBuilder.java
index 779dc6dfe..7d166a11d 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransactionBuilder.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/ServerTransactionBuilder.java
@@ -54,8 +54,8 @@ public class ServerTransactionBuilder {
*
* @param callback the callback to set, may be null
*/
- public void setGattCallback(@Nullable GattServerCallback callback) {
- mTransaction.setGattCallback(callback);
+ public void setCallback(@Nullable GattServerCallback callback) {
+ mTransaction.setCallback(callback);
}
public
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/Transaction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/Transaction.java
index a64c256e6..90f8296c9 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/Transaction.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/Transaction.java
@@ -54,7 +54,7 @@ public class Transaction extends AbstractTransaction {
return mActions.isEmpty();
}
- public void setGattCallback(@Nullable GattCallback callback) {
+ public void setCallback(@Nullable GattCallback callback) {
gattCallback = callback;
modifyGattCallback = true;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java
index e622636a8..0e3b811e7 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java
@@ -108,8 +108,8 @@ public class TransactionBuilder {
*
* @param callback the callback to set, may be null
*/
- public void setGattCallback(@Nullable GattCallback callback) {
- mTransaction.setGattCallback(callback);
+ public void setCallback(@Nullable GattCallback callback) {
+ mTransaction.setCallback(callback);
}
public
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/AbstractBleProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/AbstractBleProfile.java
index 346586cf2..3bc3350e7 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/AbstractBleProfile.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/AbstractBleProfile.java
@@ -88,7 +88,7 @@ public abstract class AbstractBleProfile ex
*/
public TransactionBuilder performInitialized(String taskName) throws IOException {
TransactionBuilder builder = mSupport.performInitialized(taskName);
- builder.setGattCallback(this);
+ builder.setCallback(this);
return builder;
}
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java
index b8b44b248..591ed6835 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/banglejs/BangleJSDeviceSupport.java
@@ -313,7 +313,7 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
rxCharacteristic = getCharacteristic(BangleJSConstants.UUID_CHARACTERISTIC_NORDIC_UART_RX);
txCharacteristic = getCharacteristic(BangleJSConstants.UUID_CHARACTERISTIC_NORDIC_UART_TX);
- builder.setGattCallback(this);
+ builder.setCallback(this);
builder.notify(rxCharacteristic, true);
Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSharedPrefs(gbDevice.getAddress()));
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/CasioGB6900DeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/CasioGB6900DeviceSupport.java
index 19ac8a532..2e30bd5ba 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/CasioGB6900DeviceSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/CasioGB6900DeviceSupport.java
@@ -171,7 +171,7 @@ public class CasioGB6900DeviceSupport extends CasioSupport {
getDevice().setFirmwareVersion2("N/A");
- builder.setGattCallback(this);
+ builder.setCallback(this);
configureWatch(builder);
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/operations/FetchStepCountDataOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/operations/FetchStepCountDataOperation.java
index c935e058e..281cc47bb 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/operations/FetchStepCountDataOperation.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/casio/operations/FetchStepCountDataOperation.java
@@ -51,7 +51,7 @@ public class FetchStepCountDataOperation extends AbstractBTLEOperation {
this.authFlags = authFlags;
this.cryptFlags = cryptFlags;
this.builder = builder;
- builder.setGattCallback(this);
+ builder.setCallback(this);
}
@Override
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/id115/AbstractID115Operation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/id115/AbstractID115Operation.java
index 5b4885c9c..a25d6ce07 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/id115/AbstractID115Operation.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/id115/AbstractID115Operation.java
@@ -62,7 +62,7 @@ public abstract class AbstractID115Operation extends AbstractBTLEOperation{
super(support);
this.needsAuth = needsAuth;
this.builder = builder;
- builder.setGattCallback(this);
+ builder.setCallback(this);
}
@Override
@@ -73,7 +73,7 @@ public class InitOperation extends AbstractBTLEOperation{
getSupport().logMessageContent(value);
if (ArrayUtils.equals(value, Watch9Constants.RESP_AUTHORIZATION_TASK, 5) && value[8] == 0x01) {
TransactionBuilder builder = getSupport().createTransactionBuilder("authInit");
- builder.setGattCallback(this);
+ builder.setCallback(this);
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
getSupport().initialize(builder).performImmediately(builder);
} else {