TrackStatisticsUpdater updates only by adding TrackPoints.

#316.
This commit is contained in:
Dennis Guse
2021-01-14 19:38:27 +01:00
parent d157e94220
commit c3741611dc
5 changed files with 82 additions and 77 deletions
@@ -268,6 +268,30 @@ public class TrackRecordingServiceTest {
assertEquals(TrackPoint.Type.TRACKPOINT, trackPoints.get(3).getType());
}
@MediumTest
@Test
public void testRecording_stopPausedTrack() throws TimeoutException {
// given
TrackRecordingServiceInterface service = ((TrackRecordingServiceInterface) mServiceRule.bindService(createStartIntent(context)));
Track.Id trackId = service.startNewTrack();
assertTrue(service.isRecording());
service.pauseCurrentTrack();
assertEquals(2, contentProviderUtils.getTrackPoints(trackId).size());
// when
service.endCurrentTrack();
// then
assertFalse(service.isRecording());
assertNull(service.getRecordingTrackId());
List<TrackPoint> trackPoints = contentProviderUtils.getTrackPoints(trackId);
assertEquals(2, trackPoints.size());
assertEquals(TrackPoint.Type.SEGMENT_START_MANUAL, trackPoints.get(0).getType());
assertEquals(TrackPoint.Type.SEGMENT_END_MANUAL, trackPoints.get(1).getType());
}
@Ignore("Sometimes fails on CI.")
@MediumTest
@Test
@@ -54,7 +54,7 @@ public class TrackController implements View.OnTouchListener {
private final TransitionDrawable transition;
private boolean isRecording;
private boolean isPaused;
private boolean isRecordingPaused;
private Duration totalTime;
private boolean isResumed = false;
@@ -63,8 +63,9 @@ public class TrackController implements View.OnTouchListener {
// A runnable to update the total time.
private final Runnable updateTotalTimeRunnable = new Runnable() {
public void run() {
if (isResumed && isRecording && !isPaused) {
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
if (isResumed && isRecording && !isRecordingPaused) {
updateTotalTime();
setTotalTime();
handlerUpdateTotalTime.postDelayed(this, UnitConversions.ONE_SECOND_MS);
}
}
@@ -82,7 +83,7 @@ public class TrackController implements View.OnTouchListener {
viewBinding.trackControllerRecord.setOnTouchListener(this);
viewBinding.trackControllerRecord.setOnClickListener((view) -> {
if (buttonDelay != null || (isRecording && !isPaused)) {
if (buttonDelay != null || (isRecording && !isRecordingPaused)) {
return;
}
@@ -118,7 +119,7 @@ public class TrackController implements View.OnTouchListener {
//To pause a recording
if (viewBinding.trackControllerRecord.equals(view)
&& event.getAction() == MotionEvent.ACTION_DOWN
&& isRecording && !isPaused) {
&& isRecording && !isRecordingPaused) {
transition.startTransition(buttonDelayDuration);
@@ -165,10 +166,11 @@ public class TrackController implements View.OnTouchListener {
public void update(boolean recording, boolean paused) {
if (!isResumed) {
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
return;
}
isRecording = recording;
isPaused = paused;
isRecordingPaused = paused;
boolean visible = alwaysShow || isRecording;
viewBinding.trackControllerContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
@@ -177,27 +179,26 @@ public class TrackController implements View.OnTouchListener {
return;
}
viewBinding.trackControllerRecord.setImageResource(isRecording && !isPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
viewBinding.trackControllerRecord.setContentDescription(activity.getString(isRecording && !isPaused ? R.string.image_pause : R.string.image_record));
if (isRecording && !isRecordingPaused) {
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UnitConversions.ONE_SECOND_MS);
}
viewBinding.trackControllerRecord.setImageResource(isRecording && !isRecordingPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
viewBinding.trackControllerRecord.setContentDescription(activity.getString(isRecording && !isRecordingPaused ? R.string.image_pause : R.string.image_record));
viewBinding.trackControllerStop.setEnabled(isRecording);
viewBinding.trackControllerStatus.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
if (isRecording) {
viewBinding.trackControllerStatus.setTextColor(activity.getResources().getColor(isPaused ? android.R.color.white : R.color.recording_text));
viewBinding.trackControllerStatus.setTextColor(activity.getResources().getColor(isRecordingPaused ? android.R.color.white : R.color.recording_text));
showStatusSetDefaultText();
}
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
if (isRecording) {
totalTime = getTotalTime();
if (totalTime != null) {
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
}
if (!isPaused) {
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UnitConversions.ONE_SECOND_MS);
}
updateTotalTime();
setTotalTime();
}
}
@@ -219,16 +220,21 @@ public class TrackController implements View.OnTouchListener {
viewBinding.trackControllerContainer.setVisibility(View.VISIBLE);
}
/**
* Gets the total time for the current recording track.
*/
private Duration getTotalTime() {
private void updateTotalTime() {
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
return trackRecordingService != null ? trackRecordingService.getTotalTime() : null;
if (trackRecordingService != null) {
totalTime = trackRecordingService.getTotalTime();
}
}
private void setTotalTime() {
if (totalTime != null) {
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
}
}
private void showStatusSetDefaultText() {
viewBinding.trackControllerStatus.setText(isPaused ? R.string.generic_paused : R.string.generic_recording);
viewBinding.trackControllerStatus.setText(isRecordingPaused ? R.string.generic_paused : R.string.generic_recording);
}
public interface Callback {
@@ -15,7 +15,6 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -409,26 +408,15 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
}
private void updateTotalTime() {
Duration totalTime;
Duration totalTime = lastTrackStatistics.getTotalTime();
if (isSelectedTrackRecording()) {
totalTime = calculateTotalTime();
} else {
totalTime = lastTrackStatistics.getTotalTime();
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
if (trackRecordingService != null) {
totalTime = trackRecordingService.getTotalTime();
}
}
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime));
}
/**
* Return time from service.
* If service isn't bound then use lastTrackStatistics for calculate it.
*/
private Duration calculateTotalTime() {
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
if (trackRecordingService != null) {
return trackRecordingService.getTotalTime();
} else {
return Duration.between(lastTrackStatistics.getStopTime().plus(lastTrackStatistics.getTotalTime()), Instant.now());
}
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime));
}
private void setLocationValues() {
@@ -234,10 +234,13 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
if (trackStatisticsUpdater == null) {
return Duration.ofSeconds(0);
}
if (!isPaused()) {
trackStatisticsUpdater.updateTime(Instant.now());
if (isPaused()) {
return trackStatisticsUpdater.getTrackStatistics().getTotalTime();
}
return trackStatisticsUpdater.getTrackStatistics().getTotalTime();
TrackStatistics statistics = trackStatisticsUpdater.getTrackStatistics();
return Duration.between(statistics.getStopTime(), Instant.now())
.plus(statistics.getTotalTime());
}
public Marker.Id insertMarker(String name, String category, String description, String photoUrl) {
@@ -420,24 +423,24 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
}
// Need to remember the recordingTrackId before setting it to -1L
boolean wasPause = isPaused();
Track.Id trackId = recordingTrackId;
boolean wasPaused = recordingTrackPaused;
updateRecordingState(null, true);
// Update database
Track track = contentProviderUtils.getTrack(trackId);
if (track != null) {
if (lastTrackPoint != null) {
insertTrackPointIfNewer(track, lastTrackPoint);
if (!wasPause) {
// Update database
Track track = contentProviderUtils.getTrack(trackId);
if (track != null) {
if (lastTrackPoint != null) {
insertTrackPointIfNewer(track, lastTrackPoint);
}
insertTrackPoint(track, TrackPoint.createSegmentEnd());
}
insertTrackPoint(track, TrackPoint.createSegmentEnd());
// Update the recording track time
updateTrackTotalTime(track);
}
Track track = contentProviderUtils.getTrack(trackId);
ExportUtils.postWorkoutExport(this, track, new ExportServiceResultReceiver(new Handler(), this));
endRecording(true);
@@ -663,7 +666,9 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
}
contentProviderUtils.insertTrackPoint(trackPoint, track.getId());
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
updateTrackTotalTime(track);
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
contentProviderUtils.updateTrack(track);
} catch (SQLiteException e) {
/*
* Insert failed, most likely because of SqlLite error code 5 (SQLite_BUSY).
@@ -674,17 +679,6 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
voiceExecutor.update();
}
/**
* Updates the recording track time.
*
* @param track the track
*/
private void updateTrackTotalTime(Track track) {
trackStatisticsUpdater.updateTime(Instant.now());
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
contentProviderUtils.updateTrack(track);
}
SensorDataSet getSensorDataSet() {
if (remoteSensorManager == null) {
return null;
@@ -22,7 +22,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import java.time.Instant;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
@@ -91,11 +90,6 @@ public class TrackStatisticsUpdater {
trackInitialized = true;
}
public void updateTime(Instant time) {
currentSegment.setStopTime(time);
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), time));
}
public TrackStatistics getTrackStatistics() {
// Take a snapshot - we don't want anyone messing with our trackStatistics
TrackStatistics stats = new TrackStatistics(trackStatistics);
@@ -120,7 +114,9 @@ public class TrackStatisticsUpdater {
}
// Always update time
updateTime(trackPoint.getTime());
currentSegment.setStopTime(trackPoint.getTime());
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), trackPoint.getTime()));
if (trackPoint.isSegmentStart() || trackPoint.isSegmentEnd()) {
if (trackPoint.isSegmentEnd()) {
if (lastTrackPoint != null && lastMovingTrackPoint != null && lastTrackPoint != lastMovingTrackPoint) {
@@ -240,9 +236,6 @@ public class TrackStatisticsUpdater {
return newAverage - oldAverage;
}
/**
* Returns true if the speed is valid.
*/
private boolean isValidSpeed(@NonNull TrackPoint trackPoint, @NonNull TrackPoint lastTrackPoint) {
// There are a lot of noisy speed readings. Do the cheapest checks first, most expensive last.
if (trackPoint.getSpeed() == 0) {