Remove location listener from TrackDataHub.

This commit is contained in:
Jimmy Shih
2013-05-22 15:00:35 -07:00
parent 4a9f7778bd
commit 4eb8f4fff3
10 changed files with 7 additions and 328 deletions
@@ -17,8 +17,6 @@
package com.google.android.apps.mytracks.content;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.services.MyTracksLocationManager;
import com.google.android.gms.location.LocationListener;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,7 +24,6 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Looper;
/**
* Data source on the phone.
@@ -36,27 +33,13 @@ import android.os.Looper;
public class DataSource {
private final ContentResolver contentResolver;
private final MyTracksLocationManager myTracksLocationManager;
private final SharedPreferences sharedPreferences;
public DataSource(Context context) {
contentResolver = context.getContentResolver();
myTracksLocationManager = new MyTracksLocationManager(context, Looper.myLooper());
sharedPreferences = context.getSharedPreferences(Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
}
public void close() {
myTracksLocationManager.close();
}
public boolean isAllowed() {
return myTracksLocationManager.isAllowed();
}
public boolean isGpsProviderEnabled() {
return myTracksLocationManager.isGpsProviderEnabled();
}
/**
* Registers a content observer.
*
@@ -76,31 +59,6 @@ public class DataSource {
contentResolver.unregisterContentObserver(observer);
}
/**
* Registers a location listener.
*
* @param listener the listener
*/
public void registerLocationListener(LocationListener listener) {
myTracksLocationManager.requestLocationUpdates(0, 0, listener);
}
/**
* Unregisters a location listener.
*
* @param listener the listener
*/
public void unregisterLocationListener(LocationListener listener) {
myTracksLocationManager.removeLocationUpdates(listener);
}
/**
* Request last location.
*/
public void requestLastLocation(LocationListener locationListener) {
myTracksLocationManager.requestLastLocation(locationListener);
}
/**
* Registers a shared preference change listener.
*
@@ -16,7 +16,6 @@
package com.google.android.apps.mytracks.content;
import android.location.Location;
/**
* Listener to be invoked when {@link DataSource} changes.
@@ -40,20 +39,6 @@ public interface DataSourceListener {
*/
public void notifyTrackPointsTableUpdated();
/**
* Notifies when the current location changes.
*
* @param location the location
*/
public void notifyLocationChanged(Location location);
/**
* Notifies when the location provider enabled status changes.
*
* @param enabled true if enabled, false if not
*/
public void notifyLocationProviderEnabled(boolean enabled);
/**
* Notifies when a preference changes.
*
@@ -18,13 +18,9 @@ package com.google.android.apps.mytracks.content;
import static com.google.android.apps.mytracks.Constants.TAG;
import com.google.android.gms.location.LocationListener;
import com.google.common.annotations.VisibleForTesting;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.location.Location;
import android.os.Handler;
import android.util.Log;
@@ -91,22 +87,6 @@ public class DataSourceManager {
}
}
/**
* Listener for location changes.
*
* @author Jimmy Shih
*/
@VisibleForTesting
class CurrentLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
if (!dataSource.isAllowed()) {
return;
}
dataSourceListener.notifyLocationChanged(location);
}
}
/**
* Listener for preference changes.
*
@@ -130,7 +110,6 @@ public class DataSourceManager {
private final TracksTableObserver tracksTableObserver;
private final WaypointsTableObserver waypointsTableObserver;
private final TrackPointsTableObserver trackPointsTableObserver;
private final CurrentLocationListener currentLocationListener;
private final PreferenceListener preferenceListener;
public DataSourceManager(DataSource dataSource, DataSourceListener dataSourceListener) {
@@ -141,7 +120,6 @@ public class DataSourceManager {
tracksTableObserver = new TracksTableObserver();
waypointsTableObserver = new WaypointsTableObserver();
trackPointsTableObserver = new TrackPointsTableObserver();
currentLocationListener = new CurrentLocationListener();
preferenceListener = new PreferenceListener();
}
@@ -210,18 +188,6 @@ public class DataSourceManager {
case SAMPLED_OUT_TRACK_POINTS_TABLE:
// Do nothing. SAMPLED_OUT_POINT_UPDATES is mapped to POINT_UPDATES.
break;
case LOCATION:
if (dataSource.isGpsProviderEnabled()) {
dataSourceListener.notifyLocationProviderEnabled(true);
} else {
dataSourceListener.notifyLocationProviderEnabled(false);
}
if (dataSource.isAllowed()) {
dataSource.registerLocationListener(currentLocationListener);
} else {
dataSource.unregisterLocationListener(currentLocationListener);
}
break;
case PREFERENCE:
dataSource.registerOnSharedPreferenceChangeListener(preferenceListener);
break;
@@ -252,9 +218,6 @@ public class DataSourceManager {
case SAMPLED_OUT_TRACK_POINTS_TABLE:
// Do nothing. SAMPLED_OUT_POINT_UPDATES is mapped to POINT_UPDATES.
break;
case LOCATION:
dataSource.unregisterLocationListener(currentLocationListener);
break;
case PREFERENCE:
dataSource.unregisterOnSharedPreferenceChangeListener(preferenceListener);
break;
@@ -21,7 +21,6 @@ import static com.google.android.apps.mytracks.Constants.TARGET_DISPLAYED_TRACK_
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.content.TrackDataListener.LocationState;
import com.google.android.apps.mytracks.util.LocationUtils;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.maps.mytracks.R;
@@ -29,7 +28,6 @@ import com.google.common.annotations.VisibleForTesting;
import android.content.Context;
import android.database.Cursor;
import android.hardware.GeomagneticField;
import android.location.Location;
import android.os.Handler;
import android.os.HandlerThread;
@@ -48,12 +46,7 @@ import java.util.Set;
public class TrackDataHub implements DataSourceListener {
private static final String TAG = TrackDataHub.class.getSimpleName();
/**
* Maximum age of a location to be considered current.
*/
private static final long MAX_LOCATION_AGE_MS = 60 * 1000; // 1 minute
private final Context context;
private final TrackDataManager trackDataManager;
private final MyTracksProviderUtils myTracksProviderUtils;
@@ -74,12 +67,6 @@ public class TrackDataHub implements DataSourceListener {
private int minRequiredAccuracy;
private int minRecordingDistance;
// Location values
private Location lastSeenLocation = null;
private boolean hasProviderEnabled = true;
private boolean hasFix = false;
private boolean hasGoodFix = false;
// Track points sampling state
private int numLoadedPoints;
private long firstSeenLocationId;
@@ -151,7 +138,6 @@ public class TrackDataHub implements DataSourceListener {
handlerThread = null;
handler = null;
dataSource.close();
dataSource = null;
dataSourceManager = null;
}
@@ -351,28 +337,6 @@ public class TrackDataHub implements DataSourceListener {
});
}
@Override
public void notifyLocationProviderEnabled(final boolean enabled) {
runInHanderThread(new Runnable() {
@Override
public void run() {
hasProviderEnabled = enabled;
notifyLocationStateChanged(trackDataManager.getListeners(TrackDataType.LOCATION));
}
});
}
@Override
public void notifyLocationChanged(final Location location) {
runInHanderThread(new Runnable() {
@Override
public void run() {
notifyLocationChanged(
location, false, trackDataManager.getListeners(TrackDataType.LOCATION));
}
});
}
/**
* Loads data for all listeners. To be run in the {@link #handler} thread.
*/
@@ -401,13 +365,6 @@ public class TrackDataHub implements DataSourceListener {
trackDataManager.getListeners(TrackDataType.SAMPLED_IN_TRACK_POINTS_TABLE),
trackDataManager.getListeners(TrackDataType.SAMPLED_OUT_TRACK_POINTS_TABLE));
notifyWaypointsTableUpdate(trackDataManager.getListeners(TrackDataType.WAYPOINTS_TABLE));
if (lastSeenLocation != null) {
notifyLocationChanged(
lastSeenLocation, true, trackDataManager.getListeners(TrackDataType.LOCATION));
} else {
notifyLocationStateChanged(trackDataManager.getListeners(TrackDataType.LOCATION));
}
}
/**
@@ -451,14 +408,6 @@ public class TrackDataHub implements DataSourceListener {
if (trackDataTypes.contains(TrackDataType.WAYPOINTS_TABLE)) {
notifyWaypointsTableUpdate(trackDataListeners);
}
if (trackDataTypes.contains(TrackDataType.LOCATION)) {
if (lastSeenLocation != null) {
notifyLocationChanged(lastSeenLocation, true, trackDataListeners);
} else {
notifyLocationStateChanged(trackDataListeners);
}
}
}
/**
@@ -620,64 +569,6 @@ public class TrackDataHub implements DataSourceListener {
}
}
/**
* Notifies location state changed. To be run in the {@link #handler} thread.
*
* @param trackDataListeners the track data listeners to notify
*/
private void notifyLocationStateChanged(Set<TrackDataListener> trackDataListeners) {
if (trackDataListeners.isEmpty()) {
return;
}
TrackDataListener.LocationState locationState;
if (!hasProviderEnabled) {
locationState = LocationState.DISABLED;
lastSeenLocation = null;
} else if (!hasFix) {
locationState = LocationState.NO_FIX;
} else if (!hasGoodFix) {
locationState = LocationState.BAD_FIX;
} else {
locationState = LocationState.GOOD_FIX;
}
for (TrackDataListener trackDataListener : trackDataListeners) {
trackDataListener.onLocationStateChanged(locationState);
}
}
/**
* Notifies location changed. To be run in the {@link #handler} thread.
*
* @param location the location
* @param notifyLocationStateChange true to always notify location state
* change
* @param trackDataListeners the track data listeners to notify
*/
private void notifyLocationChanged(Location location, boolean notifyLocationStateChange,
Set<TrackDataListener> trackDataListeners) {
if (location == null) {
return;
}
boolean oldHasFix = hasFix;
boolean oldHasGoodFix = hasGoodFix;
hasFix = !isLocationOld(location, System.currentTimeMillis(), MAX_LOCATION_AGE_MS);
hasGoodFix = location.getAccuracy() <= minRequiredAccuracy;
lastSeenLocation = location;
if (trackDataListeners.isEmpty()) {
return;
}
if (notifyLocationStateChange || hasFix != oldHasFix || hasGoodFix != oldHasGoodFix) {
notifyLocationStateChanged(trackDataListeners);
}
for (TrackDataListener trackDataListener : trackDataListeners) {
trackDataListener.onLocationChanged(lastSeenLocation);
}
}
/**
* Resets the track points sampling states.
*/
@@ -687,17 +578,6 @@ public class TrackDataHub implements DataSourceListener {
lastSeenLocationId = -1L;
}
/**
* Returns true if a location is invalid or too old.
*
* @param location the location
* @param now the current time
* @param maxAge the maximum age
*/
private boolean isLocationOld(Location location, long now, long maxAge) {
return !LocationUtils.isValidLocation(location) || (now - location.getTime() > maxAge);
}
/**
* Creates a {@link DataSource}.
*/
@@ -706,19 +586,6 @@ public class TrackDataHub implements DataSourceListener {
return new DataSource(context);
}
/**
* Gets a declination.
*
* @param location the location
* @param time the time
*/
@VisibleForTesting
protected float getDeclination(Location location, long time) {
GeomagneticField field = new GeomagneticField((float) location.getLatitude(), (float) location
.getLongitude(), (float) location.getAltitude(), time);
return field.getDeclination();
}
/**
* Run in the handler thread.
*
@@ -773,14 +640,4 @@ public class TrackDataHub implements DataSourceListener {
boolean isReportSpeed() {
return reportSpeed;
}
/**
* Sets the value of lastSeenLocation.
*
* @param lastSeenLocation value of lastSeenLocation
*/
@VisibleForTesting
void setLastSeenLocation(Location lastSeenLocation) {
this.lastSeenLocation = lastSeenLocation;
}
}
@@ -34,21 +34,6 @@ public interface TrackDataListener {
DISABLED, NO_FIX, BAD_FIX, GOOD_FIX;
}
/**
* Called when the location state changes.
*/
public void onLocationStateChanged(LocationState locationState);
/**
* Called when the location changes. This is meant for location display only,
* track point data is reported with other methods like
* {@link #onSampledInTrackPoint(Location)} and
* {@link #onSampledOutTrackPoint(Location)}.
*
* @param location the location
*/
public void onLocationChanged(Location location);
/**
* Called when the selected track changes. This will be followed by calls to
* data methods such as {@link #onTrackUpdated(Track)},
@@ -27,6 +27,5 @@ public enum TrackDataType {
WAYPOINTS_TABLE, // waypoints table changes
SAMPLED_IN_TRACK_POINTS_TABLE, // sampled-in track points table changes
SAMPLED_OUT_TRACK_POINTS_TABLE, // sampled-out track points table changes
LOCATION, // location changes
PREFERENCE // preference changes
}
@@ -155,16 +155,6 @@ public class ChartFragment extends Fragment implements TrackDataListener {
layout.removeView(chartView);
}
@Override
public void onLocationStateChanged(LocationState state) {
// We don't care.
}
@Override
public void onLocationChanged(Location loc) {
// We don't care.
}
@Override
public void onSelectedTrackChanged(Track track) {
// We don't care.
@@ -386,16 +386,6 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
}
return true;
}
@Override
public void onLocationStateChanged(LocationState locationState) {
// We don't care.
}
@Override
public void onLocationChanged(Location location) {
// We don't care.
}
@Override
public void onSelectedTrackChanged(final Track track) {
@@ -97,16 +97,6 @@ public class StatsFragment extends Fragment implements TrackDataListener {
handler.removeCallbacks(updateTotalTime);
}
@Override
public void onLocationStateChanged(LocationState state) {
// We don't care.
}
@Override
public void onLocationChanged(final Location location) {
// We don't care.
}
@Override
public void onSelectedTrackChanged(Track track) {
if (isResumed()) {
@@ -22,13 +22,10 @@ import static com.google.android.testing.mocking.AndroidMock.isA;
import com.google.android.apps.mytracks.Constants;
import com.google.android.apps.mytracks.TrackStubUtils;
import com.google.android.apps.mytracks.content.DataSourceManager.CurrentLocationListener;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationFactory;
import com.google.android.apps.mytracks.content.MyTracksProviderUtils.LocationIterator;
import com.google.android.apps.mytracks.content.TrackDataListener.LocationState;
import com.google.android.apps.mytracks.services.TrackRecordingServiceTest.MockContext;
import com.google.android.apps.mytracks.util.PreferencesUtils;
import com.google.android.gms.location.LocationListener;
import com.google.android.maps.mytracks.R;
import com.google.android.testing.mocking.AndroidMock;
import com.google.android.testing.mocking.UsesMocks;
@@ -72,7 +69,6 @@ public class TrackDataHubTest extends AndroidTestCase {
private TrackDataListener trackDataListener2;
private Capture<OnSharedPreferenceChangeListener> preferenceChangeListenerCapture = new Capture<
SharedPreferences.OnSharedPreferenceChangeListener>();
private float declination;
@UsesMocks({ MyTracksProviderUtils.class, DataSource.class, TrackDataListener.class })
@Override
@@ -96,11 +92,6 @@ public class TrackDataHubTest extends AndroidTestCase {
// Run everything in the same thread
runnable.run();
}
@Override
protected float getDeclination(Location location, long timestamp) {
return declination;
}
};
trackDataListener1 = AndroidMock.createStrictMock(
@@ -118,10 +109,8 @@ public class TrackDataHubTest extends AndroidTestCase {
// Expect everything to be unregistered.
dataSource.unregisterContentObserver(isA(ContentObserver.class));
AndroidMock.expectLastCall().times(3);
dataSource.unregisterLocationListener(isA(LocationListener.class));
dataSource.unregisterOnSharedPreferenceChangeListener(
isA(OnSharedPreferenceChangeListener.class));
dataSource.close();
AndroidMock.replay(dataSource);
trackDataHub.stop();
@@ -540,16 +529,22 @@ public class TrackDataHubTest extends AndroidTestCase {
// Register two listeners
PreferencesUtils.setBoolean(context, R.string.report_speed_key, true);
PreferencesUtils.setBoolean(context, R.string.metric_units_key, true);
PreferencesUtils.setInt(context, R.string.min_required_accuracy_key,
PreferencesUtils.MIN_REQUIRED_ACCURACY_DEFAULT);
PreferencesUtils.setInt(context, R.string.min_recording_distance_key,
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT);
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
expect(trackDataListener1.onMetricUnitsChanged(true)).andReturn(false);
expect(trackDataListener1.onReportSpeedChanged(true)).andReturn(false);
expect(trackDataListener1.onMinRequiredAccuracy(PreferencesUtils.MIN_REQUIRED_ACCURACY_DEFAULT))
.andReturn(false);
expect(trackDataListener1.onMinRecordingDistanceChanged(
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT)).andReturn(false);
expect(trackDataListener2.onMetricUnitsChanged(true)).andReturn(false);
expect(trackDataListener2.onReportSpeedChanged(true)).andReturn(false);
expect(trackDataListener2.onMinRequiredAccuracy(PreferencesUtils.MIN_REQUIRED_ACCURACY_DEFAULT))
.andReturn(false);
expect(trackDataListener2.onMinRecordingDistanceChanged(
PreferencesUtils.MIN_RECORDING_DISTANCE_DEFAULT)).andReturn(false);
replay();
@@ -766,39 +761,6 @@ public class TrackDataHubTest extends AndroidTestCase {
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()} when no last seen location.
*/
public void testRegisterLocationListener_noLastSeenLocation() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<CurrentLocationListener> currentLocationListener = new Capture<
CurrentLocationListener>();
dataSource.registerLocationListener(capture(currentLocationListener));
trackDataListener1.onLocationStateChanged(capture(new Capture<LocationState>()));
replay();
trackDataHub.setLastSeenLocation(null);
trackDataHub.start();
trackDataHub.registerTrackDataListener(trackDataListener1, EnumSet.of(TrackDataType.LOCATION));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#start()} when has last seen location.
*/
public void testRegisterLocationListener_hasLastSeenLocation() {
dataSource.registerOnSharedPreferenceChangeListener(capture(preferenceChangeListenerCapture));
Capture<CurrentLocationListener> currentLocationListener = new Capture<
CurrentLocationListener>();
dataSource.registerLocationListener(capture(currentLocationListener));
trackDataListener1.onLocationStateChanged(capture(new Capture<LocationState>()));
trackDataListener1.onLocationChanged(capture(new Capture<Location>()));
replay();
trackDataHub.setLastSeenLocation(new Location("gps"));
trackDataHub.start();
trackDataHub.registerTrackDataListener(trackDataListener1, EnumSet.of(TrackDataType.LOCATION));
verifyAndReset();
}
/**
* Tests the method {@link TrackDataHub#notifyPreferenceChanged(String)} when
* the key is R.string.min_required_accuracy_key.