forked from upstream-mirrors/OpenTracks
@@ -190,9 +190,15 @@ public class ChartFragmentTest {
|
||||
*/
|
||||
@Test
|
||||
public void testCreatePendingPoint_time() {
|
||||
// given
|
||||
chartFragment.setChartByDistance(false);
|
||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||
trackPoint1.setTime(TrackStubUtils.INITIAL_TIME); //Keep old TrackPoint behavior of having time=0 for this test
|
||||
|
||||
// when
|
||||
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||
|
||||
// then
|
||||
assertEquals(0.0, point.getTimeOrDistance(), 0.01);
|
||||
long timeSpan = 222;
|
||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||
|
||||
+8
-1
@@ -3,10 +3,12 @@ package de.dennisguse.opentracks.services.handlers;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -32,6 +34,12 @@ public class LocationHandlerTest {
|
||||
@InjectMocks
|
||||
private LocationHandler locationHandler;
|
||||
|
||||
@BeforeClass
|
||||
public static void preSetUp() {
|
||||
// Prepare looper for Android's message queue
|
||||
if (Looper.myLooper() == null) Looper.prepare();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
// Let's use default values.
|
||||
@@ -80,7 +88,6 @@ public class LocationHandlerTest {
|
||||
int prefAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context);
|
||||
|
||||
// when
|
||||
// poor latitude
|
||||
locationHandler.onLocationChanged(createLocation(45f, 35f, prefAccuracy + 1, 5, System.currentTimeMillis()));
|
||||
|
||||
// then
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package de.dennisguse.opentracks.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TrackPointUtilsTest {
|
||||
|
||||
@Test
|
||||
public void fixTime_none() {
|
||||
// given
|
||||
long time = System.currentTimeMillis();
|
||||
TrackPoint trackPoint = new TrackPoint();
|
||||
trackPoint.setTime(time);
|
||||
|
||||
// when
|
||||
TrackPointUtils.fixTime(trackPoint);
|
||||
|
||||
// then
|
||||
assertEquals(time, trackPoint.getTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fixTime_0() {
|
||||
// given
|
||||
long time = System.currentTimeMillis();
|
||||
TrackPoint trackPoint = new TrackPoint();
|
||||
trackPoint.setTime(0);
|
||||
|
||||
// when
|
||||
TrackPointUtils.fixTime(trackPoint);
|
||||
|
||||
// then
|
||||
assertEquals(time, trackPoint.getTime(), 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fixTime_gpsWeekRollover() {
|
||||
// given
|
||||
long time = System.currentTimeMillis();
|
||||
TrackPoint trackPoint = new TrackPoint();
|
||||
trackPoint.setTime(time - 1024 * UnitConversions.ONE_WEEK_MS);
|
||||
|
||||
// when
|
||||
TrackPointUtils.fixTime(trackPoint);
|
||||
|
||||
// then
|
||||
assertEquals(time, trackPoint.getTime());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,7 +27,8 @@ import java.util.Objects;
|
||||
/**
|
||||
* This class extends the standard Android location with extra information.
|
||||
* <p>
|
||||
* NOTE: default location will be latitude=0.0 and longitude=0.0 (this is not meaningful).
|
||||
* NOTE: default location will be latitude=0.0 and longitude=0.0.
|
||||
* For {@link TrackPoint}s with `type == null` this is not meaningful.
|
||||
* <p>
|
||||
* NOTE: For Locations provided by the GPS.
|
||||
* We are replacing the GPS-provided time using the system time.
|
||||
@@ -99,6 +100,7 @@ public class TrackPoint {
|
||||
public TrackPoint(@NonNull Location location) {
|
||||
this.type = Type.TRACKPOINT;
|
||||
this.location = location;
|
||||
setTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public TrackPoint(@NonNull Type type, @NonNull Location location) {
|
||||
|
||||
@@ -554,8 +554,6 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
|
||||
notificationManager.updateTrackPoint(this, trackPoint, recordingGpsAccuracy);
|
||||
|
||||
TrackPointUtils.fixTime(trackPoint);
|
||||
|
||||
//TODO Figure out how to avoid loading the lastValidTrackPoint from the database
|
||||
TrackPoint lastValidTrackPoint = getLastValidTrackPointInCurrentSegment(track.getId());
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package de.dennisguse.opentracks.services.handlers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Handler;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
@@ -27,10 +29,12 @@ class GpsStatus {
|
||||
private GpsStatusListener client;
|
||||
private final Context context;
|
||||
|
||||
// Last location. It can be null.
|
||||
private Location lastLocation = null;
|
||||
@Nullable
|
||||
private TrackPoint lastTrackPoint = null;
|
||||
|
||||
@Nullable
|
||||
// The last valid (not null) location. Null value means that there have not been any location yet.
|
||||
private Location lastValidLocation = null;
|
||||
private TrackPoint lastValidTrackPoint = null;
|
||||
|
||||
// Flag to prevent GpsStatus checks two or more locations at the same time.
|
||||
private boolean checking = false;
|
||||
@@ -97,28 +101,28 @@ class GpsStatus {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method must be called from the client every time a new location is received.
|
||||
* Receive new location and calculate the new status if needed.
|
||||
* This method must be called from the client every time a new trackPoint is received.
|
||||
* Receive new trackPoint and calculate the new status if needed.
|
||||
* It look for GPS changes in lastLocation if it's not null. If it's null then look for in lastValidLocation if any.
|
||||
*/
|
||||
public void onLocationChanged(final Location location) {
|
||||
public void onLocationChanged(final TrackPoint trackPoint) {
|
||||
if (checking) {
|
||||
return;
|
||||
}
|
||||
|
||||
checking = true;
|
||||
if (lastLocation != null) {
|
||||
if (lastTrackPoint != null) {
|
||||
checkStatusFromLastLocation();
|
||||
} else if (lastValidLocation != null) {
|
||||
} else if (lastValidTrackPoint != null) {
|
||||
checkStatusFromLastValidLocation();
|
||||
}
|
||||
|
||||
if (location != null) {
|
||||
// Update location's time to the current time millis when location has been received.
|
||||
location.setTime(System.currentTimeMillis());
|
||||
lastValidLocation = location;
|
||||
if (trackPoint != null) {
|
||||
// Update trackPoint's time to the current time millis when trackPoint has been received.
|
||||
trackPoint.setTime(System.currentTimeMillis());
|
||||
lastValidTrackPoint = trackPoint;
|
||||
}
|
||||
lastLocation = location;
|
||||
lastTrackPoint = trackPoint;
|
||||
checking = false;
|
||||
}
|
||||
|
||||
@@ -129,19 +133,19 @@ 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() - lastLocation.getTime() > signalLostThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) {
|
||||
if (System.currentTimeMillis() - lastTrackPoint.getTime() > signalLostThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) {
|
||||
// Too much time without receiving signal -> signal lost.
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST;
|
||||
sendStatus(oldStatus, gpsStatus);
|
||||
stopStatusRunner();
|
||||
} else if (lastLocation.getAccuracy() > signalBadThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_BAD) {
|
||||
} else if (lastTrackPoint.getAccuracy() > signalBadThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_BAD) {
|
||||
// Too little accuracy -> bad signal.
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_SIGNAL_BAD;
|
||||
sendStatus(oldStatus, gpsStatus);
|
||||
startStatusRunner();
|
||||
} else if (lastLocation.getAccuracy() <= signalBadThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_FIX) {
|
||||
} else if (lastTrackPoint.getAccuracy() <= signalBadThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_FIX) {
|
||||
// Gps okay.
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_SIGNAL_FIX;
|
||||
@@ -156,13 +160,13 @@ class GpsStatus {
|
||||
* If there is any change then it does the change.
|
||||
*/
|
||||
private void checkStatusFromLastValidLocation() {
|
||||
if (System.currentTimeMillis() - lastValidLocation.getTime() > signalLostThreshold) {
|
||||
if (System.currentTimeMillis() - lastValidTrackPoint.getTime() > signalLostThreshold) {
|
||||
// Too much time without locations -> lost signal? (wait signalLostThreshold from last valid location).
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST;
|
||||
sendStatus(oldStatus, gpsStatus);
|
||||
stopStatusRunner();
|
||||
lastValidLocation = null;
|
||||
lastValidTrackPoint = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,8 +196,8 @@ class GpsStatus {
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_DISABLED;
|
||||
sendStatus(oldStatus, gpsStatus);
|
||||
lastLocation = null;
|
||||
lastValidLocation = null;
|
||||
lastTrackPoint = null;
|
||||
lastValidTrackPoint = null;
|
||||
stopStatusRunner();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,18 +90,20 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(@NonNull Location location) {
|
||||
TrackPoint trackPoint = new TrackPoint(location);
|
||||
boolean isAccurate = TrackPointUtils.fulfillsAccuracy(trackPoint, recordingGpsAccuracy);
|
||||
boolean isValid = LocationUtils.isValidLocation(location);
|
||||
|
||||
if (gpsStatus != null) {
|
||||
gpsStatus.onLocationChanged(location);
|
||||
gpsStatus.onLocationChanged(trackPoint);
|
||||
}
|
||||
|
||||
if (!LocationUtils.isValidLocation(location)) {
|
||||
if (!isValid) {
|
||||
Log.w(TAG, "Ignore newTrackPoint. location is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
TrackPoint trackPoint = new TrackPoint(location);
|
||||
|
||||
if (!TrackPointUtils.fulfillsAccuracy(trackPoint, recordingGpsAccuracy)) {
|
||||
if (!isAccurate) {
|
||||
Log.d(TAG, "Ignore newTrackPoint. Poor accuracy.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package de.dennisguse.opentracks.util;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
@@ -16,27 +14,6 @@ public class TrackPointUtils {
|
||||
private TrackPointUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Ancient fix for phones that do not set the time in {@link android.location.Location}.
|
||||
* 2. Fix for GPS time rollover happening every 19.7 years: https://en.wikipedia.org/wiki/GPS_Week_Number_Rollover
|
||||
*/
|
||||
public static void fixTime(@NonNull TrackPoint trackPoint) {
|
||||
if (trackPoint.getTime() == 0L) {
|
||||
Log.w(TAG, "Time of provided location was 0. Using current time.");
|
||||
trackPoint.setTime(System.currentTimeMillis());
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
long timeDiff = Math.abs(trackPoint.getTime() - System.currentTimeMillis());
|
||||
|
||||
if (timeDiff > 1023 * UnitConversions.ONE_WEEK_MS) {
|
||||
Log.w(TAG, "GPS week rollover.");
|
||||
trackPoint.setTime(trackPoint.getTime() + 1024 * UnitConversions.ONE_WEEK_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMoving(@NonNull TrackPoint trackPoint) {
|
||||
return trackPoint.hasSpeed() && trackPoint.getSpeed() >= MAX_NO_MOVEMENT_SPEED;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user