From f8aa4565495f06d2fc88629533ff8b06fc470e40 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Thu, 29 Jan 2026 18:17:15 +0100 Subject: [PATCH] Extract SensorHandler from GainManager for re-use. --- .../io/file/importer/ExportImportTest.java | 4 +- .../TrackRecordingServiceRecordingTest.java | 2 +- .../opentracks/sensors/GainManager.java | 141 +++++------------- .../opentracks/sensors/SensorHandler.java | 126 ++++++++++++++++ .../opentracks/sensors/SensorManager.java | 9 +- .../opentracks/sensors/SensorType.java | 4 +- .../opentracks/sensors/driver/Driver.java | 2 + .../opentracks/settings/PreferencesUtils.java | 6 +- 8 files changed, 178 insertions(+), 116 deletions(-) create mode 100644 src/main/java/de/dennisguse/opentracks/sensors/SensorHandler.java diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java index f0c455c67..43bcbc68d 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java @@ -725,7 +725,7 @@ public class ExportImportTest { SensorManager sensorManager = trackPointCreator.getSensorManager(); if (altitudeGain == null) { - sensorManager.getAltitudeSumManager().setAggregatorBarometer(new AggregatorBarometer("test", null)); + sensorManager.getAltitudeSumManager().setAggregator(new AggregatorBarometer("test", null)); return; } @@ -741,7 +741,7 @@ public class ExportImportTest { return true; } }; - sensorManager.getAltitudeSumManager().setAggregatorBarometer(aggregatorBarometer); + sensorManager.getAltitudeSumManager().setAggregator(aggregatorBarometer); } private void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) { diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java index d8a8e7686..3eea9229e 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java @@ -962,7 +962,7 @@ public class TrackRecordingServiceRecordingTest { } private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) { - trackPointCreator.getSensorManager().getAltitudeSumManager().setAggregatorBarometer(new AggregatorBarometer("", "") { + trackPointCreator.getSensorManager().getAltitudeSumManager().setAggregator(new AggregatorBarometer("", "") { @Override public boolean hasReceivedData() { return true; diff --git a/src/main/java/de/dennisguse/opentracks/sensors/GainManager.java b/src/main/java/de/dennisguse/opentracks/sensors/GainManager.java index 1f4e0e880..8aa136bc1 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/GainManager.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/GainManager.java @@ -1,132 +1,69 @@ package de.dennisguse.opentracks.sensors; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Handler; -import android.util.Log; +import androidx.annotation.NonNull; +import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.AtmosphericPressure; import de.dennisguse.opentracks.sensors.driver.BarometerInternal; import de.dennisguse.opentracks.sensors.driver.Driver; -import de.dennisguse.opentracks.sensors.driver.DriverObserver; import de.dennisguse.opentracks.sensors.driver.DriverObserver0; import de.dennisguse.opentracks.sensors.sensorData.Aggregator; import de.dennisguse.opentracks.sensors.sensorData.AggregatorBarometer; -import de.dennisguse.opentracks.settings.PreferencesUtils; /** * Estimates the altitude gain and altitude loss using the device's pressure sensor (i.e., barometer). */ //TODO Rename class -public class GainManager implements DriverObserver { - - private static final String TAG = GainManager.class.getSimpleName(); - - - private final SensorManager sensorManager; - - private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> connect(); - - private Context context; - private Handler handler; - private Driver driver; - - private AggregatorBarometer aggregatorBarometer; +public class GainManager extends SensorHandler { public GainManager(SensorManager sensorManager) { - this.sensorManager = sensorManager; - } - - public void start(Context context, Handler handler) { - this.context = context; - this.handler = handler; - PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); - } - - public void stop() { - Log.d(TAG, "Stop"); - this.context = null; - this.handler = null; - PreferencesUtils.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); - - disconnect(); - } - - @Deprecated - public AggregatorBarometer getAggregatorBarometer() { - return aggregatorBarometer; - } - - @Deprecated - public void setAggregatorBarometer(AggregatorBarometer aggregatorBarometer) { - this.aggregatorBarometer = aggregatorBarometer; - } - - private void connect() { - disconnect(); - - String address = PreferencesUtils.getBarometerSensorAddress(); - switch (PreferencesUtils.getSensorType(address)) { - case NONE -> { - return; - } - case INTERNAL -> driver = new BarometerInternal(this); - case REMOTE -> driver = - new BluetoothConnectionManager( - BluetoothUtils.getAdapter(context), - new DriverObserver0() { - @Override - public void onConnect(Aggregator emptySensorData) { - GainManager.this.onConnect(); - } - - @Override - public void onDisconnect(Aggregator emptySensorData) { - GainManager.this.onDisconnect(); - } - - @Override - public void onRemove(Aggregator emptySensorData) { - GainManager.this.onRemove(); - } - - @Override - public void onChange(Record value) { - onData((AtmosphericPressure) value); - } - }, - new BluetoothHandlerBarometricPressure() - ); - default -> throw new RuntimeException("Not implemented"); - } - - driver.connect(context, handler, address); - } - - private void disconnect() { - if (driver == null) return; - - driver.disconnect(); - driver = null; + super(sensorManager); } @Override - public void onConnect() { - this.aggregatorBarometer = new AggregatorBarometer("", null); + protected int getSensorPreferenceKey() { + return R.string.settings_sensor_bluetooth_pressure_key; } + @NonNull @Override - public void onDisconnect() { - this.aggregatorBarometer.resetAggregated(); + protected Driver createDriverInternal() { + return new BarometerInternal(driverObserver); } + @NonNull @Override - public void onData(AtmosphericPressure value) { - this.aggregatorBarometer.add(sensorManager.getNow(), value); + protected Driver createDriverBluetooth(String address) { + return new BluetoothConnectionManager( + BluetoothUtils.getAdapter(getContext()), + new DriverObserver0() { + @Override + public void onConnect(Aggregator emptySensorData) { + driverObserver.onConnect(); + } + + @Override + public void onDisconnect(Aggregator emptySensorData) { + driverObserver.onDisconnect(); + } + + @Override + public void onRemove(Aggregator emptySensorData) { + driverObserver.onRemove(); + } + + @Override + public void onChange(Record value) { + driverObserver.onData((AtmosphericPressure) value); + } + }, + new BluetoothHandlerBarometricPressure() + ); } + @NonNull @Override - public void onRemove() { - this.aggregatorBarometer = null; + public Aggregator createAggregator() { + return new AggregatorBarometer("", null); } } diff --git a/src/main/java/de/dennisguse/opentracks/sensors/SensorHandler.java b/src/main/java/de/dennisguse/opentracks/sensors/SensorHandler.java new file mode 100644 index 000000000..32cbf1d7e --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/sensors/SensorHandler.java @@ -0,0 +1,126 @@ +package de.dennisguse.opentracks.sensors; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Handler; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import de.dennisguse.opentracks.sensors.driver.Driver; +import de.dennisguse.opentracks.sensors.driver.DriverObserver; +import de.dennisguse.opentracks.sensors.sensorData.Aggregator; +import de.dennisguse.opentracks.settings.PreferencesUtils; + + +public abstract class SensorHandler { + + private final SensorManager sensorManager; + + private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> connect(); + + private Context context; + private Handler handler; + private Driver driver; + + private Aggregator aggregator; + + protected final DriverObserver driverObserver = new DriverObserver() { + @Override + public void onConnect() { + SensorHandler.this.aggregator = createAggregator(); + } + + @Override + public void onDisconnect() { + SensorHandler.this.aggregator.resetAggregated(); + } + + @Override + public void onData(T value) { + SensorHandler.this.aggregator.add(sensorManager.getNow(), value); + sensorManager.onChange(); + } + + @Override + public void onRemove() { + SensorHandler.this.aggregator = null; + } + }; + + + protected SensorHandler(SensorManager sensorManager) { + this.sensorManager = sensorManager; + } + + //TODO Do we really need start and stop? + void start(Context context, Handler handler) { + this.context = context; + this.handler = handler; + PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); + } + + void stop() { + this.context = null; + this.handler = null; + PreferencesUtils.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); + + disconnect(); + } + + void connect() { + disconnect(); + + String address = PreferencesUtils.getString(getSensorPreferenceKey(), PreferencesUtils.getBluetoothSensorAddressNone()); + + switch (PreferencesUtils.getSensorType(address)) { + case NONE -> { + return; + } + case INTERNAL -> { + driver = createDriverInternal(); + } + case REMOTE -> { + driver = createDriverBluetooth(address); + } + default -> throw new UnsupportedOperationException(); + } + + driver.connect(context, handler, address); + } + + void disconnect() { + if (driver == null) return; + + driver.disconnect(); + driver = null; + } + + @NonNull + protected Driver createDriverInternal() { + throw new RuntimeException("Not implemented"); + } + + @NonNull + protected Driver createDriverBluetooth(String address) { + throw new RuntimeException("Not implemented"); + } + + @NonNull + protected abstract Aggregator createAggregator(); + + protected Context getContext() { + return context; + } + + //TODO Try to keep aggregator private. + Aggregator getAggregator() { + return aggregator; + } + + //TODO REMOVE + @VisibleForTesting + public void setAggregator(Aggregator aggregator) { + this.aggregator = aggregator; + } +} diff --git a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java index f8d2d4250..3e1f78276 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java @@ -84,10 +84,11 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange this.cyclingPowerManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerCyclingPower()); this.runningSpeedAndCadenceManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerRunningSpeedAndCadence()); + altitudeSumManager.start(context, handler); + onSharedPreferenceChanged(null, null); gpsManager.start(context, handler); - altitudeSumManager.start(context, handler); } public void stop() { @@ -137,7 +138,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange if (cyclingDistanceSpeed != null) cyclingDistanceSpeed.resetAggregated(); if (cyclingPower != null) cyclingPower.resetAggregated(); if (runningDistanceSpeedCadence != null) runningDistanceSpeedCadence.resetAggregated(); - if (altitudeSumManager.getAggregatorBarometer() != null) altitudeSumManager.getAggregatorBarometer().resetAggregated(); + if (altitudeSumManager.getAggregator() != null) altitudeSumManager.getAggregator().resetAggregated(); if (gpsManager.getAggregatorGPS() != null) gpsManager.getAggregatorGPS().resetAggregated(); } @@ -355,7 +356,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange //TODO This is to ExportImportTest alive; refactor test. if (this.altitudeSumManager != null) { - this.altitudeSumManager.setAggregatorBarometer(null); + this.altitudeSumManager.setAggregator(null); } if (this.gpsManager != null) { this.gpsManager.setAggregatorGPS(); @@ -364,7 +365,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange public SensorDataSet getSensorDataSet(Instant now) { AggregatorGPS gps = gpsManager.getAggregatorGPS(); - AggregatorBarometer barometer = altitudeSumManager.getAggregatorBarometer(); + AggregatorBarometer barometer = (AggregatorBarometer) altitudeSumManager.getAggregator(); return new SensorDataSet( gps != null && gps.hasReceivedData() ? gps.getAggregatedValueWithSensorName(now) : new SensorData<>(Position.of(now), ""), diff --git a/src/main/java/de/dennisguse/opentracks/sensors/SensorType.java b/src/main/java/de/dennisguse/opentracks/sensors/SensorType.java index 9fefe5195..2a64246e2 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/SensorType.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/SensorType.java @@ -1,8 +1,8 @@ package de.dennisguse.opentracks.sensors; public enum SensorType { - NONE("NONE"), - INTERNAL("INTERNAL"), + NONE("NONE"), //TODO Use R.string.sensor_type_value_none + INTERNAL("INTERNAL"), //TODO Use R.string.sensor_type_value_none //NOTE: preferenceValue of REMOTE should not be used anywhere. REMOTE("*"); diff --git a/src/main/java/de/dennisguse/opentracks/sensors/driver/Driver.java b/src/main/java/de/dennisguse/opentracks/sensors/driver/Driver.java index 6aac465b5..bc5628393 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/driver/Driver.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/driver/Driver.java @@ -4,6 +4,8 @@ import android.content.Context; import android.os.Handler; public interface Driver { + + //TODO Address is optional for internal drivers. Move address to driver instantiation. void connect(Context context, Handler handler, String address); //TODO Remove from interface? diff --git a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java index 3854035f7..4e2175eb7 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java @@ -253,7 +253,7 @@ public class PreferencesUtils { return isReportSpeed(track.activityTypeLocalized()); } - private static String getBluetoothSensorAddressNone() { + public static String getBluetoothSensorAddressNone() { return SensorType.NONE.getPreferenceValue(); } @@ -264,10 +264,6 @@ public class PreferencesUtils { .orElse(SensorType.REMOTE); } - public static String getBarometerSensorAddress() { - return getString(R.string.settings_sensor_bluetooth_pressure_key, getBluetoothSensorAddressNone()); - } - public static String getBluetoothHeartRateSensorAddress() { return getString(R.string.settings_sensor_bluetooth_heart_rate_key, getBluetoothSensorAddressNone()); }