mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
BtLEAction: code review
This commit is contained in:
+15
-8
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2024 Carsten Pfeiffer, Uwe Hermann
|
/* Copyright (C) 2015-2026 Carsten Pfeiffer, Uwe Hermann, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -19,15 +19,19 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle;
|
|||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Bluedroid implementation only allows performing one GATT request at a time.
|
* The Bluedroid implementation only allows performing one GATT request at a time.
|
||||||
* As they are asynchronous anyway, we encapsulate every GATT request (read and write)
|
* As they are asynchronous anyway, we encapsulate every GATT request (read and write)
|
||||||
* inside a runnable action.
|
* inside a runnable action.
|
||||||
* <p/>
|
* <p>
|
||||||
* These actions are then executed one after another, ensuring that every action's result
|
* These actions are then executed one after another, ensuring that every action's result
|
||||||
* has been posted before invoking the next action.
|
* has been posted before invoking the next action.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public abstract class BtLEAction {
|
public abstract class BtLEAction {
|
||||||
private final BluetoothGattCharacteristic characteristic;
|
private final BluetoothGattCharacteristic characteristic;
|
||||||
@@ -41,33 +45,36 @@ public abstract class BtLEAction {
|
|||||||
/**
|
/**
|
||||||
* Returns true if this action expects an (async) result which must
|
* Returns true if this action expects an (async) result which must
|
||||||
* be waited for, before continuing with other actions.
|
* be waited for, before continuing with other actions.
|
||||||
* <p/>
|
* <p>
|
||||||
* This is needed because the current Bluedroid stack can only deal
|
* This is needed because the current Bluedroid stack can only deal
|
||||||
* with one single bluetooth operation at a time.
|
* with one single bluetooth operation at a time.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public abstract boolean expectsResult();
|
public abstract boolean expectsResult();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes this action, e.g. reads or write a GATT characteristic.
|
* Executes this action, e.g. reads or write a {@link GattCharacteristic}.
|
||||||
*
|
*
|
||||||
* @param gatt the characteristic to manipulate, or null if none.
|
* @return {@code true} if the action was successful, {@code false} otherwise
|
||||||
* @return true if the action was successful, false otherwise
|
|
||||||
*/
|
*/
|
||||||
public abstract boolean run(BluetoothGatt gatt);
|
public abstract boolean run(@NonNull BluetoothGatt gatt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the GATT characteristic being read/written/...
|
* Returns the GATT characteristic being read/written/...
|
||||||
*
|
*
|
||||||
* @return the GATT characteristic, or <code>null</code>
|
* @return the GATT characteristic, or {@code null}
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public BluetoothGattCharacteristic getCharacteristic() {
|
public BluetoothGattCharacteristic getCharacteristic() {
|
||||||
return characteristic;
|
return characteristic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
protected String getCreationTime() {
|
protected String getCreationTime() {
|
||||||
return DateTimeUtils.formatLocalTime(creationTimestamp);
|
return DateTimeUtils.formatLocalTime(creationTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public String toString() {
|
public String toString() {
|
||||||
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
||||||
String uuid = characteristic == null ? "(null)" : characteristic.getUuid().toString();
|
String uuid = characteristic == null ? "(null)" : characteristic.getUuid().toString();
|
||||||
|
|||||||
+5
-2
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2024 Carsten Pfeiffer
|
/* Copyright (C) 2015-2026 Carsten Pfeiffer
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -18,6 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ public abstract class AbortTransactionAction extends PlainAction {
|
|||||||
private static final Logger LOG = LoggerFactory.getLogger(AbortTransactionAction.class);
|
private static final Logger LOG = LoggerFactory.getLogger(AbortTransactionAction.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
if (shouldAbort()) {
|
if (shouldAbort()) {
|
||||||
LOG.info("Aborting transaction because abort criteria met.");
|
LOG.info("Aborting transaction because abort criteria met.");
|
||||||
return false;
|
return false;
|
||||||
@@ -39,6 +41,7 @@ public abstract class AbortTransactionAction extends PlainAction {
|
|||||||
|
|
||||||
protected abstract boolean shouldAbort();
|
protected abstract boolean shouldAbort();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName() + " abort=" + shouldAbort();
|
return getCreationTime() + " " + getClass().getSimpleName() + " abort=" + shouldAbort();
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2023-2025 Andreas Böhler, Thomas Kuehne
|
/* Copyright (C) 2023-2026 Andreas Böhler, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -22,6 +22,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ public class BondAction extends PlainAction implements BondingInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
BluetoothDevice device = gatt.getDevice();
|
BluetoothDevice device = gatt.getDevice();
|
||||||
mCandidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN, null, null);
|
mCandidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN, null, null);
|
||||||
BondingUtil.tryBondThenComplete(this, device);
|
BondingUtil.tryBondThenComplete(this, device);
|
||||||
|
|||||||
+6
-3
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2016-2024 Carsten Pfeiffer
|
/* Copyright (C) 2016-2026 Carsten Pfeiffer
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -29,9 +31,10 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|||||||
public class CheckInitializedAction extends AbortTransactionAction {
|
public class CheckInitializedAction extends AbortTransactionAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CheckInitializedAction.class);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private final GBDevice device;
|
private final GBDevice device;
|
||||||
|
|
||||||
public CheckInitializedAction(GBDevice gbDevice) {
|
public CheckInitializedAction(@NonNull GBDevice gbDevice) {
|
||||||
device = gbDevice;
|
device = gbDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +42,7 @@ public class CheckInitializedAction extends AbortTransactionAction {
|
|||||||
protected boolean shouldAbort() {
|
protected boolean shouldAbort() {
|
||||||
boolean abort = device.isInitialized();
|
boolean abort = device.isInitialized();
|
||||||
if (abort) {
|
if (abort) {
|
||||||
LOG.info("Aborting device initialization, because already initialized: " + device);
|
LOG.info("Aborting device initialization, because already initialized: {}", device);
|
||||||
}
|
}
|
||||||
return abort;
|
return abort;
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-7
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2016-2025 Andreas Shimokawa, Carsten Pfeiffer, Thomas Kuehne
|
/* Copyright (C) 2016-2026 Andreas Shimokawa, Carsten Pfeiffer, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -19,16 +19,19 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
|||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
public abstract class ConditionalWriteAction extends WriteAction {
|
public abstract class ConditionalWriteAction extends WriteAction {
|
||||||
private boolean actualGenerated;
|
private boolean actualGenerated;
|
||||||
private byte[] actual;
|
private byte[] actual;
|
||||||
|
|
||||||
public ConditionalWriteAction(BluetoothGattCharacteristic characteristic) {
|
public ConditionalWriteAction(@NonNull BluetoothGattCharacteristic characteristic) {
|
||||||
super(characteristic, null);
|
super(characteristic, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
byte[] value = getValue();
|
byte[] value = getValue();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
return super.run(gatt);
|
return super.run(gatt);
|
||||||
@@ -47,12 +50,14 @@ public abstract class ConditionalWriteAction extends WriteAction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the condition whether the write shall happen or not.
|
* Checks the condition whether the write shall happen or not.
|
||||||
* Returns the actual value to be written or null in case nothing shall be written.
|
* Returns the actual value to be written or {@code null} in case nothing shall be written.
|
||||||
* <p/>
|
* <p>
|
||||||
* Note that returning null will not cause {@link #run()} to return false, in other words,
|
* Note that returning {@code null} will not cause {@link #run(BluetoothGatt)} to return {@code false}, in other words,
|
||||||
* the rest of the queue will still be executed.
|
* the rest of the queue will still be executed.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @return the value to be written or null to not write anything
|
* @return the value to be written or {@code null} to not write anything
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
protected abstract byte[] checkCondition();
|
protected abstract byte[] checkCondition();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2023-2025 Johannes Krude, Thomas Kuehne
|
/* Copyright (C) 2023-2026 Johannes Krude, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class FunctionAction extends BtLEAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
try {
|
try {
|
||||||
final boolean success;
|
final boolean success;
|
||||||
if (mRunnable != null) {
|
if (mRunnable != null) {
|
||||||
|
|||||||
+11
-5
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2024 Alicia Hormann, Carsten Pfeiffer, Daniele Gobbetti
|
/* Copyright (C) 2015-2026 Alicia Hormann, Carsten Pfeiffer, Daniele Gobbetti
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -32,6 +32,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
|||||||
|
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.service.btle.GattDescriptor.UUID_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION;
|
import static nodomain.freeyourgadget.gadgetbridge.service.btle.GattDescriptor.UUID_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresPermission;
|
import androidx.annotation.RequiresPermission;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,16 +45,19 @@ public class NotifyAction extends BtLEAction {
|
|||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(NotifyAction.class);
|
private static final Logger LOG = LoggerFactory.getLogger(NotifyAction.class);
|
||||||
private final boolean enableFlag;
|
private final boolean enableFlag;
|
||||||
private boolean hasWrittenDescriptor = false;
|
private boolean hasWrittenDescriptor;
|
||||||
|
|
||||||
public NotifyAction(BluetoothGattCharacteristic characteristic, boolean enable) {
|
public NotifyAction(@NonNull BluetoothGattCharacteristic characteristic, boolean enable) {
|
||||||
super(characteristic);
|
super(characteristic);
|
||||||
enableFlag = enable;
|
enableFlag = enable;
|
||||||
|
hasWrittenDescriptor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// shared write implementation that can be used without a BtLEAction
|
/// shared write implementation that can be used without a BtLEAction
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
public static boolean writeDescriptor(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final byte[] value) {
|
public static boolean writeDescriptor(@Nullable final BluetoothGatt gatt,
|
||||||
|
@Nullable final BluetoothGattDescriptor descriptor,
|
||||||
|
@NonNull final byte[] value) {
|
||||||
if (gatt == null) {
|
if (gatt == null) {
|
||||||
LOG.error("gatt == null");
|
LOG.error("gatt == null");
|
||||||
return false;
|
return false;
|
||||||
@@ -96,7 +101,7 @@ public class NotifyAction extends BtLEAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@RequiresPermission("android.permission.BLUETOOTH_CONNECT")
|
@RequiresPermission("android.permission.BLUETOOTH_CONNECT")
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
// register gatt's callback to receive notifications
|
// register gatt's callback to receive notifications
|
||||||
boolean result = gatt.setCharacteristicNotification(getCharacteristic(), enableFlag);
|
boolean result = gatt.setCharacteristicNotification(getCharacteristic(), enableFlag);
|
||||||
|
|
||||||
@@ -137,6 +142,7 @@ public class NotifyAction extends BtLEAction {
|
|||||||
return hasWrittenDescriptor;
|
return hasWrittenDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2024 Carsten Pfeiffer
|
/* Copyright (C) 2015-2026 Carsten Pfeiffer
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCharacteristic;
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ public abstract class PlainAction extends BtLEAction {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName();
|
return getCreationTime() + " " + getClass().getSimpleName();
|
||||||
|
|||||||
+6
-3
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2024 Carsten Pfeiffer, Daniele Gobbetti
|
/* Copyright (C) 2015-2026 Carsten Pfeiffer, Daniele Gobbetti
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -20,6 +20,8 @@ import android.annotation.SuppressLint;
|
|||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -34,13 +36,13 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
|||||||
public class ReadAction extends BtLEAction {
|
public class ReadAction extends BtLEAction {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ReadAction.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ReadAction.class);
|
||||||
|
|
||||||
public ReadAction(BluetoothGattCharacteristic characteristic) {
|
public ReadAction(@NonNull BluetoothGattCharacteristic characteristic) {
|
||||||
super(characteristic);
|
super(characteristic);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
int properties = getCharacteristic().getProperties();
|
int properties = getCharacteristic().getProperties();
|
||||||
if ((properties & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
|
if ((properties & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
|
||||||
return gatt.readCharacteristic(getCharacteristic());
|
return gatt.readCharacteristic(getCharacteristic());
|
||||||
@@ -54,6 +56,7 @@ public class ReadAction extends BtLEAction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
||||||
|
|||||||
+4
-2
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Thomas Kuehne
|
/* Copyright (C) 2025-2026 Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ import android.annotation.SuppressLint;
|
|||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -47,7 +48,7 @@ public class ReadPhyAction extends BtLEAction {
|
|||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
try {
|
try {
|
||||||
gatt.readPhy();
|
gatt.readPhy();
|
||||||
return true;
|
return true;
|
||||||
@@ -57,6 +58,7 @@ public class ReadPhyAction extends BtLEAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName();
|
return getCreationTime() + " " + getClass().getSimpleName();
|
||||||
|
|||||||
+5
-2
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2023-2024 José Rebelo
|
/* Copyright (C) 2023-2026 José Rebelo
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BleNamesResolver;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BleNamesResolver;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
||||||
|
|
||||||
@@ -38,10 +40,11 @@ public class RequestConnectionPriorityAction extends BtLEAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
public boolean run(final BluetoothGatt gatt) {
|
public boolean run(@NonNull final BluetoothGatt gatt) {
|
||||||
return gatt.requestConnectionPriority(priority);
|
return gatt.requestConnectionPriority(priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName() + " " +
|
return getCreationTime() + " " + getClass().getSimpleName() + " " +
|
||||||
|
|||||||
+8
-4
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2019-2024 Andreas Shimokawa, Daniel Dakhno
|
/* Copyright (C) 2019-2026 Andreas Shimokawa, Daniel Dakhno
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -19,6 +19,9 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
||||||
|
|
||||||
@@ -27,7 +30,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback;
|
|||||||
public class RequestMtuAction extends BtLEAction {
|
public class RequestMtuAction extends BtLEAction {
|
||||||
private final int mtu;
|
private final int mtu;
|
||||||
|
|
||||||
public RequestMtuAction(int mtu) {
|
public RequestMtuAction(@IntRange(from = 23L, to = 517L) final int mtu) {
|
||||||
super(null);
|
super(null);
|
||||||
this.mtu = mtu;
|
this.mtu = mtu;
|
||||||
}
|
}
|
||||||
@@ -40,10 +43,11 @@ public class RequestMtuAction extends BtLEAction {
|
|||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull final BluetoothGatt gatt) {
|
||||||
return gatt.requestMtu(this.mtu);
|
return gatt.requestMtu(mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName() + " mtu=" + mtu;
|
return getCreationTime() + " " + getClass().getSimpleName() + " mtu=" + mtu;
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2025 Carsten Pfeiffer, Thomas Kuehne
|
/* Copyright (C) 2015-2026 Carsten Pfeiffer, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public class SetDeviceBusyAction extends PlainAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
if (busyTask == 0) {
|
if (busyTask == 0) {
|
||||||
device.unsetBusyTask();
|
device.unsetBusyTask();
|
||||||
} else {
|
} else {
|
||||||
@@ -56,6 +56,7 @@ public class SetDeviceBusyAction extends PlainAction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getName() + " "
|
return getCreationTime() + " " + getClass().getName() + " "
|
||||||
|
|||||||
+4
-3
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2025 Andreas Shimokawa, Carsten Pfeiffer, Daniel Dakhno, Thomas Kuehne
|
/* Copyright (C) 2015-2026 Andreas Shimokawa, Carsten Pfeiffer, Daniel Dakhno, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -28,18 +28,19 @@ public class SetDeviceStateAction extends PlainAction {
|
|||||||
private final GBDevice.State deviceState;
|
private final GBDevice.State deviceState;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
public SetDeviceStateAction(GBDevice device, GBDevice.State deviceState, Context context) {
|
public SetDeviceStateAction(@NonNull GBDevice device, @NonNull GBDevice.State deviceState, @NonNull Context context) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.deviceState = deviceState;
|
this.deviceState = deviceState;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
device.setUpdateState(deviceState, context);
|
device.setUpdateState(deviceState, context);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2025 Thomas Kuehne
|
/* Copyright (C) 2025-2026 Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -21,6 +21,7 @@ import android.annotation.SuppressLint;
|
|||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -41,7 +42,7 @@ public class SetPreferredPhyAction extends BtLEAction {
|
|||||||
private final int mRxPhy;
|
private final int mRxPhy;
|
||||||
private final int mPhyOptions;
|
private final int mPhyOptions;
|
||||||
|
|
||||||
public SetPreferredPhyAction(int txPhy, int rxPhy, int phyOptions) {
|
public SetPreferredPhyAction(final int txPhy, final int rxPhy, final int phyOptions) {
|
||||||
super(null);
|
super(null);
|
||||||
mTxPhy = txPhy;
|
mTxPhy = txPhy;
|
||||||
mRxPhy = rxPhy;
|
mRxPhy = rxPhy;
|
||||||
@@ -57,7 +58,7 @@ public class SetPreferredPhyAction extends BtLEAction {
|
|||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull final BluetoothGatt gatt) {
|
||||||
try {
|
try {
|
||||||
gatt.setPreferredPhy(mTxPhy, mRxPhy, mPhyOptions);
|
gatt.setPreferredPhy(mTxPhy, mRxPhy, mPhyOptions);
|
||||||
return true;
|
return true;
|
||||||
@@ -68,6 +69,7 @@ public class SetPreferredPhyAction extends BtLEAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName() + " tx=" + mTxPhy
|
return getCreationTime() + " " + getClass().getSimpleName() + " tx=" + mTxPhy
|
||||||
|
|||||||
+6
-4
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2025 Andreas Shimokawa, Carsten Pfeiffer, José Rebelo, Thomas Kuehne
|
/* Copyright (C) 2015-2026 Andreas Shimokawa, Carsten Pfeiffer, José Rebelo, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ import android.bluetooth.BluetoothGatt;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
@@ -40,15 +41,15 @@ public class SetProgressAction extends PlainAction {
|
|||||||
* @param percentage Current percentage indicating how far along the action has progressed
|
* @param percentage Current percentage indicating how far along the action has progressed
|
||||||
* @param context Context in which to create the notification
|
* @param context Context in which to create the notification
|
||||||
*/
|
*/
|
||||||
public SetProgressAction(@StringRes int textRes, boolean ongoing, int percentage, Context context) {
|
public SetProgressAction(@StringRes int textRes, boolean ongoing, int percentage, @NonNull Context context) {
|
||||||
this.text = context.getString(textRes);;
|
this.text = context.getString(textRes);
|
||||||
this.ongoing = ongoing;
|
this.ongoing = ongoing;
|
||||||
this.percentage = percentage;
|
this.percentage = percentage;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
GB.updateInstallNotification(this.text, this.ongoing, this.percentage, this.context);
|
GB.updateInstallNotification(this.text, this.ongoing, this.percentage, this.context);
|
||||||
|
|
||||||
final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(context);
|
final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(context);
|
||||||
@@ -63,6 +64,7 @@ public class SetProgressAction extends PlainAction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName() + ": " + text + "; " + percentage + "%";
|
return getCreationTime() + " " + getClass().getSimpleName() + ": " + text + "; " + percentage + "%";
|
||||||
|
|||||||
+9
-5
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2024 Carsten Pfeiffer
|
/* Copyright (C) 2015-2026 Carsten Pfeiffer
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
@@ -18,6 +18,9 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions;
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothGatt;
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An action that will cause the queue to {@link Thread#sleep(long) sleep} for the specified time.
|
* An action that will cause the queue to {@link Thread#sleep(long) sleep} for the specified time.
|
||||||
* Note that this is usually a bad idea, since it will not be able to process messages
|
* Note that this is usually a bad idea, since it will not be able to process messages
|
||||||
@@ -25,22 +28,23 @@ import android.bluetooth.BluetoothGatt;
|
|||||||
*/
|
*/
|
||||||
public class SleepAction extends PlainAction {
|
public class SleepAction extends PlainAction {
|
||||||
|
|
||||||
private final int mMillis;
|
private final long mMillis;
|
||||||
|
|
||||||
public SleepAction(int millis) {
|
public SleepAction(@IntRange(from = 0L) final long millis) {
|
||||||
mMillis = millis;
|
mMillis = millis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull final BluetoothGatt gatt) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(mMillis);
|
Thread.sleep(mMillis);
|
||||||
return true;
|
return true;
|
||||||
} catch (InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getCreationTime() + " " + getClass().getSimpleName() + " " + mMillis + " ms";
|
return getCreationTime() + " " + getClass().getSimpleName() + " " + mMillis + " ms";
|
||||||
|
|||||||
+8
-5
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2015-2025 Andreas Shimokawa, Carsten Pfeiffer, Daniele
|
/* Copyright (C) 2015-2026 Andreas Shimokawa, Carsten Pfeiffer, Daniele
|
||||||
Gobbetti, José Rebelo, Uwe Hermann, Thomas Kuehne
|
Gobbetti, José Rebelo, Uwe Hermann, Thomas Kuehne
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
This file is part of Gadgetbridge.
|
||||||
@@ -22,6 +22,8 @@ import android.bluetooth.BluetoothGatt;
|
|||||||
import android.bluetooth.BluetoothGattCharacteristic;
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
import android.bluetooth.BluetoothStatusCodes;
|
import android.bluetooth.BluetoothStatusCodes;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -42,18 +44,18 @@ public class WriteAction extends BtLEAction {
|
|||||||
private final byte[] value;
|
private final byte[] value;
|
||||||
private final boolean legacyCompat;
|
private final boolean legacyCompat;
|
||||||
|
|
||||||
public WriteAction(BluetoothGattCharacteristic characteristic, byte[] value) {
|
public WriteAction(@NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) {
|
||||||
this(characteristic, value, false);
|
this(characteristic, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WriteAction(BluetoothGattCharacteristic characteristic, byte[] value, boolean legacyCompat) {
|
public WriteAction(@NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, boolean legacyCompat) {
|
||||||
super(characteristic);
|
super(characteristic);
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.legacyCompat = legacyCompat;
|
this.legacyCompat = legacyCompat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean run(BluetoothGatt gatt) {
|
public boolean run(@NonNull BluetoothGatt gatt) {
|
||||||
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
||||||
int properties = characteristic.getProperties();
|
int properties = characteristic.getProperties();
|
||||||
//TODO: expectsResult should return false if PROPERTY_WRITE_NO_RESPONSE is true, but this leads to timing issues
|
//TODO: expectsResult should return false if PROPERTY_WRITE_NO_RESPONSE is true, but this leads to timing issues
|
||||||
@@ -74,7 +76,7 @@ public class WriteAction extends BtLEAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
private static boolean writeCharacteristicImp(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value, boolean legacyCompat) {
|
private static boolean writeCharacteristicImp(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, boolean legacyCompat) {
|
||||||
if (GBApplication.isRunningTiramisuOrLater() && !legacyCompat) {
|
if (GBApplication.isRunningTiramisuOrLater() && !legacyCompat) {
|
||||||
// use API introduced in SDK level 33 to catch exceptions and more specific errors
|
// use API introduced in SDK level 33 to catch exceptions and more specific errors
|
||||||
try {
|
try {
|
||||||
@@ -109,6 +111,7 @@ public class WriteAction extends BtLEAction {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
BluetoothGattCharacteristic characteristic = getCharacteristic();
|
||||||
|
|||||||
Reference in New Issue
Block a user