Merge "Update batching APIs" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-02-04 19:47:40 +00:00
committed by Android (Google) Code Review
18 changed files with 260 additions and 167 deletions

View File

@@ -19457,7 +19457,7 @@ package android.location {
public interface LocationListener {
method public default void onFlushComplete(int);
method public void onLocationChanged(@NonNull android.location.Location);
method public default void onLocationChanged(@NonNull android.location.LocationResult);
method public default void onLocationChanged(@NonNull java.util.List<android.location.Location>);
method public default void onProviderDisabled(@NonNull String);
method public default void onProviderEnabled(@NonNull String);
method @Deprecated public default void onStatusChanged(String, int, android.os.Bundle);
@@ -19543,8 +19543,8 @@ package android.location {
field public static final String FUSED_PROVIDER = "fused";
field public static final String GPS_PROVIDER = "gps";
field public static final String KEY_FLUSH_COMPLETE = "flushComplete";
field public static final String KEY_LOCATIONS = "locations";
field public static final String KEY_LOCATION_CHANGED = "location";
field public static final String KEY_LOCATION_RESULT = "locationResult";
field public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
field public static final String KEY_PROXIMITY_ENTERING = "entering";
field @Deprecated public static final String KEY_STATUS_CHANGED = "status";
@@ -19602,18 +19602,6 @@ package android.location {
method @NonNull public android.location.LocationRequest.Builder setQuality(int);
}
public final class LocationResult implements android.os.Parcelable {
method @NonNull public java.util.List<android.location.Location> asList();
method @NonNull public static android.location.LocationResult create(@NonNull android.location.Location);
method @NonNull public static android.location.LocationResult create(@NonNull java.util.List<android.location.Location>);
method public int describeContents();
method @NonNull public android.location.Location get(@IntRange(from=0) int);
method @NonNull public android.location.Location getLastLocation();
method @IntRange(from=1) public int size();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationResult> CREATOR;
}
public interface OnNmeaMessageListener {
method public void onNmeaMessage(String, long);
}

View File

@@ -4718,10 +4718,6 @@ package android.location {
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
}
public final class LocationResult implements android.os.Parcelable {
method @NonNull public static android.location.LocationResult wrap(@NonNull android.location.Location);
}
public final class SatellitePvt implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.location.SatellitePvt.ClockInfo getClockInfo();
@@ -4788,7 +4784,7 @@ package android.location.provider {
method public abstract void onSendExtraCommand(@NonNull String, @Nullable android.os.Bundle);
method public abstract void onSetRequest(@NonNull android.location.provider.ProviderRequest);
method public void reportLocation(@NonNull android.location.Location);
method public void reportLocation(@NonNull android.location.LocationResult);
method public void reportLocations(@NonNull java.util.List<android.location.Location>);
method public void setAllowed(boolean);
method public void setProperties(@NonNull android.location.provider.ProviderProperties);
field public static final String ACTION_FUSED_PROVIDER = "com.android.location.service.FusedLocationProvider";

View File

@@ -16,7 +16,7 @@
package android.location;
import android.location.LocationResult;
import android.location.Location;
import android.os.IRemoteCallback;
/**
@@ -24,7 +24,7 @@ import android.os.IRemoteCallback;
*/
oneway interface ILocationListener
{
void onLocationChanged(in LocationResult locationResult, in @nullable IRemoteCallback onCompleteCallback);
void onLocationChanged(in List<Location> locations, in @nullable IRemoteCallback onCompleteCallback);
void onProviderEnabledChanged(String provider, boolean enabled);
void onFlushComplete(int requestCode);
}

View File

@@ -19,6 +19,7 @@ package android.location;
import android.annotation.NonNull;
import android.os.Bundle;
import java.util.List;
import java.util.concurrent.Executor;
/**
@@ -48,15 +49,18 @@ public interface LocationListener {
/**
* Called when the location has changed and locations are being delivered in batches. The
* default implementation calls through to ({@link #onLocationChanged(Location)} with all
* locations in the batch, from earliest to latest.
* locations in the batch. The list of locations is always guaranteed to be non-empty, and is
* always guaranteed to be ordered from earliest location to latest location (so that the
* earliest location in the batch is at index 0 in the list, and the latest location in the
* batch is at index size-1 in the list).
*
* @see LocationRequest#getMaxUpdateDelayMillis()
* @param locationResult the location result list
* @param locations the location list
*/
default void onLocationChanged(@NonNull LocationResult locationResult) {
final int size = locationResult.size();
for (int i = 0; i < size; ++i) {
onLocationChanged(locationResult.get(i));
default void onLocationChanged(@NonNull List<Location> locations) {
final int size = locations.size();
for (int i = 0; i < size; i++) {
onLocationChanged(locations.get(i));
}
}

View File

@@ -232,19 +232,26 @@ public class LocationManager {
/**
* Key used for an extra holding a {@link Location} value when a location change is sent using
* a PendingIntent.
* a PendingIntent. If the location change includes a list of batched locations via
* {@link #KEY_LOCATIONS} then this key will still be present, and will hold the last location
* in the batch. Use {@link Intent#getParcelableExtra(String)} to retrieve the location.
*
* @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
*/
public static final String KEY_LOCATION_CHANGED = "location";
/**
* Key used for an extra holding a {@link LocationResult} value when a location change is sent
* using a PendingIntent.
* Key used for an extra holding a array of {@link Location}s when a location change is sent
* using a PendingIntent. This key will only be present if the location change includes
* multiple (ie, batched) locations, otherwise only {@link #KEY_LOCATION_CHANGED} will be
* present. Use {@link Intent#getParcelableArrayExtra(String)} to retrieve the locations.
*
* <p>The array of locations will never be empty, and will ordered from earliest location to
* latest location, the same as with {@link LocationListener#onLocationChanged(List)}.
*
* @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
*/
public static final String KEY_LOCATION_RESULT = "locationResult";
public static final String KEY_LOCATIONS = "locations";
/**
* Key used for an extra holding an integer request code when location flush completion is sent
@@ -3018,12 +3025,12 @@ public class LocationManager {
}
@Override
public void onLocationChanged(LocationResult locationResult,
public void onLocationChanged(List<Location> locations,
@Nullable IRemoteCallback onCompleteCallback) {
executeSafely(mExecutor, () -> mListener, new ListenerOperation<LocationListener>() {
@Override
public void operate(LocationListener listener) {
listener.onLocationChanged(locationResult);
listener.onLocationChanged(locations);
}
@Override
@@ -3366,8 +3373,8 @@ public class LocationManager {
}
@Override
public void onLocationChanged(@NonNull LocationResult locationResult) {
mCallback.onLocationBatch(locationResult.asList());
public void onLocationChanged(@NonNull List<Location> locations) {
mCallback.onLocationBatch(locations);
}
}

View File

@@ -605,7 +605,7 @@ public final class LocationRequest implements Parcelable {
* When available, batching can provide substantial power savings to the device, and clients are
* encouraged to take advantage where appropriate for the use case.
*
* @see LocationListener#onLocationChanged(LocationResult)
* @see LocationListener#onLocationChanged(java.util.List)
* @return the maximum time by which a location update may be delayed
*/
public @IntRange(from = 0) long getMaxUpdateDelayMillis() {

View File

@@ -19,7 +19,6 @@ package android.location;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,21 +33,14 @@ import java.util.function.Predicate;
/**
* A location result representing a list of locations, ordered from earliest to latest.
*
* @hide
*/
public final class LocationResult implements Parcelable {
/**
* Creates a new LocationResult from the given location.
*/
public static @NonNull LocationResult create(@NonNull Location location) {
ArrayList<Location> locations = new ArrayList<>(1);
locations.add(new Location(Objects.requireNonNull(location)));
return new LocationResult(locations);
}
/**
* Creates a new LocationResult from the given locations. Locations must be ordered in the same
* order they were derived (earliest to latest).
* Creates a new LocationResult from the given locations, making a copy of each location.
* Locations must be ordered in the same order they were derived (earliest to latest).
*/
public static @NonNull LocationResult create(@NonNull List<Location> locations) {
Preconditions.checkArgument(!locations.isEmpty());
@@ -60,16 +52,40 @@ public final class LocationResult implements Parcelable {
}
/**
* Creates a new LocationResult that takes ownership of the given location without copying it.
* Callers must ensure the given location is never mutated after this method is called.
*
* @hide
* Creates a new LocationResult from the given locations, making a copy of each location.
* Locations must be ordered in the same order they were derived (earliest to latest).
*/
@SystemApi
public static @NonNull LocationResult wrap(@NonNull Location location) {
ArrayList<Location> locations = new ArrayList<>(1);
locations.add(Objects.requireNonNull(location));
return new LocationResult(locations);
public static @NonNull LocationResult create(@NonNull Location... locations) {
Preconditions.checkArgument(locations.length > 0);
ArrayList<Location> locationsCopy = new ArrayList<>(locations.length);
for (Location location : locations) {
locationsCopy.add(new Location(Objects.requireNonNull(location)));
}
return new LocationResult(locationsCopy);
}
/**
* Creates a new LocationResult that takes ownership of the given locations without copying
* them. Callers must ensure the given locations are never mutated after this method is called.
* Locations must be ordered in the same order they were derived (earliest to latest).
*/
public static @NonNull LocationResult wrap(@NonNull List<Location> locations) {
Preconditions.checkArgument(!locations.isEmpty());
return new LocationResult(new ArrayList<>(locations));
}
/**
* Creates a new LocationResult that takes ownership of the given locations without copying
* them. Callers must ensure the given locations are never mutated after this method is called.
* Locations must be ordered in the same order they were derived (earliest to latest).
*/
public static @NonNull LocationResult wrap(@NonNull Location... locations) {
Preconditions.checkArgument(locations.length > 0);
ArrayList<Location> newLocations = new ArrayList<>(locations.length);
for (Location location : locations) {
newLocations.add(Objects.requireNonNull(location));
}
return new LocationResult(newLocations);
}
private final ArrayList<Location> mLocations;
@@ -112,7 +128,7 @@ public final class LocationResult implements Parcelable {
}
/**
* Returns the numer of locations in this location result.
* Returns the number of locations in this location result.
*/
public @IntRange(from = 1) int size() {
return mLocations.size();
@@ -139,9 +155,9 @@ public final class LocationResult implements Parcelable {
* @hide
*/
public @NonNull LocationResult deepCopy() {
ArrayList<Location> copy = new ArrayList<>(mLocations.size());
final int size = mLocations.size();
for (int i = 0; i < size; ++i) {
ArrayList<Location> copy = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
copy.add(new Location(mLocations.get(i)));
}
return new LocationResult(copy);
@@ -164,7 +180,7 @@ public final class LocationResult implements Parcelable {
* Returns a LocationResult with only locations that pass the given predicate. This
* implementation will avoid allocations when no locations are filtered out. The predicate is
* guaranteed to be invoked once per location, in order from earliest to latest. If all
* locations are filtered out a null value is returned instead of an empty LocationResult.
* locations are filtered out a null value is returned.
*
* @hide
*/

View File

@@ -16,7 +16,7 @@
package android.location.provider;
import android.location.LocationResult;
import android.location.Location;
import android.location.provider.ProviderProperties;
/**
@@ -28,6 +28,7 @@ interface ILocationProviderManager {
void onSetAllowed(boolean allowed);
void onSetProperties(in ProviderProperties properties);
void onReportLocation(in LocationResult locationResult);
void onReportLocation(in Location location);
void onReportLocations(in List<Location> locations);
void onFlushComplete();
}

View File

@@ -25,12 +25,13 @@ import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationResult;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
@@ -200,35 +201,29 @@ public abstract class LocationProviderBase {
* Reports a new location from this provider.
*/
public void reportLocation(@NonNull Location location) {
reportLocation(LocationResult.create(location));
ILocationProviderManager manager = mManager;
if (manager != null) {
try {
manager.onReportLocation(stripExtras(location));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (RuntimeException e) {
Log.w(mTag, e);
}
}
}
/**
* Reports a new location result from this provider.
*
* <p>May only be used from Android S onwards.
* Reports a new batch of locations from this provider. Locations must be ordered in the list
* from earliest first to latest last.
*/
public void reportLocation(@NonNull LocationResult locationResult) {
public void reportLocations(@NonNull List<Location> locations) {
ILocationProviderManager manager = mManager;
if (manager != null) {
locationResult = locationResult.map(location -> {
// remove deprecated extras to save on serialization costs
Bundle extras = location.getExtras();
if (extras != null && (extras.containsKey(EXTRA_NO_GPS_LOCATION)
|| extras.containsKey("coarseLocation"))) {
location = new Location(location);
extras = location.getExtras();
extras.remove(EXTRA_NO_GPS_LOCATION);
extras.remove("coarseLocation");
if (extras.isEmpty()) {
location.setExtras(null);
}
}
return location;
});
try {
manager.onReportLocation(locationResult);
manager.onReportLocations(stripExtras(locations));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (RuntimeException e) {
@@ -246,9 +241,9 @@ public abstract class LocationProviderBase {
/**
* Requests a flush of any pending batched locations. The callback must always be invoked once
* per invocation, and should be invoked after {@link #reportLocation(LocationResult)} has been
* invoked with any flushed locations. The callback may be invoked immediately if no locations
* are flushed.
* per invocation, and should be invoked after {@link #reportLocation(Location)} or
* {@link #reportLocations(List)} has been invoked with any flushed locations. The callback may
* be invoked immediately if no locations are flushed.
*/
public abstract void onFlush(@NonNull OnFlushCompleteCallback callback);
@@ -259,6 +254,49 @@ public abstract class LocationProviderBase {
@SuppressLint("NullableCollection")
@Nullable Bundle extras);
private static Location stripExtras(Location location) {
Bundle extras = location.getExtras();
if (extras != null && (extras.containsKey(EXTRA_NO_GPS_LOCATION)
|| extras.containsKey("indoorProbability")
|| extras.containsKey("coarseLocation"))) {
location = new Location(location);
extras = location.getExtras();
extras.remove(EXTRA_NO_GPS_LOCATION);
extras.remove("indoorProbability");
extras.remove("coarseLocation");
if (extras.isEmpty()) {
location.setExtras(null);
}
}
return location;
}
private static List<Location> stripExtras(List<Location> locations) {
List<Location> mapped = locations;
final int size = locations.size();
int i = 0;
for (Location location : locations) {
Location newLocation = stripExtras(location);
if (mapped != locations) {
mapped.add(newLocation);
} else if (newLocation != location) {
mapped = new ArrayList<>(size);
int j = 0;
for (Location copiedLocation : locations) {
if (j >= i) {
break;
}
mapped.add(copiedLocation);
j++;
}
mapped.add(newLocation);
}
i++;
}
return mapped;
}
private final class Service extends ILocationProvider.Stub {
Service() {}

View File

@@ -21,8 +21,8 @@ package com.android.location.provider {
method @Deprecated protected void onInit();
method @Deprecated protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle);
method @Deprecated protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource);
method @Deprecated public void reportLocation(android.location.Location);
method @Deprecated public void reportLocation(android.location.LocationResult);
method @Deprecated public void reportLocation(@NonNull android.location.Location);
method @Deprecated public void reportLocations(@NonNull java.util.List<android.location.Location>);
method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setAdditionalProviderPackages(java.util.List<java.lang.String>);
method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.R) public void setAllowed(boolean);
method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);

View File

@@ -16,13 +16,13 @@
package com.android.location.provider;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.location.LocationResult;
import android.location.provider.ILocationProvider;
import android.location.provider.ILocationProviderManager;
import android.location.provider.ProviderProperties;
@@ -39,6 +39,7 @@ import androidx.annotation.RequiresApi;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
@@ -94,10 +95,6 @@ public abstract class LocationProviderBase {
*/
public static final String FUSED_PROVIDER = LocationManager.FUSED_PROVIDER;
private static final String EXTRA_KEY_COARSE_LOCATION = "coarseLocation";
private static final String EXTRA_KEY_NO_GPS_LOCATION = "noGPSLocation";
private static final String EXTRA_KEY_INDOOR_PROB = "indoorProbability";
final String mTag;
@Nullable final String mPackageName;
@Nullable final String mAttributionTag;
@@ -254,20 +251,11 @@ public abstract class LocationProviderBase {
/**
* Reports a new location from this provider.
*/
public void reportLocation(Location location) {
reportLocation(LocationResult.create(location));
}
/**
* Reports a new location from this provider.
*/
public void reportLocation(LocationResult locationResult) {
public void reportLocation(@NonNull Location location) {
ILocationProviderManager manager = mManager;
if (manager != null) {
locationResult = locationResult.map(this::cleanUpExtras);
try {
manager.onReportLocation(locationResult);
manager.onReportLocation(stripExtras(location));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (RuntimeException e) {
@@ -277,30 +265,20 @@ public abstract class LocationProviderBase {
}
/**
* Remove deprecated/unnecessary extras to save on serialization costs.
*
* {@link #EXTRA_KEY_NO_GPS_LOCATION} and {@link #EXTRA_KEY_COARSE_LOCATION} are deprecated.
*
* {@link #EXTRA_KEY_INDOOR_PROB} should only be used in the framework.
* Reports a new batch of locations from this provider. Locations must be ordered in the list
* from earliest first to latest last.
*/
private Location cleanUpExtras(Location location) {
Bundle extras = location.getExtras();
if (extras == null) {
return location;
}
if (extras.containsKey(EXTRA_KEY_NO_GPS_LOCATION)
|| extras.containsKey(EXTRA_KEY_COARSE_LOCATION)
|| extras.containsKey(EXTRA_KEY_INDOOR_PROB)) {
location = new Location(location);
extras = location.getExtras();
extras.remove(EXTRA_KEY_NO_GPS_LOCATION);
extras.remove(EXTRA_KEY_COARSE_LOCATION);
extras.remove(EXTRA_KEY_INDOOR_PROB);
if (extras.isEmpty()) {
location.setExtras(null);
public void reportLocations(@NonNull List<Location> locations) {
ILocationProviderManager manager = mManager;
if (manager != null) {
try {
manager.onReportLocations(stripExtras(locations));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (RuntimeException e) {
Log.w(mTag, e);
}
}
return location;
}
protected void onInit() {
@@ -336,9 +314,9 @@ public abstract class LocationProviderBase {
/**
* Requests a flush of any pending batched locations. The callback must always be invoked once
* per invocation, and should be invoked after {@link #reportLocation(LocationResult)} has been
* invoked with any flushed locations. The callback may be invoked immediately if no locations
* are flushed.
* per invocation, and should be invoked after {@link #reportLocation(Location)} or
* {@link #reportLocations(List)} has been invoked with any flushed locations. The callback may
* be invoked immediately if no locations are flushed.
*/
protected void onFlush(OnFlushCompleteCallback callback) {
callback.onFlushComplete();
@@ -433,4 +411,47 @@ public abstract class LocationProviderBase {
onSendExtraCommand(command, extras);
}
}
private static Location stripExtras(Location location) {
Bundle extras = location.getExtras();
if (extras != null && (extras.containsKey(EXTRA_NO_GPS_LOCATION)
|| extras.containsKey("indoorProbability")
|| extras.containsKey("coarseLocation"))) {
location = new Location(location);
extras = location.getExtras();
extras.remove(EXTRA_NO_GPS_LOCATION);
extras.remove("indoorProbability");
extras.remove("coarseLocation");
if (extras.isEmpty()) {
location.setExtras(null);
}
}
return location;
}
private static List<Location> stripExtras(List<Location> locations) {
List<Location> mapped = locations;
final int size = locations.size();
int i = 0;
for (Location location : locations) {
Location newLocation = stripExtras(location);
if (mapped != locations) {
mapped.add(newLocation);
} else if (newLocation != location) {
mapped = new ArrayList<>(size);
int j = 0;
for (Location copiedLocation : locations) {
if (j >= i) {
break;
}
mapped.add(copiedLocation);
j++;
}
mapped.add(newLocation);
}
i++;
}
return mapped;
}
}

View File

@@ -26,7 +26,6 @@ import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.location.LocationResult;
import android.location.provider.ILocationProvider;
import android.location.provider.ILocationProviderManager;
import android.location.provider.ProviderProperties;
@@ -49,6 +48,7 @@ import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -167,10 +167,13 @@ public class FusedLocationServiceTest {
}
@Override
public void onReportLocation(LocationResult locationResult) {
for (int i = 0; i < locationResult.size(); i++) {
mLocations.add(locationResult.get(i));
}
public void onReportLocation(Location location) {
mLocations.add(location);
}
@Override
public void onReportLocations(List<Location> locations) {
mLocations.addAll(locations);
}
@Override

View File

@@ -103,7 +103,6 @@ import com.android.server.location.provider.AbstractLocationProvider;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -1489,7 +1488,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
if (locations.length > 0) {
reportLocation(LocationResult.create(Arrays.asList(locations)).validate());
reportLocation(LocationResult.wrap(locations).validate());
}
for (Runnable listener : listeners) {

View File

@@ -20,8 +20,8 @@ import static android.app.compat.CompatChanges.isChangeEnabled;
import static android.location.LocationManager.DELIVER_HISTORICAL_LOCATIONS;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.KEY_FLUSH_COMPLETE;
import static android.location.LocationManager.KEY_LOCATIONS;
import static android.location.LocationManager.KEY_LOCATION_CHANGED;
import static android.location.LocationManager.KEY_LOCATION_RESULT;
import static android.location.LocationManager.KEY_PROVIDER_ENABLED;
import static android.location.LocationManager.PASSIVE_PROVIDER;
import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE;
@@ -187,7 +187,8 @@ public class LocationProviderManager extends
@Override
public void deliverOnLocationChanged(LocationResult locationResult,
@Nullable Runnable onCompleteCallback) throws RemoteException {
mListener.onLocationChanged(locationResult, SingleUseCallback.wrap(onCompleteCallback));
mListener.onLocationChanged(locationResult.asList(),
SingleUseCallback.wrap(onCompleteCallback));
}
@Override
@@ -222,12 +223,16 @@ public class LocationProviderManager extends
// allows apps to start a fg service in response to a location PI
options.setTemporaryAppWhitelistDuration(TEMPORARY_APP_ALLOWLIST_DURATION_MS);
Intent intent = new Intent().putExtra(KEY_LOCATION_CHANGED,
locationResult.getLastLocation());
if (locationResult.size() > 1) {
intent.putExtra(KEY_LOCATIONS, locationResult.asList().toArray(new Location[0]));
}
mPendingIntent.send(
mContext,
0,
new Intent()
.putExtra(KEY_LOCATION_CHANGED, locationResult.getLastLocation())
.putExtra(KEY_LOCATION_RESULT, locationResult),
intent,
onCompleteCallback != null ? (pI, i, rC, rD, rE) -> onCompleteCallback.run()
: null,
null,

View File

@@ -53,7 +53,7 @@ public class MockLocationProvider extends AbstractLocationProvider {
Location location = new Location(l);
location.setIsFromMockProvider(true);
mLocation = location;
reportLocation(LocationResult.wrap(location));
reportLocation(LocationResult.wrap(location).validate());
}
@Override

View File

@@ -21,6 +21,7 @@ import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.location.Location;
import android.location.LocationResult;
import android.location.provider.ILocationProvider;
import android.location.provider.ILocationProviderManager;
@@ -40,6 +41,7 @@ import com.android.server.location.provider.AbstractLocationProvider;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
@@ -260,13 +262,25 @@ public class ProxyLocationProvider extends AbstractLocationProvider {
// executed on binder thread
@Override
public void onReportLocation(LocationResult locationResult) {
public void onReportLocation(Location location) {
synchronized (mLock) {
if (mProxy != this) {
return;
}
reportLocation(locationResult.validate());
reportLocation(LocationResult.wrap(location).validate());
}
}
// executed on binder thread
@Override
public void onReportLocations(List<Location> locations) {
synchronized (mLock) {
if (mProxy != this) {
return;
}
reportLocation(LocationResult.wrap(locations).validate());
}
}

View File

@@ -96,6 +96,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -383,7 +384,7 @@ public class LocationProviderManagerTest {
LocationResult loc = createLocationResult(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener).onLocationChanged(eq(loc), nullable(IRemoteCallback.class));
verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
}
@Test
@@ -406,13 +407,13 @@ public class LocationProviderManagerTest {
LocationResult loc = createLocationResult(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener).onLocationChanged(eq(loc), nullable(IRemoteCallback.class));
verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, false);
loc = createLocationResult(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener, times(1)).onLocationChanged(any(LocationResult.class),
verify(listener, times(1)).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
@@ -422,7 +423,7 @@ public class LocationProviderManagerTest {
verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, false);
loc = createLocationResult(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener, times(1)).onLocationChanged(any(LocationResult.class),
verify(listener, times(1)).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
mProvider.setAllowed(true);
@@ -430,7 +431,7 @@ public class LocationProviderManagerTest {
loc = createLocationResult(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener).onLocationChanged(eq(loc), nullable(IRemoteCallback.class));
verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
}
@Test
@@ -447,7 +448,7 @@ public class LocationProviderManagerTest {
LocationResult loc = createLocationResult(NAME, mRandom);
mProvider.setProviderLocation(loc);
verify(listener, timeout(TIMEOUT_MS).times(1)).onLocationChanged(eq(loc),
verify(listener, timeout(TIMEOUT_MS).times(1)).onLocationChanged(eq(loc.asList()),
nullable(IRemoteCallback.class));
}
@@ -462,7 +463,7 @@ public class LocationProviderManagerTest {
mManager.unregisterLocationRequest(listener);
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, never()).onLocationChanged(any(LocationResult.class),
verify(listener, never()).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
@@ -493,7 +494,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(createLocation(NAME, mRandom));
mManager.unregisterLocationRequest(listener);
blocker.countDown();
verify(listener, after(TIMEOUT_MS).never()).onLocationChanged(any(LocationResult.class),
verify(listener, after(TIMEOUT_MS).never()).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
}
@@ -513,7 +514,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(createLocation(NAME, mRandom));
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, times(5)).onLocationChanged(any(LocationResult.class),
verify(listener, times(5)).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
}
@@ -528,7 +529,7 @@ public class LocationProviderManagerTest {
mInjector.getAlarmHelper().incrementAlarmTime(5000);
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, never()).onLocationChanged(any(LocationResult.class),
verify(listener, never()).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
}
@@ -544,7 +545,7 @@ public class LocationProviderManagerTest {
Thread.sleep(25);
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, never()).onLocationChanged(any(LocationResult.class),
verify(listener, never()).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
}
@@ -561,7 +562,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, times(1)).onLocationChanged(
any(LocationResult.class), nullable(IRemoteCallback.class));
any(List.class), nullable(IRemoteCallback.class));
}
@Test
@@ -578,7 +579,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(loc);
verify(listener, times(1)).onLocationChanged(
any(LocationResult.class), nullable(IRemoteCallback.class));
any(List.class), nullable(IRemoteCallback.class));
}
@Test
@@ -592,7 +593,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, never()).onLocationChanged(any(LocationResult.class),
verify(listener, never()).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
}
@@ -622,7 +623,7 @@ public class LocationProviderManagerTest {
verify(mWakeLock, never()).release();
blocker.countDown();
verify(listener, timeout(TIMEOUT_MS)).onLocationChanged(any(LocationResult.class),
verify(listener, timeout(TIMEOUT_MS)).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
verify(mWakeLock).acquire(anyLong());
verify(mWakeLock, timeout(TIMEOUT_MS)).release();
@@ -640,7 +641,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(createLocation(NAME, mRandom));
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, times(1))
.onLocationChanged(any(LocationResult.class), nullable(IRemoteCallback.class));
.onLocationChanged(any(List.class), nullable(IRemoteCallback.class));
}
@Test
@@ -657,7 +658,7 @@ public class LocationProviderManagerTest {
mProvider.setProviderLocation(createLocation(NAME, mRandom));
mProvider.setProviderLocation(createLocation(NAME, mRandom));
verify(listener, times(1))
.onLocationChanged(any(LocationResult.class), nullable(IRemoteCallback.class));
.onLocationChanged(any(List.class), nullable(IRemoteCallback.class));
}
@Test
@@ -746,7 +747,7 @@ public class LocationProviderManagerTest {
mProvider.completeFlushes();
InOrder inOrder = inOrder(listener);
inOrder.verify(listener).onLocationChanged(eq(loc), any(IRemoteCallback.class));
inOrder.verify(listener).onLocationChanged(eq(loc.asList()), any(IRemoteCallback.class));
inOrder.verify(listener).onFlushComplete(99);
}
@@ -838,7 +839,7 @@ public class LocationProviderManagerTest {
.build();
mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
verify(listener1).onLocationChanged(any(LocationResult.class),
verify(listener1).onLocationChanged(any(List.class),
nullable(IRemoteCallback.class));
assertThat(mProvider.getRequest().isActive()).isFalse();
@@ -989,7 +990,7 @@ public class LocationProviderManagerTest {
private ILocationListener createMockLocationListener() {
return spy(new ILocationListener.Stub() {
@Override
public void onLocationChanged(LocationResult location,
public void onLocationChanged(List<Location> locations,
IRemoteCallback onCompleteCallback) {
if (onCompleteCallback != null) {
try {

View File

@@ -185,8 +185,8 @@ public class MockableLocationProviderTest {
@Test
public void testReportLocation() {
LocationResult realLocation = LocationResult.create(new Location("real"));
LocationResult mockLocation = LocationResult.create(new Location("mock"));
LocationResult realLocation = LocationResult.wrap(new Location("real"));
LocationResult mockLocation = LocationResult.wrap(new Location("mock"));
mRealProvider.reportLocation(realLocation);
assertThat(mListener.getNextLocationResult()).isEqualTo(realLocation);