Merge pull request #1461 from OpenTracksApp/refactorSensor

Refactor: unify the internal sensor handling.
This commit is contained in:
Dennis Guse
2023-03-28 21:08:08 +02:00
committed by GitHub
19 changed files with 180 additions and 157 deletions
@@ -166,7 +166,7 @@ public class ExportImportTest {
trackPointCreator.setClock("2020-02-02T02:02:18Z"); trackPointCreator.setClock("2020-02-02T02:02:18Z");
BluetoothRemoteSensorManager mockRemoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class); BluetoothRemoteSensorManager mockRemoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class);
trackPointCreator.setRemoteSensorManager(mockRemoteSensorManager); trackPointCreator.getSensorManager().setBluetoothSensorManager(mockRemoteSensorManager);
service.endCurrentTrack(); service.endCurrentTrack();
trackPointCreator.setClock("2020-02-02T02:03:20Z"); trackPointCreator.setClock("2020-02-02T02:03:20Z");
@@ -179,7 +179,7 @@ public class ExportImportTest {
sendLocation(trackPointCreator, "2020-02-02T02:03:23Z", 3, 16.001, 10, 27, 15, 10, 0); sendLocation(trackPointCreator, "2020-02-02T02:03:23Z", 3, 16.001, 10, 27, 15, 10, 0);
trackPointCreator.setClock("2020-02-02T02:03:24Z"); trackPointCreator.setClock("2020-02-02T02:03:24Z");
trackPointCreator.setRemoteSensorManager(mockRemoteSensorManager); trackPointCreator.getSensorManager().setBluetoothSensorManager(mockRemoteSensorManager);
service.endCurrentTrack(); service.endCurrentTrack();
Track track = contentProviderUtils.getTrack(trackId); Track track = contentProviderUtils.getTrack(trackId);
@@ -521,12 +521,12 @@ public class ExportImportTest {
sensorDataSet.fillTrackPoint(trackPoint); sensorDataSet.fillTrackPoint(trackPoint);
return sensorDataSet; return sensorDataSet;
}); });
trackPointCreator.setRemoteSensorManager(remoteSensorManager); trackPointCreator.getSensorManager().setBluetoothSensorManager(remoteSensorManager);
trackPointCreator.onChange(new SensorDataSet()); trackPointCreator.onChange(new SensorDataSet());
} }
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) { private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
AltitudeSumManager altitudeSumManager = trackPointCreator.getAltitudeSumManager(); AltitudeSumManager altitudeSumManager = trackPointCreator.getSensorManager().getAltitudeSumManager();
altitudeSumManager.setAltitudeGain_m(altitudeGain); altitudeSumManager.setAltitudeGain_m(altitudeGain);
altitudeSumManager.setAltitudeLoss_m(altitudeGain); altitudeSumManager.setAltitudeLoss_m(altitudeGain);
} }
@@ -45,6 +45,8 @@ import de.dennisguse.opentracks.stats.TrackStatistics;
/** /**
* Tests insert location. * Tests insert location.
* Note: on API23, the TrackRecordingService may not be stopped properly before the next test.
* So, if something fails, subsequent tests may be affected.
*/ */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class TrackRecordingServiceTestRecording { public class TrackRecordingServiceTestRecording {
@@ -112,7 +114,7 @@ public class TrackRecordingServiceTestRecording {
String startTime = "2020-02-02T02:02:02Z"; String startTime = "2020-02-02T02:02:02Z";
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// then // then
assertEquals(new TrackStatistics(startTime, startTime, 0, 0, 0, 0, null, null) assertEquals(new TrackStatistics(startTime, startTime, 0, 0, 0, 0, null, null)
@@ -149,7 +151,7 @@ public class TrackRecordingServiceTestRecording {
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String pauseTime = "2020-02-02T02:02:03Z"; String pauseTime = "2020-02-02T02:02:03Z";
@@ -195,7 +197,7 @@ public class TrackRecordingServiceTestRecording {
String starTime = "2020-02-02T02:02:02Z"; String starTime = "2020-02-02T02:02:02Z";
trackPointCreator.setClock(starTime); trackPointCreator.setClock(starTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
String pauseTime = "2020-02-02T02:02:03Z"; String pauseTime = "2020-02-02T02:02:03Z";
trackPointCreator.setClock(pauseTime); trackPointCreator.setClock(pauseTime);
@@ -227,7 +229,7 @@ public class TrackRecordingServiceTestRecording {
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
String stopTime = "2020-02-02T02:02:03Z"; String stopTime = "2020-02-02T02:02:03Z";
trackPointCreator.setClock(stopTime); trackPointCreator.setClock(stopTime);
@@ -237,7 +239,7 @@ public class TrackRecordingServiceTestRecording {
String resumeTime = "2020-02-02T02:02:04Z"; String resumeTime = "2020-02-02T02:02:04Z";
trackPointCreator.setClock(resumeTime); trackPointCreator.setClock(resumeTime);
service.resumeTrack(trackId); service.resumeTrack(trackId);
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// then // then
new TrackPointAssert().assertEquals(List.of( new TrackPointAssert().assertEquals(List.of(
@@ -258,12 +260,13 @@ public class TrackRecordingServiceTestRecording {
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getRemoteSensorManager(); BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getSensorManager().getBluetoothSensorManager();
// when // when
String sensor1 = "2020-02-02T02:02:03Z"; String sensor1 = "2020-02-02T02:02:03Z";
trackPointCreator.setClock(sensor1); trackPointCreator.setClock(sensor1);
remoteSensorManager.onChanged(new SensorDataHeartRate("", "", HeartRate.of(5))); //Should be ignored remoteSensorManager.onChanged(new SensorDataHeartRate("", "", HeartRate.of(5))); //Should be ignored
String sensor3 = "2020-02-02T02:02:13Z"; String sensor3 = "2020-02-02T02:02:13Z";
@@ -297,7 +300,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
@@ -371,7 +374,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -436,7 +439,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -500,7 +503,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -564,7 +567,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -652,7 +655,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -702,7 +705,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -748,7 +751,7 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
// when // when
String gps1 = "2020-02-02T02:02:03Z"; String gps1 = "2020-02-02T02:02:03Z";
@@ -812,8 +815,8 @@ public class TrackRecordingServiceTestRecording {
TrackPointCreator trackPointCreator = service.getTrackPointCreator(); TrackPointCreator trackPointCreator = service.getTrackPointCreator();
trackPointCreator.setClock(startTime); trackPointCreator.setClock(startTime);
Track.Id trackId = service.startNewTrack(); Track.Id trackId = service.startNewTrack();
trackPointCreator.setAltitudeSumManager(altitudeSumManager); trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getRemoteSensorManager(); BluetoothRemoteSensorManager remoteSensorManager = trackPointCreator.getSensorManager().getBluetoothSensorManager();
// when // when
String sensor1 = "2020-02-02T02:02:03Z"; String sensor1 = "2020-02-02T02:02:03Z";
@@ -1,17 +1,12 @@
package de.dennisguse.opentracks.services; package de.dennisguse.opentracks.services;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.location.Location; import android.location.Location;
import androidx.test.rule.ServiceTestRule; import androidx.test.rule.ServiceTestRule;
import org.mockito.Mockito;
import java.time.Clock;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator; import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -24,15 +19,6 @@ public class TrackRecordingServiceTestUtils {
public static void resetService(ServiceTestRule mServiceRule, Context context) throws TimeoutException { public static void resetService(ServiceTestRule mServiceRule, Context context) throws TimeoutException {
// Let's use default values. // Let's use default values.
PreferencesUtils.clear(); PreferencesUtils.clear();
// Reset service (if some previous test failed)
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
.getService();
BluetoothRemoteSensorManager remoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class);
service.getTrackPointCreator().setRemoteSensorManager(remoteSensorManager);
service.getTrackPointCreator().setClock(Clock.systemUTC());
service.endCurrentTrack();
} }
static void sendGPSLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, long speed) { static void sendGPSLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, long speed) {
@@ -26,7 +26,7 @@ import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class GPSHandlerTest { public class GPSManagerTest {
private final Context context = ApplicationProvider.getApplicationContext(); private final Context context = ApplicationProvider.getApplicationContext();
@@ -34,7 +34,7 @@ public class GPSHandlerTest {
private TrackPointCreator trackPointCreator; private TrackPointCreator trackPointCreator;
@InjectMocks @InjectMocks
private GPSHandler locationHandler; private GPSManager locationHandler;
@BeforeClass @BeforeClass
public static void preSetUp() { public static void preSetUp() {
@@ -50,7 +50,7 @@ public class GPSHandlerTest {
Mockito.when(trackPointCreator.createNow()) Mockito.when(trackPointCreator.createNow())
.thenReturn(Instant.now()); .thenReturn(Instant.now());
locationHandler.onStart(context, new Handler()); locationHandler.start(context, new Handler());
} }
/** /**
@@ -25,7 +25,7 @@ public class TrackPointCreatorTest {
private TrackPointCreator.Callback server; private TrackPointCreator.Callback server;
@Mock @Mock
private GPSHandler locationHandler; private GPSManager locationHandler;
private TrackPointCreator subject; private TrackPointCreator subject;
@@ -40,9 +40,9 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorData;
* Manages connection to a Bluetooth LE sensor and subscribes for onChange-notifications. * Manages connection to a Bluetooth LE sensor and subscribes for onChange-notifications.
* Also parses the transferred data into {@link SensorDataObserver}. * Also parses the transferred data into {@link SensorDataObserver}.
*/ */
public abstract class BluetoothConnectionManager<DataType> { public abstract class AbstractBluetoothConnectionManager<DataType> {
private static final String TAG = BluetoothConnectionManager.class.getSimpleName(); private static final String TAG = AbstractBluetoothConnectionManager.class.getSimpleName();
private final SensorDataObserver observer; private final SensorDataObserver observer;
@@ -136,12 +136,12 @@ public abstract class BluetoothConnectionManager<DataType> {
} }
}; };
BluetoothConnectionManager(ServiceMeasurementUUID serviceUUUID, SensorDataObserver observer) { AbstractBluetoothConnectionManager(ServiceMeasurementUUID serviceUUUID, SensorDataObserver observer) {
this.serviceMeasurementUUIDs = List.of(serviceUUUID); this.serviceMeasurementUUIDs = List.of(serviceUUUID);
this.observer = observer; this.observer = observer;
} }
BluetoothConnectionManager(List<ServiceMeasurementUUID> serviceUUUID, SensorDataObserver observer) { AbstractBluetoothConnectionManager(List<ServiceMeasurementUUID> serviceUUUID, SensorDataObserver observer) {
this.serviceMeasurementUUIDs = serviceUUUID; this.serviceMeasurementUUIDs = serviceUUUID;
this.observer = observer; this.observer = observer;
} }
@@ -19,7 +19,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
/** /**
* Estimates the altitude gain and altitude loss using the device's pressure sensor (i.e., barometer). * Estimates the altitude gain and altitude loss using the device's pressure sensor (i.e., barometer).
*/ */
public class AltitudeSumManager implements SensorEventListener { public class AltitudeSumManager implements SensorConnector, SensorEventListener {
private static final String TAG = AltitudeSumManager.class.getSimpleName(); private static final String TAG = AltitudeSumManager.class.getSimpleName();
@@ -8,11 +8,11 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
public class BluetoothRemoteSensorManagerCyclingCadence extends BluetoothConnectionManager<Cadence> { public class BluetoothConnectionManagerCyclingCadence extends AbstractBluetoothConnectionManager<Cadence> {
private static final String TAG = BluetoothRemoteSensorManagerCyclingCadence.class.getSimpleName(); private static final String TAG = BluetoothConnectionManagerCyclingCadence.class.getSimpleName();
BluetoothRemoteSensorManagerCyclingCadence(SensorDataObserver observer) { BluetoothConnectionManagerCyclingCadence(SensorDataObserver observer) {
super(BluetoothUtils.CYCLING_CADENCE, observer); super(BluetoothUtils.CYCLING_CADENCE, observer);
} }
@@ -5,9 +5,9 @@ import android.bluetooth.BluetoothGattCharacteristic;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed;
public class BluetoothRemoteSensorManagerCyclingDistanceSpeed extends BluetoothConnectionManager<SensorDataCyclingDistanceSpeed.Data> { public class BluetoothConnectionManagerCyclingDistanceSpeed extends AbstractBluetoothConnectionManager<SensorDataCyclingDistanceSpeed.Data> {
BluetoothRemoteSensorManagerCyclingDistanceSpeed(SensorDataObserver observer) { BluetoothConnectionManagerCyclingDistanceSpeed(SensorDataObserver observer) {
super(BluetoothUtils.CYCLING_SPEED_CADENCE, observer); super(BluetoothUtils.CYCLING_SPEED_CADENCE, observer);
} }
@@ -7,9 +7,9 @@ import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.models.Power; import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
public class BluetoothRemoteSensorManagerCyclingPower extends BluetoothConnectionManager<Power> { public class BluetoothConnectionManagerCyclingPower extends AbstractBluetoothConnectionManager<Power> {
BluetoothRemoteSensorManagerCyclingPower(@NonNull SensorDataObserver observer) { BluetoothConnectionManagerCyclingPower(@NonNull SensorDataObserver observer) {
super(BluetoothUtils.CYCLING_POWER, observer); super(BluetoothUtils.CYCLING_POWER, observer);
} }
@@ -7,9 +7,9 @@ import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.models.HeartRate; import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataHeartRate; import de.dennisguse.opentracks.sensors.sensorData.SensorDataHeartRate;
public class BluetoothRemoteSensorManagerHeartRate extends BluetoothConnectionManager<HeartRate> { public class BluetoothConnectionManagerHeartRate extends AbstractBluetoothConnectionManager<HeartRate> {
BluetoothRemoteSensorManagerHeartRate(@NonNull SensorDataObserver observer) { BluetoothConnectionManagerHeartRate(@NonNull SensorDataObserver observer) {
super(BluetoothUtils.HEARTRATE, observer); super(BluetoothUtils.HEARTRATE, observer);
} }
@@ -6,9 +6,9 @@ import androidx.annotation.NonNull;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning; import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
public class BluetoothRemoteSensorManagerRunningSpeedAndCadence extends BluetoothConnectionManager<SensorDataRunning.Data> { public class BluetoothConnectionRunningSpeedAndCadence extends AbstractBluetoothConnectionManager<SensorDataRunning.Data> {
BluetoothRemoteSensorManagerRunningSpeedAndCadence(@NonNull SensorDataObserver observer) { BluetoothConnectionRunningSpeedAndCadence(@NonNull SensorDataObserver observer) {
super(BluetoothUtils.RUNNING_SPEED_CADENCE, observer); super(BluetoothUtils.RUNNING_SPEED_CADENCE, observer);
} }
@@ -52,7 +52,7 @@ import de.dennisguse.opentracks.util.PermissionRequester;
* *
* @author Sandor Dornbush * @author Sandor Dornbush
*/ */
public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.SensorDataObserver { public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBluetoothConnectionManager.SensorDataObserver {
private static final String TAG = BluetoothRemoteSensorManager.class.getSimpleName(); private static final String TAG = BluetoothRemoteSensorManager.class.getSimpleName();
@@ -65,15 +65,15 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
private Distance preferenceWheelCircumference; private Distance preferenceWheelCircumference;
private final BluetoothRemoteSensorManagerHeartRate heartRate = new BluetoothRemoteSensorManagerHeartRate(this); private final BluetoothConnectionManagerHeartRate heartRate = new BluetoothConnectionManagerHeartRate(this);
private final BluetoothRemoteSensorManagerCyclingCadence cyclingCadence = new BluetoothRemoteSensorManagerCyclingCadence(this); private final BluetoothConnectionManagerCyclingCadence cyclingCadence = new BluetoothConnectionManagerCyclingCadence(this);
private final BluetoothRemoteSensorManagerCyclingDistanceSpeed cyclingSpeed = new BluetoothRemoteSensorManagerCyclingDistanceSpeed(this); private final BluetoothConnectionManagerCyclingDistanceSpeed cyclingSpeed = new BluetoothConnectionManagerCyclingDistanceSpeed(this);
private final BluetoothRemoteSensorManagerCyclingPower cyclingPower = new BluetoothRemoteSensorManagerCyclingPower(this); private final BluetoothConnectionManagerCyclingPower cyclingPower = new BluetoothConnectionManagerCyclingPower(this);
private final BluetoothRemoteSensorManagerRunningSpeedAndCadence runningSpeedAndCadence = new BluetoothRemoteSensorManagerRunningSpeedAndCadence(this); private final BluetoothConnectionRunningSpeedAndCadence runningSpeedAndCadence = new BluetoothConnectionRunningSpeedAndCadence(this);
private final SensorDataSet sensorDataSet = new SensorDataSet(); private final SensorDataSet sensorDataSet = new SensorDataSet();
private final SensorDataSetChangeObserver observer; private final SensorManager.SensorDataSetChangeObserver observer;
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override @Override
@@ -114,21 +114,23 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
} }
}; };
public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @NonNull SensorDataSetChangeObserver observer) { public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @NonNull SensorManager.SensorDataSetChangeObserver observer) {
this.context = context; this.context = context;
this.handler = handler; this.handler = handler;
this.observer = observer; this.observer = observer;
bluetoothAdapter = BluetoothUtils.getAdapter(context); bluetoothAdapter = BluetoothUtils.getAdapter(context);
} }
public void start() { @Override
public void start(Context context, Handler handler) {
started = true; started = true;
//Registering triggers connection startup //Registering triggers connection startup
PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
} }
public synchronized void stop() { @Override
public synchronized void stop(Context context) {
heartRate.disconnect(); heartRate.disconnect();
cyclingCadence.disconnect(); cyclingCadence.disconnect();
cyclingSpeed.disconnect(); cyclingSpeed.disconnect();
@@ -145,7 +147,7 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
return bluetoothAdapter != null && bluetoothAdapter.isEnabled(); return bluetoothAdapter != null && bluetoothAdapter.isEnabled();
} }
private synchronized void connect(BluetoothConnectionManager<?> connectionManager, String address) { private synchronized void connect(AbstractBluetoothConnectionManager<?> connectionManager, String address) {
if (!isEnabled()) { if (!isEnabled()) {
Log.w(TAG, "Bluetooth not enabled."); Log.w(TAG, "Bluetooth not enabled.");
return; return;
@@ -230,8 +232,4 @@ public class BluetoothRemoteSensorManager implements BluetoothConnectionManager.
public Handler getHandler() { public Handler getHandler() {
return handler; return handler;
} }
public interface SensorDataSetChangeObserver {
void onChange(SensorDataSet sensorDataSet);
}
} }
@@ -0,0 +1,11 @@
package de.dennisguse.opentracks.sensors;
import android.content.Context;
import android.os.Handler;
public interface SensorConnector {
void start(Context context, Handler handler);
void stop(Context context);
}
@@ -0,0 +1,85 @@
package de.dennisguse.opentracks.sensors;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorData;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
public class SensorManager {
private static final String TAG = SensorManager.class.getSimpleName();
private BluetoothRemoteSensorManager bluetoothSensorManager;
private AltitudeSumManager altitudeSumManager;
public SensorManager(Context context, Handler handler, SensorDataSetChangeObserver observer) {
bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, observer);
altitudeSumManager = new AltitudeSumManager();
}
public void start(Context context, Handler handler) {
bluetoothSensorManager.start(context, handler);
altitudeSumManager.start(context, handler);
}
public void stop(Context context) {
if (bluetoothSensorManager != null) {
bluetoothSensorManager.stop(context);
bluetoothSensorManager = null;
}
if (altitudeSumManager != null) {
altitudeSumManager.stop(context);
altitudeSumManager = null;
}
}
public SensorDataSet fill(TrackPoint trackPoint) {
altitudeSumManager.fill(trackPoint);
return bluetoothSensorManager.fill(trackPoint);
}
public void reset() {
if (bluetoothSensorManager == null || altitudeSumManager == null) {
Log.d(TAG, "No recording running and no reset necessary.");
return;
}
bluetoothSensorManager.reset();
altitudeSumManager.reset();
}
@Deprecated
@VisibleForTesting
public BluetoothRemoteSensorManager getBluetoothSensorManager() {
return bluetoothSensorManager;
}
@Deprecated
@VisibleForTesting
public void setBluetoothSensorManager(BluetoothRemoteSensorManager remoteSensorManager) {
this.bluetoothSensorManager = remoteSensorManager;
}
@Deprecated
@VisibleForTesting
public AltitudeSumManager getAltitudeSumManager() {
return altitudeSumManager;
}
@Deprecated
@VisibleForTesting
public void setAltitudeSumManager(AltitudeSumManager altitudeSumManager) {
this.altitudeSumManager = altitudeSumManager;
}
@Deprecated
public interface SensorDataSetChangeObserver {
void onChange(SensorDataSet sensorDataSet);
}
}
@@ -1,7 +1,6 @@
package de.dennisguse.opentracks.sensors.sensorData; package de.dennisguse.opentracks.sensors.sensorData;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import java.time.Instant; import java.time.Instant;
@@ -32,16 +31,6 @@ public abstract class SensorData<T> {
this.time = time; this.time = time;
} }
@NonNull
public String getSensorAddress() {
return sensorAddress;
}
@Nullable
public String getSensorName() {
return sensorName;
}
public String getSensorNameOrAddress() { public String getSensorNameOrAddress() {
return sensorName != null ? sensorName : sensorAddress; return sensorName != null ? sensorName : sensorAddress;
} }
@@ -111,7 +111,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
egm2008CorrectionManager = new EGM2008CorrectionManager(); egm2008CorrectionManager = new EGM2008CorrectionManager();
trackRecordingManager = new TrackRecordingManager(this); trackRecordingManager = new TrackRecordingManager(this);
trackRecordingManager.start(); trackRecordingManager.start();
trackPointCreator = new TrackPointCreator(this); trackPointCreator = new TrackPointCreator(this, this, handler);
voiceAnnouncementManager = new VoiceAnnouncementManager(this); voiceAnnouncementManager = new VoiceAnnouncementManager(this);
notificationManager = new TrackRecordingServiceNotificationManager(this); notificationManager = new TrackRecordingServiceNotificationManager(this);
@@ -177,7 +177,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
} }
public void resumeTrack(Track.Id trackId) { public void resumeTrack(Track.Id trackId) {
trackPointCreator.reset();
if (!trackRecordingManager.resumeExistingTrack(trackId, trackPointCreator)) { if (!trackRecordingManager.resumeExistingTrack(trackId, trackPointCreator)) {
Log.w(TAG, "Cannot resume a non-existing track."); Log.w(TAG, "Cannot resume a non-existing track.");
return; return;
@@ -20,14 +20,15 @@ import java.time.Instant;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.SensorConnector;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.LocationUtils; import de.dennisguse.opentracks.util.LocationUtils;
import de.dennisguse.opentracks.util.PermissionRequester; import de.dennisguse.opentracks.util.PermissionRequester;
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public class GPSHandler implements LocationListenerCompat, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener { public class GPSManager implements SensorConnector, LocationListenerCompat, GpsStatus.GpsStatusListener, SharedPreferences.OnSharedPreferenceChangeListener {
private final String TAG = GPSHandler.class.getSimpleName(); private final String TAG = GPSManager.class.getSimpleName();
public static final String LOCATION_PROVIDER = LocationManager.GPS_PROVIDER; public static final String LOCATION_PROVIDER = LocationManager.GPS_PROVIDER;
@@ -40,11 +41,11 @@ public class GPSHandler implements LocationListenerCompat, GpsStatus.GpsStatusLi
private Duration gpsInterval; private Duration gpsInterval;
private Distance thresholdHorizontalAccuracy; private Distance thresholdHorizontalAccuracy;
public GPSHandler(TrackPointCreator trackPointCreator) { public GPSManager(TrackPointCreator trackPointCreator) {
this.trackPointCreator = trackPointCreator; this.trackPointCreator = trackPointCreator;
} }
public void onStart(@NonNull Context context, @NonNull Handler handler) { public void start(@NonNull Context context, @NonNull Handler handler) {
this.context = context; this.context = context;
this.handler = handler; this.handler = handler;
@@ -61,7 +62,7 @@ public class GPSHandler implements LocationListenerCompat, GpsStatus.GpsStatusLi
@SuppressWarnings({"MissingPermission"}) @SuppressWarnings({"MissingPermission"})
//TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates. //TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates.
public void onStop() { public void stop(Context context) {
if (locationManager != null && context != null) { if (locationManager != null && context != null) {
if (PermissionRequester.GPS.hasPermission(context)) { if (PermissionRequester.GPS.hasPermission(context)) {
LocationManagerCompat.removeUpdates(locationManager, this); LocationManagerCompat.removeUpdates(locationManager, this);
@@ -16,14 +16,13 @@ import java.time.ZoneId;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.AltitudeSumManager; import de.dennisguse.opentracks.sensors.SensorManager;
import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet; import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
/** /**
* Creates TrackPoints while recording by fusing data from different sensors (e.g., GNSS, barometer, BLE sensors). * Creates TrackPoints while recording by fusing data from different sensors (e.g., GNSS, barometer, BLE sensors).
*/ */
public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDataSetChangeObserver { public class TrackPointCreator implements SensorManager.SensorDataSetChangeObserver {
private static final String TAG = TrackPointCreator.class.getSimpleName(); private static final String TAG = TrackPointCreator.class.getSimpleName();
@@ -34,45 +33,34 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
@NonNull @NonNull
private Clock clock = new MonotonicClock(); private Clock clock = new MonotonicClock();
private final GPSHandler gpsHandler; private final GPSManager gpsManager;
private BluetoothRemoteSensorManager remoteSensorManager; private SensorManager sensorManager;
private AltitudeSumManager altitudeSumManager;
public TrackPointCreator(Callback service) { public TrackPointCreator(Callback service, Context context, Handler handler) {
this.service = service; this.service = service;
this.gpsHandler = new GPSHandler(this); this.gpsManager = new GPSManager(this);
this.sensorManager = new SensorManager(context, handler, this);
} }
@VisibleForTesting @VisibleForTesting
TrackPointCreator(GPSHandler gpsHandler, Callback service) { TrackPointCreator(GPSManager gpsManager, Callback service) {
this.service = service; this.service = service;
this.gpsHandler = gpsHandler; this.gpsManager = gpsManager;
} }
public synchronized void start(@NonNull Context context, @NonNull Handler handler) { public synchronized void start(@NonNull Context context, @NonNull Handler handler) {
this.context = context; this.context = context;
gpsHandler.onStart(context, handler); gpsManager.start(context, handler);
sensorManager.start(context, handler);
remoteSensorManager = new BluetoothRemoteSensorManager(context, handler, this);
altitudeSumManager = new AltitudeSumManager();
remoteSensorManager.start();
altitudeSumManager.start(context, handler);
} }
private boolean isStarted() { private boolean isStarted() {
return context != null; return context != null;
} }
public synchronized void reset() { private synchronized void reset() {
if (remoteSensorManager == null || altitudeSumManager == null) { sensorManager.reset();
Log.d(TAG, "No recording running and no reset necessary.");
return;
}
remoteSensorManager.reset();
altitudeSumManager.reset();
} }
private SensorDataSet addSensorData(TrackPoint trackPoint) { private SensorDataSet addSensorData(TrackPoint trackPoint) {
@@ -80,31 +68,12 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
Log.w(TAG, "Not started, should not be called."); Log.w(TAG, "Not started, should not be called.");
return null; return null;
} }
SensorDataSet sensorDataSet = null;
BluetoothRemoteSensorManager localRemoteSensorManager = remoteSensorManager;
if (localRemoteSensorManager != null) {
sensorDataSet = localRemoteSensorManager.fill(trackPoint);
}
AltitudeSumManager localAltitudeSumManager = altitudeSumManager;
if (localAltitudeSumManager != null) {
localAltitudeSumManager.fill(trackPoint);
}
return sensorDataSet; return sensorManager.fill(trackPoint);
} }
public synchronized void stop() { public synchronized void stop() {
gpsHandler.onStop(); gpsManager.stop(context);
if (remoteSensorManager != null) {
remoteSensorManager.stop();
remoteSensorManager = null;
}
if (altitudeSumManager != null) {
altitudeSumManager.stop(context);
altitudeSumManager = null;
}
this.context = null; this.context = null;
} }
@@ -125,7 +94,7 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
public void onNewTrackPoint(@NonNull TrackPoint trackPoint) { public void onNewTrackPoint(@NonNull TrackPoint trackPoint) {
addSensorData(trackPoint); addSensorData(trackPoint);
boolean stored = service.newTrackPoint(trackPoint, gpsHandler.getThresholdHorizontalAccuracy()); boolean stored = service.newTrackPoint(trackPoint, gpsManager.getThresholdHorizontalAccuracy());
if (stored) { if (stored) {
reset(); reset();
} }
@@ -169,26 +138,8 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
} }
@VisibleForTesting @VisibleForTesting
public AltitudeSumManager getAltitudeSumManager() { public SensorManager getSensorManager() {
return altitudeSumManager; return sensorManager;
}
@Deprecated
@VisibleForTesting
public void setAltitudeSumManager(AltitudeSumManager altitudeSumManager) {
this.altitudeSumManager = altitudeSumManager;
}
@Deprecated
@VisibleForTesting
public BluetoothRemoteSensorManager getRemoteSensorManager() {
return remoteSensorManager;
}
@Deprecated
@VisibleForTesting
public void setRemoteSensorManager(BluetoothRemoteSensorManager remoteSensorManager) {
this.remoteSensorManager = remoteSensorManager;
} }
@VisibleForTesting @VisibleForTesting
@@ -202,8 +153,8 @@ public class TrackPointCreator implements BluetoothRemoteSensorManager.SensorDat
} }
@VisibleForTesting @VisibleForTesting
public GPSHandler getGpsHandler() { public GPSManager getGpsHandler() {
return gpsHandler; return gpsManager;
} }
void sendGpsStatus(GpsStatusValue gpsStatusValue) { void sendGpsStatus(GpsStatusValue gpsStatusValue) {