Add setting to force legacy GATT

This commit is contained in:
José Rebelo
2025-09-27 19:52:12 +02:00
committed by José Rebelo
parent 4e915647d1
commit ded65032cd
8 changed files with 64 additions and 3 deletions
@@ -141,7 +141,7 @@ public class GBApplication extends Application {
private static SharedPreferences sharedPrefs;
private static final String PREFS_VERSION = "shared_preferences_version";
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
private static final int CURRENT_PREFS_VERSION = 53;
private static final int CURRENT_PREFS_VERSION = 54;
private static final LimitedQueue<Integer, String> mIDSenderLookup = new LimitedQueue<>(16);
private static GBPrefs prefs;
@@ -2151,6 +2151,25 @@ public class GBApplication extends Application {
}
}
if (oldVersion < 54) {
// #5414 - Some old Android versions misbehave
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
try (DBHandler db = acquireDB()) {
final DaoSession daoSession = db.getDaoSession();
final List<Device> activeDevices = DBHelper.getActiveDevices(daoSession);
for (final Device dbDevice : activeDevices) {
final SharedPreferences deviceSharedPrefs = GBApplication.getDeviceSpecificSharedPrefs(dbDevice.getIdentifier());
final SharedPreferences.Editor deviceSharedPrefsEdit = deviceSharedPrefs.edit();
deviceSharedPrefsEdit.putBoolean("connection_force_legacy_gatt", true);
deviceSharedPrefsEdit.apply();
}
} catch (Exception e) {
Log.e(TAG, "Failed to migrate prefs to version 54", e);
}
}
}
editor.putString(PREFS_VERSION, Integer.toString(CURRENT_PREFS_VERSION));
editor.apply();
}
@@ -663,6 +663,7 @@ public class DeviceSettingsPreferenceConst {
public static final String PREF_DISPLAY_ON_START = "display_on_start";
public static final String PREF_DISPLAY_ON_END = "display_on_end";
public static final String PREF_CONNECTION_PRIORITY_LOW_POWER = "connection_priority_low_power";
public static final String PREF_CONNECTION_FORCE_LEGACY_GATT = "connection_force_legacy_gatt";
public static final String PREF_EVEN_REALITIES_SCREEN_HEIGHT = "pref_even_realities_g1_screen_height";
public static final String PREF_EVEN_REALITIES_SCREEN_DEPTH = "pref_even_realities_g1_screen_depth";
public static final String PREF_EVEN_REALITIES_SCREEN_ACTIVATION_ANGLE = "pref_even_realities_g1_screen_activation_angle";
@@ -1588,6 +1588,12 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
DeviceSpecificSettingsScreen.DEVELOPER,
R.xml.devicesettings_gatt_synchronous_writes
);
if (GBApplication.isRunningOreoOrLater()) {
deviceSpecificSettings.addRootScreen(
DeviceSpecificSettingsScreen.DEVELOPER,
R.xml.devicesettings_connection_force_legacy_gatt
);
}
}
if(BuildConfig.DEBUG) {
deviceSpecificSettings.addRootScreen(
@@ -26,7 +26,9 @@ import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanFilter;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.widget.Toast;
import androidx.annotation.DrawableRes;
@@ -55,6 +57,7 @@ import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
@@ -98,6 +101,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.gadgetbridge.util.preferences.DevicePrefs;
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class);
@@ -157,6 +161,17 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
public GBDevice createDevice(GBDeviceCandidate candidate, DeviceType deviceType) {
GBDevice gbDevice = new GBDevice(candidate.getDevice().getAddress(), candidate.getName(), null, null, deviceType);
setBatteryConfigOnDevice(gbDevice);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
final DevicePrefs devicePreferences = GBApplication.getDevicePrefs(gbDevice);
final SharedPreferences.Editor editor = devicePreferences.getPreferences().edit();
// #5414 - Some old Android versions misbehave
editor.putBoolean(DeviceSettingsPreferenceConst.PREF_CONNECTION_FORCE_LEGACY_GATT, true);
editor.apply();
}
return gbDevice;
}
@@ -93,6 +93,7 @@ public final class BtLEQueue implements Thread.UncaughtExceptionHandler {
private final boolean mImplicitGattCallbackModify;
private final boolean mSendWriteRequestResponse;
private final boolean connectionForceLegacyGatt;
private final Thread mDispatchThread;
private final HandlerThread mReceiverThread;
private final Handler mReceiverHandler;
@@ -224,6 +225,8 @@ public final class BtLEQueue implements Thread.UncaughtExceptionHandler {
mPauseTransaction = false;
mSendWriteRequestResponse = deviceSupport.getSendWriteRequestResponse();
mSupportedServerServices = supportedServerServices;
// #5414 - some older android versions misbehave with the new constructor
connectionForceLegacyGatt = deviceSupport.getDevicePrefs().getConnectionForceLegacyGatt();
long threadIdx = THREAD_COUNTER.getAndIncrement();
@@ -240,7 +243,7 @@ public final class BtLEQueue implements Thread.UncaughtExceptionHandler {
mDispatchThread.start();
// 4) handler thread ensure serial processing and informative thread name in the log
if(GBApplication.isRunningOreoOrLater()){
if(GBApplication.isRunningOreoOrLater() && !connectionForceLegacyGatt){
mReceiverThread = new HandlerThread("BtLEQueue_" + threadIdx + "_in");
mReceiverThread.setUncaughtExceptionHandler(this);
mReceiverThread.start();
@@ -335,7 +338,7 @@ public final class BtLEQueue implements Thread.UncaughtExceptionHandler {
// connectGatt with true doesn't really work ;( too often connection problems
if (GBApplication.isRunningOreoOrLater()){
if (GBApplication.isRunningOreoOrLater() && !connectionForceLegacyGatt) {
mBluetoothGatt = remoteDevice.connectGatt(mContext, false,
internalGattCallback, BluetoothDevice.TRANSPORT_LE,
BluetoothDevice.PHY_LE_CODED_MASK, mReceiverHandler);
@@ -23,6 +23,7 @@ import java.util.Locale;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
import android.content.SharedPreferences;
import android.os.Build;
import android.text.format.DateFormat;
import androidx.annotation.NonNull;
@@ -127,6 +128,10 @@ public class DevicePrefs extends Prefs {
return getBoolean(PREF_CONNECTION_PRIORITY_LOW_POWER, false);
}
public boolean getConnectionForceLegacyGatt() {
return getBoolean(PREF_CONNECTION_FORCE_LEGACY_GATT, Build.VERSION.SDK_INT < Build.VERSION_CODES.Q);
}
public DeviceCoordinator.ConnectionType getForcedConnectionTypeFromPrefs() {
final String connTypePref = getString(DeviceSettingsPreferenceConst.PREF_FORCE_CONNECTION_TYPE, "BOTH");
+2
View File
@@ -482,6 +482,8 @@
<string name="pref_summary_notifications_and_calls_title_shake_reject">Duplicates watch button action</string>
<string name="connection_priority_low_power_title">Request low power</string>
<string name="connection_priority_low_power_summary">Reduce Bluetooth priority and data rate connection parameters.</string>
<string name="connection_force_legacy_gatt_title">Force legacy GATT</string>
<string name="connection_force_legacy_gatt_summary">Prevent issues on old Android versions, but might introduce race conditions</string>
<!-- Device Settings - Device Settings - Used in devicesettings_watchxplus.xml -->
<string name="pref_header_device_spec_settings">Device settings</string>
<string name="pref_title_device_spec_settings_force_time">Force synchronize time</string>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_bluetooth"
android:key="connection_force_legacy_gatt"
android:layout="@layout/preference_checkbox"
android:summary="@string/connection_force_legacy_gatt_summary"
android:title="@string/connection_force_legacy_gatt_title" />
</PreferenceScreen>