From 6deadaa2904ba642415138b9b3c25699ec9bb6ab Mon Sep 17 00:00:00 2001 From: Sarah Lensing Date: Tue, 6 Jun 2017 15:00:06 -0400 Subject: [PATCH 1/5] Add equals & hashCode to LocationRequest --- .../android/lost/api/LocationRequest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lost/src/main/java/com/mapzen/android/lost/api/LocationRequest.java b/lost/src/main/java/com/mapzen/android/lost/api/LocationRequest.java index a47affd..3371b68 100644 --- a/lost/src/main/java/com/mapzen/android/lost/api/LocationRequest.java +++ b/lost/src/main/java/com/mapzen/android/lost/api/LocationRequest.java @@ -73,6 +73,28 @@ public LocationRequest setPriority(int priority) { return this; } + @Override public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + LocationRequest that = (LocationRequest) o; + + if (interval != that.interval) return false; + if (fastestInterval != that.fastestInterval) return false; + if (Float.compare(that.smallestDisplacement, smallestDisplacement) != 0) return false; + return priority == that.priority; + } + + @Override public int hashCode() { + int result = (int) (interval ^ (interval >>> 32)); + result = 31 * result + (int) (fastestInterval ^ (fastestInterval >>> 32)); + result = + 31 * result + (smallestDisplacement != +0.0f ? Float.floatToIntBits(smallestDisplacement) + : 0); + result = 31 * result + priority; + return result; + } + @Override public int describeContents() { return 0; } From 42b8e744058c34cde98d43ef4f907347e3cfb1bb Mon Sep 17 00:00:00 2001 From: Sarah Lensing Date: Tue, 6 Jun 2017 15:05:12 -0400 Subject: [PATCH 2/5] remove location request and update engine when location updates removed --- .../IFusedLocationProviderService.aidl | 2 +- .../android/lost/api/LocationServices.java | 3 +- .../lost/internal/ClientCallbackWrapper.java | 44 +++ .../FusedLocationProviderApiImpl.java | 41 ++- .../FusedLocationProviderService.java | 5 +- .../FusedLocationProviderServiceDelegate.java | 8 +- .../android/lost/internal/LocationEngine.java | 28 +- .../internal/LocationRequestUnbundled.java | 15 + .../lost/internal/LostRequestManager.java | 97 ++++++ .../android/lost/internal/RequestManager.java | 32 ++ .../FusedLocationProviderApiImplTest.java | 87 +++++- ...edLocationProviderServiceDelegateTest.java | 9 +- .../lost/internal/FusionEngineTest.java | 47 +-- .../internal/LostRequestManagerTests.java | 288 ++++++++++++++++++ .../android/lost/internal/MockEngineTest.java | 2 +- .../lost/internal/TestServiceStub.java | 2 +- 16 files changed, 651 insertions(+), 59 deletions(-) create mode 100644 lost/src/main/java/com/mapzen/android/lost/internal/ClientCallbackWrapper.java create mode 100644 lost/src/main/java/com/mapzen/android/lost/internal/LostRequestManager.java create mode 100644 lost/src/main/java/com/mapzen/android/lost/internal/RequestManager.java create mode 100644 lost/src/test/java/com/mapzen/android/lost/internal/LostRequestManagerTests.java diff --git a/lost/src/main/aidl/com/mapzen/android/lost/internal/IFusedLocationProviderService.aidl b/lost/src/main/aidl/com/mapzen/android/lost/internal/IFusedLocationProviderService.aidl index 54ae9db..7b0c026 100644 --- a/lost/src/main/aidl/com/mapzen/android/lost/internal/IFusedLocationProviderService.aidl +++ b/lost/src/main/aidl/com/mapzen/android/lost/internal/IFusedLocationProviderService.aidl @@ -14,7 +14,7 @@ interface IFusedLocationProviderService { void requestLocationUpdates(in LocationRequest request); - void removeLocationUpdates(); + void removeLocationUpdates(in LocationRequest request); void setMockMode(boolean isMockMode); diff --git a/lost/src/main/java/com/mapzen/android/lost/api/LocationServices.java b/lost/src/main/java/com/mapzen/android/lost/api/LocationServices.java index 19155e0..5dffab3 100644 --- a/lost/src/main/java/com/mapzen/android/lost/api/LocationServices.java +++ b/lost/src/main/java/com/mapzen/android/lost/api/LocationServices.java @@ -6,6 +6,7 @@ import com.mapzen.android.lost.internal.FusedLocationServiceConnectionManager; import com.mapzen.android.lost.internal.GeofencingApiImpl; import com.mapzen.android.lost.internal.GeofencingServiceIntentFactory; +import com.mapzen.android.lost.internal.LostRequestManager; import com.mapzen.android.lost.internal.PendingIntentIdGenerator; import com.mapzen.android.lost.internal.SettingsApiImpl; @@ -19,7 +20,7 @@ public class LocationServices { */ public static final FusedLocationProviderApi FusedLocationApi = new FusedLocationProviderApiImpl(new FusedLocationServiceConnectionManager(), - new FusedLocationServiceCallbackManager()); + new FusedLocationServiceCallbackManager(), LostRequestManager.shared()); /** * Entry point for APIs concerning geofences. diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/ClientCallbackWrapper.java b/lost/src/main/java/com/mapzen/android/lost/internal/ClientCallbackWrapper.java new file mode 100644 index 0000000..e9d2030 --- /dev/null +++ b/lost/src/main/java/com/mapzen/android/lost/internal/ClientCallbackWrapper.java @@ -0,0 +1,44 @@ +package com.mapzen.android.lost.internal; + +import com.mapzen.android.lost.api.LocationCallback; +import com.mapzen.android.lost.api.LocationListener; +import com.mapzen.android.lost.api.LostApiClient; + +import android.app.PendingIntent; + +/** + * Wraps a {@link LostApiClient} to either a {@link LocationListener}, {@link PendingIntent}, or + * {@link LocationCallback}. + */ +class ClientCallbackWrapper { + + private LostApiClient client; + private Object callback; + + public ClientCallbackWrapper(LostApiClient client, T callback) { + this.client = client; + this.callback = callback; + } + + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ClientCallbackWrapper wrapper = (ClientCallbackWrapper) o; + + if (!client.equals(wrapper.client)) { + return false; + } + return callback.equals(wrapper.callback); + } + + @Override public int hashCode() { + int result = client.hashCode(); + result = 31 * result + callback.hashCode(); + return result; + } +} diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java index 8ebfe6c..2cd195b 100644 --- a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java +++ b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImpl.java @@ -33,6 +33,7 @@ public class FusedLocationProviderApiImpl extends ApiImpl private Context context; private FusedLocationServiceConnectionManager serviceConnectionManager; private FusedLocationServiceCallbackManager serviceCallbackManager; + private RequestManager requestManager; private boolean isBound; IFusedLocationProviderService service; @@ -88,9 +89,10 @@ public void onLocationChanged(final Location location) throws RemoteException { } public FusedLocationProviderApiImpl(FusedLocationServiceConnectionManager connectionManager, - FusedLocationServiceCallbackManager callbackManager) { + FusedLocationServiceCallbackManager callbackManager, RequestManager requestManager) { serviceConnectionManager = connectionManager; serviceCallbackManager = callbackManager; + this.requestManager = requestManager; serviceConnectionManager.setEventCallbacks(this); } @@ -135,6 +137,7 @@ public boolean isConnected() { @Override public PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, LocationListener listener) { throwIfNotConnected(client); + requestManager.requestLocationUpdates(client, request, listener); LostClientManager.shared().addListener(client, request, listener); requestLocationUpdatesInternal(request); return new SimplePendingResult(true); @@ -148,6 +151,7 @@ public boolean isConnected() { @Override public PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, LocationCallback callback, Looper looper) { throwIfNotConnected(client); + requestManager.requestLocationUpdates(client, request, callback); LostClientManager.shared().addLocationCallback(client, request, callback, looper); requestLocationUpdatesInternal(request); return new SimplePendingResult(true); @@ -156,6 +160,7 @@ public boolean isConnected() { @Override public PendingResult requestLocationUpdates(LostApiClient client, LocationRequest request, PendingIntent callbackIntent) { throwIfNotConnected(client); + requestManager.requestLocationUpdates(client, request, callbackIntent); LostClientManager.shared().addPendingIntent(client, request, callbackIntent); requestLocationUpdatesInternal(request); return new SimplePendingResult(true); @@ -173,9 +178,24 @@ private void requestLocationUpdatesInternal(LocationRequest request) { } } + private void removeLocationUpdatesInternal(Set requests) { + if (requests == null) { + return; + } + for (LocationRequest request : requests) { + try { + service.removeLocationUpdates(request); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + } + @Override public PendingResult removeLocationUpdates(LostApiClient client, LocationListener listener) { throwIfNotConnected(client); + Set requests = requestManager.removeLocationUpdates(client, listener); + removeLocationUpdatesInternal(requests); boolean hasResult = LostClientManager.shared().removeListener(client, listener); checkAllListenersPendingIntentsAndCallbacks(); return new SimplePendingResult(hasResult); @@ -184,6 +204,8 @@ private void requestLocationUpdatesInternal(LocationRequest request) { @Override public PendingResult removeLocationUpdates(LostApiClient client, PendingIntent callbackIntent) { throwIfNotConnected(client); + Set requests = requestManager.removeLocationUpdates(client, callbackIntent); + removeLocationUpdatesInternal(requests); boolean hasResult = LostClientManager.shared().removePendingIntent(client, callbackIntent); checkAllListenersPendingIntentsAndCallbacks(); return new SimplePendingResult(hasResult); @@ -192,6 +214,8 @@ private void requestLocationUpdatesInternal(LocationRequest request) { @Override public PendingResult removeLocationUpdates(LostApiClient client, LocationCallback callback) { throwIfNotConnected(client); + Set requests = requestManager.removeLocationUpdates(client, callback); + removeLocationUpdatesInternal(requests); boolean hasResult = LostClientManager.shared().removeLocationCallback(client, callback); checkAllListenersPendingIntentsAndCallbacks(); return new SimplePendingResult(hasResult); @@ -202,13 +226,14 @@ private void requestLocationUpdatesInternal(LocationRequest request) { * then shutdown the location engines. */ private void checkAllListenersPendingIntentsAndCallbacks() { - if (LostClientManager.shared().hasNoListeners()) { - try { - service.removeLocationUpdates(); - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } + //TODO: potentially remove hasNoListeners method, not needed anymore + //if (LostClientManager.shared().hasNoListeners()) { + // try { + // service.removeAllLocationUpdates(); + // } catch (RemoteException e) { + // throw new RuntimeException(e); + // } + //} } @Override public PendingResult setMockMode(LostApiClient client, boolean isMockMode) { diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderService.java b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderService.java index cbb972a..c7fa757 100644 --- a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderService.java +++ b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderService.java @@ -36,8 +36,9 @@ public class FusedLocationProviderService extends Service { delegate.requestLocationUpdates(request); } - @Override public void removeLocationUpdates() throws RemoteException { - delegate.removeLocationUpdates(); + @Override public void removeLocationUpdates(LocationRequest request) + throws RemoteException { + delegate.removeLocationUpdates(request); } @Override public void setMockMode(boolean isMockMode) throws RemoteException { diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegate.java b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegate.java index 087d121..b8b6333 100644 --- a/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegate.java +++ b/lost/src/main/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegate.java @@ -43,11 +43,11 @@ public LocationAvailability getLocationAvailability() { } public void requestLocationUpdates(LocationRequest request) { - locationEngine.setRequest(request); + locationEngine.addRequest(request); } - public void removeLocationUpdates() { - locationEngine.setRequest(null); + public void removeLocationUpdates(LocationRequest request) { + locationEngine.removeRequest(request); } public void setMockMode(boolean isMockMode) { @@ -114,7 +114,7 @@ public void onProviderDisabled(String s) { private void toggleMockMode() { mockMode = !mockMode; - locationEngine.setRequest(null); + locationEngine.removeAllRequests(); if (mockMode) { locationEngine = new MockEngine(context, this, new GpxTraceThreadFactory()); } else { diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/LocationEngine.java b/lost/src/main/java/com/mapzen/android/lost/internal/LocationEngine.java index 2724d5f..d63f284 100644 --- a/lost/src/main/java/com/mapzen/android/lost/internal/LocationEngine.java +++ b/lost/src/main/java/com/mapzen/android/lost/internal/LocationEngine.java @@ -35,21 +35,37 @@ public LocationEngine(Context context, Callback callback) { public abstract boolean isProviderEnabled(String provider); /** - * Enables the engine on receiving a valid location request. Disables the engine on receiving a - * {@code null} request. + * Enables the engine on receiving a valid location request. * - * @param request Valid location request to enable or {@code null} to disable. + * @param request Valid location request to enable. */ - public void setRequest(LocationRequest request) { + public void addRequest(LocationRequest request) { if (request != null) { this.request.addRequest(request); enable(); - } else { - this.request.removeAllRequests(); + } + } + + /** + * Disables the engine when no requests remain, otherwise updates the engine's configuration. + * + * @param request Valid location request to enable. + */ + public void removeRequest(LocationRequest request) { + if (request != null) { + this.request.removeRequest(request); disable(); + if (!this.request.getRequests().isEmpty()) { + enable(); + } } } + public void removeAllRequests() { + this.request.removeAllRequests(); + disable(); + } + /** * Subclass should perform all operations required to enable the engine. (ex. Register for * location updates.) diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/LocationRequestUnbundled.java b/lost/src/main/java/com/mapzen/android/lost/internal/LocationRequestUnbundled.java index 57fa8af..12ce818 100644 --- a/lost/src/main/java/com/mapzen/android/lost/internal/LocationRequestUnbundled.java +++ b/lost/src/main/java/com/mapzen/android/lost/internal/LocationRequestUnbundled.java @@ -20,6 +20,11 @@ public void addRequest(LocationRequest request) { requests.add(request); } + public void removeRequest(LocationRequest request) { + requests.remove(request); + fastestInterval = calculateFastestInterval(); + } + public void removeAllRequests() { fastestInterval = Long.MAX_VALUE; requests.clear(); @@ -32,4 +37,14 @@ public List getRequests() { public long getFastestInterval() { return fastestInterval; } + + public long calculateFastestInterval() { + long interval = Long.MAX_VALUE; + for (LocationRequest request : requests) { + if (request.getFastestInterval() < interval) { + interval = request.getFastestInterval(); + } + } + return interval; + } } diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/LostRequestManager.java b/lost/src/main/java/com/mapzen/android/lost/internal/LostRequestManager.java new file mode 100644 index 0000000..c35e9c9 --- /dev/null +++ b/lost/src/main/java/com/mapzen/android/lost/internal/LostRequestManager.java @@ -0,0 +1,97 @@ +package com.mapzen.android.lost.internal; + +import com.mapzen.android.lost.api.LocationCallback; +import com.mapzen.android.lost.api.LocationListener; +import com.mapzen.android.lost.api.LocationRequest; +import com.mapzen.android.lost.api.LostApiClient; + +import android.app.PendingIntent; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Manages requests for {@link ClientCallbackWrapper}s so that the system can properly remove + * unused requests from the {@link LocationEngine}. + */ +public class LostRequestManager implements RequestManager { + + private static LostRequestManager instance; + private Map> clientCallbackToLocationRequests; + + LostRequestManager() { + clientCallbackToLocationRequests = new HashMap<>(); + } + + public static LostRequestManager shared() { + if (instance == null) { + instance = new LostRequestManager(); + } + return instance; + } + + @Override public void requestLocationUpdates(LostApiClient client, LocationRequest request, + LocationListener listener) { + ClientCallbackWrapper wrapper = getWrapper(client, listener); + registerRequest(wrapper, request); + } + + @Override public void requestLocationUpdates(LostApiClient client, LocationRequest request, + LocationCallback callback) { + ClientCallbackWrapper wrapper = getWrapper(client, callback); + registerRequest(wrapper, request); + } + + @Override public void requestLocationUpdates(LostApiClient client, LocationRequest request, + PendingIntent callbackIntent) { + ClientCallbackWrapper wrapper = getWrapper(client, callbackIntent); + registerRequest(wrapper, request); + } + + @Override public Set removeLocationUpdates(LostApiClient client, LocationListener listener) { + ClientCallbackWrapper wrapper = getWrapper(client, listener); + return getRequestOnlyUsedBy(wrapper); + } + + @Override public Set removeLocationUpdates(LostApiClient client, PendingIntent callbackIntent) { + ClientCallbackWrapper wrapper = getWrapper(client, callbackIntent); + return getRequestOnlyUsedBy(wrapper); + } + + @Override public Set removeLocationUpdates(LostApiClient client, LocationCallback callback) { + ClientCallbackWrapper wrapper = getWrapper(client, callback); + return getRequestOnlyUsedBy(wrapper); + } + + private ClientCallbackWrapper getWrapper(LostApiClient client, T callback) { + return new ClientCallbackWrapper(client, callback); + } + + private void registerRequest(ClientCallbackWrapper wrapper, LocationRequest request) { + Set requests = clientCallbackToLocationRequests.get(wrapper); + if (requests == null) { + requests = new HashSet<>(); + clientCallbackToLocationRequests.put(wrapper, requests); + } + requests.add(request); + } + + private Set getRequestOnlyUsedBy(ClientCallbackWrapper wrapper) { + Set requestsToRemove = clientCallbackToLocationRequests.get(wrapper); + if (requestsToRemove == null) { + return requestsToRemove; + } + clientCallbackToLocationRequests.remove(wrapper); + for (ClientCallbackWrapper w : clientCallbackToLocationRequests.keySet()) { + Set requests = clientCallbackToLocationRequests.get(w); + requestsToRemove.removeAll(requests); + } + return requestsToRemove; + } + + Map> getClientCallbackMap() { + return clientCallbackToLocationRequests; + } +} diff --git a/lost/src/main/java/com/mapzen/android/lost/internal/RequestManager.java b/lost/src/main/java/com/mapzen/android/lost/internal/RequestManager.java new file mode 100644 index 0000000..a88f0c0 --- /dev/null +++ b/lost/src/main/java/com/mapzen/android/lost/internal/RequestManager.java @@ -0,0 +1,32 @@ +package com.mapzen.android.lost.internal; + +import com.mapzen.android.lost.api.LocationCallback; +import com.mapzen.android.lost.api.LocationListener; +import com.mapzen.android.lost.api.LocationRequest; +import com.mapzen.android.lost.api.LostApiClient; + +import android.app.PendingIntent; + +import java.util.Set; + +/** + * Keeps track of which {@link LocationListener}s, {@link PendingIntent}s, and + * {@link LocationCallback}s have made which {@link LocationRequest}s so that requests can be + * properly removed from the underlying {@link LocationEngine}. + */ +interface RequestManager { + void requestLocationUpdates(LostApiClient client, LocationRequest request, + LocationListener listener); + + void requestLocationUpdates(LostApiClient client, LocationRequest request, + LocationCallback callback); + + void requestLocationUpdates(LostApiClient client, LocationRequest request, + PendingIntent callbackIntent); + + Set removeLocationUpdates(LostApiClient client, LocationListener listener); + + Set removeLocationUpdates(LostApiClient client, PendingIntent callbackIntent); + + Set removeLocationUpdates(LostApiClient client, LocationCallback callback); +} diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java b/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java index 580b332..c8c0542 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderApiImplTest.java @@ -10,6 +10,8 @@ import com.mapzen.android.lost.api.Status; import com.mapzen.lost.BuildConfig; +import com.google.common.collect.Lists; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,6 +28,8 @@ import android.os.Looper; import android.support.annotation.NonNull; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.TimeUnit; import static org.fest.assertions.api.Assertions.assertThat; @@ -35,6 +39,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.robolectric.RuntimeEnvironment.application; @RunWith(RobolectricTestRunner.class) @@ -44,6 +49,7 @@ public class FusedLocationProviderApiImplTest extends BaseRobolectricTest { private LostApiClient connectedClient; private LostApiClient disconnectedClient; + private RequestManager requestManager; private FusedLocationProviderApiImpl api; private IFusedLocationProviderService service = mock(IFusedLocationProviderService.class); private FusedLocationServiceConnectionManager connectionManager; @@ -57,12 +63,13 @@ public class FusedLocationProviderApiImplTest extends BaseRobolectricTest { disconnectedClient = new LostApiClient.Builder(RuntimeEnvironment.application).build(); connectionManager = spy(new FusedLocationServiceConnectionManager()); + requestManager = mock(RequestManager.class); Mockito.doCallRealMethod().when(connectionManager).setEventCallbacks(any( FusedLocationServiceConnectionManager.EventCallbacks.class)); Mockito.doCallRealMethod().when(connectionManager).connect(any(Context.class), any( LostApiClient.ConnectionCallbacks.class)); api = new FusedLocationProviderApiImpl(connectionManager, - new FusedLocationServiceCallbackManager()); + new FusedLocationServiceCallbackManager(), requestManager); api.connect(application, null); api.service = service; } @@ -198,20 +205,35 @@ public void removeLocationUpdates_callback_shouldThrowIfNotConnected() throws Ex @Test public void removeLocationUpdates_listener_shouldCallService() throws Exception { LocationListener listener = new TestLocationListener(); + LocationRequest request = LocationRequest.create(); + Set requests = new HashSet<>(); + requests.add(request); + when(requestManager.removeLocationUpdates(connectedClient, listener)). + thenReturn(requests); api.removeLocationUpdates(connectedClient, listener); - verify(service).removeLocationUpdates(); + verify(service).removeLocationUpdates(any(LocationRequest.class)); } @Test public void removeLocationUpdates_pendingIntent_shouldCallService() throws Exception { PendingIntent callbackIntent = mock(PendingIntent.class); + LocationRequest request = LocationRequest.create(); + Set requests = new HashSet<>(); + requests.add(request); + when(requestManager.removeLocationUpdates(connectedClient, callbackIntent)). + thenReturn(requests); api.removeLocationUpdates(connectedClient, callbackIntent); - verify(service).removeLocationUpdates(); + verify(service).removeLocationUpdates(request); } @Test public void removeLocationUpdates_callback_shouldCallService() throws Exception { TestLocationCallback callback = new TestLocationCallback(); + LocationRequest request = LocationRequest.create(); + Set requests = new HashSet<>(); + requests.add(request); + when(requestManager.removeLocationUpdates(connectedClient, callback)). + thenReturn(requests); api.removeLocationUpdates(connectedClient, callback); - verify(service).removeLocationUpdates(); + verify(service).removeLocationUpdates(request); } @Test(expected = IllegalStateException.class) @@ -366,19 +388,68 @@ public void setMockTrace_shouldThrowIfNotConnected() throws Exception { @Test public void removeLocationUpdates_shouldKillEngineIfNoListenersStillActive() throws Exception { TestLocationListener listener = new TestLocationListener(); - api.requestLocationUpdates(connectedClient, LocationRequest.create(), listener); + LocationRequest request = LocationRequest.create(); + Set requests = new HashSet<>(); + requests.add(request); + when(requestManager.removeLocationUpdates(connectedClient, listener)). + thenReturn(requests); + api.requestLocationUpdates(connectedClient, request, listener); api.removeLocationUpdates(connectedClient, listener); - verify(service).removeLocationUpdates(); + verify(service).removeLocationUpdates(request); } @Test public void removeLocationUpdates_shouldNotKillEngineIfListenerStillActive() throws Exception { TestLocationListener listener1 = new TestLocationListener(); TestLocationListener listener2 = new TestLocationListener(); - api.requestLocationUpdates(connectedClient, LocationRequest.create(), listener1); + LocationRequest request = LocationRequest.create(); + Set requests = new HashSet<>(); + requests.add(request); + when(requestManager.removeLocationUpdates(connectedClient, listener1)). + thenReturn(requests); + api.requestLocationUpdates(connectedClient, request, listener1); api.requestLocationUpdates(connectedClient, LocationRequest.create(), listener2); api.removeLocationUpdates(connectedClient, listener1); - verify(service, never()).removeLocationUpdates(); + verify(service).removeLocationUpdates(request); + } + + @Test public void removeLocationUpdates_listener_shouldCallRequestManager() { + LocationListener listener = mock(LocationListener.class); + api.removeLocationUpdates(connectedClient, listener); + verify(requestManager).removeLocationUpdates(connectedClient, listener); + } + + @Test public void removeLocationUpdates_pendingIntent_shouldCallRequestManager() { + PendingIntent intent = mock(PendingIntent.class); + api.removeLocationUpdates(connectedClient, intent); + verify(requestManager).removeLocationUpdates(connectedClient, intent); + } + + @Test public void removeLocationUpdates_callback_shouldCallRequestManager() { + LocationCallback callback = mock(LocationCallback.class); + api.removeLocationUpdates(connectedClient, callback); + verify(requestManager).removeLocationUpdates(connectedClient, callback); + } + + @Test public void requestLocationUpdates_listener_shouldCallRequestManager() { + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + api.requestLocationUpdates(connectedClient, request, listener); + verify(requestManager).requestLocationUpdates(connectedClient, request, listener); + } + + @Test public void requestLocationUpdates_pendingIntent_shouldCallRequestManager() { + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + api.requestLocationUpdates(connectedClient, request, intent); + verify(requestManager).requestLocationUpdates(connectedClient, request, intent); + } + + @Test public void requestLocationUpdates_callback_shouldCallRequestManager() { + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + api.requestLocationUpdates(connectedClient, request, callback, mock(Looper.class)); + verify(requestManager).requestLocationUpdates(connectedClient, request, callback); } @Test public void requestLocationUpdates_listener_shouldReturnFusedLocationPendingResult() { diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegateTest.java b/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegateTest.java index d9174c6..3f18c59 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegateTest.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/FusedLocationProviderServiceDelegateTest.java @@ -134,8 +134,9 @@ public class FusedLocationProviderServiceDelegateTest extends BaseRobolectricTes } @Test public void removeLocationUpdates_shouldUnregisterAllListeners() throws Exception { - delegate.requestLocationUpdates(LocationRequest.create()); - delegate.removeLocationUpdates(); + LocationRequest request = LocationRequest.create(); + delegate.requestLocationUpdates(request); + delegate.removeLocationUpdates(request); assertThat(shadowLocationManager.getRequestLocationUpdateListeners()).isEmpty(); } @@ -265,7 +266,7 @@ private void initTestGpxTrace() throws IOException { LocationRequest locationRequest = LocationRequest.create().setPriority(PRIORITY_BALANCED_POWER_ACCURACY); delegate.requestLocationUpdates(locationRequest); - delegate.removeLocationUpdates(); + delegate.removeLocationUpdates(locationRequest); assertThat(shadowLocationManager.getRequestLocationUpdateListeners()).isEmpty(); } @@ -338,7 +339,7 @@ private void initTestGpxTrace() throws IOException { @Test public void removeLocationUpdates_locationCallback_shouldUnregisterAllListeners() { LocationRequest request = LocationRequest.create(); delegate.requestLocationUpdates(request); - delegate.removeLocationUpdates(); + delegate.removeLocationUpdates(request); assertThat(shadowLocationManager.getRequestLocationUpdateListeners()).isEmpty(); } diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/FusionEngineTest.java b/lost/src/test/java/com/mapzen/android/lost/internal/FusionEngineTest.java index 4ee229c..018826b 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/FusionEngineTest.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/FusionEngineTest.java @@ -149,51 +149,52 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr assertThat(fusionEngine.getLastLocation()).isNull(); } - @Test public void setRequest_shouldRegisterGpsAndNetworkIfPriorityHighAccuracy() + @Test public void addRequest_shouldRegisterGpsAndNetworkIfPriorityHighAccuracy() throws Exception { - fusionEngine.setRequest(LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY)); + fusionEngine.addRequest(LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY)); Collection providers = shadowLocationManager.getProvidersForListener(fusionEngine); assertThat(providers).hasSize(2); assertThat(providers).contains(GPS_PROVIDER); assertThat(providers).contains(NETWORK_PROVIDER); } - @Test public void setRequest_shouldRegisterNetworkOnlyIfPriorityBalanced() throws Exception { - fusionEngine.setRequest(LocationRequest.create().setPriority(PRIORITY_BALANCED_POWER_ACCURACY)); + @Test public void addRequest_shouldRegisterNetworkOnlyIfPriorityBalanced() throws Exception { + fusionEngine.addRequest(LocationRequest.create().setPriority(PRIORITY_BALANCED_POWER_ACCURACY)); Collection providers = shadowLocationManager.getProvidersForListener(fusionEngine); assertThat(providers).hasSize(1); assertThat(providers).contains(NETWORK_PROVIDER); } - @Test public void setRequest_shouldRegisterNetworkOnlyIfPriorityLowPower() throws Exception { - fusionEngine.setRequest(LocationRequest.create().setPriority(PRIORITY_LOW_POWER)); + @Test public void addRequest_shouldRegisterNetworkOnlyIfPriorityLowPower() throws Exception { + fusionEngine.addRequest(LocationRequest.create().setPriority(PRIORITY_LOW_POWER)); Collection providers = shadowLocationManager.getProvidersForListener(fusionEngine); assertThat(providers).hasSize(1); assertThat(providers).contains(NETWORK_PROVIDER); } - @Test public void setRequest_shouldRegisterPassiveProviderOnlyNoPower() throws Exception { - fusionEngine.setRequest(LocationRequest.create().setPriority(PRIORITY_NO_POWER)); + @Test public void addRequest_shouldRegisterPassiveProviderOnlyNoPower() throws Exception { + fusionEngine.addRequest(LocationRequest.create().setPriority(PRIORITY_NO_POWER)); Collection providers = shadowLocationManager.getProvidersForListener(fusionEngine); assertThat(providers).hasSize(1); assertThat(providers).contains(PASSIVE_PROVIDER); } - @Test public void setRequest_shouldDisableLocationUpdatesForNullRequest() throws Exception { - fusionEngine.setRequest(LocationRequest.create()); - fusionEngine.setRequest(null); + @Test public void addRequest_shouldDisableLocationUpdatesForNullRequest() throws Exception { + LocationRequest request = LocationRequest.create(); + fusionEngine.addRequest(request); + fusionEngine.removeRequest(request); assertThat(shadowLocationManager.getRequestLocationUpdateListeners()).isEmpty(); } @Test public void onLocationChanged_shouldReportGps() throws Exception { - fusionEngine.setRequest(LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY)); + fusionEngine.addRequest(LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY)); Location location = new Location(GPS_PROVIDER); shadowLocationManager.simulateLocation(location); assertThat(callback.location).isEqualTo(location); } @Test public void onLocationChanged_shouldReportNetwork() throws Exception { - fusionEngine.setRequest(LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY)); + fusionEngine.addRequest(LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY)); Location location = new Location(NETWORK_PROVIDER); shadowLocationManager.simulateLocation(location); assertThat(callback.location).isEqualTo(location); @@ -202,7 +203,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr @Test public void onLocationChanged_shouldNotReportLessThanFastestIntervalGps() throws Exception { LocationRequest request = LocationRequest.create().setFastestInterval(5000).setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); final long time = System.currentTimeMillis(); Location location1 = getTestLocation(GPS_PROVIDER, 0, 0, time); @@ -217,7 +218,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr throws Exception { LocationRequest request = LocationRequest.create().setFastestInterval(5000).setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); final long time = System.currentTimeMillis(); Location location1 = getTestLocation(NETWORK_PROVIDER, 0, 0, time); @@ -232,7 +233,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr LocationRequest request = LocationRequest.create() .setSmallestDisplacement(200000) .setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); final long time = System.currentTimeMillis(); Location location1 = getTestLocation(GPS_PROVIDER, 0, 0, time); @@ -246,7 +247,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr @Test public void onLocationChanged_shouldNotReportLessThanMinDisplacementNetwork() throws Exception { LocationRequest request = LocationRequest.create().setSmallestDisplacement(200000); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); final long time = System.currentTimeMillis(); Location location1 = getTestLocation(NETWORK_PROVIDER, 0, 0, time); @@ -260,7 +261,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr @Test public void onLocationChanged_shouldIgnoreNetworkWhenGpsIsMoreAccurate() throws Exception { LocationRequest request = LocationRequest.create().setFastestInterval(0).setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); final long time = System.currentTimeMillis(); Location gpsLocation = getTestLocation(GPS_PROVIDER, 0, 0, time); @@ -275,7 +276,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr @Test public void onLocationChanged_shouldIgnoreGpsWhenNetworkIsMoreAccurate() throws Exception { LocationRequest request = LocationRequest.create().setFastestInterval(0); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); final long time = System.currentTimeMillis(); Location networkLocation = getTestLocation(NETWORK_PROVIDER, 0, 0, time + 1); @@ -293,7 +294,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr shadowLocationManager.setLastKnownLocation(GPS_PROVIDER, gpsLocation); LocationRequest request = LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); assertThat(callback.location).isEqualTo(gpsLocation); } @@ -304,7 +305,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr LocationRequest request = LocationRequest.create().setPriority( PRIORITY_BALANCED_POWER_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); assertThat(callback.location).isEqualTo(networkLocation); } @@ -316,7 +317,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr shadowLocationManager.setLastKnownLocation(NETWORK_PROVIDER, networkLocation); LocationRequest request = LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); assertThat(callback.location).isEqualTo(networkLocation); } @@ -329,7 +330,7 @@ public void getLastLocation_shouldReturnNullIfNoLocationPermissionsGranted() thr shadowLocationManager.setLastKnownLocation(NETWORK_PROVIDER, networkLocation); LocationRequest request = LocationRequest.create().setPriority(PRIORITY_HIGH_ACCURACY); - fusionEngine.setRequest(request); + fusionEngine.addRequest(request); assertThat(callback.numLocationReports).isEqualTo(1); } diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/LostRequestManagerTests.java b/lost/src/test/java/com/mapzen/android/lost/internal/LostRequestManagerTests.java new file mode 100644 index 0000000..1a537d3 --- /dev/null +++ b/lost/src/test/java/com/mapzen/android/lost/internal/LostRequestManagerTests.java @@ -0,0 +1,288 @@ +package com.mapzen.android.lost.internal; + +import com.mapzen.android.lost.api.LocationCallback; +import com.mapzen.android.lost.api.LocationListener; +import com.mapzen.android.lost.api.LocationRequest; +import com.mapzen.android.lost.api.LostApiClient; + +import org.junit.Before; +import org.junit.Test; + +import android.app.PendingIntent; + +import static org.fest.assertions.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +public class LostRequestManagerTests { + + LostRequestManager requestManager; + + @Before + public void setup() { + requestManager = new LostRequestManager(); + } + + @Test + public void requestLocationUpdates_clientListener_oneRequest_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + requestManager.requestLocationUpdates(client, request, listener); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + } + + @Test + public void requestLocationUpdates_clientListener_twoRequests_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + requestManager.requestLocationUpdates(client, request, listener); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(client, anotherRequest, listener); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + + ClientCallbackWrapper wrapper = new ClientCallbackWrapper(client, listener); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(request); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(anotherRequest); + } + + @Test + public void requestLocationUpdates_twoClientListeners_twoRequests_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + requestManager.requestLocationUpdates(client, request, listener); + LostApiClient anotherClient = mock(LostApiClient.class); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(anotherClient, anotherRequest, listener); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(2); + + ClientCallbackWrapper wrapper = new ClientCallbackWrapper(client, listener); + assertThat(requestManager.getClientCallbackMap().get(wrapper).size()).isEqualTo(1); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(request); + + ClientCallbackWrapper anotherWrapper = new ClientCallbackWrapper(anotherClient, listener); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper).size()).isEqualTo(1); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper)).contains(anotherRequest); + } + + @Test + public void requestLocationUpdates_clientPendingIntent_oneRequest_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + requestManager.requestLocationUpdates(client, request, intent); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + } + + @Test + public void requestLocationUpdates_clientPendingIntent_twoRequests_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + requestManager.requestLocationUpdates(client, request, intent); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(client, anotherRequest, intent); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + + ClientCallbackWrapper wrapper = new ClientCallbackWrapper(client, intent); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(request); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(anotherRequest); + } + + @Test + public void requestLocationUpdates_twoClientPendingIntents_twoRequests_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + requestManager.requestLocationUpdates(client, request, intent); + LostApiClient anotherClient = mock(LostApiClient.class); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(anotherClient, anotherRequest, intent); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(2); + + ClientCallbackWrapper wrapper = new ClientCallbackWrapper(client, intent); + assertThat(requestManager.getClientCallbackMap().get(wrapper).size()).isEqualTo(1); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(request); + + ClientCallbackWrapper anotherWrapper = new ClientCallbackWrapper(anotherClient, intent); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper).size()).isEqualTo(1); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper)).contains(anotherRequest); + } + + @Test + public void requestLocationUpdates_clientCallback_oneRequest_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + requestManager.requestLocationUpdates(client, request, callback); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + } + + @Test + public void requestLocationUpdates_clientCallback_twoRequests_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + requestManager.requestLocationUpdates(client, request, callback); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(client, anotherRequest, callback); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + + ClientCallbackWrapper wrapper = new ClientCallbackWrapper(client, callback); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(request); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(anotherRequest); + } + + @Test + public void requestLocationUpdates_twoClientCallbacks_twoRequests_shouldUpdateMap() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + requestManager.requestLocationUpdates(client, request, callback); + LostApiClient anotherClient = mock(LostApiClient.class); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(anotherClient, anotherRequest, callback); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(2); + + ClientCallbackWrapper wrapper = new ClientCallbackWrapper(client, callback); + assertThat(requestManager.getClientCallbackMap().get(wrapper).size()).isEqualTo(1); + assertThat(requestManager.getClientCallbackMap().get(wrapper)).contains(request); + + ClientCallbackWrapper anotherWrapper = new ClientCallbackWrapper(anotherClient, callback); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper).size()).isEqualTo(1); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper)).contains(anotherRequest); + } + + @Test + public void removeLocationUpdates_clientListener_oneRequest_shouldRemoveAll() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + requestManager.requestLocationUpdates(client, request, listener); + requestManager.removeLocationUpdates(client, listener); + + assertThat(requestManager.getClientCallbackMap()).isEmpty(); + } + + @Test + public void removeLocationUpdates_clientListener_twoRequests_shouldRemoveAll() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + requestManager.requestLocationUpdates(client, request, listener); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(client, anotherRequest, listener); + requestManager.removeLocationUpdates(client, listener); + + assertThat(requestManager.getClientCallbackMap()).isEmpty(); + } + + @Test + public void removeLocationUpdates_twoClientListeners_twoRequests_shouldRemoveOne() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationListener listener = mock(LocationListener.class); + requestManager.requestLocationUpdates(client, request, listener); + LostApiClient anotherClient = mock(LostApiClient.class); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(anotherClient, anotherRequest, listener); + requestManager.removeLocationUpdates(client, listener); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + + ClientCallbackWrapper anotherWrapper = new ClientCallbackWrapper(anotherClient, listener); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper)).contains(anotherRequest); + } + + @Test + public void removeLocationUpdates_clientPendingIntent_oneRequest_shouldRemoveAll() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + requestManager.requestLocationUpdates(client, request, intent); + requestManager.removeLocationUpdates(client, intent); + + assertThat(requestManager.getClientCallbackMap()).isEmpty(); + } + + @Test + public void removeLocationUpdates_clientPendingIntent_twoRequests_shouldRemoveAll() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + requestManager.requestLocationUpdates(client, request, intent); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(client, anotherRequest, intent); + requestManager.removeLocationUpdates(client, intent); + + assertThat(requestManager.getClientCallbackMap()).isEmpty(); + } + + @Test + public void removeLocationUpdates_twoClientPendingIntents_twoRequests_shouldRemoveOne() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + PendingIntent intent = mock(PendingIntent.class); + requestManager.requestLocationUpdates(client, request, intent); + LostApiClient anotherClient = mock(LostApiClient.class); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(anotherClient, anotherRequest, intent); + requestManager.removeLocationUpdates(client, intent); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + + ClientCallbackWrapper anotherWrapper = new ClientCallbackWrapper(anotherClient, intent); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper)).contains(anotherRequest); + } + + @Test + public void removeLocationUpdates_clientCallback_oneRequest_shouldRemoveAll() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + requestManager.requestLocationUpdates(client, request, callback); + requestManager.removeLocationUpdates(client, callback); + + assertThat(requestManager.getClientCallbackMap()).isEmpty(); + } + + @Test + public void removeLocationUpdates_clientCallback_twoRequests_shouldRemoveAll() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + requestManager.requestLocationUpdates(client, request, callback); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(client, anotherRequest, callback); + requestManager.removeLocationUpdates(client, callback); + + assertThat(requestManager.getClientCallbackMap()).isEmpty(); + } + + @Test + public void removeLocationUpdates_twoClientCallbacks_twoRequests_shouldRemoveOne() { + LostApiClient client = mock(LostApiClient.class); + LocationRequest request = LocationRequest.create(); + LocationCallback callback = mock(LocationCallback.class); + requestManager.requestLocationUpdates(client, request, callback); + LostApiClient anotherClient = mock(LostApiClient.class); + LocationRequest anotherRequest = LocationRequest.create(); + requestManager.requestLocationUpdates(anotherClient, anotherRequest, callback); + requestManager.removeLocationUpdates(client, callback); + + assertThat(requestManager.getClientCallbackMap().size()).isEqualTo(1); + + ClientCallbackWrapper anotherWrapper = new ClientCallbackWrapper(anotherClient, callback); + assertThat(requestManager.getClientCallbackMap().get(anotherWrapper)).contains(anotherRequest); + } +} \ No newline at end of file diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/MockEngineTest.java b/lost/src/test/java/com/mapzen/android/lost/internal/MockEngineTest.java index 0bddcf3..a83f318 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/MockEngineTest.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/MockEngineTest.java @@ -50,7 +50,7 @@ public class MockEngineTest extends BaseRobolectricTest { @Test public void disable_shouldCancelTraceReplay() throws Exception { mockEngine.setTrace(getTestGpxTrace()); - mockEngine.setRequest(LocationRequest.create().setFastestInterval(100)); + mockEngine.addRequest(LocationRequest.create().setFastestInterval(100)); mockEngine.disable(); assertThat(traceThreadFactory.traceThread.isCanceled()).isTrue(); } diff --git a/lost/src/test/java/com/mapzen/android/lost/internal/TestServiceStub.java b/lost/src/test/java/com/mapzen/android/lost/internal/TestServiceStub.java index 956127d..e3cef0c 100644 --- a/lost/src/test/java/com/mapzen/android/lost/internal/TestServiceStub.java +++ b/lost/src/test/java/com/mapzen/android/lost/internal/TestServiceStub.java @@ -26,7 +26,7 @@ public class TestServiceStub extends IFusedLocationProviderService.Stub { } - @Override public void removeLocationUpdates() throws RemoteException { + @Override public void removeLocationUpdates(LocationRequest request) throws RemoteException { } From d0d171259f27d95cc48888aa6e1dadd52c04dcb8 Mon Sep 17 00:00:00 2001 From: Sarah Lensing Date: Wed, 7 Jun 2017 15:10:11 -0400 Subject: [PATCH 3/5] Add sample for multiple clients w/diff request priorities --- lost-sample/src/main/AndroidManifest.xml | 1 + ...ltiplePriorityMultipleClientsActivity.java | 105 ++++++++++++++++++ .../java/com/example/lost/SamplesList.java | 3 + .../activity_multiple_clients_requests.xml | 36 ++++++ lost-sample/src/main/res/values/strings.xml | 2 + .../android/lost/api/LocationRequest.java | 20 +++- .../lost/internal/ClientCallbackWrapper.java | 7 +- .../lost/internal/LostRequestManager.java | 9 +- .../FusedLocationProviderApiImplTest.java | 2 - .../internal/LostRequestManagerTests.java | 2 +- 10 files changed, 171 insertions(+), 16 deletions(-) create mode 100644 lost-sample/src/main/java/com/example/lost/MultiplePriorityMultipleClientsActivity.java create mode 100644 lost-sample/src/main/res/layout/activity_multiple_clients_requests.xml diff --git a/lost-sample/src/main/AndroidManifest.xml b/lost-sample/src/main/AndroidManifest.xml index 457da0c..7a64379 100644 --- a/lost-sample/src/main/AndroidManifest.xml +++ b/lost-sample/src/main/AndroidManifest.xml @@ -37,6 +37,7 @@ + + + +