diff options
author | 2024-11-29 15:57:34 +0000 | |
---|---|---|
committer | 2024-12-02 18:04:22 +0000 | |
commit | 49fe79bc03c51a4f925d085a4ed3fb3c938c36e7 (patch) | |
tree | 1c911ae1b2c96f1a96ac3ccf733c4389a3a9ebf8 | |
parent | dc5236d9f1a819d479994e85fd2c6ebcfba2806e (diff) |
Population Density Provider: add cache hint
Adds a parameter to indicate the desired answer size when querying the coarsened cells. This allows the framework to indicate its cache size, and the provider to answer with the right amount of cells.
Tests:
- atest CtsLocationNoneTestCases:PopulationDensityProviderBaseTest
- atest FrameworksMockingServicesTests:LocationProviderManagerTest
- atest FrameworksMockingServicesTests:LocationFudgerTest
- atest FrameworksMockingServicesTests:LocationFudgerCacheTest
Test: manual atest on Pixel 7 pro (see above)
Bug: 381286551
Flag: android.location.flags.density_based_coarse_locations
Change-Id: Ib0d26e8ce0e1164ff30b45e2d3deddb67f68a83b
7 files changed, 47 insertions, 29 deletions
diff --git a/location/api/system-current.txt b/location/api/system-current.txt index 8cd08d3aad6c..9478e350de57 100644 --- a/location/api/system-current.txt +++ b/location/api/system-current.txt @@ -645,7 +645,7 @@ package android.location.provider { @FlaggedApi("android.location.flags.population_density_provider") public abstract class PopulationDensityProviderBase { ctor public PopulationDensityProviderBase(@NonNull android.content.Context, @NonNull String); method @Nullable public final android.os.IBinder getBinder(); - method public abstract void onGetCoarsenedS2Cell(double, double, @NonNull android.os.OutcomeReceiver<long[],java.lang.Throwable>); + method public abstract void onGetCoarsenedS2Cells(double, double, @IntRange(from=0) int, @NonNull android.os.OutcomeReceiver<long[],java.lang.Throwable>); method public abstract void onGetDefaultCoarseningLevel(@NonNull android.os.OutcomeReceiver<java.lang.Integer,java.lang.Throwable>); field public static final String ACTION_POPULATION_DENSITY_PROVIDER = "com.android.location.service.PopulationDensityProvider"; } diff --git a/location/java/android/location/provider/IPopulationDensityProvider.aidl b/location/java/android/location/provider/IPopulationDensityProvider.aidl index 9b5cb5ae8c7a..41fe5006983d 100644 --- a/location/java/android/location/provider/IPopulationDensityProvider.aidl +++ b/location/java/android/location/provider/IPopulationDensityProvider.aidl @@ -35,11 +35,11 @@ oneway interface IPopulationDensityProvider { void getDefaultCoarseningLevel(in IS2LevelCallback callback); /** - * Returns a list of IDs of the S2 cells to be used to coarsen a location. The answer should + * Requests a list of IDs of the S2 cells to be used to coarsen a location. The answer should * contain at least one S2 cell, which should contain the requested location. Its level - * represents the population density. Optionally, additional nearby cells can be also returned, - * to assist in coarsening nearby locations. + * represents the population density. Optionally, if numAdditionalCells is greater than 0, + * additional nearby cells can be also returned, to assist in coarsening nearby locations. */ - void getCoarsenedS2Cell(double latitudeDegrees, double longitudeDegrees, in IS2CellIdsCallback - callback); + void getCoarsenedS2Cells(double latitudeDegrees, double longitudeDegrees, + int numAdditionalCells, in IS2CellIdsCallback callback); } diff --git a/location/java/android/location/provider/PopulationDensityProviderBase.java b/location/java/android/location/provider/PopulationDensityProviderBase.java index 3907516f6aaa..0177cf8694df 100644 --- a/location/java/android/location/provider/PopulationDensityProviderBase.java +++ b/location/java/android/location/provider/PopulationDensityProviderBase.java @@ -17,6 +17,7 @@ package android.location.provider; import android.annotation.FlaggedApi; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -89,17 +90,18 @@ public abstract class PopulationDensityProviderBase { * Called upon receiving a new request for population density at a specific latitude/longitude, * expressed in degrees. * The answer is at least one S2CellId corresponding to the coarsening level at the specified - * location. This must be the first element of the result array. Optionally, additional nearby - * S2CellIds can be returned. One use for the optional nearby cells is when the client has a - * local cache that needs to be filled with the local area around a certain latitude/longitude. - * The callback {@link OutcomeReceiver#onResult} should be called with the result; or, in case - * an error occurs, {@link OutcomeReceiver#onError} should be called. - * The callback is single-use, calling more than any one of these two methods throws an - * AssertionException. + * location. This must be the first element of the result array. Optionally, if + * numAdditionalCells is greater than zero, additional nearby S2CellIds can be returned. One use + * for the optional nearby cells is when the client has a local cache that needs to be filled + * with the local area around a certain latitude/longitude. The callback + * {@link OutcomeReceiver#onResult} should be called with the result; or, in case an error + * occurs, {@link OutcomeReceiver#onError} should be called. The callback is single-use, calling + * more than any one of these two methods throws an AssertionException. * * @param callback A single-use callback that either returns S2CellIds, or an error. */ - public abstract void onGetCoarsenedS2Cell(double latitudeDegrees, double longitudeDegrees, + public abstract void onGetCoarsenedS2Cells(double latitudeDegrees, double longitudeDegrees, + @IntRange(from = 0) int numAdditionalCells, @NonNull OutcomeReceiver<long[], Throwable> callback); private final class Service extends IPopulationDensityProvider.Stub { @@ -119,10 +121,10 @@ public abstract class PopulationDensityProviderBase { } @Override - public void getCoarsenedS2Cell(double latitudeDegrees, double longitudeDegrees, - @NonNull IS2CellIdsCallback callback) { + public void getCoarsenedS2Cells(double latitudeDegrees, double longitudeDegrees, + int numAdditionalCells, @NonNull IS2CellIdsCallback callback) { try { - onGetCoarsenedS2Cell(latitudeDegrees, longitudeDegrees, + onGetCoarsenedS2Cells(latitudeDegrees, longitudeDegrees, numAdditionalCells, new SingleUseS2CellIdsCallback(callback)); } catch (RuntimeException e) { // exceptions on one-way binder threads are dropped - move to a different thread diff --git a/services/core/java/com/android/server/location/fudger/LocationFudgerCache.java b/services/core/java/com/android/server/location/fudger/LocationFudgerCache.java index 3670c1f5c51b..ce8bec8f0147 100644 --- a/services/core/java/com/android/server/location/fudger/LocationFudgerCache.java +++ b/services/core/java/com/android/server/location/fudger/LocationFudgerCache.java @@ -180,7 +180,8 @@ public class LocationFudgerCache { Log.e(sTAG, "could not get population density"); } }; - mPopulationDensityProvider.getCoarsenedS2Cell(latitude, longitude, callback); + mPopulationDensityProvider.getCoarsenedS2Cells(latitude, longitude, MAX_CACHE_SIZE - 1, + callback); } /** diff --git a/services/core/java/com/android/server/location/provider/proxy/ProxyPopulationDensityProvider.java b/services/core/java/com/android/server/location/provider/proxy/ProxyPopulationDensityProvider.java index b0a0f0b0c83b..7b454e481dda 100644 --- a/services/core/java/com/android/server/location/provider/proxy/ProxyPopulationDensityProvider.java +++ b/services/core/java/com/android/server/location/provider/proxy/ProxyPopulationDensityProvider.java @@ -96,14 +96,15 @@ public class ProxyPopulationDensityProvider { /** Gets the population density at the requested location. */ - public void getCoarsenedS2Cell(double latitudeDegrees, double longitudeDegrees, - IS2CellIdsCallback callback) { + public void getCoarsenedS2Cells(double latitudeDegrees, double longitudeDegrees, + int numAdditionalCells, IS2CellIdsCallback callback) { mServiceWatcher.runOnBinder( new ServiceWatcher.BinderOperation() { @Override public void run(IBinder binder) throws RemoteException { IPopulationDensityProvider.Stub.asInterface(binder) - .getCoarsenedS2Cell(latitudeDegrees, longitudeDegrees, callback); + .getCoarsenedS2Cells(latitudeDegrees, longitudeDegrees, + numAdditionalCells, callback); } @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/location/fudger/LocationFudgerCacheTest.java b/services/tests/mockingservicestests/src/com/android/server/location/fudger/LocationFudgerCacheTest.java index 04b82c4890af..6b7eda26b945 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/fudger/LocationFudgerCacheTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/fudger/LocationFudgerCacheTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyDouble; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -226,8 +227,8 @@ public class LocationFudgerCacheTest { cache.getCoarseningLevel(POINT_IN_TIMES_SQUARE[0], POINT_IN_TIMES_SQUARE[1]); - verify(provider).getCoarsenedS2Cell(eq(POINT_IN_TIMES_SQUARE[0]), - eq(POINT_IN_TIMES_SQUARE[1]), any()); + verify(provider).getCoarsenedS2Cells(eq(POINT_IN_TIMES_SQUARE[0]), + eq(POINT_IN_TIMES_SQUARE[1]), anyInt(), any()); } @Test @@ -242,8 +243,8 @@ public class LocationFudgerCacheTest { ArgumentCaptor<IS2CellIdsCallback> argumentCaptor = ArgumentCaptor.forClass( IS2CellIdsCallback.class); - verify(provider).getCoarsenedS2Cell(eq(POINT_IN_TIMES_SQUARE[0]), - eq(POINT_IN_TIMES_SQUARE[1]), argumentCaptor.capture()); + verify(provider).getCoarsenedS2Cells(eq(POINT_IN_TIMES_SQUARE[0]), + eq(POINT_IN_TIMES_SQUARE[1]), anyInt(), argumentCaptor.capture()); // Results from the proxy should set the cache int expectedLevel = 4; @@ -264,10 +265,23 @@ public class LocationFudgerCacheTest { cache.addToCache(TIMES_SQUARE_S2_ID); - verify(provider, never()).getCoarsenedS2Cell(anyDouble(), anyDouble(), any()); + verify(provider, never()).getCoarsenedS2Cells(anyDouble(), anyDouble(), anyInt(), any()); } @Test + public void locationFudgerCache_whenQueryIsCached_askForMaxCacheSizeElems() { + ProxyPopulationDensityProvider provider = mock(ProxyPopulationDensityProvider.class); + LocationFudgerCache cache = new LocationFudgerCache(provider); + int numAdditionalCells = cache.MAX_CACHE_SIZE - 1; + + cache.getCoarseningLevel(POINT_IN_TIMES_SQUARE[0], POINT_IN_TIMES_SQUARE[1]); + + verify(provider).getCoarsenedS2Cells(eq(POINT_IN_TIMES_SQUARE[0]), + eq(POINT_IN_TIMES_SQUARE[1]), eq(numAdditionalCells), any()); + } + + + @Test public void locationFudgerCache_canContainUpToMaxSizeItems() { // This test has two sequences of arrange-act-assert. // The first checks that the cache correctly store up to MAX_CACHE_SIZE items. diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java index cd1990407806..6d78defe2943 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java @@ -1448,7 +1448,7 @@ public class LocationProviderManagerTest { Location test = new Location("any-provider"); mManager.getPermittedLocation(test, PERMISSION_COARSE); - verify(provider, never()).getCoarsenedS2Cell(anyDouble(), anyDouble(), any()); + verify(provider, never()).getCoarsenedS2Cells(anyDouble(), anyDouble(), anyInt(), any()); } @Test @@ -1472,7 +1472,7 @@ public class LocationProviderManagerTest { Location test = new Location("any-provider"); mManager.getPermittedLocation(test, PERMISSION_COARSE); - verify(provider, never()).getCoarsenedS2Cell(anyDouble(), anyDouble(), any()); + verify(provider, never()).getCoarsenedS2Cells(anyDouble(), anyDouble(), anyInt(), any()); } @Test @@ -1499,7 +1499,7 @@ public class LocationProviderManagerTest { // We can't test that 10.0, 20.0 was passed due to the offset. We only test that a call // happened. - verify(provider).getCoarsenedS2Cell(anyDouble(), anyDouble(), any()); + verify(provider).getCoarsenedS2Cells(anyDouble(), anyDouble(), anyInt(), any()); } @MediumTest |