mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
BluetoothGattCharacteristic: prefer WRITE_TYPE_DEFAULT over WRITE_TYPE_NO_RESPONSE if both are supported
If both PROPERTY_WRITE and PROPERTY_WRITE_NO_RESPONSE are supported by a BluetoothGattCharacteristic Android defaults to WRITE_TYPE_NO_RESPONSE. This then may cause early BluetoothGattCallback.onCharacteristicWrite calls when the write has been queued on the mobile but potentially not yet actually completely reached the gadget. Depending on the queued BtLEAction(s) and timing details this is often harmless but may sporadically cause inconsistencies. Must be explicitly enabled in the device specific developer settings.
This commit is contained in:
committed by
José Rebelo
parent
5e038a831f
commit
dff57d6e37
+1
@@ -611,6 +611,7 @@ public class DeviceSettingsPreferenceConst {
|
||||
public static final String PREFS_KEY_DEVICE_BLE_API_CHARACTERISTIC = "prefs_device_ble_api_filter_char";
|
||||
public static final String PREFS_KEY_DEVICE_BLE_API_PACKAGE = "prefs_device_ble_api_package";
|
||||
|
||||
public static final String PREFS_DEVICE_GATT_SYNCHRONOUS_WRITES = "prefs_device_gatt_synchronous_writes";
|
||||
public static final String PREF_BATTERY_DISCHARGE_INTERVAL1_WATT = "battery_discharge_interval1_watt";
|
||||
public static final String PREF_BATTERY_DISCHARGE_INTERVAL2_WATT = "battery_discharge_interval2_watt";
|
||||
public static final String PREF_BATTERY_DISCHARGE_INTERVAL3_WATT = "battery_discharge_interval3_watt";
|
||||
|
||||
+4
@@ -1459,6 +1459,10 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
|
||||
DeviceSpecificSettingsScreen.DEVELOPER,
|
||||
R.xml.devicesettings_ble_api
|
||||
);
|
||||
deviceSpecificSettings.addRootScreen(
|
||||
DeviceSpecificSettingsScreen.DEVELOPER,
|
||||
R.xml.devicesettings_gatt_synchronous_writes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -18,6 +18,8 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.btle;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREFS_DEVICE_GATT_SYNCHRONOUS_WRITES;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
@@ -39,11 +41,13 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.Logging;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.CheckInitializedAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
/**
|
||||
* Abstract base class for all devices connected through Bluetooth Low Energy (LE) aka
|
||||
@@ -308,6 +312,10 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
|
||||
}
|
||||
Set<UUID> supportedServices = getSupportedServices();
|
||||
Map<UUID, BluetoothGattCharacteristic> newCharacteristics = new HashMap<>();
|
||||
|
||||
final Prefs devicePrefs = GBApplication.getDevicePrefs(getDevice());
|
||||
final boolean prefs_device_gatt_synchronous_writes = devicePrefs.getBoolean(PREFS_DEVICE_GATT_SYNCHRONOUS_WRITES, false);
|
||||
|
||||
for (BluetoothGattService service : discoveredGattServices) {
|
||||
if(bleApi != null) {
|
||||
bleApi.addService(service);
|
||||
@@ -324,6 +332,17 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
|
||||
for (BluetoothGattCharacteristic characteristic : characteristics) {
|
||||
intmAvailableCharacteristics.put(characteristic.getUuid(), characteristic);
|
||||
logger.info(" characteristic: {}: {} ({})", BleNamesResolver.resolveCharacteristicName(characteristic.getUuid().toString()), characteristic.getUuid(), BleNamesResolver.getCharacteristicPropertyString(characteristic.getProperties()));
|
||||
|
||||
if (prefs_device_gatt_synchronous_writes && characteristic.getWriteType() == BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) {
|
||||
if (0 != (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE)) {
|
||||
// if both PROPERTY_WRITE and PROPERTY_WRITE_NO_RESPONSE are set Android
|
||||
// defaults to WRITE_TYPE_NO_RESPONSE and then calls onCharacteristicWrite
|
||||
// when the write has been queued on the mobile but potentially not yet
|
||||
// actually completely reached the gadget
|
||||
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
logger.debug("changed WriteType of characteristic {} to synchronous", characteristic.getUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
newCharacteristics.putAll(intmAvailableCharacteristics);
|
||||
|
||||
|
||||
+18
-1
@@ -17,6 +17,8 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.btle;
|
||||
|
||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREFS_DEVICE_GATT_SYNCHRONOUS_WRITES;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
@@ -26,7 +28,6 @@ import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -37,11 +38,13 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.Logging;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.CheckInitializedAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||
|
||||
/**
|
||||
* Abstract base class for all devices connected through Bluetooth Low Energy (LE) aka
|
||||
@@ -373,6 +376,9 @@ public abstract class AbstractBTLEMultiDeviceSupport extends AbstractDeviceSuppo
|
||||
return;
|
||||
}
|
||||
|
||||
final Prefs devicePrefs = GBApplication.getDevicePrefs(getDevice());
|
||||
final boolean prefs_device_ble_synchronous_writes = devicePrefs.getBoolean(PREFS_DEVICE_GATT_SYNCHRONOUS_WRITES, false);
|
||||
|
||||
Set<UUID> supportedServices = getSupportedServices(deviceIdx);
|
||||
Map<UUID, BluetoothGattCharacteristic> newCharacteristics = new HashMap<>();
|
||||
for (BluetoothGattService service : discoveredGattServices) {
|
||||
@@ -402,6 +408,17 @@ public abstract class AbstractBTLEMultiDeviceSupport extends AbstractDeviceSuppo
|
||||
characteristic.getUuid(),
|
||||
BleNamesResolver.getCharacteristicPropertyString(
|
||||
characteristic.getProperties()));
|
||||
|
||||
if (prefs_device_ble_synchronous_writes && characteristic.getWriteType() == BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE) {
|
||||
if (0 != (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE)) {
|
||||
// if both PROPERTY_WRITE and PROPERTY_WRITE_NO_RESPONSE are set Android
|
||||
// defaults to WRITE_TYPE_NO_RESPONSE and then calls onCharacteristicWrite
|
||||
// when the write has been queued on the mobile but potentially not yet
|
||||
// actually completely reached the gadget
|
||||
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||
logger.debug("changed WriteType of characteristic {} to synchronous", characteristic.getUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
newCharacteristics.putAll(intmAvailableCharacteristics);
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,840L80,640L280,440L337,496L233,600L840,600L840,680L233,680L337,784L280,840ZM680,520L623,464L727,360L120,360L120,280L727,280L623,176L680,120L880,320L680,520Z"/>
|
||||
</vector>
|
||||
@@ -626,6 +626,9 @@
|
||||
<string name="pref_auto_fetch_limit_fetches">Minimum time between fetches</string>
|
||||
<string name="pref_auto_fetch_limit_fetches_summary">Fetches every %d minutes</string>
|
||||
<!-- developer/debug preferences-->
|
||||
<string name="prefs_title_gatt_settings">Generic Attribute Profile</string>
|
||||
<string name="gatt_synchronous_writes_title">Synchronous GATT writes</string>
|
||||
<string name="gatt_synchronous_writes_summary">Prefer synchronous GATT writes over asynchronous writes if a characteristic supports both.</string>
|
||||
<string name="pref_disable_new_ble_scanning">Disable new BLE scanning</string>
|
||||
<string name="pref_summary_disable_new_ble_scanning">Check this option if your device cannot be found during discovery</string>
|
||||
<string name="not_connected">Not connected</string>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory android:title="@string/prefs_title_gatt_settings" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_sync_alt"
|
||||
android:key="prefs_device_gatt_synchronous_writes"
|
||||
android:layout="@layout/preference_checkbox"
|
||||
android:summary="@string/gatt_synchronous_writes_summary"
|
||||
android:title="@string/gatt_synchronous_writes_title" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
Reference in New Issue
Block a user