Replace long time_ms with Instant and Duration, respectively.

Fixes #561.
This commit is contained in:
Dennis Guse
2021-01-09 13:27:14 +01:00
parent 3bbcbfe202
commit e990b413cd
47 changed files with 442 additions and 434 deletions
@@ -35,6 +35,8 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.TaskStackBuilder;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
@@ -228,12 +230,12 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
}
//TODO Throw exception, when not recording.
public long getTotalTime() {
public Duration getTotalTime() {
if (trackStatisticsUpdater == null) {
return 0;
return Duration.ofSeconds(0);
}
if (!isPaused()) {
trackStatisticsUpdater.updateTime(System.currentTimeMillis());
trackStatisticsUpdater.updateTime(Instant.now());
}
return trackStatisticsUpdater.getTrackStatistics().getTotalTime();
}
@@ -264,7 +266,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
TrackStatistics stats = trackStatisticsUpdater.getTrackStatistics();
double length = stats.getTotalDistance();
long duration = stats.getTotalTime();
long duration = stats.getTotalTime().toMillis();
// Insert marker
Marker marker = new Marker(name, description, category, icon, recordingTrackId, length, duration, trackPoint.getLocation(), photoUrl);
@@ -325,7 +327,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
}
// Sync the real time setting the stop time with current time.
track.getTrackStatistics().setStopTime_ms(System.currentTimeMillis());
track.getTrackStatistics().setStopTime(Instant.now());
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
insertTrackPoint(track, TrackPoint.createSegmentStartManual());
@@ -637,7 +639,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
*/
private void insertTrackPointIfNewer(@NonNull Track track, @NonNull TrackPoint trackPoint) {
TrackPoint lastValidTrackPoint = getLastValidTrackPointInCurrentSegment(track.getId());
if (TrackPointUtils.equalTime(trackPoint, lastValidTrackPoint)) {
if (lastValidTrackPoint != null && trackPoint.getTime().equals(lastValidTrackPoint.getTime())) {
// Do not insert if inserted already
Log.w(TAG, "Ignore insertTrackPoint. trackPoint time same as last valid track point time.");
return;
@@ -678,7 +680,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
* @param track the track
*/
private void updateTrackTotalTime(Track track) {
trackStatisticsUpdater.updateTime(System.currentTimeMillis());
trackStatisticsUpdater.updateTime(Instant.now());
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
contentProviderUtils.updateTrack(track);
}
@@ -2,6 +2,8 @@ package de.dennisguse.opentracks.services;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import de.dennisguse.opentracks.content.data.Marker;
import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint;
@@ -85,7 +87,7 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
}
@Override
public long getTotalTime() {
public Duration getTotalTime() {
return trackRecordingService.getTotalTime();
}
@@ -17,6 +17,8 @@ package de.dennisguse.opentracks.services;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import de.dennisguse.opentracks.content.data.Marker;
import de.dennisguse.opentracks.content.data.Track;
import de.dennisguse.opentracks.content.data.TrackPoint;
@@ -59,8 +61,7 @@ public interface TrackRecordingServiceInterface {
/**
* Gets the total time for the current recording track. Returns 0 if not recording.
*/
//TODO milliseconds?
long getTotalTime();
Duration getTotalTime();
Marker.Id insertMarker(String name, String category, String description, String photoUrl);
@@ -16,6 +16,8 @@
package de.dennisguse.opentracks.services.handlers;
import java.time.Duration;
/**
* This is a simple location listener policy that will always dictate the same polling interval.
*
@@ -23,19 +25,19 @@ package de.dennisguse.opentracks.services.handlers;
*/
public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {
private final long interval;
private final Duration interval;
/**
* Constructor.
*
* @param interval the interval to request for gps signal
*/
public AbsoluteLocationListenerPolicy(long interval) {
public AbsoluteLocationListenerPolicy(Duration interval) {
this.interval = interval;
}
@Override
public long getDesiredPollingInterval() {
public Duration getDesiredPollingInterval() {
return interval;
}
@@ -45,7 +47,7 @@ public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {
}
@Override
public void updateIdleTime(long idleTime) {
public void updateIdleTime(Duration idleTime) {
// Ignore
}
}
@@ -16,6 +16,8 @@
package de.dennisguse.opentracks.services.handlers;
import java.time.Duration;
/**
* A {@link LocationListenerPolicy} that will change based on how long the user has been stationary.
* This policy will dictate a policy based on a min, max and idle time.
@@ -25,35 +27,41 @@ package de.dennisguse.opentracks.services.handlers;
*/
public class AdaptiveLocationListenerPolicy implements LocationListenerPolicy {
private final long minInterval_ms;
private final long maxInterval_ms;
private final Duration minInterval;
private final Duration maxInterval;
private final int minDistance_m;
// The time the user has been idle at the current location, in milliseconds.
private long idleTime;
private Duration idleTime;
/**
* Creates a policy that will be bounded by the given minInterval_ms and maxInterval_ms.
*
* @param minInterval_ms the smallest interval this policy will dictate
* @param maxInterval_ms the largest interval this policy will dictate
* @param minInterval the smallest interval this policy will dictate
* @param maxInterval the largest interval this policy will dictate
* @param minDistance_m the minimum distance
*/
public AdaptiveLocationListenerPolicy(long minInterval_ms, long maxInterval_ms, int minDistance_m) {
this.minInterval_ms = minInterval_ms;
this.maxInterval_ms = maxInterval_ms;
public AdaptiveLocationListenerPolicy(Duration minInterval, Duration maxInterval, int minDistance_m) {
this.minInterval = minInterval;
this.maxInterval = maxInterval;
this.minDistance_m = minDistance_m;
}
/*
* Returns an interval half of the idle time, but bounded by minInterval_ms and maxInterval_ms.
* Returns an interval half of the idle time, but bounded by minInterval and maxInterval.
*/
@Override
public long getDesiredPollingInterval() {
long desiredInterval_ms = idleTime / 2;
public Duration getDesiredPollingInterval() {
Duration desiredInterval = idleTime.dividedBy(2);
// Round to second to avoid setting the interval too often
desiredInterval_ms = (desiredInterval_ms / 1000) * 1000;
return Math.max(Math.min(maxInterval_ms, desiredInterval_ms), minInterval_ms);
desiredInterval = Duration.ofSeconds(desiredInterval.getSeconds());
if (minInterval.compareTo(desiredInterval) > 0) {
return minInterval;
} else if (maxInterval.compareTo(desiredInterval) < 0) {
return maxInterval;
}
return desiredInterval;
}
@Override
@@ -62,7 +70,7 @@ public class AdaptiveLocationListenerPolicy implements LocationListenerPolicy {
}
@Override
public void updateIdleTime(long newIdleTime) {
public void updateIdleTime(Duration newIdleTime) {
idleTime = newIdleTime;
}
}
@@ -6,9 +6,11 @@ import android.os.Handler;
import androidx.annotation.Nullable;
import java.time.Duration;
import java.time.Instant;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.UnitConversions;
/**
* This class handle GPS status according to received locations and some thresholds.
@@ -17,13 +19,13 @@ class GpsStatus {
private static final String TAG = GpsStatus.class.getSimpleName();
// The quantity of milliseconds that GpsStatus waits from minimal interval to consider GPS lost.
private static final int SIGNAL_LOST_THRESHOLD = (int) (10 * UnitConversions.S_TO_MS);
// The duration that GpsStatus waits from minimal interval to consider GPS lost.
private static final Duration SIGNAL_LOST_THRESHOLD = Duration.ofSeconds(10);
// Threshold for accuracy.
private double signalBadThreshold;
// Threshold for time without points.
private int signalLostThreshold;
private Duration signalLostThreshold;
private GpsStatusValue gpsStatus = GpsStatusValue.GPS_NONE;
private GpsStatusListener client;
@@ -46,7 +48,7 @@ class GpsStatus {
public void run() {
if (gpsStatus != null && !stopped) {
onLocationChanged(null);
gpsStatusHandler.postDelayed(gpsStatusRunner, getIntervalThreshold());
gpsStatusHandler.postDelayed(gpsStatusRunner, getIntervalThreshold().toMillis());
}
}
@@ -63,11 +65,11 @@ class GpsStatus {
* @param client The client.
* @param minRecordingInterval Value of min recording interval preference.
*/
public GpsStatus(Context context, GpsStatusListener client, int minRecordingInterval) {
public GpsStatus(Context context, GpsStatusListener client, Duration minRecordingInterval) {
this.client = client;
this.context = context;
signalBadThreshold = PreferencesUtils.getRecordingDistanceInterval(context);
signalLostThreshold = minRecordingInterval > 0 ? minRecordingInterval * (int) UnitConversions.ONE_SECOND_MS + SIGNAL_LOST_THRESHOLD : SIGNAL_LOST_THRESHOLD;
signalLostThreshold = !minRecordingInterval.isNegative() ? SIGNAL_LOST_THRESHOLD.plus(minRecordingInterval) : SIGNAL_LOST_THRESHOLD;
gpsStatusHandler = new Handler();
}
@@ -97,7 +99,7 @@ class GpsStatus {
* @param value Minimal recording interval preference value in seconds or an special value: -1, -2, 0.
*/
public void onMinRecordingIntervalChanged(int value) {
signalLostThreshold = value > 0 ? value * (int) UnitConversions.ONE_SECOND_MS + SIGNAL_LOST_THRESHOLD : SIGNAL_LOST_THRESHOLD;
signalLostThreshold = value > 0 ? SIGNAL_LOST_THRESHOLD.plus(Duration.ofSeconds(value)) : SIGNAL_LOST_THRESHOLD;
}
/**
@@ -119,7 +121,7 @@ class GpsStatus {
if (trackPoint != null) {
// Update trackPoint's time to the current time millis when trackPoint has been received.
trackPoint.setTime(System.currentTimeMillis());
trackPoint.setTime(Instant.now());
lastValidTrackPoint = trackPoint;
}
lastTrackPoint = trackPoint;
@@ -133,7 +135,7 @@ class GpsStatus {
* Also, it'll run the runnable if signal is bad or stop it if the signal is lost.
*/
private void checkStatusFromLastLocation() {
if (System.currentTimeMillis() - lastTrackPoint.getTime() > signalLostThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) {
if (Duration.between(lastTrackPoint.getTime(), Instant.now()).compareTo(signalLostThreshold) > 0 && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) {
// Too much time without receiving signal -> signal lost.
GpsStatusValue oldStatus = gpsStatus;
gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST;
@@ -160,7 +162,8 @@ class GpsStatus {
* If there is any change then it does the change.
*/
private void checkStatusFromLastValidLocation() {
if (System.currentTimeMillis() - lastValidTrackPoint.getTime() > signalLostThreshold) {
Duration elapsed = Duration.between(lastValidTrackPoint.getTime(), Instant.now());
if (signalLostThreshold.minus(elapsed).isNegative()) {
// Too much time without locations -> lost signal? (wait signalLostThreshold from last valid location).
GpsStatusValue oldStatus = gpsStatus;
gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST;
@@ -222,7 +225,7 @@ class GpsStatus {
}
}
public int getIntervalThreshold() {
public Duration getIntervalThreshold() {
return signalLostThreshold;
}
@@ -10,12 +10,13 @@ import android.util.Log;
import androidx.annotation.NonNull;
import java.time.Duration;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.TrackPoint;
import de.dennisguse.opentracks.util.LocationUtils;
import de.dennisguse.opentracks.util.PreferencesUtils;
import de.dennisguse.opentracks.util.TrackPointUtils;
import de.dennisguse.opentracks.util.UnitConversions;
class LocationHandler implements HandlerServer.Handler, LocationListener, GpsStatus.GpsStatusListener {
@@ -25,7 +26,7 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
private final HandlerServer handlerServer;
private GpsStatus gpsStatus;
private LocationListenerPolicy locationListenerPolicy;
private long currentRecordingInterval;
private Duration currentRecordingInterval;
private int recordingGpsAccuracy;
private TrackPoint lastValidTrackPoint;
@@ -35,7 +36,7 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
@Override
public void onStart(Context context) {
gpsStatus = new GpsStatus(context, this, PreferencesUtils.getMinRecordingInterval(context));
gpsStatus = new GpsStatus(context, this, Duration.ofSeconds(PreferencesUtils.getMinRecordingInterval(context)));
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
registerLocationListener();
}
@@ -56,12 +57,12 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
int minRecordingInterval = PreferencesUtils.getMinRecordingInterval(context);
if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptBatteryLife(context)) {
// Choose battery life over moving time accuracy.
locationListenerPolicy = new AdaptiveLocationListenerPolicy(30 * UnitConversions.ONE_SECOND_MS, 5 * UnitConversions.ONE_MINUTE_MS, 5);
locationListenerPolicy = new AdaptiveLocationListenerPolicy(Duration.ofSeconds(30), Duration.ofSeconds(5), 5);
} else if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptAccuracy(context)) {
// Get all the updates.
locationListenerPolicy = new AdaptiveLocationListenerPolicy(UnitConversions.ONE_SECOND_MS, 30 * UnitConversions.ONE_SECOND_MS, 0);
locationListenerPolicy = new AdaptiveLocationListenerPolicy(Duration.ofSeconds(1), Duration.ofSeconds(30), 0);
} else {
locationListenerPolicy = new AbsoluteLocationListenerPolicy(minRecordingInterval * UnitConversions.ONE_SECOND_MS);
locationListenerPolicy = new AbsoluteLocationListenerPolicy(Duration.ofSeconds(minRecordingInterval));
}
if (locationManager != null) {
@@ -108,9 +109,9 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
return;
}
long idleTime = 0L;
if (TrackPointUtils.after(trackPoint, lastValidTrackPoint)) {
idleTime = trackPoint.getTime() - lastValidTrackPoint.getTime();
Duration idleTime = Duration.ofSeconds(0);
if (lastValidTrackPoint != null && trackPoint.getTime().isAfter(lastValidTrackPoint.getTime())) {
idleTime = Duration.between(lastValidTrackPoint.getTime(), trackPoint.getTime());
}
locationListenerPolicy.updateIdleTime(idleTime);
@@ -146,9 +147,9 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
return;
}
try {
long interval = locationListenerPolicy.getDesiredPollingInterval();
Duration interval = locationListenerPolicy.getDesiredPollingInterval();
currentRecordingInterval = interval;
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval, locationListenerPolicy.getMinDistance_m(), this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval.toMillis(), locationListenerPolicy.getMinDistance_m(), this);
} catch (SecurityException e) {
Log.e(TAG, "Could not register location listener; permissions not granted.", e);
}
@@ -16,6 +16,8 @@
package de.dennisguse.opentracks.services.handlers;
import java.time.Duration;
/**
* This is an interface for classes that will manage the location listener policy.
*
@@ -28,7 +30,7 @@ interface LocationListenerPolicy {
*
* @return the polling interval
*/
long getDesiredPollingInterval();
Duration getDesiredPollingInterval();
/**
* Returns the minimum distance between updates.
@@ -40,5 +42,5 @@ interface LocationListenerPolicy {
*
* @param idleTime the time that the user has been idle at his current location
*/
void updateIdleTime(long idleTime);
void updateIdleTime(Duration idleTime);
}
@@ -17,6 +17,8 @@ package de.dennisguse.opentracks.services.tasks;
import android.util.Log;
import java.time.Duration;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.stats.TrackStatistics;
@@ -92,7 +94,7 @@ public class PeriodicTaskExecutor {
if (timerTaskExecutor == null) {
timerTaskExecutor = new TimerTaskExecutor(periodicTask, trackRecordingService);
}
timerTaskExecutor.scheduleTask(taskFrequency * UnitConversions.ONE_MINUTE_MS);
timerTaskExecutor.scheduleTask(Duration.ofSeconds(taskFrequency));
} else {
// For distance periodic task
calculateNextTaskDistance();
@@ -16,6 +16,7 @@
package de.dennisguse.opentracks.services.tasks;
import java.time.Duration;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
@@ -42,15 +43,9 @@ class TimerTaskExecutor {
}
/**
* Schedules the periodic task in milliseconds.
*
* @param interval_ms the interval_ms
* Schedules the periodic task.
*/
void scheduleTask(long interval_ms) {
if (interval_ms <= 0) {
return;
}
void scheduleTask(Duration interval) {
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused()) {
return;
}
@@ -69,8 +64,10 @@ class TimerTaskExecutor {
}
};
timer = new Timer(TimerTaskExecutor.class.getSimpleName());
long next = System.currentTimeMillis() + interval_ms - (trackStatistics.getTotalTime() % interval_ms);
timer.scheduleAtFixedRate(timerTask, new Date(next), interval_ms);
//TODO Simplify: far too complicated for it's purpose
long next = System.currentTimeMillis() + interval.toMillis() - (trackStatistics.getTotalTime().toMillis() % interval.toMillis());
timer.scheduleAtFixedRate(timerTask, new Date(next), interval.toMillis());
}
void shutdown() {