Cleanup: extract RecordingData and RecordingStatus from TrackRecordingService.

This commit is contained in:
Dennis Guse
2022-01-28 18:58:42 +01:00
parent 094c97f78d
commit cf32c81035
15 changed files with 217 additions and 211 deletions
@@ -123,7 +123,7 @@ public class TrackRecordingServiceTestStateMachine {
assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue());
// when // when
service.tryStartGps(); service.tryStartSensors();
Thread.sleep(1000); Thread.sleep(1000);
// then // then
@@ -132,7 +132,7 @@ public class TrackRecordingServiceTestStateMachine {
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
// when // when
service.stopGps(true); service.stopSensors(true);
Thread.sleep(1000); Thread.sleep(1000);
// then // then
@@ -153,7 +153,7 @@ public class TrackRecordingServiceTestStateMachine {
// then // then
assertTrue(service.isRecording()); assertTrue(service.isRecording());
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue()); assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue()); assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
@@ -165,7 +165,7 @@ public class TrackRecordingServiceTestStateMachine {
// then // then
assertTrue(service.isRecording()); assertTrue(service.isRecording());
assertTrue(service.isPaused()); assertTrue(service.isPaused());
assertEquals(new TrackRecordingService.RecordingStatus(trackId, true), service.getRecordingStatusObservable().getValue()); assertEquals(new RecordingStatus(trackId, true), service.getRecordingStatusObservable().getValue());
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue()); assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue()); //TODO The GPS is kept in pause, right? Might be a bug. assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue()); //TODO The GPS is kept in pause, right? Might be a bug.
@@ -177,7 +177,7 @@ public class TrackRecordingServiceTestStateMachine {
// then // then
assertTrue(service.isRecording()); assertTrue(service.isRecording());
assertFalse(service.isPaused()); assertFalse(service.isPaused());
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue()); assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue()); assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
@@ -201,7 +201,7 @@ public class TrackRecordingServiceTestStateMachine {
// then // then
assertTrue(service.isRecording()); assertTrue(service.isRecording());
assertFalse(service.isPaused()); assertFalse(service.isPaused());
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue()); assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
Thread.sleep(1000); //TODO Figure out why we need to wait here until the update is happening Thread.sleep(1000); //TODO Figure out why we need to wait here until the update is happening
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue()); assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
@@ -252,13 +252,13 @@ public class TrackRecordingServiceTestStateMachine {
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
// when // when
service.stopGps(false); //TODO Should be ignored as service is recording service.stopSensors(false); //TODO Should be ignored as service is recording
Thread.sleep(1000); Thread.sleep(1000);
// then // then
assertTrue(service.isRecording()); assertTrue(service.isRecording());
assertFalse(service.isPaused()); assertFalse(service.isPaused());
assertEquals(new TrackRecordingService.RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue()); assertEquals(new RecordingStatus(trackId, false), service.getRecordingStatusObservable().getValue());
Thread.sleep(1000); //TODO Figure out why we need to wait here until the update is happening Thread.sleep(1000); //TODO Figure out why we need to wait here until the update is happening
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue()); assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue()); assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
@@ -22,7 +22,7 @@ import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate; import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Power; import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.stats.SensorStatistics; import de.dennisguse.opentracks.stats.SensorStatistics;
import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout; import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
@@ -39,7 +39,7 @@ public class StatisticDataBuilderTest extends TestCase {
private TrackStatistics trackStatisticsMock; private TrackStatistics trackStatisticsMock;
@Mock @Mock
private TrackRecordingService.RecordingData recordingDataMock; private RecordingData recordingDataMock;
@Mock @Mock
private SensorStatistics sensorStatisticsMock; private SensorStatistics sensorStatisticsMock;
@@ -33,6 +33,8 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import de.dennisguse.opentracks.databinding.ControllerFragmentBinding; import de.dennisguse.opentracks.databinding.ControllerFragmentBinding;
import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.ui.util.ActivityUtils; import de.dennisguse.opentracks.ui.util.ActivityUtils;
@@ -57,8 +59,8 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
private TransitionDrawable transition; private TransitionDrawable transition;
private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackRecordingService.RecordingStatus recordingStatus; private RecordingStatus recordingStatus;
private TrackRecordingService.RecordingData recordingData; private RecordingData recordingData;
private final TrackRecordingServiceConnection.Callback bindChangedCallback = service -> { private final TrackRecordingServiceConnection.Callback bindChangedCallback = service -> {
service.getRecordingStatusObservable() service.getRecordingStatusObservable()
@@ -237,7 +239,7 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
void recordStop(); void recordStop();
} }
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { private void onRecordingStatusChanged(RecordingStatus status) {
recordingStatus = status; recordingStatus = status;
viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record); viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record);
@@ -254,7 +256,7 @@ public class ControllerFragment extends Fragment implements View.OnTouchListener
viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE); viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
} }
private void onTotalTimeChanged(TrackRecordingService.RecordingData recordingData) { private void onTotalTimeChanged(RecordingData recordingData) {
this.recordingData = recordingData; this.recordingData = recordingData;
viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(this.recordingData.getTrackStatistics().getTotalTime())); viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(this.recordingData.getTrackStatistics().getTotalTime()));
@@ -58,6 +58,7 @@ import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.data.tables.TracksColumns;
import de.dennisguse.opentracks.databinding.TrackListBinding; import de.dennisguse.opentracks.databinding.TrackListBinding;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
@@ -95,7 +96,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
private boolean metricUnits = true; private boolean metricUnits = true;
private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT; private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT;
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
// Callback when an item is selected in the contextual action mode // Callback when an item is selected in the contextual action mode
private final ActivityUtils.ContextualActionModeCallback contextualActionModeCallback = new ActivityUtils.ContextualActionModeCallback() { private final ActivityUtils.ContextualActionModeCallback contextualActionModeCallback = new ActivityUtils.ContextualActionModeCallback() {
@@ -144,7 +145,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
} }
//TODO Not cool to do this in a callback that might be called more than once! //TODO Not cool to do this in a callback that might be called more than once!
service.tryStartGps(); service.tryStartSensors();
}; };
@Override @Override
@@ -300,7 +301,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
} else { } else {
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound(); TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
if (trackRecordingService != null) { if (trackRecordingService != null) {
trackRecordingService.stopGpsAndShutdown(); //TODO Handle this in TrackRecordingServiceConnection trackRecordingService.stopSensorsAndShutdown(); //TODO Handle this in TrackRecordingServiceConnection
} }
trackRecordingServiceConnection.unbindAndStop(this); trackRecordingServiceConnection.unbindAndStop(this);
} }
@@ -569,7 +570,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
updateGpsMenuItem(true, recordingStatus.isRecording()); updateGpsMenuItem(true, recordingStatus.isRecording());
} }
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { private void onRecordingStatusChanged(RecordingStatus status) {
recordingStatus = status; recordingStatus = status;
} }
} }
@@ -39,6 +39,7 @@ import de.dennisguse.opentracks.data.TrackDataHub;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.databinding.TrackRecordedBinding; import de.dennisguse.opentracks.databinding.TrackRecordedBinding;
import de.dennisguse.opentracks.fragments.StatisticsRecordedFragment; import de.dennisguse.opentracks.fragments.StatisticsRecordedFragment;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackDeleteService; import de.dennisguse.opentracks.services.TrackDeleteService;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
@@ -74,7 +75,7 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
private TrackRecordedBinding viewBinding; private TrackRecordedBinding viewBinding;
private Track.Id trackId; private Track.Id trackId;
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackRecordingServiceConnection trackRecordingServiceConnection;
@@ -299,7 +300,7 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
startPostponedEnterTransition(); startPostponedEnterTransition();
} }
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { private void onRecordingStatusChanged(RecordingStatus status) {
recordingStatus = status; recordingStatus = status;
} }
} }
@@ -29,6 +29,7 @@ import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.databinding.TrackRecordingBinding; import de.dennisguse.opentracks.databinding.TrackRecordingBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment; import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -68,7 +69,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
@Deprecated @Deprecated
private Track.Id trackId; private Track.Id trackId;
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
private final TrackRecordingServiceConnection.Callback bindChangedCallback = new TrackRecordingServiceConnection.Callback() { private final TrackRecordingServiceConnection.Callback bindChangedCallback = new TrackRecordingServiceConnection.Callback() {
@Override @Override
@@ -391,7 +392,7 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
} }
} }
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { private void onRecordingStatusChanged(RecordingStatus status) {
recordingStatus = status; recordingStatus = status;
trackDataHub.setRecordingStatus(recordingStatus); trackDataHub.setRecordingStatus(recordingStatus);
@@ -40,6 +40,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns; import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns; import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.data.tables.TracksColumns;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager; import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager;
import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatistics;
@@ -83,7 +84,7 @@ public class TrackDataHub {
private Track.Id selectedTrackId; private Track.Id selectedTrackId;
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
// Track points sampling state // Track points sampling state
private int numLoadedPoints; private int numLoadedPoints;
@@ -407,7 +408,7 @@ public class TrackDataHub {
return handlerThread != null; return handlerThread != null;
} }
public void setRecordingStatus(TrackRecordingService.RecordingStatus recordingStatus) { public void setRecordingStatus(RecordingStatus recordingStatus) {
this.recordingStatus = recordingStatus; this.recordingStatus = recordingStatus;
} }
@@ -22,6 +22,7 @@ import de.dennisguse.opentracks.adapters.StatisticsAdapter;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding; import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -44,7 +45,7 @@ public class StatisticsRecordingFragment extends Fragment {
} }
private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackRecordingService.RecordingData recordingData = TrackRecordingService.NOT_RECORDING; private RecordingData recordingData = TrackRecordingService.NOT_RECORDING;
private TrackPoint latestTrackPoint; private TrackPoint latestTrackPoint;
private Layout layout; private Layout layout;
@@ -158,7 +159,7 @@ public class StatisticsRecordingFragment extends Fragment {
} }
} }
private void onRecordingDataChanged(TrackRecordingService.RecordingData recordingData) { private void onRecordingDataChanged(RecordingData recordingData) {
String oldCategory = this.recordingData.getTrackCategory(); String oldCategory = this.recordingData.getTrackCategory();
String newCategory = recordingData.getTrackCategory(); String newCategory = recordingData.getTrackCategory();
this.recordingData = recordingData; this.recordingData = recordingData;
@@ -0,0 +1,79 @@
package de.dennisguse.opentracks.services;
import androidx.annotation.NonNull;
import java.util.Objects;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.stats.TrackStatistics;
public class RecordingData {
private final Track track;
private final TrackPoint latestTrackPoint;
private final SensorDataSet sensorDataSet;
/**
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
*/
public RecordingData(Track track, TrackPoint lastTrackPoint, SensorDataSet sensorDataSet) {
this.track = track;
this.latestTrackPoint = lastTrackPoint;
this.sensorDataSet = sensorDataSet;
}
public Track getTrack() {
return track;
}
public String getTrackCategory() {
if (track == null) {
return "";
}
return track.getCategory();
}
@NonNull
public TrackStatistics getTrackStatistics() {
if (track == null) {
return new TrackStatistics();
}
return track.getTrackStatistics();
}
public TrackPoint getLatestTrackPoint() {
return latestTrackPoint;
}
public SensorDataSet getSensorDataSet() {
return sensorDataSet;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecordingData that = (RecordingData) o;
return Objects.equals(track, that.track) && Objects.equals(latestTrackPoint, that.latestTrackPoint) && Objects.equals(sensorDataSet, that.sensorDataSet);
}
@Override
public int hashCode() {
return Objects.hash(track, latestTrackPoint, sensorDataSet);
}
@NonNull
@Override
public String toString() {
return "RecordingData{" +
"track=" + track +
", latestTrackPoint=" + latestTrackPoint +
", sensorDataSet=" + sensorDataSet +
'}';
}
}
@@ -0,0 +1,73 @@
package de.dennisguse.opentracks.services;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import java.util.Objects;
import de.dennisguse.opentracks.data.models.Track;
public class RecordingStatus {
private final Track.Id trackId;
private final boolean paused;
@VisibleForTesting
RecordingStatus(Track.Id trackId, boolean paused) {
this.trackId = trackId;
this.paused = paused;
}
public Track.Id getTrackId() {
return trackId;
}
public boolean isRecording() {
return trackId != null;
}
public boolean isPaused() {
return paused;
}
public boolean isRecordingAndNotPaused() {
return isRecording() && !isPaused();
}
static RecordingStatus notRecording() {
return new RecordingStatus(null, false);
}
static RecordingStatus record(@NonNull Track.Id trackId) {
return new RecordingStatus(trackId, false);
}
RecordingStatus pause() {
return new RecordingStatus(getTrackId(), true);
}
public RecordingStatus stop() {
return TrackRecordingService.STATUS_DEFAULT;
}
@NonNull
@Override
public String toString() {
return "RecordingStatus{" +
"trackId=" + trackId +
", paused=" + paused +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecordingStatus that = (RecordingStatus) o;
return paused == that.paused && Objects.equals(trackId, that.trackId);
}
@Override
public int hashCode() {
return Objects.hash(trackId, paused);
}
}
@@ -24,14 +24,12 @@ import android.os.PowerManager.WakeLock;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import java.time.Duration; import java.time.Duration;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.util.Objects;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.CustomContentProvider; import de.dennisguse.opentracks.data.CustomContentProvider;
@@ -46,7 +44,6 @@ import de.dennisguse.opentracks.services.handlers.EGM2008CorrectionManager;
import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator; import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.settings.SettingsActivity;
import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.util.ExportUtils; import de.dennisguse.opentracks.util.ExportUtils;
import de.dennisguse.opentracks.util.SystemUtils; import de.dennisguse.opentracks.util.SystemUtils;
@@ -66,9 +63,20 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null); public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null);
public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE; public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
public class Binder extends android.os.Binder {
private Binder() {
super();
}
public TrackRecordingService getService() {
return TrackRecordingService.this;
}
}
private final Binder binder = new Binder(); private final Binder binder = new Binder();
// The following variables are setFrequency in onCreate: // The following variables are set in onCreate:
private VoiceAnnouncementManager voiceAnnouncementManager; private VoiceAnnouncementManager voiceAnnouncementManager;
private TrackRecordingServiceNotificationManager notificationManager; private TrackRecordingServiceNotificationManager notificationManager;
@@ -180,11 +188,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
return trackRecordingManager.insertMarker(name, category, description, photoUrl); return trackRecordingManager.insertMarker(name, category, description, photoUrl);
} }
/**
* Starts a new track.
*
* @return the track id
*/
public Track.Id startNewTrack() { public Track.Id startNewTrack() {
if (isRecording()) { if (isRecording()) {
Log.w(TAG, "Ignore startNewTrack. Already recording."); Log.w(TAG, "Ignore startNewTrack. Already recording.");
@@ -201,12 +204,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
return trackId; return trackId;
} }
/**
* Resumes the track identified by trackId.
* It results in a pause/continue.
*
* @param trackId the id of the track to be resumed.
*/
public void resumeTrack(Track.Id trackId) { public void resumeTrack(Track.Id trackId) {
trackPointCreator.reset(); trackPointCreator.reset();
trackRecordingManager.resumeExistingTrack(trackId, trackPointCreator.createSegmentStartManual()); trackRecordingManager.resumeExistingTrack(trackId, trackPointCreator.createSegmentStartManual());
@@ -234,18 +231,18 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
// Update instance variables // Update instance variables
handler.postDelayed(updateRecordingData, RECORDING_DATA_UPDATE_INTERVAL.toMillis()); handler.postDelayed(updateRecordingData, RECORDING_DATA_UPDATE_INTERVAL.toMillis());
startGps(); startSensors();
voiceAnnouncementManager.restore(trackRecordingManager.getTrackStatistics()); voiceAnnouncementManager.restore(trackRecordingManager.getTrackStatistics());
} }
public void tryStartGps() { public void tryStartSensors() {
if (isRecording()) return; if (isRecording()) return;
startGps(); startSensors();
} }
private void startGps() { private void startSensors() {
wakeLock = SystemUtils.acquireWakeLock(this, wakeLock); wakeLock = SystemUtils.acquireWakeLock(this, wakeLock);
trackPointCreator.start(this); trackPointCreator.start(this);
showNotification(true); showNotification(true);
@@ -303,25 +300,19 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
recordingDataObservable.postValue(NOT_RECORDING); recordingDataObservable.postValue(NOT_RECORDING);
} }
// Shutdown periodic tasks
voiceAnnouncementManager.shutdown(); voiceAnnouncementManager.shutdown();
// Update instance variables // Update instance variables
trackPointCreator.stop(); trackPointCreator.stop();
stopGps(trackStopped); stopSensors(trackStopped);
} }
public void stopGpsAndShutdown() { public void stopSensorsAndShutdown() {
stopGps(true); stopSensors(true);
} }
/** void stopSensors(boolean shutdown) {
* Stops gps.
*
* @param shutdown true to shutdown self
*/
void stopGps(boolean shutdown) {
if (!isRecording()) return; if (!isRecording()) return;
trackPointCreator.stop(); trackPointCreator.stop();
@@ -441,150 +432,4 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
startActivity(intent); startActivity(intent);
} }
} }
public class Binder extends android.os.Binder {
private Binder() {
super();
}
public TrackRecordingService getService() {
return TrackRecordingService.this;
}
}
public static class RecordingStatus {
private final Track.Id trackId;
private final boolean paused;
@VisibleForTesting
RecordingStatus(Track.Id trackId, boolean paused) {
this.trackId = trackId;
this.paused = paused;
}
public Track.Id getTrackId() {
return trackId;
}
public boolean isRecording() {
return trackId != null;
}
public boolean isPaused() {
return paused;
}
public boolean isRecordingAndNotPaused() {
return isRecording() && !isPaused();
}
private static RecordingStatus notRecording() {
return new RecordingStatus(null, false);
}
private static RecordingStatus record(@NonNull Track.Id trackId) {
return new RecordingStatus(trackId, false);
}
private RecordingStatus pause() {
return new RecordingStatus(getTrackId(), true);
}
public RecordingStatus stop() {
return STATUS_DEFAULT;
}
@NonNull
@Override
public String toString() {
return "RecordingStatus{" +
"trackId=" + trackId +
", paused=" + paused +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecordingStatus that = (RecordingStatus) o;
return paused == that.paused && Objects.equals(trackId, that.trackId);
}
@Override
public int hashCode() {
return Objects.hash(trackId, paused);
}
}
public static class RecordingData {
private final Track track;
private final TrackPoint latestTrackPoint;
private final SensorDataSet sensorDataSet;
/**
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
*/
public RecordingData(Track track, TrackPoint lastTrackPoint, SensorDataSet sensorDataSet) {
this.track = track;
this.latestTrackPoint = lastTrackPoint;
this.sensorDataSet = sensorDataSet;
}
public Track getTrack() {
return track;
}
public String getTrackCategory() {
if (track == null) {
return "";
}
return track.getCategory();
}
@NonNull
public TrackStatistics getTrackStatistics() {
if (track == null) {
return new TrackStatistics();
}
return track.getTrackStatistics();
}
public TrackPoint getLatestTrackPoint() {
return latestTrackPoint;
}
public SensorDataSet getSensorDataSet() {
return sensorDataSet;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecordingData that = (RecordingData) o;
return Objects.equals(track, that.track) && Objects.equals(latestTrackPoint, that.latestTrackPoint) && Objects.equals(sensorDataSet, that.sensorDataSet);
}
@Override
public int hashCode() {
return Objects.hash(track, latestTrackPoint, sensorDataSet);
}
@NonNull
@Override
public String toString() {
return "RecordingData{" +
"track=" + track +
", latestTrackPoint=" + latestTrackPoint +
", sensorDataSet=" + sensorDataSet +
'}';
}
}
} }
@@ -7,6 +7,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
@@ -14,7 +15,7 @@ public class MainSettingsFragment extends PreferenceFragmentCompat {
private static final String TAG = MainSettingsFragment.class.getSimpleName(); private static final String TAG = MainSettingsFragment.class.getSimpleName();
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
private TrackRecordingServiceConnection trackRecordingServiceConnection; private TrackRecordingServiceConnection trackRecordingServiceConnection;
private final TrackRecordingServiceConnection.Callback bindServiceCallback = private final TrackRecordingServiceConnection.Callback bindServiceCallback =
service -> service.getRecordingStatusObservable() service -> service.getRecordingStatusObservable()
@@ -98,7 +99,7 @@ public class MainSettingsFragment extends PreferenceFragmentCompat {
super.onDisplayPreferenceDialog(preference); super.onDisplayPreferenceDialog(preference);
} }
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { private void onRecordingStatusChanged(RecordingStatus status) {
this.recordingStatus = status; this.recordingStatus = status;
if (isAdded()) { if (isAdded()) {
updatePrefsDependOnRecording(); updatePrefsDependOnRecording();
@@ -38,6 +38,7 @@ import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.tables.MarkerColumns; import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.databinding.MarkerListBinding; import de.dennisguse.opentracks.databinding.MarkerListBinding;
import de.dennisguse.opentracks.services.RecordingStatus;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
import de.dennisguse.opentracks.share.ShareUtils; import de.dennisguse.opentracks.share.ShareUtils;
@@ -59,7 +60,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
private ContentProviderUtils contentProviderUtils; private ContentProviderUtils contentProviderUtils;
private TrackRecordingService.RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
private Track track; private Track track;
private MarkerResourceCursorAdapter resourceCursorAdapter; private MarkerResourceCursorAdapter resourceCursorAdapter;
@@ -284,7 +285,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
// Do nothing // Do nothing
} }
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) { private void onRecordingStatusChanged(RecordingStatus status) {
recordingStatus = status; recordingStatus = status;
} }
@@ -15,7 +15,7 @@ import de.dennisguse.opentracks.data.models.Cadence;
import de.dennisguse.opentracks.data.models.Speed; import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet; import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.stats.SensorStatistics; import de.dennisguse.opentracks.stats.SensorStatistics;
import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField; import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
@@ -24,7 +24,7 @@ import de.dennisguse.opentracks.util.StringUtils;
public class StatisticDataBuilder { public class StatisticDataBuilder {
public static List<StatisticData> fromRecordingData(@NonNull Context context, @NonNull TrackRecordingService.RecordingData recordingData, @NonNull Layout layout, boolean metricUnits) { public static List<StatisticData> fromRecordingData(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull Layout layout, boolean metricUnits) {
List<StatisticData> statisticDataList = layout.getFields().stream() List<StatisticData> statisticDataList = layout.getFields().stream()
.filter(DataField::isVisible) .filter(DataField::isVisible)
.map(field -> build(context, recordingData, field.getKey(), field.isPrimary(), metricUnits)) .map(field -> build(context, recordingData, field.getKey(), field.isPrimary(), metricUnits))
@@ -34,7 +34,7 @@ public class StatisticDataBuilder {
return statisticDataList; return statisticDataList;
} }
private static StatisticData build(@NonNull Context context, @NonNull TrackRecordingService.RecordingData recordingData, @NonNull String fieldKey, boolean isPrimary, boolean metricUnits) { private static StatisticData build(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull String fieldKey, boolean isPrimary, boolean metricUnits) {
final TrackPoint latestTrackPoint = recordingData.getLatestTrackPoint(); final TrackPoint latestTrackPoint = recordingData.getLatestTrackPoint();
final SensorDataSet sensorDataSet = recordingData.getSensorDataSet(); final SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
final TrackStatistics trackStatistics = recordingData.getTrackStatistics(); final TrackStatistics trackStatistics = recordingData.getTrackStatistics();
@@ -153,7 +153,7 @@ public class StatisticDataBuilder {
/** /**
* Builds a list of StatisticData with sensors configured but not in statisticDataList. * Builds a list of StatisticData with sensors configured but not in statisticDataList.
*/ */
private static List<StatisticData> getSensorStatsDataIfNeeded(Context context, TrackRecordingService.RecordingData recordingData, List<StatisticData> statisticDataList, boolean metricUnits) { private static List<StatisticData> getSensorStatsDataIfNeeded(Context context, RecordingData recordingData, List<StatisticData> statisticDataList, boolean metricUnits) {
List<StatisticData> sensorDataList = new ArrayList<>(); List<StatisticData> sensorDataList = new ArrayList<>();
SensorDataSet sensorDataSet = recordingData.getSensorDataSet(); SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
if (sensorDataSet == null) { if (sensorDataSet == null) {
@@ -8,7 +8,7 @@ import androidx.lifecycle.MutableLiveData;
import java.util.List; import java.util.List;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout; import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
public class StatisticsDataModel extends AndroidViewModel { public class StatisticsDataModel extends AndroidViewModel {
@@ -26,7 +26,7 @@ public class StatisticsDataModel extends AndroidViewModel {
return statsData; return statsData;
} }
public void update(TrackRecordingService.RecordingData recordingData, Layout layout, boolean metricUnit) { public void update(RecordingData recordingData, Layout layout, boolean metricUnit) {
new Thread(() -> { new Thread(() -> {
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(getApplication(), recordingData, layout, metricUnit); List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(getApplication(), recordingData, layout, metricUnit);
statsData.postValue(statisticDataList); statsData.postValue(statisticDataList);